From 74b43175b3686193f0c9c46d5acaad3747e03ecb Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Tue, 30 Dec 2008 08:10:04 +0100 Subject: [PATCH] Devel test rules converted to snippets --- snippets/Makefile.rules.test | 2 + snippets/base | 52 ++++++------ snippets/build | 150 ++++------------------------------- snippets/prepare | 57 +++++++++++++ snippets/test | 90 +++++++++++++++++++++ 5 files changed, 193 insertions(+), 158 deletions(-) create mode 100644 snippets/prepare create mode 100644 snippets/test diff --git a/snippets/Makefile.rules.test b/snippets/Makefile.rules.test index 44304da..6e92dc9 100644 --- a/snippets/Makefile.rules.test +++ b/snippets/Makefile.rules.test @@ -1,2 +1,4 @@ include base #omkbuild +include prepare #omkbuild +include test #omkbuild include build #omkbuild diff --git a/snippets/base b/snippets/base index 31a1929..470b9a0 100644 --- a/snippets/base +++ b/snippets/base @@ -145,6 +145,25 @@ else QUIET_CMD_ECHO = echo endif +# Convenient variables +comma := , +squote := ' +#' +empty := +space := $(empty) $(empty) + +### +# Escape single quote for use in echo statements +escsq = $(subst $(squote),'\$(squote)',$1) + +### +# Strip/replace OUTPUT_DIR from/in the argument +strip_out = $(patsubst $(OUTPUT_DIR)/%,%,$(1)) +repl_out = $(patsubst $(OUTPUT_DIR)/%,$$(OUTPUT_DIR)/%,$(1)) + +.PHONY: FORCE + + MAKEFILE_OMK=Makefile.omk # All subdirectories (even linked ones) containing Makefile.omk # Usage in Makefile.omk: SUBDIRS = $(ALL_OMK_SUBDIRS) @@ -199,14 +218,12 @@ pass = $(strip $(1)) # Usage: $(call omk_pass_subdir_template,,,) define omk_pass_subdir_template .PHONY: $(pass)-$(3)-subdir -$(pass)-submakes: $(pass)-$(3)-subdir +$(pass)-subdirs: $(pass)-$(3)-subdir $(pass)-$(3)-subdir: @$(call mkdir_def,$(2)/$(3)) +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(3) $(NO_PRINT_DIRECTORY) \ RELATIVE_DIR=$(RELATIVE_PREFIX)$(3) -C $(2)/$(3) \ - -f $(SUBDIR_MAKEFILE) $(pass)-submakes -# In subdirectories we can call submakes directly since passes are -# already searialized on the toplevel make. + -f $(SUBDIR_MAKEFILE) $(pass) endef ifdef OMK_TESTSROOT @@ -229,26 +246,13 @@ $(foreach subdir,$(EXTRA_RULES_SUBDIRS),$(eval $(call extra_rules_subdir_templat # Usage: $(call omk_pass_template,,,[],[]) define omk_pass_template -.PHONY: $(pass) $(pass)-local $(pass)-check $(pass)-submakes -$(foreach subdir,$(SUBDIRS),$(eval $(call omk_pass_subdir_template,$(pass),$(2),$(subdir)))) -$(pass): -# Submakes have to be called this way and not as dependecies for pass -# serialization to work - +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR) $(NO_PRINT_DIRECTORY) \ - RELATIVE_DIR=$(RELATIVE_DIR) \ - -f $(SOURCESDIR_MAKEFILE) $(pass)-submakes -$(pass)-submakes: - @true # Do not emit "nothing to be done" messages - -ifneq ($(4)$($(pass)_HOOKS),) -$(pass)-submakes: $(pass)-this-dir -$(pass)-this-dir: $(foreach subdir,$(SUBDIRS),$(pass)-$(subdir)-subdir) +.PHONY: $(pass) $(pass)-local $(pass)-msg $(pass)-subdirs +$(pass): $(pass)-local +$(pass)-local: $(pass)-subdirs $(pass)-msg +$(foreach subdir,$(SUBDIRS),$(call omk_pass_subdir_template,$(pass),$(2),$(subdir))) + +$(pass)-msg: $(pass)-subdirs +@echo "make[omk]: $(pass) in $(RELATIVE_DIR)" - @$(call mkdir_def,$(2)) - +@$(MAKE) $(NO_PRINT_DIRECTORY) SOURCES_DIR=$(SOURCES_DIR) RELATIVE_DIR=$(RELATIVE_DIR) -C $(2) \ - -f $(SOURCESDIR_MAKEFILE) $(3) $(check-target) $(1:%=%-local) -$(pass)-local: $($(pass)_HOOKS) -endif endef # ======================= @@ -259,7 +263,7 @@ default-config: @echo "# This file should not be altered manually" >> "$(CONFIG_FILE)-default" @echo "# Overrides should be stored in file $(notdir $(CONFIG_FILE))" >> "$(CONFIG_FILE)-default" @echo >> "$(CONFIG_FILE)-default" - @$(MAKE) $(NO_PRINT_DIRECTORY) -C $(OUTPUT_DIR) \ + @$(MAKE) $(NO_PRINT_DIRECTORY) -C $(MAKERULES_DIR) \ RELATIVE_DIR="" SOURCES_DIR=$(OUTPUT_DIR) \ -f $(OUTPUT_DIR)/Makefile default-config-pass diff --git a/snippets/build b/snippets/build index fe08e19..038cd9e 100644 --- a/snippets/build +++ b/snippets/build @@ -1,146 +1,28 @@ -#### -# kbuild: Generic definitions -# Convenient variables -comma := , -squote := ' -#' -empty := -space := $(empty) $(empty) - -BUILD_DIR_NAME = _build -COMPILED_DIR_NAME = _compiled - -USER_INCLUDE_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/include -USER_LIB_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/lib -USER_UTILS_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-utils -USER_TESTS_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-tests -USER_BIN_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin -USER_BUILD_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/user -LINK_BUILD_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/link - -USER_OBJS_DIR = $(USER_BUILD_DIR)/$(RELATIVE_DIR) -KERN_OBJS_DIR = $(KERN_BUILD_DIR)/$(RELATIVE_DIR) -OMK_WORK_DIR = $(USER_OBJS_DIR) - -strip_out = $(patsubst $(OUTPUT_DIR)/%,%,$(1)) -repl_out = $(patsubst $(OUTPUT_DIR)/%,$$(OUTPUT_DIR)/%,$(1)) - -.PHONY: FORCE - -##################### +##################### -*- makefile-gmake -*- # Build pseudo-pass # ##################### +ifneq (,$(filter build,$(MAKECMDGOALS))) +all: build-pseudo-pass -rule_targets = $($(1)_targets) -rule_deps = $($(1)_deps) -rule_msg = $($(1)_msg) -rule_cmd = $($(1)_cmd) +rule_targets = $(value $(1)_targets) +rule_deps = $(value $(1)_deps) +rule_msg = $(value $(1)_msg) +rule_cmd = $(value $(1)_cmd) -# Usage: $(call build_rule,) +# Usage: $(eval $(call build_rule,)) define build_rule -$(rule_target): $(rule_deps) $(omk_inc_file) - @$(QUIET_CMD_ECHO) " "$(rule_msg) "$$(call strip_out,$$(@))" +$(rule_targets): $(rule_deps) #$(omk_inc_file) + @$(QUIET_CMD_ECHO) " "$(rule_msg)"$$@" #"$$(call strip_out,$$@)" $(Q)$(rule_cmd) endef -# TODO: Include target.omk only in the subtree --include $(shell true; find $(USER_BUILD_DIR) -name '*omk.inc') # `true' is a hack for MinGW +# TODO: Include __goals.omk.inc only in the subtree +-include $(shell true; find $(USER_BUILD_DIR) -name '*.omk.inc') # `true' is a hack for MinGW +# FIXME: Disable automatic remake of included files $(foreach rule,$(prepared_rules),$(eval $(call build_rule,$(rule)))) -.PHONY: build-pseudo-pass -build-pseudo-pass: $(foreach target,$(default_build_targets),$(target)) - -################ -# Prepare pass # -################ - -$(eval $(call omk_pass_template,prepare-pass,$(USER_OBJS_DIR),,always)) - -### -# Name of the prepared rule. This name is used as prefix of variable -# names in .omk.inc and is based on the first target -omk_inc_rule = $(firstword $(1:$(OUTPUT_DIR)/%=%)) - -# The name of .omk.inc file is derived from $(omk_inc_rule) and -# depends whether the target is under _build or elsewhere. -omk_inc_file = $(if $(filter $(BUILD_DIR_NAME)%,$(omk_inc_rule)),\ - $(OMK_WORK_DIR)/$(notdir $(omk_inc_rule)).omk.inc,\ - $(OMK_WORK_DIR)/$(subst /,_,$(omk_inc_rule)).omk.inc) - -target_omk_file = $(OMK_WORK_DIR)/$(notdir $(1)).target.omk - -### -# prepare_rule is used to generate .omk.inc files during prepare-pass. -# All paths in this file should be relative to $(OUTPUT_DIR) -# Usage: $(call prepare_rule,,,,) -define prepare_rule -prepare-pass-local: $(omk_inc_file) - -$(omk_inc_file): FORCE - $(Q)echo 'prepared_rules += $(omk_inc_rule)' > $$@.tmp; \ - echo '$(omk_inc_rule)_targets = $$(call strip_out,$(1))' >> $$@.tmp; \ - echo '$(omk_inc_rule)_deps += $$(call strip_out,$(2))' >> $$@.tmp; \ - echo '$(omk_inc_rule)_msg = $(3)' >> $$@.tmp; \ - echo '$(omk_inc_rule)_cmd = $$(call repl_out,$(4))' >> $$@.tmp; \ - if cmp -s $$@.tmp $$@; then rm $$@.tmp; else mv $$@.tmp $$@; fi -endef - -### -# prepare_rule_default - same as prepare rules but the target is put -# as dependency to the default build rule, which causes it to be built -# upon calling make -define prepare_rule_default -$(call prepare_rule,$(1),$(2),$(3),$(4)) -prepared_default_build_targets += $(call strip_out,$(1)) -endef - -prepare-pass-local: $(OMK_WORK_DIR)/omk.inc -$(OMK_WORK_DIR)/omk.inc: FORCE - $(Q)echo 'default_build_targets += $(prepared_default_build_targets)' > $@.tmp; \ - if cmp -s $@.tmp $@; then rm $@.tmp; else mv $@.tmp $@; fi - - -############ -# Programs # -############ - -# Usage: $(call program_template,,) -define program_template -$(1)_OBJS += $$(patsubst %.c,%.o,$$(filter %.c,$$($(1)_SOURCES))) -$(1)_OBJS := $$(addprefix $(USER_OBJS_DIR),$$(sort $$($(1)_OBJS:%/=%))) - -USER_OBJS += $$($(1)_OBJS) -USER_SOURCES += $$($(1)_SOURCES) - - - -program_cmd = $$(if $$(filter %.cc,$$($(1)_SOURCES)),$$(CXX),$$(CC)) \ - $$($(1)_OBJS) $$($(1)_LIBS:%=-l%) $$(LOADLIBES) $$(LDFLAGS) -Wl,-rpath-link,$(USER_LIB_DIR) \ - -Wl,-Map,$(USER_OBJS_DIR)/$(1).exe.map -o $$$$@ - -$(call prepare_rule_default,\ - $(USER_BIN_DIR)/$(1)$(EXE_SUFFIX),\ - $$($(1)_OBJS) $$($(1)_LIBS),\ - "LINK ",\ - $$(program_cmd)) -endef - -c_o_cmd := set -e; cd $$(dir $$@); \ - if $$(c_o_COMPILE) $$(CC_DEPFLAGS) -o $$@ -c $$< ; \ - then mv -f "$$@.d.tmp" "$$@.d" ; \ - else rm -f "$$@.d.tmp" ; \ - fi - - -$(foreach prog,$(bin_PROGRAMS),$(eval $(call program_template,$(prog),bin))) -$(foreach src,$(filter %.c,$(USER_SOURCES)),$(eval $(call prepare_rule,\ - $(USER_OBJS_DIR)/$(src:%.c=%.o),\ - $(SOURCES_DIR)/$(src),\ - "CC ",\ - $(c_o_cmd)))) - -default: prepare-pass - $(MAKE) -qp build-pseudo-pass > make.dp.build-pseudo-pass - $(MAKE) build-pseudo-pass +.PHONY: build +build: $(foreach target,$(omk_goals),$(target)) +endif # (,$(filter build,$(MAKECMDGOALS))) diff --git a/snippets/prepare b/snippets/prepare new file mode 100644 index 0000000..ed7fded --- /dev/null +++ b/snippets/prepare @@ -0,0 +1,57 @@ + +################ +# Prepare pass # +################ + +$(eval $(call omk_pass_template,prepare-pass,$(USER_OBJS_DIR),,always)) + +### +# Name of the prepared rule. This name is used as prefix of variable +# names in .omk.inc and is based on the first target +omk_inc_rule = $(firstword $(1:$(OUTPUT_DIR)/%=%)) + +# The name of .omk.inc file is derived from $(omk_inc_rule) and +# depends whether the target is under _build or elsewhere. +omk_inc_file = $(if $(filter $(BUILD_DIR_NAME)%,$(omk_inc_rule)),\ + $(OMK_WORK_DIR)/$(notdir $(omk_inc_rule)).omk.inc,\ + $(OMK_WORK_DIR)/$(subst /,_,$(omk_inc_rule)).omk.inc) + +target_omk_file = $(OMK_WORK_DIR)/$(notdir $(1)).target.omk + +# >'< substitution is for echo to work, +# >$< substitution to preserve $ when reloading .omk.inc file +subst-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(1)))) + +### +# prepare_rule is used to generate .omk.inc files during prepare-pass. +# All paths in this file should be relative to $(OUTPUT_DIR) +# Usage: $(eval $(call prepare_rule,,,,)) +define prepare_rule +prepare-pass-local: $(omk_inc_file) + +$(omk_inc_file): FORCE +#TODO remove the next line + @echo " PREP "$$(call strip_out,$$@); \ + echo 'prepared_rules += $(omk_inc_rule)' > $$@.tmp; \ + echo '$(omk_inc_rule)_targets = $$(call strip_out,$(1))' >> $$@.tmp; \ + echo '$(omk_inc_rule)_deps += $$(call strip_out,$(2))' >> $$@.tmp; \ + echo '$(omk_inc_rule)_msg = $(3)' >> $$@.tmp; \ + echo '$(omk_inc_rule)_cmd = $(call subst-cmd,$(4))' >> $$@.tmp; \ + if cmp -s $$@.tmp $$@; then rm $$@.tmp; else mv $$@.tmp $$@; fi +endef + +### +# prepare_rule_goal - same as prepare rules but the target is put +# as dependency to the default goal, which causes it to be built +# upon calling make +define prepare_rule_goal +$(call prepare_rule,$(1),$(2),$(3),$(4)) +prepared_goals += $(call strip_out,$(1)) +endef + +prepare-pass-local: $(OMK_WORK_DIR)/__goals.omk.inc +$(OMK_WORK_DIR)/__goals.omk.inc: FORCE + $(Q)echo 'omk_goals += $(prepared_goals)' > $@.tmp; \ + if cmp -s $@.tmp $@; then rm $@.tmp; else mv $@.tmp $@; fi + + diff --git a/snippets/test b/snippets/test new file mode 100644 index 0000000..bafcb3c --- /dev/null +++ b/snippets/test @@ -0,0 +1,90 @@ +BUILD_DIR_NAME = _build +COMPILED_DIR_NAME = _compiled + +USER_INCLUDE_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/include +USER_LIB_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/lib +USER_UTILS_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-utils +USER_TESTS_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-tests +USER_BIN_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin +USER_BUILD_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/user +LINK_BUILD_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/link + +# Avoid double slash at the end in the top-level directory +USER_OBJS_DIR = $(USER_BUILD_DIR)$(RELATIVE_DIR:%=/%) +KERN_OBJS_DIR = $(KERN_BUILD_DIR)$(RELATIVE_DIR:%=/%) +OMK_WORK_DIR = $(USER_OBJS_DIR) + +############ +# Programs # +############ + +# Check GCC version for user build +ifndef CC_MAJOR_VERSION +CC_MAJOR_VERSION := $(shell $(CC) -dumpversion | sed -e 's/\([^.]\)\..*/\1/') +endif +# Prepare suitable define for dependency building +ifeq ($(CC_MAJOR_VERSION),2) +CC_DEPFLAGS = -Wp,-MD,"$$@.d.tmp" +else +CC_DEPFLAGS = -MT $$@ -MD -MP -MF "$$@.d.tmp" +endif + +c_o_COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DOMK_FOR_USER + +c_o_cmd = \ + if $(c_o_COMPILE) $(CC_DEPFLAGS) -o $$@ -c $$< ; \ + then mv -f "$$@.d.tmp" "$$@.d"; \ + else rm -f "$$@.d.tmp"; exit 1; \ + fi + + +# Usage: $(call program_template,,) +define program_template +$(1)_OBJS += $$(patsubst %.c,%.o,$$(filter %.c,$$($(1)_SOURCES))) +$(1)_OBJS := $$(addprefix $(USER_OBJS_DIR)/,$$(sort $$($(1)_OBJS:%/=%))) + +USER_OBJS += $$($(1)_OBJS) +USER_SOURCES += $$($(1)_SOURCES) + +$(call prepare_rule_goal,\ + $(USER_BIN_DIR)/$(1)$(EXE_SUFFIX),\ + $$($(1)_OBJS) $$($(1)_LIBS),\ + "LINK ",\ + $(program_cmd)) +endef + +program_cmd = $(if $(filter %.cc,$$($(1)_SOURCES)),$(CXX),$(CC)) \ + $($(1)_OBJS) $($(1)_LIBS:%=-l%) $(LOADLIBES) $(LDFLAGS) -Wl,-rpath-link,$(USER_LIB_DIR) \ + -Wl,-Map,$(USER_OBJS_DIR)/$(1).exe.map -o $$@ + +$(foreach prog,$(bin_PROGRAMS),$(eval $(call program_template,$(prog),bin))) +#$(foreach prog,$(bin_PROGRAMS),$(info >>>$(call program_template,$(prog),bin)<<<)) +$(foreach src,$(filter %.c,$(USER_SOURCES)),\ + $(eval $(call prepare_rule,\ + $(USER_OBJS_DIR)/$(src:%.c=%.o),\ + $(SOURCES_DIR)/$(src),\ + "CC ",\ + $(c_o_cmd)))) + +$(eval $(call prepare_rule_goal,\ + $(USER_OBJS_DIR)/test.X.o,\ + $(SOURCES_DIR)/test.c,\ + "CC ",\ + $(c_o_cmd))) + +# OUTPUT_DIR is not defined in Makefile.build so we has to pass it on +# command-line. After this file will be merged with Makefile.rules, it +# will not be necessary to pass it. +default: check-dir prepare-pass + -$(MAKE) -qp -f $(MAKERULES_DIR)/Makefile.rules build > make.db.build-pseudo-pass; + +@echo "make[omk]: build" + @$(MAKE) $(NO_PRINT_DIRECTORY) -f $(MAKERULES_DIR)/Makefile.rules build + +check-dir: + @$(call mkdir_def,$(USER_BUILD_DIR)) + @$(call mkdir_def,$(USER_INCLUDE_DIR)) + @$(call mkdir_def,$(USER_LIB_DIR)) + @$(call mkdir_def,$(USER_BIN_DIR)) + @$(call mkdir_def,$(USER_UTILS_DIR)) + @$(call mkdir_def,$(USER_TESTS_DIR)) -- 2.39.2