# Copyright (c) 2017-2021, Patrick Pelissier # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # + Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # + Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. CC=cc -std=c99 WCFLAGS_GCC=-Wall -W -pedantic -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wswitch-default -Wswitch-enum -Wcast-align -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 -Wundef -Wnested-externs -Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op -Wstrict-aliasing=2 -Wredundant-decls -Wold-style-definition -Wunused-function -ftrapv -Wsign-conversion -Wdate-time -Wconversion -Wformat=2 -Winit-self -Wjump-misses-init -Wstack-protector -Wtrampolines -Wwrite-strings -Wformat-security -Wno-float-conversion -O WCFLAGS_CLANG=-Wall -W -pedantic -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wswitch-default -Wswitch-enum -Wcast-align -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 -Winline -Wundef -Wnested-externs -Wcast-qual -Wshadow -Wunreachable-code -Wstrict-aliasing=2 -Wredundant-decls -Wold-style-definition -Wunused-function -ftrapv -Wsign-conversion -O WCFLAGS_CPP=-Wall -W -pedantic -Wshadow -Wpointer-arith -Wcast-qual -Wswitch-default -Wswitch-enum -Wcast-align -Wpointer-arith -Wstrict-overflow=5 -Winline -Wundef -Wcast-qual -Wshadow -Wunreachable-code -Wstrict-aliasing=2 -Wredundant-decls -Wunused-function -ftrapv -Wsign-conversion XCFLAGS= CFLAGS=$(WCFLAGS_GCC) $(XCFLAGS) CPPFLAGS=-I.. LDFLAGS=-pthread RM=rm -f RMDIR=rm -rf LOG_COMPILER= SED=sed -e all: @echo "Nothing to be done." ##################################################################################################### # Rules ##################################################################################################### .POSIX: .PHONY: scan-build sanitize check clean *.log coverage synthesis .SUFFIXES: .SUFFIXES: .c .exe .log .depend .gcov .SECONDARY: .c.exe: $(CC) $(CFLAGS) $(CPPFLAGS) -g $(LDFLAGS) $< -o $@ .c.depend: $(CC) $(CFLAGS) $(CPPFLAGS) -MM -MT `echo $< |$(SED) 's/\.c/\.exe/g'` $< > $@ .exe.log: $(LOG_COMPILER) ./$< .c.gcov: awk '/START_COVERAGE/ { printit=1} (printit == 0) { print }' $< > $<.first.c awk ' printit { print } /END_COVERAGE/ { printit=1}' $< > $<.end.c $(CC) $(CPPFLAGS) -E -DNDEBUG -DWITHIN_COVERAGE $< |grep -v '^#' |awk ' /END_COVERAGE/ { printit=0} printit { print } /START_COVERAGE/ { printit=1 }' |perl -p -e "s/;(?![\"'])/;\n/g ; s/}(?![\"'])/}\n/g ; s/{(?![\"'])/{\n/g" > $<.middle.c cat $<.first.c $<.middle.c $<.end.c > $<.c $(CC) $(CPPFLAGS) $(LDFLAGS) -ftest-coverage -fprofile-arcs -g $<.c -o $<.exe $(LOG_COMPILER) ./$<.exe LANG=C gcov $<.gcno > `basename $< .c`.synt cat `basename $< .c`.synt mv $<.c.gcov `basename $< .c`.gcov $(RM) $<.first.c $<.end.c $<.middle.c $<.c $<.exe -include depend depend: $(RM) depend echo "" > depend $(MAKE) `ls test-*.c|$(SED) 's/\.c/\.depend/g'` cat *.depend > depend $(RM) *.depend ##################################################################################################### # Clean ##################################################################################################### exe: depend $(MAKE) `ls test-*.c|$(SED) 's/\.c/\.exe/g'` CC="$(CC)" CFLAGS="$(CFLAGS)" @echo All executable generated check: depend $(MAKE) `ls test-*.c|$(SED) 's/\.c/\.log/g'` `ls fail-*.c|$(SED) 's/\.c/\.log/g'` CC="$(CC)" CFLAGS="$(CFLAGS)" @echo All tests passed clean: $(RM) *.exe *.s *~ *.o *.log a*.dat $(RM) *.gcda *.gcno *.gcov all.info test.tar *.synt clang_output_* *.c.c *.end.c *.first.c *.middle.c $(RMDIR) coverage coverage-dir mlib-report distclean: clean $(RM) *.depend depend ##################################################################################################### # Proper failure generation (test if the code properly fails to compile) ##################################################################################################### # TODO: should grep failure message? FAIL_BASE= FAIL_SEQ= fail-generic.log: for i in `seq 1 $(FAIL_SEQ)` ; do \ if $(CC) $(CFLAGS) $(CPPFLAGS) -g -c $(FAIL_BASE).c -o tmp.o -DTEST=$$i 2> $(FAIL_BASE)-$$i.log ; then echo "$(FAIL_BASE) -- TEST $$i : ERROR (compilation succeeded)" ; false ; elif grep -q "M_LIB_" $(FAIL_BASE)-$$i.log ; then echo "$(FAIL_BASE) -- TEST $$i : OK" ; else echo "$(FAIL_BASE) -- TEST $$i : WARNING (Not a M*LIB detected error)" ; fi \ done fail-no-oplist.log: @$(MAKE) fail-generic.log FAIL_BASE=fail-no-oplist FAIL_SEQ=44 fail-chain-oplist.log: @$(MAKE) fail-generic.log FAIL_BASE=fail-chain-oplist FAIL_SEQ=24 fail-incompatible.log: @$(MAKE) fail-generic.log FAIL_BASE=fail-incompatible FAIL_SEQ=24 ##################################################################################################### # Code generation analysis ##################################################################################################### gene-list: $(CC) $(CFLAGS) $(CPPFLAGS) -O3 -march=native -DNDEBUG -S tgen-mlist.c && less tgen-mlist.s gene-array: $(CC) $(CFLAGS) $(CPPFLAGS) -O3 -march=native -DNDEBUG -S tgen-marray.c && less tgen-marray.s gene-shared: $(CC) $(CFLAGS) $(CPPFLAGS) -O3 -march=native -DNDEBUG -S tgen-shared.c && less tgen-shared.s gene-bitset: $(CC) $(CFLAGS) $(CPPFLAGS) -O3 -march=native -DNDEBUG -S tgen-bitset.c && less tgen-bitset.s gene-dict: $(CC) $(CFLAGS) $(CPPFLAGS) -O3 -march=native -DNDEBUG -S tgen-mdict.c && less tgen-mdict.s gene-queue: $(CC) $(CFLAGS) $(CPPFLAGS) -O3 -march=native -DNDEBUG -S tgen-queue.c && less tgen-queue.s gene-string: $(CC) $(CFLAGS) $(CPPFLAGS) -O3 -march=native -DNDEBUG -S tgen-mstring.c && less tgen-mstring.s # Coverage ##################################################################################################### coverage: $(MAKE) `ls test-*.c|$(SED) 's/\.c/\.gcov/g'` $(MAKE) synthesis SYNTHESIS_DATA= M-ALGO test-malgo.c.c test-malgo.synt \ M-ARRAY test-marray.c.c test-marray.synt \ M-BITSET ../m-bitset.h test-mbitset.synt \ M-BBPTREE test-mbptree.c test-mbptree.synt \ M-BUFFER test-mbuffer.c.c test-mbuffer.synt \ M-CONCURRENT test-mconcurrent.c.c test-mconcurrent.synt \ M-CORE test-mcore.c.c test-mcore.synt \ M-DEQUE test-mdeque.c.c test-mdeque.synt \ M-DICT test-mdict.c.c test-mdict.synt \ M-FUNCOBJ test-mfuncobj.c.c test-mfuncobj.synt \ M-GENINT ../m-genint.h test-mgenint.synt \ M-I-LIST test-milist.c.c test-milist.synt \ M-I-SHARED test-mishared.c.c test-mishared.synt \ M-LIST test-mlist.c.c test-mlist.synt \ M-MEMPOOL test-mmempool.c.c test-mmempool.synt \ M-MUTEX ../m-mutex.h test-mmutex.synt \ M-PRIOQUEUE test-mprioqueue.c.c test-mprioqueue.synt \ M-RBTREE test-mrbtree.c.c test-mrbtree.synt \ M-SERIAL-BIN ../m-serial-bin.h test-mserial-bin.synt \ M-SERIAL-JSON ../m-serial-json.h test-mserial-json.synt \ M-SHARED test-mshared.c.c test-mshared.synt \ M-SNAPSHOT test-msnapshot.c.c test-msnapshot.synt \ M-STRING ../m-string.h test-mstring.synt \ M-TUPLE test-mtuple.c.c test-mtuple.synt \ M-VARIANT test-mvariant.c.c test-mvariant.synt \ M-WORKER ../m-worker.h test-mworker.synt synthesis: @printf "+-------------------------------+-------------------------------+\n" @for i in $(SYNTHESIS_DATA) ; do \ if test "$$j" = "" ; then j=$$i ; continue ; fi; \ if test "$$k" = "" ; then k=$$i ; continue ; fi; \ printf "|\t%16.16s\t|\t%16.16s\t|\n" "$$j" "`grep -v Creating $$i|grep $$k -F -A1 |tail -1|cut -f2 -d':'`"; \ j=""; \ k=""; \ done @printf "+-------------------------------+-------------------------------+\n" ##################################################################################################### # Code analyzer tools ##################################################################################################### scan-build: clean $(RM) -rf ./mlib-report scan-build -o ./mlib-report $(MAKE) exe XCFLAGS="-std=c99" sanitize: $(MAKE) clean check XCFLAGS="-fsanitize=address,undefined,leak" $(MAKE) clean check XCFLAGS="-fsanitize=thread -pie -fPIE" ##################################################################################################### # Test All ##################################################################################################### checkall: @$(MAKE) clean ; $(MAKE) check CC="gcc -std=c99 -Werror" @$(MAKE) clean ; $(MAKE) check CC="gcc -std=c99 -m32 -Werror" @$(MAKE) clean ; $(MAKE) check CC="gcc -std=c11 -Werror" @$(MAKE) clean ; $(MAKE) check CC="gcc -std=c11 -m32 -Werror" @if which clang ; then $(MAKE) clean ; $(MAKE) check CC="clang -std=c99 -Werror" CFLAGS="$(WCFLAGS_CLANG)" ; else echo "SYSTEM CLANG not found: SKIP TEST" ; fi @if which g++ ; then $(MAKE) clean ; $(MAKE) check CC="g++ -std=c++11 -Werror" CFLAGS="$(WCFLAGS_CPP)" ; else echo "SYSTEM G++ not found: SKIP TEST" ; fi @if which clang++ ; then $(MAKE) clean ; $(MAKE) check CC="clang++ -std=c++11" CFLAGS="$(WCFLAGS_CLANG)" ; else echo "SYSTEM CLANG++ not found: SKIP TEST" ; fi @if which tcc ; then $(MAKE) clean ; $(MAKE) check CC="tcc -std=c99 -Werror" ; else echo "SYSTEM TCC not found: SKIP TEST" ; fi @if which musl-gcc ; then $(MAKE) clean ; $(MAKE) check CC="musl-gcc -std=c11 -Werror" ; else echo "SYSTEM MUSL-GCC not found: SKIP TEST" ; fi @for f in /opt/gcc* ; do if test -x "$$f/bin/gcc" ; then $(MAKE) clean ; $(MAKE) check CC="$$f/bin/gcc -std=c99 -Werror" ; fi ; done @for f in /opt/clang* ; do if test -x "$$f/bin/clang" ; then $(MAKE) clean ; $(MAKE) check CC="$$f/bin/clang -std=c99 -Werror" CFLAGS="$(WCFLAGS_CLANG)" ; fi ; done @for f in /opt/tcc* ; do if test -x "$$f/bin/tcc" ; then $(MAKE) clean ; $(MAKE) check CC="$$f/bin/tcc -std=c99 -Werror" ; fi ; done