Makefile 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. ifdef BUILDDIR
  2. # make sure BUILDDIR ends with a slash
  3. override BUILDDIR := $(BUILDDIR)/
  4. # bit of a hack, but we want to make sure BUILDDIR directory structure
  5. # is correct before any commands
  6. $(if $(findstring n,$(MAKEFLAGS)),, $(shell mkdir -p \
  7. $(BUILDDIR) \
  8. $(BUILDDIR)bd \
  9. $(BUILDDIR)runners \
  10. $(BUILDDIR)tests))
  11. endif
  12. # overridable target/src/tools/flags/etc
  13. ifneq ($(wildcard test.c main.c),)
  14. TARGET ?= $(BUILDDIR)lfs
  15. else
  16. TARGET ?= $(BUILDDIR)lfs.a
  17. endif
  18. CC ?= gcc
  19. AR ?= ar
  20. SIZE ?= size
  21. CTAGS ?= ctags
  22. NM ?= nm
  23. OBJDUMP ?= objdump
  24. LCOV ?= lcov
  25. SRC ?= $(filter-out $(wildcard *.*.c),$(wildcard *.c))
  26. OBJ := $(SRC:%.c=$(BUILDDIR)%.o)
  27. DEP := $(SRC:%.c=$(BUILDDIR)%.d)
  28. ASM := $(SRC:%.c=$(BUILDDIR)%.s)
  29. CI := $(SRC:%.c=$(BUILDDIR)%.ci)
  30. GCDA := $(SRC:%.c=$(BUILDDIR)%.t.a.gcda)
  31. TESTS ?= $(wildcard tests/*.toml)
  32. TEST_SRC ?= $(SRC) \
  33. $(filter-out $(wildcard bd/*.*.c),$(wildcard bd/*.c)) \
  34. runners/test_runner.c
  35. TEST_TC := $(TESTS:%.toml=$(BUILDDIR)%.t.c) $(TEST_SRC:%.c=$(BUILDDIR)%.t.c)
  36. TEST_TAC := $(TEST_TC:%.t.c=%.t.a.c)
  37. TEST_OBJ := $(TEST_TAC:%.t.a.c=%.t.a.o)
  38. TEST_DEP := $(TEST_TAC:%.t.a.c=%.t.a.d)
  39. TEST_CI := $(TEST_TAC:%.t.a.c=%.t.a.ci)
  40. TEST_GCNO := $(TEST_TAC:%.t.a.c=%.t.a.gcno)
  41. TEST_GCDA := $(TEST_TAC:%.t.a.c=%.t.a.gcda)
  42. ifdef DEBUG
  43. override CFLAGS += -O0
  44. else
  45. override CFLAGS += -Os
  46. endif
  47. ifdef TRACE
  48. override CFLAGS += -DLFS_YES_TRACE
  49. endif
  50. override CFLAGS += -g3
  51. override CFLAGS += -I.
  52. override CFLAGS += -std=c99 -Wall -pedantic
  53. override CFLAGS += -Wextra -Wshadow -Wjump-misses-init -Wundef
  54. override CFLAGS += -ftrack-macro-expansion=0
  55. override TESTFLAGS += -b
  56. # forward -j flag
  57. override TESTFLAGS += $(filter -j%,$(MAKEFLAGS))
  58. ifdef VERBOSE
  59. override TESTFLAGS += -v
  60. override CODEFLAGS += -v
  61. override DATAFLAGS += -v
  62. override STACKFLAGS += -v
  63. override STRUCTFLAGS += -v
  64. override COVERAGEFLAGS += -v
  65. override TESTFLAGS += -v
  66. override TESTCFLAGS += -v
  67. endif
  68. ifdef EXEC
  69. override TESTFLAGS += --exec="$(EXEC)"
  70. endif
  71. ifdef BUILDDIR
  72. override CODEFLAGS += --build-dir="$(BUILDDIR:/=)"
  73. override DATAFLAGS += --build-dir="$(BUILDDIR:/=)"
  74. override STACKFLAGS += --build-dir="$(BUILDDIR:/=)"
  75. override STRUCTFLAGS += --build-dir="$(BUILDDIR:/=)"
  76. override COVERAGEFLAGS += --build-dir="$(BUILDDIR:/=)"
  77. endif
  78. ifneq ($(NM),nm)
  79. override CODEFLAGS += --nm-tool="$(NM)"
  80. override DATAFLAGS += --nm-tool="$(NM)"
  81. endif
  82. ifneq ($(OBJDUMP),objdump)
  83. override STRUCTFLAGS += --objdump-tool="$(OBJDUMP)"
  84. endif
  85. # commands
  86. .PHONY: all build
  87. all build: $(TARGET)
  88. .PHONY: asm
  89. asm: $(ASM)
  90. .PHONY: size
  91. size: $(OBJ)
  92. $(SIZE) -t $^
  93. .PHONY: tags
  94. tags:
  95. $(CTAGS) --totals --c-types=+p $(shell find -H -name '*.h') $(SRC)
  96. .PHONY: test-runner build-test
  97. test-runner build-test: override CFLAGS+=--coverage
  98. test-runner build-test: $(BUILDDIR)runners/test_runner
  99. rm -f $(TEST_GCDA)
  100. .PHONY: test
  101. test: test-runner
  102. ./scripts/test.py $(BUILDDIR)runners/test_runner $(TESTFLAGS)
  103. .PHONY: test-list
  104. test-list: test-runner
  105. ./scripts/test.py $(BUILDDIR)runners/test_runner $(TESTFLAGS) -l
  106. .PHONY: code
  107. code: $(OBJ)
  108. ./scripts/code.py $^ -S $(CODEFLAGS)
  109. .PHONY: data
  110. data: $(OBJ)
  111. ./scripts/data.py $^ -S $(DATAFLAGS)
  112. .PHONY: stack
  113. stack: $(CI)
  114. ./scripts/stack.py $^ -S $(STACKFLAGS)
  115. .PHONY: struct
  116. struct: $(OBJ)
  117. ./scripts/struct.py $^ -S $(STRUCTFLAGS)
  118. .PHONY: coverage
  119. coverage: $(GCDA)
  120. ./scripts/coverage.py $^ -s $(COVERAGEFLAGS)
  121. .PHONY: summary sizes
  122. summary sizes: $(BUILDDIR)lfs.csv
  123. $(strip ./scripts/summary.py -Y $^ \
  124. -f code=code_size,$\
  125. data=data_size,$\
  126. stack=stack_limit,$\
  127. struct=struct_size \
  128. $(SUMMARYFLAGS))
  129. # rules
  130. -include $(DEP)
  131. -include $(TEST_DEP)
  132. .SUFFIXES:
  133. .SECONDARY:
  134. $(BUILDDIR)lfs: $(OBJ)
  135. $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@
  136. $(BUILDDIR)lfs.a: $(OBJ)
  137. $(AR) rcs $@ $^
  138. $(BUILDDIR)lfs.code.csv: $(OBJ)
  139. ./scripts/code.py $^ -q $(CODEFLAGS) -o $@
  140. $(BUILDDIR)lfs.data.csv: $(OBJ)
  141. ./scripts/data.py $^ -q $(CODEFLAGS) -o $@
  142. $(BUILDDIR)lfs.stack.csv: $(CI)
  143. ./scripts/stack.py $^ -q $(CODEFLAGS) -o $@
  144. $(BUILDDIR)lfs.struct.csv: $(OBJ)
  145. ./scripts/struct.py $^ -q $(CODEFLAGS) -o $@
  146. $(BUILDDIR)lfs.coverage.csv: $(GCDA)
  147. ./scripts/coverage.py $^ -q $(COVERAGEFLAGS) -o $@
  148. $(BUILDDIR)lfs.csv: \
  149. $(BUILDDIR)lfs.code.csv \
  150. $(BUILDDIR)lfs.data.csv \
  151. $(BUILDDIR)lfs.stack.csv \
  152. $(BUILDDIR)lfs.struct.csv
  153. ./scripts/summary.py $^ -q $(SUMMARYFLAGS) -o $@
  154. $(BUILDDIR)runners/test_runner: $(TEST_OBJ)
  155. $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@
  156. # our main build rule generates .o, .d, and .ci files, the latter
  157. # used for stack analysis
  158. $(BUILDDIR)%.o $(BUILDDIR)%.ci: %.c
  159. $(CC) -c -MMD -fcallgraph-info=su $(CFLAGS) $< -o $(BUILDDIR)$*.o
  160. $(BUILDDIR)%.s: %.c
  161. $(CC) -S $(CFLAGS) $< -o $@
  162. $(BUILDDIR)%.a.c: %.c
  163. ./scripts/pretty_asserts.py -p LFS_ASSERT $< -o $@
  164. $(BUILDDIR)%.a.c: $(BUILDDIR)%.c
  165. ./scripts/pretty_asserts.py -p LFS_ASSERT $< -o $@
  166. $(BUILDDIR)%.t.c: %.toml
  167. ./scripts/test.py -c $< $(TESTCFLAGS) -o $@
  168. $(BUILDDIR)%.t.c: %.c $(TESTS)
  169. ./scripts/test.py -c $(TESTS) -s $< $(TESTCFLAGS) -o $@
  170. # clean everything
  171. .PHONY: clean
  172. clean:
  173. rm -f $(BUILDDIR)lfs
  174. rm -f $(BUILDDIR)lfs.a
  175. $(strip rm -f \
  176. $(BUILDDIR)lfs.csv \
  177. $(BUILDDIR)lfs.code.csv \
  178. $(BUILDDIR)lfs.data.csv \
  179. $(BUILDDIR)lfs.stack.csv \
  180. $(BUILDDIR)lfs.struct.csv \
  181. $(BUILDDIR)lfs.coverage.csv)
  182. rm -f $(BUILDDIR)runners/test_runner
  183. rm -f $(OBJ)
  184. rm -f $(DEP)
  185. rm -f $(ASM)
  186. rm -f $(CI)
  187. rm -f $(TEST_TC)
  188. rm -f $(TEST_TAC)
  189. rm -f $(TEST_OBJ)
  190. rm -f $(TEST_DEP)
  191. rm -f $(TEST_CI)
  192. rm -f $(TEST_GCNO)
  193. rm -f $(TEST_GCDA)