]> rtime.felk.cvut.cz Git - omk.git/blob - snippets/build
Further experiments with new rules
[omk.git] / snippets / build
1 ####
2 # kbuild: Generic definitions
3
4 # Convenient variables
5 comma   := ,
6 squote  := '
7 #'
8 empty   :=
9 space   := $(empty) $(empty)
10
11 BUILD_DIR_NAME = _build
12 COMPILED_DIR_NAME = _compiled
13
14 USER_INCLUDE_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/include
15 USER_LIB_DIR     := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/lib
16 USER_UTILS_DIR   := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-utils
17 USER_TESTS_DIR   := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-tests
18 USER_BIN_DIR     := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin
19 USER_BUILD_DIR   := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/user
20 LINK_BUILD_DIR   := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/link
21
22 USER_OBJS_DIR = $(USER_BUILD_DIR)/$(RELATIVE_DIR)
23 KERN_OBJS_DIR = $(KERN_BUILD_DIR)/$(RELATIVE_DIR)
24 OMK_WORK_DIR  = $(USER_OBJS_DIR)
25
26 strip_out = $(patsubst $(OUTPUT_DIR)/%,%,$(1))
27 repl_out  = $(patsubst $(OUTPUT_DIR)/%,$$(OUTPUT_DIR)/%,$(1))
28
29 .PHONY: FORCE
30
31 #####################
32 # Build pseudo-pass #
33 #####################
34
35 rule_targets = $($(1)_targets)
36 rule_deps    = $($(1)_deps)
37 rule_msg     = $($(1)_msg)
38 rule_cmd     = $($(1)_cmd)
39
40 # Usage: $(call build_rule,<target>)
41 define build_rule
42 $(rule_target): $(rule_deps) $(omk_inc_file)
43         @$(QUIET_CMD_ECHO) "  "$(rule_msg) "$$(call strip_out,$$(@))"
44         $(Q)$(rule_cmd)
45 endef
46
47 # TODO: Include target.omk only in the subtree
48 -include $(shell true; find $(USER_BUILD_DIR) -name '*omk.inc') # `true' is a hack for MinGW
49
50 $(foreach rule,$(prepared_rules),$(eval $(call build_rule,$(rule))))
51
52 .PHONY: build-pseudo-pass
53 build-pseudo-pass: $(foreach target,$(default_build_targets),$(target))
54
55 ################
56 # Prepare pass #
57 ################
58
59 $(eval $(call omk_pass_template,prepare-pass,$(USER_OBJS_DIR),,always))
60
61 ###
62 # Name of the prepared rule.  This name is used as prefix of variable
63 # names in .omk.inc and is based on the first target
64 omk_inc_rule = $(firstword $(1:$(OUTPUT_DIR)/%=%))
65
66 # The name of .omk.inc file is derived from $(omk_inc_rule) and
67 # depends whether the target is under _build or elsewhere.
68 omk_inc_file = $(if $(filter $(BUILD_DIR_NAME)%,$(omk_inc_rule)),\
69                     $(OMK_WORK_DIR)/$(notdir $(omk_inc_rule)).omk.inc,\
70                     $(OMK_WORK_DIR)/$(subst /,_,$(omk_inc_rule)).omk.inc)
71
72 target_omk_file = $(OMK_WORK_DIR)/$(notdir $(1)).target.omk
73
74 ###
75 # prepare_rule is used to generate .omk.inc files during prepare-pass.
76 # All paths in this file should be relative to $(OUTPUT_DIR)
77 # Usage: $(call prepare_rule,<targets>,<deps>,<msg>,<cmd>)
78 define prepare_rule
79 prepare-pass-local: $(omk_inc_file)
80
81 $(omk_inc_file): FORCE
82         $(Q)echo 'prepared_rules += $(omk_inc_rule)' > $$@.tmp; \
83             echo '$(omk_inc_rule)_targets = $$(call strip_out,$(1))' >> $$@.tmp; \
84             echo '$(omk_inc_rule)_deps += $$(call strip_out,$(2))' >> $$@.tmp; \
85             echo '$(omk_inc_rule)_msg = $(3)' >> $$@.tmp; \
86             echo '$(omk_inc_rule)_cmd = $$(call repl_out,$(4))' >> $$@.tmp; \
87         if cmp -s $$@.tmp $$@; then rm $$@.tmp; else mv $$@.tmp $$@; fi
88 endef
89
90 ###
91 # prepare_rule_default - same as prepare rules but the target is put
92 # as dependency to the default build rule, which causes it to be built
93 # upon calling make
94 define prepare_rule_default
95 $(call prepare_rule,$(1),$(2),$(3),$(4))
96 prepared_default_build_targets += $(call strip_out,$(1))
97 endef
98
99 prepare-pass-local: $(OMK_WORK_DIR)/omk.inc
100 $(OMK_WORK_DIR)/omk.inc: FORCE
101         $(Q)echo 'default_build_targets += $(prepared_default_build_targets)' > $@.tmp; \
102             if cmp -s $@.tmp $@; then rm $@.tmp; else mv $@.tmp $@; fi
103
104
105 ############
106 # Programs #
107 ############
108
109 # Usage: $(call program_template,<executable-name>,<bin|utils|test>)
110 define program_template
111 $(1)_OBJS += $$(patsubst %.c,%.o,$$(filter %.c,$$($(1)_SOURCES)))
112 $(1)_OBJS := $$(addprefix $(USER_OBJS_DIR),$$(sort $$($(1)_OBJS:%/=%)))
113
114 USER_OBJS  += $$($(1)_OBJS)
115 USER_SOURCES += $$($(1)_SOURCES)
116
117
118
119 program_cmd = $$(if $$(filter %.cc,$$($(1)_SOURCES)),$$(CXX),$$(CC)) \
120         $$($(1)_OBJS) $$($(1)_LIBS:%=-l%) $$(LOADLIBES) $$(LDFLAGS) -Wl,-rpath-link,$(USER_LIB_DIR) \
121         -Wl,-Map,$(USER_OBJS_DIR)/$(1).exe.map -o $$$$@
122
123 $(call prepare_rule_default,\
124         $(USER_BIN_DIR)/$(1)$(EXE_SUFFIX),\
125         $$($(1)_OBJS) $$($(1)_LIBS),\
126         "LINK    ",\
127         $$(program_cmd))
128 endef
129
130 c_o_cmd := set -e; cd $$(dir $$@); \
131         if $$(c_o_COMPILE) $$(CC_DEPFLAGS) -o $$@ -c $$< ; \
132         then mv -f "$$@.d.tmp" "$$@.d" ; \
133         else rm -f "$$@.d.tmp" ; \
134         fi
135
136
137 $(foreach prog,$(bin_PROGRAMS),$(eval $(call program_template,$(prog),bin)))
138 $(foreach src,$(filter %.c,$(USER_SOURCES)),$(eval $(call prepare_rule,\
139         $(USER_OBJS_DIR)/$(src:%.c=%.o),\
140         $(SOURCES_DIR)/$(src),\
141         "CC      ",\
142         $(c_o_cmd))))
143
144 default: prepare-pass
145         $(MAKE) -qp build-pseudo-pass > make.dp.build-pseudo-pass
146         $(MAKE) build-pseudo-pass