base.mk 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. ## base.mk: c02983c+, see https://github.com/jmesmon/trifles.git
  2. # Usage:
  3. #
  4. # == Targets ==
  5. # 'all'
  6. # $(TARGETS)
  7. # show-cflags Set the var FILE=some-c-file.c to see cflags for a
  8. # particular file
  9. # show-targets
  10. # install
  11. # clean
  12. # TARGET.clean
  13. # TARGET.install
  14. #
  15. # == For use by the one who runs 'make' (or in some cases the Makefile) ==
  16. # $(O) set to a directory to write build output to that directory
  17. # $(V) when defined, prints the commands that are run.
  18. # $(CFLAGS) expected to be overridden by the user or build system.
  19. # $(LDFLAGS) same as CFLAGS, except for LD.
  20. # $(ASFLAGS)
  21. # $(CXXFLAGS)
  22. # $(CPPFLAGS)
  23. #
  24. # $(CROSS_COMPILE) a prefix on $(CC) and other tools.
  25. # "CROSS_COMPILE=arm-linux-" (note the trailing '-')
  26. # $(CC)
  27. # $(CXX)
  28. # $(LD)
  29. # $(AS)
  30. # $(FLEX)
  31. # $(BISON)
  32. #
  33. # == Required in the makefile ==
  34. # all:: place this target at the top.
  35. # $(obj-sometarget) the list of objects (generated by CC) that make up a target
  36. # (in the list TARGET).
  37. # $(TARGETS) a list of binaries (the output of LD).
  38. #
  39. # == Optional (for use in the makefile) ==
  40. # $(NO_INSTALL) when defined, no install target is emitted.
  41. # $(ALL_CFLAGS) non-overriden flags. Append (+=) things that are absolutely
  42. # required for the build to work into this.
  43. # $(ALL_LDFLAGS) same as ALL_CFLAGS, except for LD.
  44. # example for adding some library:
  45. #
  46. # sometarget: ALL_LDFLAGS += -lrt
  47. #
  48. # Note that in some cases (none I can point out, I just find
  49. # this shifty) this usage could have unintended consequences
  50. # (such as some of the ldflags being passed to other link
  51. # commands). The use of $(ldflags-sometarget) is recommended
  52. # instead.
  53. #
  54. # $(ALL_CPPFLAGS)
  55. #
  56. # $(ldflags-some-target)
  57. #
  58. # $(cflags-some-object-without-suffix)
  59. # $(cflags-some-target)
  60. # $(cxxflags-some-object-without-suffix)
  61. # $(cxxflags-some-target)
  62. #
  63. # OBJ_TRASH $(1) expands to the object. Expanded for every object.
  64. # TARGET_TRASH $* expands to the target. Expanded for every target.
  65. # TRASH
  66. # BIN_EXT Add an extention to each binary produced (.elf, .exe)
  67. #
  68. # == How to use with FLEX + BISON support ==
  69. #
  70. # obj-foo = name.tab.o name.ll.o
  71. # name.ll.o : name.tab.h
  72. # TRASH += name.ll.c name.tab.c name.tab.h
  73. # # Optionally
  74. # PP_name = not_quite_name_
  75. #
  76. # TODO:
  77. # - install disable per target.
  78. # - flag tracking per target.'.obj.o.cmd'
  79. # - profile guided optimization support.
  80. # - build with different flags placed into different output directories.
  81. # - library building (shared & static)
  82. # - per-target CFLAGS (didn't I hack this in already?)
  83. # - will TARGETS always be outputs from Linking?
  84. # - continous build mechanism ('watch' is broken)
  85. # - handle the mess that is linking for C++ vs C vs ld -r
  86. # Delete the default suffixes
  87. .SUFFIXES:
  88. O = .
  89. BIN_TARGETS=$(addprefix $(O)/,$(addsuffix $(BIN_EXT),$(TARGETS)))
  90. .PHONY: all FORCE
  91. all:: $(BIN_TARGETS)
  92. # Prioritize environment specified variables over our defaults
  93. var-def = $(if $(findstring $(origin $(1)),default undefined),$(eval $(1) = $(2)))
  94. # overriding these in a Makefile while still allowing the user to
  95. # override them is tricky.
  96. $(call var-def,CC,$(CROSS_COMPILE)gcc)
  97. $(call var-def,CXX,$(CROSS_COMPILE)g++)
  98. $(call var-def,LD,$(CC))
  99. $(call var-def,AS,$(CC))
  100. $(call var-def,RM,rm -f)
  101. $(call var-def,FLEX,flex)
  102. $(call var-def,BISON,bison)
  103. show-cc:
  104. @echo $(CC)
  105. ifdef DEBUG
  106. OPT=-O0
  107. else
  108. OPT=-Os
  109. endif
  110. DBG_FLAGS = -ggdb3
  111. ifndef NO_LTO
  112. # TODO: use -flto=jobserver
  113. CFLAGS ?= -flto $(DBG_FLAGS)
  114. LDFLAGS ?= $(ALL_CFLAGS) $(OPT) -fuse-linker-plugin
  115. else
  116. CFLAGS ?= $(OPT) $(DBG_FLAGS)
  117. endif
  118. # c/c+++ shared flags
  119. COMMON_CFLAGS += -Wall
  120. COMMON_CFLAGS += -Wundef -Wshadow
  121. COMMON_CFLAGS += -pipe
  122. COMMON_CFLAGS += -Wcast-align
  123. COMMON_CFLAGS += -Wwrite-strings
  124. # C only flags that just turn on some warnings
  125. C_CFLAGS = $(COMMON_CFLAGS)
  126. C_CFLAGS += -Wstrict-prototypes
  127. C_CFLAGS += -Wmissing-prototypes
  128. C_CFLAGS += -Wold-style-definition
  129. C_CFLAGS += -Wmissing-declarations
  130. C_CFLAGS += -Wundef
  131. C_CFLAGS += -Wbad-function-cast
  132. # -Wpointer-arith I like pointer arithmetic
  133. # -Wnormalized=id not supported by clang
  134. # -Wunsafe-loop-optimizations not supported by clang
  135. ALL_CFLAGS += -std=gnu99
  136. ALL_CPPFLAGS += $(CPPFLAGS)
  137. ALL_CFLAGS += $(ALL_CPPFLAGS) $(C_CFLAGS) $(CFLAGS)
  138. ALL_CXXFLAGS += $(ALL_CPPFLAGS) $(COMMON_CFLAGS) $(CXXFLAGS)
  139. ifndef NO_BUILD_ID
  140. LDFLAGS += -Wl,--build-id
  141. else
  142. LDFLAGS += -Wl,--build-id=none
  143. endif
  144. ifndef NO_AS_NEEDED
  145. LDFLAGS += -Wl,--as-needed
  146. else
  147. LDFLAGS += -Wl,--no-as-needed
  148. endif
  149. ALL_LDFLAGS += $(LDFLAGS)
  150. ALL_ASFLAGS += $(ASFLAGS)
  151. # FIXME: need to exclude '-I', '-l', '-L' options
  152. # - potentially seperate those flags from ALL_*?
  153. MAKE_ENV = CC="$(CC)" LD="$(LD)" AS="$(AS)" CXX="$(CXX)"
  154. # CFLAGS="$(ALL_CFLAGS)" \
  155. LDFLAGS="$(ALL_LDFLAGS)" \
  156. CXXFLAGS="$(ALL_CXXFLAGS)" \
  157. ASFLAGS="$(ALL_ASFLAGS)"
  158. ifndef V
  159. QUIET_CC = @ echo ' CC ' $@;
  160. QUIET_CXX = @ echo ' CXX ' $@;
  161. QUIET_LINK = @ echo ' LINK ' $@;
  162. QUIET_LSS = @ echo ' LSS ' $@;
  163. QUIET_SYM = @ echo ' SYM ' $@;
  164. QUIET_FLEX = @ echo ' FLEX ' $@;
  165. QUIET_BISON = @ echo ' BISON' $*.tab.c $*.tab.h;
  166. QUIET_AS = @ echo ' AS ' $@;
  167. endif
  168. # Avoid deleting .o files
  169. .SECONDARY:
  170. obj-to-dep = $(foreach obj,$(1),$(dir $(obj)).$(notdir $(obj)).d)
  171. target-dep = $(addprefix $(O)/,$(call obj-to-dep,$(obj-$(1))))
  172. target-obj = $(addprefix $(O)/,$(obj-$(1)))
  173. # flags-template flag-prefix vars message
  174. # Defines a target '.TRACK-$(flag-prefix)FLAGS'.
  175. # if $(ALL_$(flag-prefix)FLAGS) or $(var) changes, any rules depending on this
  176. # target are rebuilt.
  177. define flags-template
  178. TRACK_$(1)FLAGS = $$($(2)):$$(subst ','\'',$$(ALL_$(1)FLAGS))
  179. $(O)/.TRACK-$(1)FLAGS: FORCE
  180. @FLAGS='$$(TRACK_$(1)FLAGS)'; \
  181. if test x"$$$$FLAGS" != x"`cat $(O)/.TRACK-$(1)FLAGS 2>/dev/null`" ; then \
  182. echo 1>&2 " * new $(3)"; \
  183. echo "$$$$FLAGS" >$(O)/.TRACK-$(1)FLAGS; \
  184. fi
  185. TRASH += $(O)/.TRACK-$(1)FLAGS
  186. endef
  187. $(eval $(call flags-template,AS,AS,assembler build flags))
  188. $(eval $(call flags-template,C,CC,c build flags))
  189. $(eval $(call flags-template,CXX,CXX,c++ build flags))
  190. $(eval $(call flags-template,LD,LD,link flags))
  191. parser-prefix = $(if $(PP_$*),$(PP_$*),$*_)
  192. dep-gen = -MMD -MF $(call obj-to-dep,$@)
  193. define BIN-LINK
  194. $(foreach obj,$(obj-$(1)),$(eval cflags-$(obj:.o=) += $(cflags-$(1))))
  195. $(foreach obj,$(obj-$(1)),$(eval cxxflags-$(obj:.o=) += $(cxxflags-$(1))))
  196. $(O)/$(1)$(BIN_EXT) : $(O)/.TRACK-LDFLAGS $(call target-obj,$(1))
  197. $$(QUIET_LINK)$$(LD) -o $$@ $$(call target-obj,$(1)) $$(ALL_LDFLAGS) $$(ldflags-$(1))
  198. endef
  199. $(foreach target,$(TARGETS),$(eval $(call BIN-LINK,$(target))))
  200. $(O)/%.tab.h $(O)/%.tab.c : %.y
  201. $(QUIET_BISON)$(BISON) --locations -d \
  202. -p '$(parser-prefix)' -k -b $* $<
  203. $(O)/%.ll.c : %.l
  204. $(QUIET_FLEX)$(FLEX) -P '$(parser-prefix)' --bison-locations --bison-bridge -o $@ $<
  205. $(O)/%.o: %.c $(O)/.TRACK-CFLAGS
  206. $(QUIET_CC)$(CC) $(dep-gen) -c -o $@ $< $(ALL_CFLAGS) $(cflags-$*)
  207. $(O)/%.o: %.cc $(O)/.TRACK-CXXFLAGS
  208. $(QUIET_CXX)$(CXX) $(dep-gen) -c -o $@ $< $(ALL_CXXFLAGS) $(cxxflags-$*)
  209. $(O)/%.o : %.S $(O)/.TRACK-ASFLAGS
  210. $(QUIET_AS)$(AS) -c $(ALL_ASFLAGS) $< -o $@
  211. ifndef NO_INSTALL
  212. PREFIX ?= $(HOME) # link against things here
  213. DESTDIR ?= $(PREFIX) # install into here
  214. BINDIR ?= $(DESTDIR)/bin
  215. .PHONY: install %.install
  216. %.install: %
  217. install $* $(BINDIR)/$*
  218. install: $(foreach target,$(TARGETS),$(target).install)
  219. endif
  220. obj-all = $(foreach target,$(TARGETS),$(obj-$(target)))
  221. obj-trash = $(foreach obj,$(obj-all),$(call OBJ_TRASH,$(obj)))
  222. .PHONY: clean %.clean
  223. %.clean :
  224. $(RM) $(call target-obj,$*) $(O)/$* $(TARGET_TRASH) $(call target-dep,$*)
  225. clean: $(addsuffix .clean,$(TARGETS))
  226. $(RM) $(TRASH) $(obj-trash)
  227. .PHONY: watch
  228. watch:
  229. @while true; do \
  230. echo $(MAKEFLAGS); \
  231. $(MAKE) $(MAKEFLAGS) -rR --no-print-directory; \
  232. inotifywait -q \
  233. \
  234. -- $$(find . \
  235. -name '*.c' \
  236. -or -name '*.h' \
  237. -or -name 'Makefile' \
  238. -or -name '*.mk' ); \
  239. echo "Rebuilding..."; \
  240. done
  241. .PHONY: show-targets
  242. show-targets:
  243. @echo $(TARGETS)
  244. .PHONY: show-cflags
  245. show-cflags:
  246. @echo $(ALL_CFLAGS) $(cflags-$(FILE:.c=))
  247. deps = $(foreach target,$(TARGETS),$(call target-dep,$(target)))
  248. -include $(deps)