all:
.PHONY: all
OPTIM?=2
DEBUG?=1
# FORCE_COLOR: set to non-empty, non 0 to force colorized output
# ECHO: set to non-empty, non 0 to echo commands out
help:
@echo 'Targets:'
@echo ' help (current target)'
@echo ' all (default target)'
@echo ' [EXE] - wrapperhelper'
@printf ' $(foreach obj,$(OBJLIST_wrapperhelper), [OBJ] - $(obj)\n)'
@printf ' $(foreach test,$(TESTS), [TST] - $(test)\n)'
@echo ' clean'
@echo ' distclean'
@echo ''
@echo 'Options:'
@echo ' OPTIM: GCC optimization level (-O is prepended) [default: 2]'
@echo ' DEBUG: set to 0 for release build, set to non-0 for debug build [default: 1]'
@echo ' FORCE_COLOR: set to non-0 to force colorized output'
@echo ' ECHO: set to non-0 to echo out commands executed'
@echo ''
@echo 'Current flags:'
@echo ' CPPFLAGS = $(CPPFLAGS)'
@echo ' CFLAGS = $(CFLAGS)'
# @echo ' CXXFLAGS = $(CXXFLAGS)' unused
@echo ' LDFLAGS = $(LDFLAGS)'
@echo ' LDLIBS = $(LDLIBS)'
@echo ''
@echo 'Sanitizers:'
@echo " address ------------ `[ $(ASAN_ON) -eq 1 ] && printf '\033[92mON\033[m' || printf '\033[91mOFF\033[m'`"
@echo " leak --------------- `[ $(LSAN_ON) -eq 1 ] && printf '\033[92mON\033[m' || printf '\033[91mOFF\033[m'`"
@echo " undefined behavior - `[ $(USAN_ON) -eq 1 ] && printf '\033[92mON\033[m' || printf '\033[91mOFF\033[m'`"
.PHONY: help
ifeq ($(ECHO:0=),)
SILENCER:=@
else
SILENCER:=
endif
ifneq ($(strip $(DEBUG)),0)
CPPFLAGS+= -DDEBUG -D_NRELEASE
CFLAGS+= -g
CXXFLAGS+= -g
LDFLAGS+= -g
OBJDIR?=debug
else
CPPFLAGS+= -DRELEASE -D_NDEBUG
OBJDIR?=release
endif
COMMON_WARNINGS:=-Wfatal-errors -fanalyzer -Wall -Wextra
COMMON_WARNINGS+= -Walloc-zero -Wcast-align=strict -Wcast-qual -Wconversion -Wdate-time
COMMON_WARNINGS+= -Wdisabled-optimization -Wduplicated-branches -Wfloat-equal -Wformat-truncation=2
COMMON_WARNINGS+= -Wimplicit-fallthrough=3 -Wlogical-op -Wmissing-format-attribute -Wmissing-include-dirs
COMMON_WARNINGS+= -Wmissing-noreturn -Wnull-dereference -Wredundant-decls -Wundef -Wunreachable-code -Wshift-overflow=2
COMMON_WARNINGS+= -Wstringop-overflow=4
#COMMON_WARNINGS+= -Wstringop-overflow=4 -Wsuggest-attribute=cold -Wsuggest-attribute=const -Wsuggest-attribute=format
#COMMON_WARNINGS+= -Wsuggest-attribute=malloc -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure
COMMON_WARNINGS+= -Wunknown-pragmas -Wunused-macros -Wwrite-strings
COMMON_WARNINGS+= -Werror=attribute-alias=2 -Werror=duplicated-cond -Werror=format=2 -Werror=format-overflow=2
COMMON_WARNINGS+= -Werror=format-signedness -Werror=pointer-arith
COMMON_WARNINGS+= -Werror=return-type -Werror=shadow -Werror=strict-overflow -Werror=switch-enum
CFLAGS_WARNINGS:=-Werror=implicit-function-declaration -Werror=jump-misses-init -Werror=strict-prototypes
CXXFLAGS_WARNINGS:=-Werror=overloaded-virtual -fdiagnostics-show-template-tree -Wno-analyzer-use-of-uninitialized-value
CPPFLAGS+=
CFLAGS:=$(COMMON_WARNINGS) $(CFLAGS_WARNINGS) $(CFLAGS) -std=gnu18 -O$(OPTIM)
CXXFLAGS:=$(COMMON_WARNINGS) $(CXXFLAGS_WARNINGS) $(CXXFLAGS) -std=c++20 -O$(OPTIM)
LDFLAGS+= -O$(OPTIM)
#CPPFLAGS+= -I/usr/include/SDL2 -D_REENTRANT -pthread
#CFLAGS+= -pthread
#CXXFLAGS+= -pthread
#LDLIBS+= -pthread -lSDL2
ifeq (,$(wildcard $(CURDIR)/sanaddress))
ASAN_ON:=0
else
ASAN_ON:=1
CFLAGS+= -fsanitize=address
CXXFLAGS+= -fsanitize=address
LDFLAGS+= -fsanitize=address
endif
ifeq (,$(wildcard $(CURDIR)/sanleak))
LSAN_ON:=0
else
LSAN_ON:=1
CFLAGS+= -fsanitize=leak
CXXFLAGS+= -fsanitize=leak
LDFLAGS+= -fsanitize=leak
endif
ifeq (,$(wildcard $(CURDIR)/sanundefined))
USAN_ON:=0
else
USAN_ON:=1
CFLAGS+= -fsanitize=undefined
CXXFLAGS+= -fsanitize=undefined
LDFLAGS+= -fsanitize=undefined
endif
# Default
# .SUFFIXES: .out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S .mod
# .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el
SUFFIXES =
.SUFFIXES:
.SECONDEXPANSION:
ifneq ($(MAKECMDGOALS:distclean=clean),clean)
.: ;
bin obj: ; $(SILENCER)test -d $@ || mkdir $@
# $(eval $(call reproduce_tree,))
define reproduce_tree =
$(1): | $$$$(@D) ; $(SILENCER)test -d $$@ || mkdir $$@
endef
$(eval $(call reproduce_tree,obj/$(OBJDIR)))
$(eval $(call reproduce_tree,obj/$(OBJDIR)/tests))
$(eval $(call reproduce_tree,makedir))
$(eval $(call reproduce_tree,makedir/tests))
$(eval $(call reproduce_tree,tests))
endif
# Colors:
# -------
# +--------+-----+
# | 3 | 9 |
# +-+--------+-----+
# |0| | | Black
# |1| | RM | Red
# |2| |[MSG]| Green
# |3|Creating| | Yellow
# |4| | CP | Blue
# |5| | LD | Purple
# |6| C++ | | Cyan
# |7| | | Gray/white
# +-+--------+-----+
# $(call colorize,,,,)
ifdef $(if $(FORCE_COLOR:0=),FORCE_COLOR,MAKE_TERMOUT)
CFLAGS:=$(CFLAGS) -fdiagnostics-color
CXXFLAGS:=$(CFLAGS) -fdiagnostics-color
colorize=@printf "\033[$(1)m[$(2)]\033[m \033[$(3)m$(4)\033[m\n"
else
ifeq ($(SILENCER),)
colorize=
else
colorize=@echo "[$(2)] $(4)"
endif
endif
define newline :=
endef
# $(call remove,)
define remove =
$(call colorize,1;91,RM ,91,Removing $(1))
$(SILENCER)$(RM) -r $(1)
endef
# $(eval $(call add_deptree,,,))
ifeq ($(MAKECMDGOALS),distclean)
add_deptree=
else
define add_deptree =
makedir/$(2).mk: | $$$$(@D)
$(call colorize,95,DEP,33,Creating $(3) dependancies)
$(SILENCER)set -e; $(1) -MM src/$(3) \
| sed 's,\($$(notdir $$(basename $(3)))\)\.o[ :]*,$$(dir obj/$(OBJDIR)/$(3))\1.o: $$@'"\n"'$$(dir obj/$(OBJDIR)/$(3))\1.o $$@: ,g' >$$@
include makedir/$(2).mk
endef
endif
OBJLIST=$(OBJLIST_wrapperhelper) $(foreach test,$(TESTS),$(call test_o,$(test)))
OBJLIST_wrapperhelper:=
TESTS:=
# $(call wrapperhelper_o,,,)
wrapperhelper_o=obj/$(OBJDIR)/$(1)$(3).o
# $(eval $(call compile_wrapperhelper_c,,,))
define compile_wrapperhelper_c =
$$(eval $$(call add_deptree,$$(CC) $$(CPPFLAGS) $$(CFLAGS),$(1)$(3),$(1)$(2).c))
OBJLIST_wrapperhelper+= $(call wrapperhelper_o,$(1),$(2),$(3))
$(call wrapperhelper_o,$(1),$(2),$(3)): src/$(1)$(2).c | $$$$(@D)
$(call colorize,36, C ,92,Compiling $$@)
$(SILENCER)$$(CC) $$(CPPFLAGS) $$(CFLAGS) -c src/$(1)$(2).c -o $$@
endef
# $(eval $(call compile_wrapperhelper_cxx,,,))
define compile_wrapperhelper_cxx =
$$(eval $$(call add_deptree,$$(CXX) $$(CPPFLAGS) $$(CXXFLAGS),$(1)$(3),$(1)$(2).cpp))
OBJLIST_wrapperhelper+= $(call wrapperhelper_o,$(1),$(2),$(3))
$(call wrapperhelper_o,$(1),$(2),$(3)): src/$(1)$(2).cpp | $$$$(@D)
$(call colorize,36,C++,92,Compiling $$@)
$(SILENCER)$$(CXX) $$(CPPFLAGS) $$(CXXFLAGS) -c src/$(1)$(2).cpp -o $$@
endef
# $(eval $(call compile_test_c,))
define compile_test_c =
$$(eval $$(call add_deptree,$$(CC) $$(CPPFLAGS) -Isrc/tests -Isrc $$(CFLAGS),tests/$(1),tests/$(1).c))
TESTS+= $(1)
tests/$(1): obj/$(OBJDIR)/tests/$(1).o | $$$$(@D)
$(call colorize,95,LD ,92,Linking $$@)
$(SILENCER)$$(CC) $$(LDFLAGS) -o $$@ obj/$(OBJDIR)/tests/$(1).o $$(LDLIBS)
obj/$(OBJDIR)/tests/$(1).o: src/tests/$(1).c | $$$$(@D)
$(call colorize,36,C++,92,Compiling $$@)
$(SILENCER)$$(CC) $$(CPPFLAGS) -Isrc/tests -Isrc $$(CFLAGS) -c src/tests/$(1).c -o $$@
endef
# $(eval $(call compile_test_cxx,))
define compile_test_cxx =
$$(eval $$(call add_deptree,$$(CXX) $$(CPPFLAGS) -Isrc/tests -Isrc $$(CXXFLAGS),tests/$(1),tests/$(1).cpp))
TESTS+= $(1)
tests/$(1): obj/$(OBJDIR)/tests/$(1).o | $$$$(@D)
$(call colorize,95,LD ,92,Linking $$@)
$(SILENCER)$$(CXX) $$(LDFLAGS) -o $$@ obj/$(OBJDIR)/tests/$(1).o $$(LDLIBS)
obj/$(OBJDIR)/tests/$(1).o: src/tests/$(1).cpp | $$$$(@D)
$(call colorize,36,C++,92,Compiling $$@)
$(SILENCER)$$(CXX) $$(CPPFLAGS) -Isrc/tests -Isrc $$(CXXFLAGS) -c src/tests/$(1).cpp -o $$@
endef
$(eval $(call compile_wrapperhelper_c,,cstring,cstring))
$(eval $(call compile_wrapperhelper_c,,generator,generator))
$(eval $(call compile_wrapperhelper_c,,lang,lang))
$(eval $(call compile_wrapperhelper_c,,log,log))
$(eval $(call compile_wrapperhelper_c,,machine,machine))
$(eval $(call compile_wrapperhelper_c,,main,main))
$(eval $(call compile_wrapperhelper_c,,parse,parse))
$(eval $(call compile_wrapperhelper_c,,prepare,prepare))
$(eval $(call compile_wrapperhelper_c,,preproc,preproc))
$(eval $(call compile_wrapperhelper_c,,vector,vector))
$(call wrapperhelper_o,,machine,machine): src/machine.gen
$(call wrapperhelper_o,,generator,generator): CFLAGS+= -fno-analyzer # Too slow
$(call wrapperhelper_o,,preproc,preproc): CFLAGS+= -fno-analyzer
$(call wrapperhelper_o,,parse,parse): CFLAGS+= -fno-analyzer
src/machine.gen:
$(call colorize,96,GEN,33,Generating $@)
$(SILENCER)echo | LC_ALL=C LANG=C $(CC) $(CPPFLAGS) -E -v - 2>&1 | sed ':l; $$ ! { N; b l }; s/.*#include <...> search starts here:\n//; s/End of search list.*//; s/^ /DO_PATH("/; s/\n /")\nDO_PATH("/g; s/\n$$/")/' >src/machine.gen
#$(eval $(call compile_test_cxx,core/number))
bin/wrapperhelper: $$(OBJLIST_wrapperhelper) | $$(@D)
$(call colorize,95,LD ,92,Linking $@)
$(SILENCER)$(CXX) $(LDFLAGS) -o $@ $(OBJLIST_wrapperhelper) $(LDLIBS)
wrapperhelper: bin/wrapperhelper
alltests: $(TESTS:%=tests/%)
.PHONY: wrapperhelper alltests
all: wrapperhelper alltests
clean:
$(call remove,$(OBJLIST))
$(call remove,bin/wrapperhelper)
$(call remove,$(TESTS:%=obj/$(OBJDIR)/tests/%.o))
$(call remove,$(TESTS:%=tests/%))
$(call remove,src/machine.gen)
.PHONY: clean
distclean:
$(call remove,makedir)
$(call remove,obj)
$(call remove,bin tests)
.PHONY: distclean
sanitize/help:
@echo "Sanitizers:"
@echo "- address (removes leak)"
@echo "- leak (removes address)"
@echo "- undefined behavior"
@echo ""
@echo "Currently active options:"
@[ $(ASAN_ON) -eq 0 ] || echo "- address"
@[ $(LSAN_ON) -eq 0 ] || echo "- leak"
@[ $(USAN_ON) -eq 0 ] || echo "- undefined behavior"
sanitize/address:
@[ $(ASAN_ON) -eq 0 ] && echo "Not sanitizing address" || echo "Sanitizing address"
sanitize/leak:
@[ $(LSAN_ON) -eq 0 ] && echo "Not sanitizing leak" || echo "Sanitizing leak"
sanitize/undefined:
@[ $(USAN_ON) -eq 0 ] && echo "Not sanitizing undefined behavior" || echo "Sanitizing undefined behavior"
sanitize/address/on:
$(SILENCER)touch sanaddress
$(SILENCER)$(RM) sanleak
sanitize/leak/on:
$(SILENCER)touch sanleak
$(SILENCER)$(RM) sanaddress
sanitize/undefined/on:
$(SILENCER)touch sanundefined
sanitize/address/off:
$(SILENCER)$(RM) sanaddress
sanitize/leak/off:
$(SILENCER)$(RM) sanleak
sanitize/undefined/off:
$(SILENCER)$(RM) sanundefined
.PHONY: sanitize/address sanitize/leak sanitize/undefined
.PHONY: sanitize/address/on sanitize/leak/on sanitize/undefined/on
.PHONY: sanitize/address/off sanitize/leak/off sanitize/undefined/off
tree:
@tree src
.PHONY: tree
.DELETE_ON_ERROR: