.DEFAULT_GOAL := all .PHONY: all clean install count FORCE export MAKEFLAGS MAKEFLAGS += --no-print-directory ifneq (,$(DIRNAME)) target_external := endif I=$(if $(filter install,$(MAKECMDGOALS)),1,0) ifeq (,$(MAKEFILE_LIST)) MAKEFILE_LIST := Makefile endif _INDEX := 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 EXTDIRS := $(foreach p,$(target_external),$(if $(wildcard $p),,$(dir $p))) EXTIDXS := $(addprefix make_extdir_,$(wordlist 1,$(words $(EXTDIRS)),$(_INDEX))) all:: $(addprefix make_all_,$(SUBDIRS)) $(EXTIDXS) $(target) $(target_only); install:: $(addprefix make_all_,$(SUBDIRS)) $(EXTIDXS) $(target) $(target_only); ifeq ($I,1) all:: $(addprefix install_,$(target_install)); install:: $(addprefix install_,$(target_install)); endif FORCE:; clean:: $(addprefix make_clean_,$(SUBDIRS)); #override CFLAGS += -Wall -D_GNU_SOURCE -D_REENTRANT -g -O2 override CFLAGS += -Wall -D_GNU_SOURCE -D_REENTRANT -g ifeq ($(DEBUG), ) override CFLAGS += -O2 endif ECHO = /bin/echo ifneq (0,$C) RED = \\e[1m\\e[31m DARKRED = \\e[31m GREEN = \\e[1m\\e[32m DARKGREEN = \\e[32m BLUE = \\e[1m\\e[34m DARKBLUE = \\e[34m YELLOW = \\e[1m\\e[33m DARKYELLOW = \\e[33m MAGENTA = \\e[1m\\e[35m DARKMAGENTA = \\e[35m CYAN = \\e[1m\\e[36m DARKCYAN = \\e[36m RESET = \\e[m color: @$(ECHO) -e $(RED)RED$(RESET) @$(ECHO) -e $(GREEN)GREEN$(RESET) @$(ECHO) -e $(BLUE)BLUE$(RESET) @$(ECHO) -e $(YELLOW)YELLOW$(RESET) @$(ECHO) -e $(MAGENTA)MAGENTA$(RESET) @$(ECHO) -e $(CYAN)CYAN $(RESET) @$(ECHO) -e $(DARKRED)DARKRED$(RESET) @$(ECHO) -e $(DARKGREEN)DARKGREEN$(RESET) @$(ECHO) -e $(DARKBLUE)DARKBLUE$(RESET) @$(ECHO) -e $(DARKYELLOW)DARKYELLOW$(RESET) @$(ECHO) -e $(DARKMAGENTA)DARKMAGENTA$(RESET) @$(ECHO) -e $(DARKCYAN)DARKCYAN $(RESET) endif export P PSX = $(if $(findstring -j,-$(MAKEFLAGS)),$(GREEN)$(EPREFIX) ) ifneq (,$(findstring clean,$(MAKECMDGOALS))) override P := 0 EXTIDXS := endif ifeq (0,$P) _TOTAL := _TOTAL2 := override TOTAL := else _TOTAL := $(foreach p,$(basename $(filter-out %.so,$(target))),$($p_objs)) _TOTAL2 := $(foreach p,$(basename $(filter %.so,$(target))),$($p_objs:.o=.pic.o)) _TOTAL2 := $(words $(sort $(target) $(_TOTAL) $(_TOTAL2))) _TOTAL := $(SUBDIRS) endif $(foreach p,$(_TOTAL),$(eval $(shell $(MAKE) -s -C $p count DIRNAME=$p P=$P))) $(foreach p,$(EXTIDXS),$(eval $(shell $(MAKE) -s -C $(word $(subst make_extdir_,,$p),$(EXTDIRS)) count DIRNAME=$p P=$P))) _TOTAL += $(EXTIDXS) _TOTAL := $(if $(_TOTAL),$(words $(_TOTAL))*2 $(patsubst %,+$$(TOTAL_%),$(sort $(_TOTAL)))) $(if $(_TOTAL),$(eval _TOTAL2:=$$(shell $(ECHO) $$$$(($(_TOTAL2)+$(_TOTAL)))))) $(if $(TOTAL),,$(eval TOTAL:=$(_TOTAL2))) ifeq (0,$(TOTAL)) TOTAL := endif ifeq (,$(TOTAL)) override PCT := override PCT0 := override PCT1 := override inc := else ifneq (,$(findstring -j,-$(MAKEFLAGS))) override PCT := override PCT0 := override PCT1 := override inc := else ifeq ($(START),) STEP := 0 00 else STEP := $(START) $(shell B=$$(($(START)*100/$(TOTAL))); [ $$B -le 9 ] && B=0$$B; $(ECHO) $$B) endif START = $(firstword $(STEP)) PCT0 = $(if $(findstring -j,-$(MAKEFLAGS)),," ") ifeq (2,$P) PCT1 = $(if $(findstring -j,-$(MAKEFLAGS)),,[$(TOTAL)/$(TOTAL)]) PCT = $(if $(findstring -j,-$(MAKEFLAGS)),,[$(firstword $(STEP))/$(TOTAL)]) else PCT1 = $(if $(findstring -j,-$(MAKEFLAGS)),,[100]) PCT = $(if $(findstring -j,-$(MAKEFLAGS)),,[$(word 2,$(STEP))%]) endif define inc $(if $(findstring -j,-$(MAKEFLAGS)),,STEP := $(shell A=$$(($(firstword $(STEP))+$(if $1,$1,1))); B=$$(($$A*995/$(TOTAL)/10)); [ $$B -le 9 ] && B=0$$B; $(ECHO) $$A $$B)) endef ifeq (0,$P) inc := 0 00 endif endif endif ifeq (default,$(origin LD)) LD := $(CC) endif $(eval LD := $(CXX) -Wl,--as-needed) $(eval MMD = -MMD -MF .dep.$$@) define CC @$(ECHO) -e $(PCT) $(eval $(inc)) " CC "$(PSX)$(CYAN)$(patsubst tmp.%,%,$<) $(RESET) @gcc endef define CCSO @$(ECHO) -e $(PCT) $(eval $(inc)) " CC [PIC] "$(PSX)$(CYAN)$(patsubst tmp.%,%,$<) $(RESET) @gcc -fPIC endef define CXX @$(ECHO) -e $(PCT) $(eval $(inc)) " CXX "$(PSX)$(CYAN)$(patsubst tmp.%,%,$<) $(RESET) @g++ endef define CXXSO @$(ECHO) -e $(PCT) $(eval $(inc)) " CXX [PIC] "$(PSX)$(CYAN)$(patsubst tmp.%,%,$<) $(RESET) @g++ -fPIC endef define MLD @$(ECHO) -e $(PCT) $(eval $(inc)) " LD "$(PSX)$(MAGENTA)$@ $(RESET) @$(LD) endef define MLDSO @$(ECHO) -e $(PCT) $(eval $(inc)) " LD [PIC] "$(PSX)$(MAGENTA)$@ $(RESET) @$(LD) -shared endef define AR @$(ECHO) -e $(PCT) $(eval $(inc)) " AR "$(PSX)$(MAGENTA)$@ $(RESET) @ar endef define BIN2C @$(ECHO) -e $(PCT) $(eval $(inc)) " BIN2C "$(PSX)$(YELLOW)$@ $(RESET) @xxd -i endef ENTER = @$(ECHO) -e $(PCT) $(eval $(inc)) " ENTER ==> "$(GREEN) LEAVE = @$(ECHO) -e $(PCT) $(eval $(inc)) " LEAVE <== "$(GREEN) define RM @$(ECHO) -e $(PCT0) " CLEAN "$(PSX)$(MAGENTA)$(if $(CLEAN),$(CLEAN),"<$(notdir $(CURDIR))>") $(RESET) @rm -f endef define INST @$(ECHO) -e $(PCT0) " INSTALL "$(PSX)$(YELLOW)$* $(RESET) @install endef DONE = @$(ECHO) -e $(PCT1) " DONE "$(MAGENTA)"<$(notdir $(CURDIR))>" $(RESET) BAD = ($(ECHO) -e $(PCT0) " BAD "$(PSX)$(RED)$(1) $(RESET); /bin/false) BAD = ($(ECHO) -e $(PCT0) " BAD "$(PSX)$(RED)$(1) $(RESET); /bin/false) MDEP = $(ECHO) -e $(PCT0) " MAKEDEP "$(YELLOW)$(EPREFIX)$(firstword $(MAKEFILE_LIST)) $(RESET) 1>&2 tmp.%.c: %.c @ln -s $< $@ tmp.%.cc: %.cc @ln -s $< $@ tmp.%.cpp: %.cpp @ln -s $< $@ %.pic.o: %.c $(CCSO) $(MMD) $(CFLAGS) $($*_cflags) -c -o $@ $< %_pic.o: %.c $(CCSO) $(MMD) $(CFLAGS) $($*_cflags) -c -o $@ $< %.o: %.c $(CC) $(MMD) $(CFLAGS) $($*_cflags) -c -o $@ $< %.pic.o: %.cc $(CXXSO) $(MMD) $(CFLAGS) $(CXXFLAGS) $($*_cflags) -c -o $@ $< %_pic.o: %.cc $(CXXSO) $(MMD) $(CFLAGS) $(CXXFLAGS) $($*_cflags) -c -o $@ $< %.o: %.cc $(CXX) $(MMD) $(CFLAGS) $(CXXFLAGS) $($*_cflags) -c -o $@ $< %.pic.o: %.cpp $(CXXSO) $(MMD) $(CFLAGS) $(CXXFLAGS) $($*_cflags) -c -o $@ $< %_pic.o: %.cpp $(CXXSO) $(MMD) $(CFLAGS) $(CXXFLAGS) $($*_cflags) -c -o $@ $< %.o: %.cpp $(CXX) $(MMD) $(CFLAGS) $(CXXFLAGS) $($*_cflags) -c -o $@ $< %.bin.c: % $(BIN2C) $< >$@ make_all_%:: $(ENTER) $(EPREFIX)$* $(RESET) @$(MAKE) -s -C $* all DONE= I=$I P=$P TOTAL=$(TOTAL) START=$(START) EPREFIX=$(EPREFIX)$*/ @$(eval $(call inc,$(TOTAL_$(strip $*)))) $(LEAVE) $(EPREFIX)$* $(RESET) make_extdir_%:: $(ENTER) $(word $*,$(EXTDIRS)) $(RESET) @$(MAKE) -s -C $(word $*,$(EXTDIRS)) all DONE= P=$P TOTAL=$(TOTAL) START=$(START) @$(eval $(call inc,$(TOTAL_make_extdir_$(strip $*)))) $(LEAVE) $(word $*,$(EXTDIRS)) $(RESET) make_clean_%: @$(MAKE) -s -C $* clean CLEAN=$(if $(CLEAN),$(CLEAN)/)$* install_%.so: %.so @[ -f $(install_dir) ] || mkdir -p $(install_dir) $(INST) $(if $($*_soname),$($*_soname),$*.so) $(install_dir) $(if $($*_soname),@ln -sf $($*_soname) $(install_dir)/$*.so) install_%: % @[ -f $(install_dir) ] || mkdir -p $(install_dir) $(INST) $* $(if $(install_mode),-m $(install_mode),) $(install_dir) %: %.c %: %.cc %: %.cpp %: %.o _COMMA=, _method := ifneq (,$(findstring second-expansion,$(.FEATURES))) # for gmake v3.81 or above, second-expansion method .SECONDEXPANSION: _SUB=:.o=.pic.o %.pic.a: $$(%_objs$$(_SUB)) $(AR) cr $@ $^ %.so: $$(%_objs$$(_SUB)) # $(MLDSO) -z defs $(LDFLAGS) -o $(if $($*_soname),$($*_soname) -Wl$(_COMMA)-soname=$($*_soname),$@) $^ $($*_libs) $(LIBPATH) $(LIBS) $(MLDSO) -z defs $(LDFLAGS) -o $(if $($*_soname),$(if $($*_filename), $($*_filename), $($*_soname)) -Wl$(_COMMA)-soname=$($*_soname),$@) $^ $($*_libs) $(LIBPATH) $(LIBS) $(if $($*_soname),@ln -sf $($*_soname) $@) $(if $($*_soname),$(if $($*_filename), @ln -sf $($*_filename) $($*_soname))) # libdtc.so: $$(%_objs$$(_SUB)) # $(MLDSO) -z defs $(LDFLAGS) -o $(if $($*_soname), $filename -Wl$(_COMMA)-soname=$($*_soname),$@) $^ $($*_libs) $(LIBPATH) $(LIBS) # $(if $($*_soname),@ln -sf $(filename) libdtc.so.1) # $(if $($*_soname),@ln -sf libdtc.so.1 $@) %.a: $$(%_objs) $(AR) cr $@ $^ %: $$(%_objs) @test -n "$^" || $(call BAD,$@) $(MLD) $(LDFLAGS) -o $@ $^ $($*_libs) $(LIBPATH) $(LIBS) _method := second-expansion endif $(if $(_method),,$(if $(findstring i486,$(shell gcc -dumpmachine)),,$(eval _method := eval))) ifeq (eval,$(_method)) # for gmake v3.80, $(eval) method define rule-piclib $p: $($(p:.pic.a=)_objs:.o=.pic.o) $$(AR) cr $p $$^ endef define rule-lib $p: $($(p:.a=)_objs) $$(AR) cr $p $$^ endef define rule-so $p: $($(p:.so=)_objs:.o=.pic.o) $$(MLDSO) -z defs $$(LDFLAGS) -o $(if $($(p:.so=)_soname),$($(p:.so=)_soname) -Wl$(_COMMA)-soname=$($(p:.so=)_soname),$p) $$^ $$($(p:.so=)_libs) $$(LIBPATH) $$(LIBS) $(if $($(p:.so=)_soname),@ln -s $($(p:.so=)_soname) $p) endef define rule-bin $p: $($p_objs) $$(MLD) $$(LDFLAGS) -o $p $$($p_objs) $$($p_libs) $$(LIBPATH) $$(LIBS) endef endif # gmake 3.80 don't allow ($eval) inside if/endif block $(foreach p,$(filter %.pic.a,$(target)),$(if $($(p:.pic.a=)_objs),$(eval $(rule-piclib)))) $(foreach p,$(filter %.a,$(target)),$(if $($(p:.a=)_objs),$(eval $(rule-lib)))) $(foreach p,$(filter %.so,$(target)),$(if $($(p:.so=)_objs),$(eval $(rule-so)))) $(foreach p,$(filter-out %.a %.o %.so,$(target)),$(if $($p_objs),$(eval $(rule-bin)))) ifneq (clean,$(MAKECMDGOALS)) ifneq (count,$(MAKECMDGOALS)) ifeq (,$(_method)) # without $(eval), fallback to temporary Makefile _method := makefile define cmd-piclib $(ECHO) '$p: $($(p:.pic.a=)_objs:.o=.pic.o)' >>.make.dep; \ $(ECHO) ' $$(AR) cr $p $$^' >>.make.dep endef define cmd-lib $(ECHO) '$p: $($(p:.a=)_objs)' >>.make.dep; \ $(ECHO) ' $$(AR) cr $p $$^' >>.make.dep endef define cmd-so $(ECHO) '$p: $($(p:.so=)_objs:.o=.pic.o)' >>.make.dep; \ $(ECHO) ' $$(MLDSO) -z defs $$(LDFLAGS) -o $(if $($(p:.so=)_soname),$($(p:.so=)_soname) -Wl$(_COMMA)-soname=$($(p:.so=)_soname),$p) $$^ $$($(p:.so=)_libs) $$(LIBPATH) $$(LIBS)' >>.make.dep; \ $(ECHO) ' $(if $($(p:.so=)_soname),@ln -s $($(p:.so=)_soname) $p)' >>.make.dep endef define cmd-bin $(ECHO) '$p: $($p_objs)' >>.make.dep; \ $(ECHO) ' $$(MLD) $$(LDFLAGS) -o $p $$($p_objs) $$($p_libs) $$(LIBPATH) $$(LIBS)' >>.make.dep endef ifeq (OK,$(shell [ $(firstword $(MAKEFILE_LIST)) -nt .make.dep ] && $(ECHO) OK)) $(shell $(MDEP)) $(shell >.make.dep) $(foreach p,$(filter %.pic.a,$(target)),$(if $($(p:.pic.a=)_objs),$(shell $(cmd-piclib)))) $(foreach p,$(filter %.a,$(target)),$(if $($(p:.a=)_objs),$(shell $(cmd-lib)))) $(foreach p,$(filter %.so,$(target)),$(if $($(p:.so=)_objs),$(shell $(cmd-so)))) $(foreach p,$(filter-out %.a %.o %.so,$(target)),$(if $($p_objs),$(shell $(cmd-bin)))) endif include .make.dep endif endif endif .SECONDARY: all:: $(DONE) install:: all; clean:: $(foreach p,$(filter %.so,$(target)),@-rm -f $($(p:.so=)_soname)) clean:: $(RM) .make.* *.o *.a *.d *.so .dep.* tmp.* *.log $(target) $(TSTS) count:: @$(ECHO) TOTAL_$(if $(DIRNAME),$(DIRNAME),all)=$(TOTAL) method:: @$(ECHO) rule method is $(_method). ifneq ($(wildcard .dep.*),) -include $(wildcard .dep.*) endif