Makefile 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. ifdef BUILDDIR
  2. # bit of a hack, but we want to make sure BUILDDIR directory structure
  3. # is correct before any commands
  4. $(if $(findstring n,$(MAKEFLAGS)),, $(shell mkdir -p \
  5. $(BUILDDIR)/ \
  6. $(BUILDDIR)/bd \
  7. $(BUILDDIR)/runners \
  8. $(BUILDDIR)/tests \
  9. $(BUILDDIR)/benches))
  10. endif
  11. BUILDDIR ?= .
  12. # overridable target/src/tools/flags/etc
  13. ifneq ($(wildcard test.c main.c),)
  14. TARGET ?= $(BUILDDIR)/lfs
  15. else
  16. TARGET ?= $(BUILDDIR)/liblfs.a
  17. endif
  18. CC ?= gcc
  19. AR ?= ar
  20. SIZE ?= size
  21. CTAGS ?= ctags
  22. NM ?= nm
  23. OBJDUMP ?= objdump
  24. VALGRIND ?= valgrind
  25. GDB ?= gdb
  26. PERF ?= perf
  27. SRC ?= $(filter-out $(wildcard *.*.c),$(wildcard *.c))
  28. OBJ := $(SRC:%.c=$(BUILDDIR)/%.o)
  29. DEP := $(SRC:%.c=$(BUILDDIR)/%.d)
  30. ASM := $(SRC:%.c=$(BUILDDIR)/%.s)
  31. CI := $(SRC:%.c=$(BUILDDIR)/%.ci)
  32. GCDA := $(SRC:%.c=$(BUILDDIR)/%.t.a.gcda)
  33. TESTS ?= $(wildcard tests/*.toml)
  34. TEST_SRC ?= $(SRC) \
  35. $(filter-out $(wildcard bd/*.*.c),$(wildcard bd/*.c)) \
  36. runners/test_runner.c
  37. TEST_RUNNER ?= $(BUILDDIR)/runners/test_runner
  38. TEST_TC := $(TESTS:%.toml=$(BUILDDIR)/%.t.c) \
  39. $(TEST_SRC:%.c=$(BUILDDIR)/%.t.c)
  40. TEST_TAC := $(TEST_TC:%.t.c=%.t.a.c)
  41. TEST_OBJ := $(TEST_TAC:%.t.a.c=%.t.a.o)
  42. TEST_DEP := $(TEST_TAC:%.t.a.c=%.t.a.d)
  43. TEST_CI := $(TEST_TAC:%.t.a.c=%.t.a.ci)
  44. TEST_GCNO := $(TEST_TAC:%.t.a.c=%.t.a.gcno)
  45. TEST_GCDA := $(TEST_TAC:%.t.a.c=%.t.a.gcda)
  46. TEST_PERF := $(TEST_RUNNER:%=%.perf)
  47. TEST_TRACE := $(TEST_RUNNER:%=%.trace)
  48. BENCHES ?= $(wildcard benches/*.toml)
  49. BENCH_SRC ?= $(SRC) \
  50. $(filter-out $(wildcard bd/*.*.c),$(wildcard bd/*.c)) \
  51. runners/bench_runner.c
  52. BENCH_RUNNER ?= $(BUILDDIR)/runners/bench_runner
  53. BENCH_BC := $(BENCHES:%.toml=$(BUILDDIR)/%.b.c) \
  54. $(BENCH_SRC:%.c=$(BUILDDIR)/%.b.c)
  55. BENCH_BAC := $(BENCH_BC:%.b.c=%.b.a.c)
  56. BENCH_OBJ := $(BENCH_BAC:%.b.a.c=%.b.a.o)
  57. BENCH_DEP := $(BENCH_BAC:%.b.a.c=%.b.a.d)
  58. BENCH_CI := $(BENCH_BAC:%.b.a.c=%.b.a.ci)
  59. BENCH_GCNO := $(BENCH_BAC:%.b.a.c=%.b.a.gcno)
  60. BENCH_GCDA := $(BENCH_BAC:%.b.a.c=%.b.a.gcda)
  61. BENCH_PERF := $(BENCH_RUNNER:%=%.perf)
  62. BENCH_TRACE := $(BENCH_RUNNER:%=%.trace)
  63. ifdef DEBUG
  64. override CFLAGS += -O0
  65. else
  66. override CFLAGS += -Os
  67. endif
  68. ifdef TRACE
  69. override CFLAGS += -DLFS_YES_TRACE
  70. endif
  71. override CFLAGS += -g3
  72. override CFLAGS += -I.
  73. override CFLAGS += -std=c99 -Wall -Wextra -pedantic
  74. override CFLAGS += -ftrack-macro-expansion=0
  75. ifdef YES_COV
  76. override CFLAGS += --coverage
  77. endif
  78. ifdef YES_PERF
  79. override CFLAGS += -fno-omit-frame-pointer
  80. endif
  81. ifdef YES_PERFBD
  82. override CFLAGS += -fno-omit-frame-pointer
  83. endif
  84. ifdef VERBOSE
  85. override CODEFLAGS += -v
  86. override DATAFLAGS += -v
  87. override STACKFLAGS += -v
  88. override STRUCTFLAGS += -v
  89. override COVFLAGS += -v
  90. override PERFFLAGS += -v
  91. override PERFBDFLAGS += -v
  92. endif
  93. # forward -j flag
  94. override PERFFLAGS += $(filter -j%,$(MAKEFLAGS))
  95. override PERFBDFLAGS += $(filter -j%,$(MAKEFLAGS))
  96. ifneq ($(NM),nm)
  97. override CODEFLAGS += --nm-path="$(NM)"
  98. override DATAFLAGS += --nm-path="$(NM)"
  99. endif
  100. ifneq ($(OBJDUMP),objdump)
  101. override CODEFLAGS += --objdump-path="$(OBJDUMP)"
  102. override DATAFLAGS += --objdump-path="$(OBJDUMP)"
  103. override STRUCTFLAGS += --objdump-path="$(OBJDUMP)"
  104. override PERFFLAGS += --objdump-path="$(OBJDUMP)"
  105. override PERFBDFLAGS += --objdump-path="$(OBJDUMP)"
  106. endif
  107. ifneq ($(PERF),perf)
  108. override PERFFLAGS += --perf-path="$(PERF)"
  109. endif
  110. override TESTFLAGS += -b
  111. override BENCHFLAGS += -b
  112. # forward -j flag
  113. override TESTFLAGS += $(filter -j%,$(MAKEFLAGS))
  114. override BENCHFLAGS += $(filter -j%,$(MAKEFLAGS))
  115. ifdef YES_PERF
  116. override TESTFLAGS += -p$(TEST_PERF)
  117. override BENCHFLAGS += -p$(BENCH_PERF)
  118. endif
  119. ifdef YES_PERFBD
  120. override TESTFLAGS += -t$(TEST_TRACE) --trace-backtrace --trace-freq=100
  121. endif
  122. ifndef NO_PERFBD
  123. override BENCHFLAGS += -t$(BENCH_TRACE) --trace-backtrace --trace-freq=100
  124. endif
  125. ifdef VERBOSE
  126. override TESTFLAGS += -v
  127. override TESTCFLAGS += -v
  128. override BENCHFLAGS += -v
  129. override BENCHCFLAGS += -v
  130. endif
  131. ifdef EXEC
  132. override TESTFLAGS += --exec="$(EXEC)"
  133. override BENCHFLAGS += --exec="$(EXEC)"
  134. endif
  135. ifneq ($(GDB),gdb)
  136. override TESTFLAGS += --gdb-path="$(GDB)"
  137. override BENCHFLAGS += --gdb-path="$(GDB)"
  138. endif
  139. ifneq ($(VALGRIND),valgrind)
  140. override TESTFLAGS += --valgrind-path="$(VALGRIND)"
  141. override BENCHFLAGS += --valgrind-path="$(VALGRIND)"
  142. endif
  143. ifneq ($(PERF),perf)
  144. override TESTFLAGS += --perf-path="$(PERF)"
  145. override BENCHFLAGS += --perf-path="$(PERF)"
  146. endif
  147. # commands
  148. ## Build littlefs
  149. .PHONY: all build
  150. all build: $(TARGET)
  151. ## Build assembly files
  152. .PHONY: asm
  153. asm: $(ASM)
  154. ## Find the total size
  155. .PHONY: size
  156. size: $(OBJ)
  157. $(SIZE) -t $^
  158. ## Generate a ctags file
  159. .PHONY: tags
  160. tags:
  161. $(CTAGS) --totals --c-types=+p $(shell find -H -name '*.h') $(SRC)
  162. ## Show this help text
  163. .PHONY: help
  164. help:
  165. @$(strip awk '/^## / { \
  166. sub(/^## /,""); \
  167. getline rule; \
  168. while (rule ~ /^(#|\.PHONY|ifdef|ifndef)/) getline rule; \
  169. gsub(/:.*/, "", rule); \
  170. printf " "" %-25s %s\n", rule, $$0 \
  171. }' $(MAKEFILE_LIST))
  172. ## Build the test-runner
  173. .PHONY: test-runner build-test
  174. ifndef NO_COV
  175. test-runner build-test: override CFLAGS+=--coverage
  176. endif
  177. ifdef YES_PERF
  178. test-runner build-test: override CFLAGS+=-fno-omit-frame-pointer
  179. endif
  180. ifdef YES_PERFBD
  181. test-runner build-test: override CFLAGS+=-fno-omit-frame-pointer
  182. endif
  183. # note we remove some binary dependent files during compilation,
  184. # otherwise it's way to easy to end up with outdated results
  185. test-runner build-test: $(TEST_RUNNER)
  186. ifndef NO_COV
  187. rm -f $(TEST_GCDA)
  188. endif
  189. ifdef YES_PERF
  190. rm -f $(TEST_PERF)
  191. endif
  192. ifdef YES_PERFBD
  193. rm -f $(TEST_TRACE)
  194. endif
  195. ## Run the tests, -j enables parallel tests
  196. .PHONY: test
  197. test: test-runner
  198. ./scripts/test.py $(TEST_RUNNER) $(TESTFLAGS)
  199. ## List the tests
  200. .PHONY: test-list
  201. test-list: test-runner
  202. ./scripts/test.py $(TEST_RUNNER) $(TESTFLAGS) -l
  203. ## Build the bench-runner
  204. .PHONY: bench-runner build-bench
  205. ifdef YES_COV
  206. bench-runner build-bench: override CFLAGS+=--coverage
  207. endif
  208. ifdef YES_PERF
  209. bench-runner build-bench: override CFLAGS+=-fno-omit-frame-pointer
  210. endif
  211. ifndef NO_PERFBD
  212. bench-runner build-bench: override CFLAGS+=-fno-omit-frame-pointer
  213. endif
  214. # note we remove some binary dependent files during compilation,
  215. # otherwise it's way to easy to end up with outdated results
  216. bench-runner build-bench: $(BENCH_RUNNER)
  217. ifdef YES_COV
  218. rm -f $(BENCH_GCDA)
  219. endif
  220. ifdef YES_PERF
  221. rm -f $(BENCH_PERF)
  222. endif
  223. ifndef NO_PERFBD
  224. rm -f $(BENCH_TRACE)
  225. endif
  226. ## Run the benchmarks, -j enables parallel benchmarks
  227. .PHONY: bench
  228. bench: bench-runner
  229. ./scripts/bench.py $(BENCH_RUNNER) $(BENCHFLAGS)
  230. ## List the benchmarks
  231. .PHONY: bench-list
  232. bench-list: bench-runner
  233. ./scripts/bench.py $(BENCH_RUNNER) $(BENCHFLAGS) -l
  234. ## Find the per-function code size
  235. .PHONY: code
  236. code: $(OBJ)
  237. ./scripts/code.py $^ -Ssize $(CODEFLAGS)
  238. ## Find the per-function data size
  239. .PHONY: data
  240. data: $(OBJ)
  241. ./scripts/data.py $^ -Ssize $(DATAFLAGS)
  242. ## Find the per-function stack usage
  243. .PHONY: stack
  244. stack: $(CI)
  245. ./scripts/stack.py $^ -Slimit -Sframe $(STACKFLAGS)
  246. ## Find the struct sizes
  247. .PHONY: struct
  248. struct: $(OBJ)
  249. ./scripts/struct_.py $^ -Ssize $(STRUCTFLAGS)
  250. ## Find the line/branch coverage after a test run
  251. .PHONY: cov
  252. cov: $(GCDA)
  253. $(strip ./scripts/cov.py \
  254. $^ $(patsubst %,-F%,$(SRC)) \
  255. -slines -sbranches \
  256. $(COVFLAGS))
  257. ## Find the perf results after bench run with YES_PERF
  258. .PHONY: perf
  259. perf: $(BENCH_PERF)
  260. $(strip ./scripts/perf.py \
  261. $^ $(patsubst %,-F%,$(SRC)) \
  262. -Scycles \
  263. $(PERFFLAGS))
  264. ## Find the perfbd results after a bench run
  265. .PHONY: perfbd
  266. perfbd: $(BENCH_TRACE)
  267. $(strip ./scripts/perfbd.py \
  268. $(BENCH_RUNNER) $^ $(patsubst %,-F%,$(SRC)) \
  269. -Serased -Sproged -Sreaded \
  270. $(PERFBDFLAGS))
  271. ## Find a summary of compile-time sizes
  272. .PHONY: summary sizes
  273. summary sizes: $(BUILDDIR)/lfs.csv
  274. $(strip ./scripts/summary.py -Y $^ \
  275. -fcode=code_size \
  276. -fdata=data_size \
  277. -fstack=stack_limit \
  278. -fstruct=struct_size \
  279. --max=stack \
  280. $(SUMMARYFLAGS))
  281. # rules
  282. -include $(DEP)
  283. -include $(TEST_DEP)
  284. .SUFFIXES:
  285. .SECONDARY:
  286. $(BUILDDIR)/lfs: $(OBJ)
  287. $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@
  288. $(BUILDDIR)/liblfs.a: $(OBJ)
  289. $(AR) rcs $@ $^
  290. $(BUILDDIR)/lfs.code.csv: $(OBJ)
  291. ./scripts/code.py $^ -q $(CODEFLAGS) -o $@
  292. $(BUILDDIR)/lfs.data.csv: $(OBJ)
  293. ./scripts/data.py $^ -q $(CODEFLAGS) -o $@
  294. $(BUILDDIR)/lfs.stack.csv: $(CI)
  295. ./scripts/stack.py $^ -q $(CODEFLAGS) -o $@
  296. $(BUILDDIR)/lfs.struct.csv: $(OBJ)
  297. ./scripts/struct_.py $^ -q $(CODEFLAGS) -o $@
  298. $(BUILDDIR)/lfs.cov.csv: $(GCDA)
  299. ./scripts/cov.py $^ $(patsubst %,-F%,$(SRC)) -q $(COVFLAGS) -o $@
  300. $(BUILDDIR)/lfs.perf.csv: $(BENCH_PERF)
  301. ./scripts/perf.py $^ $(patsubst %,-F%,$(SRC)) -q $(PERFFLAGS) -o $@
  302. $(BUILDDIR)/lfs.perfbd.csv: $(BENCH_TRACE)
  303. $(strip ./scripts/perfbd.py \
  304. $(BENCH_RUNNER) $^ $(patsubst %,-F%,$(SRC)) \
  305. -q $(PERFBDFLAGS) -o $@)
  306. $(BUILDDIR)/lfs.csv: \
  307. $(BUILDDIR)/lfs.code.csv \
  308. $(BUILDDIR)/lfs.data.csv \
  309. $(BUILDDIR)/lfs.stack.csv \
  310. $(BUILDDIR)/lfs.struct.csv
  311. ./scripts/summary.py $^ -q $(SUMMARYFLAGS) -o $@
  312. $(BUILDDIR)/runners/test_runner: $(TEST_OBJ)
  313. $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@
  314. $(BUILDDIR)/runners/bench_runner: $(BENCH_OBJ)
  315. $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@
  316. # our main build rule generates .o, .d, and .ci files, the latter
  317. # used for stack analysis
  318. $(BUILDDIR)/%.o $(BUILDDIR)/%.ci: %.c
  319. $(CC) -c -MMD -fcallgraph-info=su $(CFLAGS) $< -o $(BUILDDIR)/$*.o
  320. $(BUILDDIR)/%.s: %.c
  321. $(CC) -S $(CFLAGS) $< -o $@
  322. $(BUILDDIR)/%.a.c: %.c
  323. ./scripts/prettyasserts.py -p LFS_ASSERT $< -o $@
  324. $(BUILDDIR)/%.a.c: $(BUILDDIR)/%.c
  325. ./scripts/prettyasserts.py -p LFS_ASSERT $< -o $@
  326. $(BUILDDIR)/%.t.c: %.toml
  327. ./scripts/test.py -c $< $(TESTCFLAGS) -o $@
  328. $(BUILDDIR)/%.t.c: %.c $(TESTS)
  329. ./scripts/test.py -c $(TESTS) -s $< $(TESTCFLAGS) -o $@
  330. $(BUILDDIR)/%.b.c: %.toml
  331. ./scripts/bench.py -c $< $(BENCHCFLAGS) -o $@
  332. $(BUILDDIR)/%.b.c: %.c $(BENCHES)
  333. ./scripts/bench.py -c $(BENCHES) -s $< $(BENCHCFLAGS) -o $@
  334. ## Clean everything
  335. .PHONY: clean
  336. clean:
  337. rm -f $(BUILDDIR)/lfs
  338. rm -f $(BUILDDIR)/liblfs.a
  339. $(strip rm -f \
  340. $(BUILDDIR)/lfs.csv \
  341. $(BUILDDIR)/lfs.code.csv \
  342. $(BUILDDIR)/lfs.data.csv \
  343. $(BUILDDIR)/lfs.stack.csv \
  344. $(BUILDDIR)/lfs.struct.csv \
  345. $(BUILDDIR)/lfs.cov.csv \
  346. $(BUILDDIR)/lfs.perf.csv \
  347. $(BUILDDIR)/lfs.perfbd.csv)
  348. rm -f $(OBJ)
  349. rm -f $(DEP)
  350. rm -f $(ASM)
  351. rm -f $(CI)
  352. rm -f $(TEST_RUNNER)
  353. rm -f $(TEST_TC)
  354. rm -f $(TEST_TAC)
  355. rm -f $(TEST_OBJ)
  356. rm -f $(TEST_DEP)
  357. rm -f $(TEST_CI)
  358. rm -f $(TEST_GCNO)
  359. rm -f $(TEST_GCDA)
  360. rm -f $(TEST_PERF)
  361. rm -f $(TEST_TRACE)
  362. rm -f $(BENCH_RUNNER)
  363. rm -f $(BENCH_BC)
  364. rm -f $(BENCH_BAC)
  365. rm -f $(BENCH_OBJ)
  366. rm -f $(BENCH_DEP)
  367. rm -f $(BENCH_CI)
  368. rm -f $(BENCH_GCNO)
  369. rm -f $(BENCH_GCDA)
  370. rm -f $(BENCH_PERF)
  371. rm -f $(BENCH_TRACE)