| 1 | ## |
| 2 | # A set of makefile rules loosely based on kbuild. |
| 3 | |
| 4 | all: compile |
| 5 | |
| 6 | ifndef build |
| 7 | |
| 8 | toplevelrun:=yes |
| 9 | |
| 10 | ## |
| 11 | # Disable default rules and make output pretty. |
| 12 | |
| 13 | MAKEFLAGS += -rR --no-print-directory |
| 14 | |
| 15 | Makefile: ; |
| 16 | |
| 17 | ifdef V |
| 18 | ifeq ("$(origin V)", "command line") |
| 19 | VERBOSE = $(V) |
| 20 | endif |
| 21 | endif |
| 22 | ifndef VERBOSE |
| 23 | VERBOSE = 0 |
| 24 | endif |
| 25 | |
| 26 | ifeq ($(VERBOSE),1) |
| 27 | quiet = |
| 28 | Q = |
| 29 | else |
| 30 | quiet=quiet_ |
| 31 | Q = @ |
| 32 | endif |
| 33 | |
| 34 | ifneq ($(findstring s,$(MAKEFLAGS)),) |
| 35 | quiet=silent_ |
| 36 | endif |
| 37 | |
| 38 | export quiet Q VERBOSE |
| 39 | |
| 40 | ## |
| 41 | # Recursion helpers. |
| 42 | srctree := $(CURDIR) |
| 43 | objtree := $(CURDIR) |
| 44 | |
| 45 | export srctree objtree |
| 46 | |
| 47 | ## |
| 48 | # Consult SCM for better version string. |
| 49 | |
| 50 | TAGPREFIX ?= v |
| 51 | |
| 52 | GIT_REV := $(shell test -d .git && git describe || echo exported) |
| 53 | ifneq ($(GIT_REV), exported) |
| 54 | FULL_VERSION := $(patsubst $(TAGPREFIX)%,%,$(GIT_REV)) |
| 55 | else |
| 56 | FULL_VERSION := $(VERSION) |
| 57 | endif |
| 58 | |
| 59 | RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o |
| 60 | |
| 61 | export FULL_VERSION RCS_FIND_IGNORE |
| 62 | |
| 63 | ## |
| 64 | # Utilities and default flags for them. |
| 65 | |
| 66 | CROSS_COMPILE ?= |
| 67 | CC := $(CROSS_COMPILE)gcc |
| 68 | LD := $(CROSS_COMPILE)ld |
| 69 | INSTALL := install |
| 70 | INSTALLDIR := $(INSTALL) -d |
| 71 | |
| 72 | CFLAGS ?= -g -O2 |
| 73 | CFLAGS_ALL := -Werror -Wall -Wstrict-prototypes -D_GNU_SOURCE -std=gnu99 |
| 74 | CFLAGS_ALL += $(CFLAGS) |
| 75 | |
| 76 | LDFLAGS ?= -g |
| 77 | LDFLAGS_ALL += $(LDFLAGS) |
| 78 | |
| 79 | export CC LD INSTALL INSTALLDIR CFLAGS_ALL LDFLAGS_ALL |
| 80 | |
| 81 | build := |
| 82 | |
| 83 | endif |
| 84 | |
| 85 | ## |
| 86 | # Reset all variables. |
| 87 | ifneq ($(origin targets),file) |
| 88 | targets := |
| 89 | endif |
| 90 | |
| 91 | src := |
| 92 | obj := |
| 93 | |
| 94 | src += $(build) |
| 95 | obj := $(build) |
| 96 | |
| 97 | ## |
| 98 | # Include directory specific stuff |
| 99 | |
| 100 | ifneq ($(build),) |
| 101 | $(build)/Makefile: ; |
| 102 | include $(build)/Makefile |
| 103 | endif |
| 104 | |
| 105 | ## |
| 106 | # Rules and helpers |
| 107 | |
| 108 | PHONY += all compile install clean FORCE |
| 109 | |
| 110 | # Convinient variables |
| 111 | comma := , |
| 112 | squote := ' |
| 113 | empty := |
| 114 | space := $(empty) $(empty) |
| 115 | |
| 116 | # The temporary file to save gcc -MD generated dependencies must not |
| 117 | # contain a comma |
| 118 | depfile = $(subst $(comma),_,$(@D)/.$(@F).d) |
| 119 | |
| 120 | build-dir = $(patsubst %/,%,$(dir $@)) |
| 121 | target-dir = $(dir $@) |
| 122 | |
| 123 | ## |
| 124 | # Build rules |
| 125 | |
| 126 | ifneq ($(NOCMDDEP),1) |
| 127 | # Check if both arguments has same arguments. Result in empty string if equal |
| 128 | # User may override this check using make NOCMDDEP=1 |
| 129 | # Check if both arguments has same arguments. Result is empty string if equal. |
| 130 | # User may override this check using make KBUILD_NOCMDDEP=1 |
| 131 | arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ |
| 132 | $(filter-out $(cmd_$@), $(cmd_$(1))) ) |
| 133 | endif |
| 134 | |
| 135 | # echo command. |
| 136 | # Short version is used, if $(quiet) equals `quiet_', otherwise full one. |
| 137 | echo-cmd = $(if $($(quiet)cmd_$(1)),\ |
| 138 | echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';) |
| 139 | |
| 140 | make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) |
| 141 | |
| 142 | # printing commands |
| 143 | cmd = @$(echo-cmd) $(cmd_$(1)) |
| 144 | |
| 145 | # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o |
| 146 | dot-target = $(dir $@).$(notdir $@) |
| 147 | |
| 148 | # The temporary file to save gcc -MD generated dependencies must not |
| 149 | # contain a comma |
| 150 | depfile = $(subst $(comma),_,$(dot-target).d) |
| 151 | |
| 152 | # Escape single quote for use in echo statements |
| 153 | escsq = $(subst $(squote),'\$(squote)',$1) |
| 154 | |
| 155 | # Find any prerequisites that is newer than target or that does not exist. |
| 156 | # PHONY targets skipped in both cases. |
| 157 | local-target-prereqs = % |
| 158 | any-prereq = $(filter $(local-target-prereqs), $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^), $^)) |
| 159 | |
| 160 | # Execute command if command has changed or prerequisite(s) are updated. |
| 161 | # |
| 162 | if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ |
| 163 | @set -e; \ |
| 164 | $(echo-cmd) $(cmd_$(1)); \ |
| 165 | echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) |
| 166 | |
| 167 | # Usage: $(call if_changed_rule,foo) |
| 168 | # Will check if $(cmd_foo) or any of the prerequisites changed, |
| 169 | # and if so will execute $(rule_foo). |
| 170 | if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \ |
| 171 | @set -e; \ |
| 172 | $(rule_$(1))) |
| 173 | |
| 174 | ##### |
| 175 | # Handle options to gcc. |
| 176 | |
| 177 | c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS_ALL) $(CFLAGS_EXTRA) \ |
| 178 | $(CFLAGS_$(notdir $@)) |
| 179 | ld_flags = $(LDFLAGS_ALL) $(LDFLAGS_EXTRA) $(LDFLAGS_$(notdir $@)) |
| 180 | |
| 181 | ##### |
| 182 | # Compile c-files. |
| 183 | quiet_cmd_cc_o_c = CC $@ |
| 184 | |
| 185 | cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< |
| 186 | |
| 187 | define rule_cc_o_c |
| 188 | $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ |
| 189 | (echo 'cmd_$@ := $(call make-cmd,cc_o_c)'; echo; cat $(depfile)) \ |
| 190 | > $(dot-target).cmd ; \ |
| 191 | rm $(depfile) |
| 192 | endef |
| 193 | |
| 194 | $(obj)/%.o: override local-target-prereqs=% |
| 195 | |
| 196 | $(obj)/%.o: $(src)/%.c FORCE |
| 197 | $(call if_changed_rule,cc_o_c) |
| 198 | |
| 199 | ##### |
| 200 | # Link programs |
| 201 | |
| 202 | # Link an executable based on list of .o files, all plain c |
| 203 | # host-cmulti -> executable |
| 204 | __progs := $(addprefix $(obj)/,$(sort $(progs-y))) |
| 205 | cobjs := $(addprefix $(obj)/,$(sort $(foreach m,$(progs-y),$($(m)-objs)))) |
| 206 | |
| 207 | quiet_cmd_ld = LD $@ |
| 208 | cmd_ld = $(CC) $(ld_flags) -o $@ \ |
| 209 | $(addprefix $(obj)/,$($(@F)-objs)) \ |
| 210 | $(LIBS) $(LIBS_$(@F)) |
| 211 | |
| 212 | $(__progs): override local-target-prereqs=$(addprefix $(obj)/,$($(*F)-objs)) |
| 213 | |
| 214 | $(__progs): $(obj)/%: $(cobjs) FORCE |
| 215 | $(call if_changed,ld) |
| 216 | |
| 217 | targets += $(__progs) $(cobjs) |
| 218 | |
| 219 | ### |
| 220 | # why - tell why a a target got build |
| 221 | ifeq ($(VERBOSE),2) |
| 222 | why = \ |
| 223 | $(if $(filter $@, $(PHONY)),- due to target is PHONY, \ |
| 224 | $(if $(wildcard $@), \ |
| 225 | $(if $(strip $(any-prereq)),- due to: $(any-prereq), \ |
| 226 | $(if $(arg-check), \ |
| 227 | $(if $(cmd_$@),- due to command line change: $(arg-check), \ |
| 228 | $(if $(filter $@, $(targets)), \ |
| 229 | - due to missing .cmd file, \ |
| 230 | - due to $(notdir $@) not in $$(targets) \ |
| 231 | ) \ |
| 232 | ) \ |
| 233 | ) \ |
| 234 | ), \ |
| 235 | - due to target missing \ |
| 236 | ) \ |
| 237 | ) |
| 238 | |
| 239 | echo-why = $(call escsq, $(strip $(why))) |
| 240 | endif |
| 241 | |
| 242 | ## |
| 243 | # Top level rules. |
| 244 | |
| 245 | %/: FORCE |
| 246 | $(Q)$(MAKE) -f Make.rules build=$(build-dir) $(MAKECMDGOALS) |
| 247 | |
| 248 | compile: $(targets) |
| 249 | @: |
| 250 | |
| 251 | install: $(targets) FORCE |
| 252 | |
| 253 | clean: $(filter %/,$(targets)) |
| 254 | ifeq ($(toplevelrun),yes) |
| 255 | $(Q)find . $(RCS_FIND_IGNORE) \ |
| 256 | \( -name '*.[oas]' -o -name '.*.cmd' -o -name '.*.d' \) \ |
| 257 | -type f -print | xargs rm -f |
| 258 | endif |
| 259 | $(Q)rm -rf $(addprefix $(obj)/,$(sort $(progs-y) $(progs-n) $(progs-))) |
| 260 | |
| 261 | ifeq ($(origin VERSION),command line) |
| 262 | DIST_VERSION=$(VERSION) |
| 263 | else |
| 264 | DIST_VERSION=$(FULL_VERSION) |
| 265 | endif |
| 266 | |
| 267 | dist: |
| 268 | git archive --format tar --prefix=$(PACKAGE)-$(DIST_VERSION)/ \ |
| 269 | $(TAGPREFIX)$(DIST_VERSION) \ |
| 270 | | bzip2 -9 > $(PACKAGE)-$(DIST_VERSION).tar.bz2 |
| 271 | |
| 272 | FORCE: |
| 273 | |
| 274 | # Read all saved command lines and dependencies for the $(targets) we |
| 275 | # may be building above, using $(if_changed{,_dep}). As an |
| 276 | # optimization, we don't need to read them if the target does not |
| 277 | # exist, we will rebuild anyway in that case. |
| 278 | |
| 279 | targets := $(wildcard $(sort $(targets))) |
| 280 | cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) |
| 281 | |
| 282 | ifneq ($(cmd_files),) |
| 283 | include $(cmd_files) |
| 284 | endif |
| 285 | |
| 286 | # Declare the contents of the .PHONY variable as phony. We keep that |
| 287 | # information in a variable se we can use it in if_changed and friends. |
| 288 | |
| 289 | .PHONY: $(PHONY) |