############################################################################## # # Definitions: basics # ############################################################################## ERROR = sh -c 'echo "adeMakefile: ERROR: $$1"; false' DUMMY DEBUG = sh -c 'echo "adeMakefile: DEBUG: $$1"' DUMMY SHELL = /bin/sh INSTALL_CMD = adeinst #INSTALL_CMD = /usr/bin/install ############################################################################## # # Definitions: load definitions from app-config # ############################################################################## # Prevent looping - app-config is very important so we'll try to make it # immediately in just a moment ('X:=$(shell ...)') but when we do make it # we'll of course invoke $(MAKE) and we don't want to that repeats the # same check ad infinitum. ifeq ($(ADE_SKIP_LOADING_APPCONFIG_FLAG),) # Find the app-config command (or where it should be if it was compiled) APPCONFIG_CMD := $(shell sh -c 'D=`pwd`; while :; do : echo "considering dir $$D ..." >&2; [ $$D = / ] && exit 1; for C in `ls $$D/bin/*-config.sh $$D/bin/*-config 2>/dev/null`; do : echo "considering file ( $$C ) ...">&2; [[ $$C =~ /[a-z]*-config.* ]] && { echo $${C%.sh}; exit 0; }; done; D=`cd $$D/.. && pwd`; done') # If we didn't find it or its sources then error - even 'make clean' needs this. ifeq ($(APPCONFIG_CMD),) $(error could not locate the app-config file sources) endif APP_LCNAME = $(shell perl -e '$$ARGV[0] =~ /^.*?([^\/]*)-config$$/; print "$$1\n";' $(APPCONFIG_CMD)) APP_UCNAME = $(shell echo $(APP_LCNAME) | tr '[a-z]' '[A-Z]') # Compile app-config if it does not exist (using $(wildcard ...) as an existence test). ifeq ($(wildcard $(APPCONFIG_CMD)),) # 'X:= $(shell ...)' is the nearest Makefiles have to 'do this right now' $(info making $(shell basename $(APPCONFIG_CMD)) ...) Y := $(shell sh -c "$(MAKE) -C $$(dirname $(APPCONFIG_CMD)) $$(basename $(APPCONFIG_CMD)) ADE_SKIP_LOADING_APPCONFIG_FLAG=1") endif ifeq ($(APP_LCNAME),ade) # Note that the settings for ADECONFIG_CMD are *only* for the use at # ADE-compile time, not APP-compile time. The problem is that we don't # support per-APP includable Makefiles, so there is no place in which # we can specify rules regarding the generation of ade-app-config in # *every* place which needs it. Therefore we out it here. ADECONFIG_CMD = $(shell dirname $(APPCONFIG_CMD))/ade-app-config # Compile app-config if it does not exist (using $(wildcard ...) as an existence test). ifeq ($(wildcard $(ADECONFIG_CMD)),) $(info making $(shell basename $(ADECONFIG_CMD)) ...) X := $(shell sh -c "$(MAKE) -C $$(dirname $(ADECONFIG_CMD)) $$(basename $(ADECONFIG_CMD)) ADE_SKIP_LOADING_APPCONFIG_FLAG=1"); endif endif # Load the app-config file $(eval $(shell $(APPCONFIG_CMD) --format=encapsulated-make)) endif ############################################################################## # # Dependencies: hook in subdirectories defined by MAKE_DIRS or NOMAKE_DIRS # ############################################################################## compile:ade_wrapper_compile install:ade_wrapper_install tests: ade_wrapper_tests clean: ade_wrapper_clean distclean: ade_wrapper_distclean # This is simply to ensure that the order in which 'make clean distclean' # is 'clean' and then 'distclean'. This is because make ignores the order # of the parameters and for this it actually is important. 'make distclean; # make clean' should leave some files around. 'make clean distclean' should # not. distclean: clean # But also note that 'make distclean' is not actually required for ADE # programs any more. But ... aderel will still call 'make clean distclean' # because other non-ADE-compatible programs may need to call it to make # sources pristine. Therefore we do at least need to ensure that make # doesn't reply with something like "distclean: unknown target", so here # we specify an empty recipe. distclean: # Recursion recipes ade_wrapper_compile ade_wrapper_install ade_wrapper_tests ade_wrapper_clean: ifeq ($(ADE_NORECURSE_FLAG),) @DIRS=*; \ : THIS NEXT COMMAND IS COMMENTED OUT; \ : reorder DIRS so that when cleaning 'bin' comes last and when; \ : making 'bin' comes first. The former ensures that dist files; \ : are cleaned, whereas the former is just an optimisation.; \ : Note cannot use the dollar-brackets way cos of the right brackets; \ : used in the case statements.; \ DIRS=`case $@ in ade_wrapper_*clean) R=r ;; *) R= ;; esac; for DIR in $$DIRS; do case $$DIR in bin) echo "1 $$DIR" ;; *) echo "2 $$DIR" ;; esac; done | sort -k 1n$$R | awk '{ print $$2 }'`; \ for DIR in $$DIRS; do \ [ -d $$DIR ] || continue; \ if [ "X$(NOMAKE_DIRS)" != X -a "X$(MAKE_DIRS)" != X ]; then \ : $(DEBUG) "NOMAKE_DIRS and MAKE_DIRS are set"; \ $(ERROR) "NOMAKE_DIRS and MAKE_DIRS should not both be defined"; \ elif [ "X$(NOMAKE_DIRS)" != X ]; then \ : $(DEBUG) "NOMAKE_DIRS is set"; \ DOIT=true; \ for NOMAKE_DIR in $(NOMAKE_DIRS); do \ [ $$NOMAKE_DIR != $$DIR ] || { \ DOIT=false; \ break; \ }; \ done; \ elif [ "X$(MAKE_DIRS)" != X ]; then \ : $(DEBUG) "MAKE_DIRS is set"; \ DOIT=false; \ for MAKE_DIR in $(MAKE_DIRS); do \ [ $$MAKE_DIR != $$DIR ] || { \ DOIT=true; \ break; \ }; \ done; \ else \ : $(DEBUG) "neither MAKE_DIRS nor NOMAKE_DIRS is set"; \ DOIT=true; \ fi; \ [ $$DOIT = false ] || \ $(MAKE) -C $$DIR $(patsubst ade_wrapper_%,%,$@) || exit $?; \ done endif # Note that there is no need to recurse for ade_wrapper_distclean because # it already depends on something that *will* recurse. In fact if I # *do* add ade_wrapper_distclean to the list of targets that do recursion # then the recursion will be done twice! The reason it is done twice is # because it is the *recipe* that does the recursion and make doesn't look # inside the recipes, it only looks inside the dependencies. That was not # very clear. Imagine this: # # foo: bar bar2 # bar: # echo "making bar" # bar2: bar # # That will result in one "making bar"s. Where as this: # # foo: # make bar # make bar2 # bar: # echo "making bar" # bar2: bar # # will result in two, because make doesn't look inside the recipe for foo # (in this second case). If it had then it would have it would see that # it was unnecessary to make both bar and bar2; just bar2 is enough. ade_wrapper_distclean: ############################################################################## # # Recipe: standard test recipe # ############################################################################## tests: [ "X$(TESTLIST_GENERATORS)" = X ] || adetest -v $(ADETEST_FLAGS) $(TESTLIST_GENERATORS) ############################################################################## # # Recipe: Compiling $(SHELL_FILES) and $(PERL_FILES) # ############################################################################## # We cannot simply say 'compile: $(SHELL_FILES) because the prerequisite is expanded immediately # but the variable assignment is expanded only afterwards (because '=' assignments have their # values' expansions deferred, and even using ':=' is no good because its expansion, although # immediate, is still later than this rule's prerequisites are expanded simply because the # variable definition is afterwards. The only trick is to ensure that the expansion of the # prerequisite is done *later*, and this is accomplished by moving it into the recipe. (See # "How `make' Reads a Makefile" in the make.info files for info on expansion.) # # Note how we do not write a recipe for 'compile' as that would mean the user could not without # incurring the 'recipe overridden' warning. So we just hook our own recipe in instead. compile: compile_shell_files compile_perl_files compile_shell_files: [ "X$(SHELL_FILES)" = X ] || { \ $(MAKE) $(SHELL_FILES); \ } compile_perl_files: [ "X$(PERL_FILES)" = X ] || { \ $(MAKE) $(PERL_FILES); \ } %: %.pl cat $< > $@ chmod a+x $@ clean: clean_shell_files clean_perl_files # $(wildcard ...) is used only as an existence test. So what we're # doing here is deleting files for which there is also a .sh version # of the same file. clean_shell_files: @[ "X$(SHELL_FILES)" = X ] || { \ FILES="$(patsubst %.sh, %, $(wildcard $(patsubst %, %.sh, $(SHELL_FILES))))"; \ : echo "removing $$FILES ..."; \ rm -f $$FILES; \ } clean_perl_files: @[ "X$(PERL_FILES)" = X ] || { \ FILES="$(patsubst %.pl, %, $(wildcard $(patsubst %, %.pl, $(PERL_FILES))))"; \ : echo "removing $$FILES ..."; \ rm -f $$FILES; \ } ############################################################################## # # Installation dependencies and recipes # ############################################################################## # It would be nice to be able to define rules *only* if there are # files that would need that rule applied, then we could avoid seeing # '[ "X" = X ] | ....' but unfortunately Makefile conditionals are # expanded *immediately* and the chances are that the variables have # not yet been defined. Hence we *must* do it with the shell. # Function to define a generic installation dependency and recipe define install_template install: install_$(5)_files install_$(5)_files: @[ "X$(1)" = X ] || { \ echo "installing $(2) ..." && \ $$(INSTALL_CMD) -d $(3) && \ $$(INSTALL_CMD) -m $(4) $(2) $(3); \ } endef # Function to define a {bin,include,lib,...} installation dependency and recipe define install_xxx_template $$(eval $$(call install_template,$$$$($(1)_FILES),$$$$($(1)_FILES),$$$$($$(APP_UCNAME)_$(1)_PREFIX),$(2),$(shell echo $(1) | tr '[A-Z]' '[a-z]'))) endef # Function to define a man page installation dependency and recipe define install_man_template $$(eval $$(call install_template,$$$$($(1)_FILES),$$$$(patsubst %, %.1, $$$$($(1)_FILES)),$$$$($$(APP_UCNAME)_$(1)_PREFIX),644,$(shell echo $(1) | tr '[A-Z]' '[a-z]'))) endef # Generate the installation dependencies and recipes $(eval $(call install_xxx_template,BIN,755)) $(eval $(call install_xxx_template,INCLUDE,644)) $(eval $(call install_man_template,MAN1)) $(eval $(call install_man_template,MAN2)) $(eval $(call install_man_template,MAN3)) $(eval $(call install_man_template,MAN4)) $(eval $(call install_man_template,MAN5)) $(eval $(call install_man_template,MAN6)) $(eval $(call install_man_template,MAN7)) $(eval $(call install_man_template,MAN8))