|
| 1 | +#usage: include Makefile.common at the end of your Makefile |
| 2 | + |
| 3 | +# no builtin rules/vars (CC, CXX, etc. are still defined but will be empty) |
| 4 | +MAKEFLAGS += -r -R |
| 5 | + |
| 6 | +HDR = $(addsuffix .h,$(MODULES) $(HEADERS)) |
| 7 | +SRC = $(addsuffix .c,$(MODULES) $(SOURCES)) |
| 8 | +ASM = $(addsuffix .S,$(ASSMBLY)) |
| 9 | +OBJ = $(addsuffix .o,$(MODULES) $(SOURCES) $(ASSEMBLY)) |
| 10 | +DEP = Makefile.common Makefile $(HDR) $(EXTERNDEP) $(EXTERNSRC) |
| 11 | +BIN = $(addsuffix .out,$(TARGETS)) |
| 12 | +DIS = $(addsuffix .dis,$(TARGETS)) |
| 13 | + |
| 14 | +# clang: |
| 15 | +# EXTRA="-Rpass=loop-vectorize" # IDs loops that were successfully V-ed |
| 16 | +# EXTRA="-Rpass-missed=loop-vectorize" # IDs loops that failed V |
| 17 | +# EXTRA="-Rpass-analysis=loop-vectorize" # IDs the statements that caused V to fail |
| 18 | +# EXTRA="-Rpass=\ *" # remarks for all passes |
| 19 | +# other passes: https://llvm.org/docs/Passes.html |
| 20 | + |
| 21 | +O ?= rg |
| 22 | + |
| 23 | +# predefined OPT: make O={rg,r,0g,3g,p,0s,3s,cov,mc,hc,wn,stk} |
| 24 | +ifeq ($O,rg) # make O=rg |
| 25 | +OPT ?= -DNDEBUG -g3 -O3 -flto -fno-stack-protector |
| 26 | +else ifeq ($O,r) # make O=r (for release) |
| 27 | +OPT ?= -DNDEBUG -O3 -flto -fno-stack-protector |
| 28 | +else ifeq ($O,ns) # make O=ns (no signal handlers) |
| 29 | +OPT ?= -DNDEBUG -O3 -flto -fno-stack-protector -DNOSIGNAL |
| 30 | +else ifeq ($O,0g) # make O=0g |
| 31 | +OPT ?= -g3 -O0 -fno-inline |
| 32 | +else ifeq ($O,2g) # make O=2g |
| 33 | +OPT ?= -g3 -O2 |
| 34 | +else ifeq ($O,3g) # make O=3g |
| 35 | +OPT ?= -g3 -O3 -flto -fno-inline |
| 36 | +else ifeq ($O,p) # make O=p (profiling: rg+noinline) |
| 37 | +OPT ?= -DNDEBUG -g3 -O3 -flto -fno-stack-protector -fno-inline |
| 38 | +else ifeq ($O,0s) # make O=0s (address sanitizer) |
| 39 | +OPT ?= -g3 -O0 -fno-inline -fsanitize=address -fno-omit-frame-pointer -DHEAPCHECKING |
| 40 | +else ifeq ($O,3s) # make O=3s (address sanitizer) |
| 41 | +OPT ?= -g3 -O3 -fno-inline -fsanitize=address -fno-omit-frame-pointer -DHEAPCHECKING |
| 42 | +else ifeq ($O,t) # make O=0t (thread sanitizer) |
| 43 | +OPT ?= -g3 -O1 -fno-inline -fsanitize=thread -fno-stack-protector |
| 44 | +else ifeq ($O,cov) # make O=cov (for gcov) |
| 45 | +OPT ?= -g3 -DNDEBUG -O0 --coverage |
| 46 | +CCC = gcc |
| 47 | +else ifeq ($O,mc) # make O=mc (for valgrind memcheck) |
| 48 | +OPT ?= -g3 -O1 -fno-inline -DHEAPCHECKING |
| 49 | +ARCH ?= broadwell |
| 50 | +else ifeq ($O,hc) # make O=hc (for gperftools heapcheck) |
| 51 | +OPT ?= -g3 -O1 -fno-inline |
| 52 | +LIB += tcmalloc |
| 53 | +else ifeq ($O,wn) # more warning |
| 54 | +OPT ?= -g3 -O3 -Wvla -Wformat=2 -Wconversion -Wstrict-prototypes -Wmissing-prototypes |
| 55 | +else ifeq ($O,stk) # check stack usage with gcc |
| 56 | +OPT ?= -g3 -O3 -DNDEBUG -fstack-usage |
| 57 | +CCC = gcc |
| 58 | +endif |
| 59 | + |
| 60 | +# malloc: g:glibc, t:tcmalloc, j:jemalloc |
| 61 | +M ?= g |
| 62 | + |
| 63 | +ifeq ($M,t) |
| 64 | + LIB += tcmalloc |
| 65 | + FLG += -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free |
| 66 | +else ifeq ($M,j) |
| 67 | + LIB += jemalloc |
| 68 | +endif |
| 69 | + |
| 70 | +UNAME_S := $(shell uname -s) |
| 71 | +ifeq ($(UNAME_S),Linux) |
| 72 | + CHECK_S := -D__linux__ |
| 73 | + LIB += rt |
| 74 | +else ifeq ($(UNAME_S),FreeBSD) |
| 75 | + CHECK_S := -D__FreeBSD__ |
| 76 | + FLG += -I/usr/local/include -L/usr/local/lib |
| 77 | + LIB += rt |
| 78 | + LIB += execinfo |
| 79 | + TPUT := /usr/local/bin/tput |
| 80 | +else ifeq ($(UNAME_S),Darwin) |
| 81 | + CHECK_S := -D__APPLE__ -D__MACH__ |
| 82 | + # do nothing |
| 83 | +else |
| 84 | + $(error "Supported Platforms: Linux, FreeBSD, Darwin") |
| 85 | +endif |
| 86 | +TPUT ?= tput |
| 87 | + |
| 88 | +CCC ?= clang |
| 89 | +CSTD = -std=gnu18 |
| 90 | +XCC ?= clang++ |
| 91 | +XSTD = -std=gnu++17 |
| 92 | + |
| 93 | +UNAME_M := $(shell uname -m) |
| 94 | +ifeq ($(UNAME_M),aarch64) # "native" does not work for clang@aarch64 |
| 95 | + CHECK_M := -D__aarch64__ |
| 96 | + ARCH ?= armv8-a+crc |
| 97 | +else ifeq ($(UNAME_M),arm64) # "native" does not work for clang@aarch64 |
| 98 | + CHECK_M := -D__aarch64__ |
| 99 | + ARCH ?= armv8-a+crc |
| 100 | +else ifeq ($(UNAME_M),x86_64) |
| 101 | + CHECK_M := -D__x86_64__ |
| 102 | + ARCH ?= native |
| 103 | +else ifeq ($(UNAME_M),amd64) # freebsd |
| 104 | + CHECK_M := -D__x86_64__ |
| 105 | + ARCH ?= native |
| 106 | +else |
| 107 | + $(error "Supported Platforms: aarch64, x86_64") |
| 108 | +endif |
| 109 | + |
| 110 | +TUNE ?= native |
| 111 | + |
| 112 | +NBI += memcpy memmove memcmp |
| 113 | + |
| 114 | +# minimal requirement on x86_64: -march=nehalem |
| 115 | +# minimal requirement on aarch64: -march=armv8-a+crc |
| 116 | +FLG += -march=$(ARCH) -mtune=$(TUNE) |
| 117 | +FLG += -pthread -Wall -Wextra -Wshadow #-Weverything |
| 118 | +FLG += $(addprefix -fno-builtin-,$(NBI)) |
| 119 | +FLG += $(OPT) |
| 120 | + |
| 121 | +ifneq ($(shell $(CCC) --version 2>/dev/null | grep clang),) |
| 122 | +FLG += -ferror-limit=3 |
| 123 | +CCCTYPE := clang |
| 124 | +else ifneq ($(shell $(CCC) --version 2>/dev/null | grep gcc),) |
| 125 | +FLG += -fmax-errors=3 |
| 126 | +FLG += -Wno-unknown-pragmas |
| 127 | +CCCTYPE := gcc |
| 128 | +else |
| 129 | + $(error "Supported Compilers: clang, gcc") |
| 130 | +endif |
| 131 | + |
| 132 | +ifeq ($(CCCTYPE),clang) |
| 133 | + CCINST = /usr/lib/clang/$(shell $(CCC) --version 2>/dev/null | awk '/^clang/ { print $$3 }') |
| 134 | + CCINC = $(CCINST)/include |
| 135 | +else ifeq ($(CCCTYPE),gcc) |
| 136 | + CCINST = /usr/lib/gcc/$(shell $(CCC) -dumpmachine)/$(shell $(CCC) -dumpversion) |
| 137 | + CCINC = $(CCINST)/include $(CCINST)/include-fixed |
| 138 | +endif |
| 139 | +CCINC = /usr/include /usr/local/include |
| 140 | + |
| 141 | +ifneq ($(shell find $(CCINC) -name backtrace-supported.h 2>/dev/null),) |
| 142 | + LIB += backtrace |
| 143 | + FLG += -DBACKTRACE |
| 144 | +endif |
| 145 | + |
| 146 | +ifneq ($(shell find $(CCINC) -name liburing.h 2>/dev/null),) |
| 147 | + LIB += uring |
| 148 | + FLG += -DLIBURING |
| 149 | +endif |
| 150 | + |
| 151 | + |
| 152 | +uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) |
| 153 | +magentatxt := $(shell $(TPUT) setaf 5) |
| 154 | +greentxt := $(shell $(TPUT) setaf 2) |
| 155 | +bluetxt := $(shell $(TPUT) setaf 4) |
| 156 | +normaltxt := $(shell $(TPUT) sgr0) |
| 157 | + |
| 158 | +.PHONY : bin dis def clean cleanx check tags |
| 159 | + |
| 160 | +bin : $(BIN) |
| 161 | +dis : $(DIS) bin |
| 162 | +.DEFAULT_GOAL = bin |
| 163 | +.SECONDEXPANSION: |
| 164 | + |
| 165 | +ifeq ($(J),o) |
| 166 | +# DANGER. Don't use unless it works! |
| 167 | +# build from .o files but target-specific flags are missing in %.o : %.x |
| 168 | +%.out : %.o $(OBJ) $$(addsuffix .o,$$(SRC-$$@) $$(MOD-$$@) $$(ASM-$$@)) |
| 169 | + $(eval ALLFLG := $(CSTD) $(EXTRA) $(FLG) $(FLG-$*) $(FLG-$*.o) $(FLG-$@) -rdynamic) |
| 170 | + $(eval ALLLIB := $(addprefix -l,$(LIB) $(LIB-$@))) |
| 171 | + $(CCC) $(ALLFLG) -o $@ $^ $(ALLLIB) |
| 172 | +# |
| 173 | +else # default: all-in-one command |
| 174 | +%.out : %.c $(SRC) $(ASM) $(DEP) $$(DEP-$$@) $$(addsuffix .c,$$(SRC-$$@) $$(MOD-$$@)) $$(addsuffix .h,$$(HDR-$$@) $$(MOD-$$@)) $$(addsuffix .S,$$(ASM-$$@)) |
| 175 | + $(eval ALLSRC := $(SRC) $(addsuffix .c,$(SRC-$@) $(MOD-$@)) $(ASM) $(addsuffix .S,$(ASM-$@))) |
| 176 | + $(eval UNIQSRC := $(call uniq,$(ALLSRC))) |
| 177 | + $(eval ALLFLG := $(CSTD) $(EXTRA) $(FLG) $(FLG-$@) -rdynamic) |
| 178 | + $(eval ALLLIB := $(addprefix -l,$(LIB) $(LIB-$@))) |
| 179 | + @printf '$(bluetxt)$@$(magentatxt) <= $(greentxt)$< $(UNIQSRC)$(normaltxt)\n' |
| 180 | + $(CCC) $(ALLFLG) -o $@ $< $(UNIQSRC) $(ALLLIB) |
| 181 | +# |
| 182 | +endif |
| 183 | + |
| 184 | + |
| 185 | +%.dis : %.out |
| 186 | + objdump -SlwtC $< 1>$@ 2>/dev/null |
| 187 | + |
| 188 | +%.o : %.cc $(DEP) $$(DEP-$$@) $$(addsuffix .h,$$(HDR-$$@) $$(MOD-$$@)) |
| 189 | + $(XCC) $(XSTD) $(EXTRA) $(FLG) $(FLG-$*) $(FLG-$@) -o $@ -c $< |
| 190 | + |
| 191 | +%.o : %.c $(DEP) $$(DEP-$$@) $$(addsuffix .h,$$(HDR-$$@) $$(MOD-$$@)) |
| 192 | + $(CCC) $(CSTD) $(EXTRA) $(FLG) $(FLG-$*) $(FLG-$@) -o $@ -c $< |
| 193 | + |
| 194 | +%.o : %.S $(DEP) $$(DEP-$$@) $$(addsuffix .h,$$(HDR-$$@) $$(MOD-$$@)) |
| 195 | + $(CCC) $(CSTD) $(EXTRA) $(FLG) $(FLG-$*) $(FLG-$@) -o $@ -c $< |
| 196 | + |
| 197 | +%.s : %.c $(DEP) $$(DEP-$$@) $$(addsuffix .h,$$(HDR-$$@) $$(MOD-$$@)) |
| 198 | + $(CCC) $(CSTD) $(EXTRA) $(FLG) $(FLG-$*) $(FLG-$*.o) -S -o $@ -c $< |
| 199 | + |
| 200 | +def : |
| 201 | + $(CCC) $(FLG) -dM -E - </dev/null |
| 202 | + |
| 203 | +clean : |
| 204 | + rm -rf *.out *.dis *.o *.so *.gcda *.gcno *.gcov *.dSYM |
| 205 | + |
| 206 | +cleanx : clean |
| 207 | + rm -rf $(EXTERNDEP) $(EXTERNSRC) |
| 208 | + |
| 209 | +check : |
| 210 | + cppcheck $(addprefix -I ,$(CCINC)) \ |
| 211 | + -q $(CHECK_M) $(CHECK_S) -DNDEBUG -U__cplusplus \ |
| 212 | + --std=c11 --language=c --platform=unix64 \ |
| 213 | + --enable=warning,style,performance,portability,information --inline-suppr . |
| 214 | + |
| 215 | +tags : |
| 216 | + ctags -R . /usr/include /usr/local/include $(CCINC) |
0 commit comments