# $HeadURL$ $LastChangedRevision$ ############################################################################## # # Definitions: basics # ############################################################################## ERROR = sh -c 'echo "ade.mk: ERROR: $$1"; false' DUMMY DEBUG = sh -c 'echo "ade.mk: DEBUG: $$1"' DUMMY SHELL = /bin/bash MAKEFLAGS = --no-print-directory ############################################################################## # # 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, if it had been compiled. (For bug ADE-7 this has # been modified slightly: it looks for any *-config.sh file excluding # add-app-config.sh. Additionally, the loop code was recoded to reduce calls # to external programs.) APPCONFIG_CMD := $(shell sh -c 'while :; do : echo "considering dir $$PWD ..." >&2; if [ $$PWD = / ]; then exit 1; fi; for FILE in bin/*-config.sh; do : echo "considering $$FILE ...">&2; if [ "$$FILE" = bin/ade-app-config.sh ]; then continue; elif [ -f "$$FILE" ]; then : echo "got it!" >&2; echo "$$PWD/$${FILE%.sh}"; exit 0; fi; done; cd ..; 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 do it here. ADECONFIG_CMD = $(shell dirname $(APPCONFIG_CMD))/ade-app-config # Compile ade-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 || echo "\"\\\$$(error see previous error)\"")) endif # The recipes for installing files and 'compiling' man pages call adeinst # and adeass. For all modules *except* ade itself, it's enough to tell the # recipes the names of these commands. For ade itself, it's a bit more complicated # because these commands have to be able to find these commands when they # are not yet installed in a directory that's in $PATH *and* these commands # need to be able to find ade.sh, although that is not yet in its standard # location. Ade will take care of this in its own Makefiles. ifneq ($(APP_LCNAME),ade) INSTALL_CMD = adeinst ADEASS_CMD = adeass 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 ... adebun 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 # Note that we 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 latter is just an optimisation. Note cannot use the # dollar-brackets way cos of the right brackets used in the case statements. ade_wrapper_compile ade_wrapper_install ade_wrapper_tests ade_wrapper_clean: ifeq ($(ADE_NORECURSE_FLAG),) @DIRS=*; \ 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) --args-are-generators $(TESTLIST_GENERATORS) ############################################################################## # # Recipe: Compiling $(SHELL_FILES), $(PERL_FILES) and $(PYTHON_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_shell_files: @[ "X$(SHELL_FILES)" = X ] || { \ $(MAKE) $(SHELL_FILES); \ } compile: compile_perl_files compile_perl_files: @[ "X$(PERL_FILES)" = X ] || { \ $(MAKE) $(PERL_FILES); \ } %: %.pl cat $< > $@ chmod a+x $@ compile: compile_python_files compile_python_files: @[ "X$(PYTHON_FILES)" = X ] || { \ $(MAKE) $(PYTHON_FILES); \ } %: %.py cat $< > $@ chmod a+x $@ compile: compile_man1_files compile_man2_files compile_man3_files compile_man4_files compile_man5_files compile_man6_files compile_man7_files compile_man8_files compile_man1_files: @[ "X$(MAN1_FILES)" = X ] || { \ $(MAKE) $(patsubst %,%.1,$(MAN1_FILES)); \ } compile_man2_files: @[ "X$(MAN2_FILES)" = X ] || { \ $(MAKE) $(patsubst %,%.2,$(MAN2_FILES)); \ } compile_man3_files: @[ "X$(MAN3_FILES)" = X ] || { \ $(MAKE) $(patsubst %,%.3,$(MAN3_FILES)); \ } compile_man4_files: @[ "X$(MAN4_FILES)" = X ] || { \ $(MAKE) $(patsubst %,%.4,$(MAN4_FILES)); \ } compile_man5_files: @[ "X$(MAN5_FILES)" = X ] || { \ $(MAKE) $(patsubst %,%.5,$(MAN5_FILES)); \ } compile_man6_files: @[ "X$(MAN6_FILES)" = X ] || { \ $(MAKE) $(patsubst %,%.6,$(MAN6_FILES)); \ } compile_man7_files: @[ "X$(MAN7_FILES)" = X ] || { \ $(MAKE) $(patsubst %,%.7,$(MAN7_FILES)); \ } compile_man8_files: @[ "X$(MAN8_FILES)" = X ] || { \ $(MAKE) $(patsubst %,%.8,$(MAN8_FILES)); \ } # ADE man pages need to include *only* ADE-related variables and share files, # whereas all other modules' man pages need to include ADE-related variables # and share files *and* their own-related variables and share files. ifeq ($(APP_LCNAME),ade) MODULES = ade else MODULES = ade,$(APP_LCNAME) # help adeass to find -config. compile_man1_files compile_man2_files compile_man3_files compile_man4_files compile_man5_files compile_man6_files compile_man7_files compile_man8_files: export PATH = ../../bin:$(shell echo $$PATH) endif %.1: %.1.ass $(ADEASS_CMD) --format=man --modules=$(MODULES) --comment $< %.2: %.2.ass $(ADEASS_CMD) --format=man --modules=$(MODULES) --comment $< %.3: %.3.ass $(ADEASS_CMD) --format=man --modules=$(MODULES) --comment $< %.4: %.4.ass $(ADEASS_CMD) --format=man --modules=$(MODULES) --comment $< %.5: %.5.ass $(ADEASS_CMD) --format=man --modules=$(MODULES) --comment $< %.6: %.6.ass $(ADEASS_CMD) --format=man --modules=$(MODULES) --comment $< %.7: %.7.ass $(ADEASS_CMD) --format=man --modules=$(MODULES) --comment $< %.8: %.8.ass $(ADEASS_CMD) --format=man --modules=$(MODULES) --comment $< # $(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: clean_shell_files clean_shell_files: @[ "X$(SHELL_FILES)" = X ] || { \ FILES="$(patsubst %.sh, %, $(wildcard $(patsubst %, %.sh, $(SHELL_FILES))))"; \ $(RM) $$FILES; \ } clean: clean_perl_files clean_perl_files: @[ "X$(PERL_FILES)" = X ] || { \ FILES="$(patsubst %.pl, %, $(wildcard $(patsubst %, %.pl, $(PERL_FILES))))"; \ $(RM) $$FILES; \ } clean: clean_python_files clean_python_files: @[ "X$(PYTHON_FILES)" = X ] || { \ FILES="$(patsubst %.py, %, $(wildcard $(patsubst %, %.py, $(PYTHON_FILES))))"; \ $(RM) $$FILES; \ } clean: clean_man1_files clean_man2_files clean_man3_files clean_man4_files clean_man5_files clean_man6_files clean_man7_files clean_man8_files clean_man1_files: @$(RM) $(patsubst %.1.ass,%.1,$(wildcard $(patsubst %,%.1.ass,$(MAN1_FILES)))) clean_man2_files: @$(RM) $(patsubst %.2.ass,%.2,$(wildcard $(patsubst %,%.2.ass,$(MAN2_FILES)))) clean_man3_files: @$(RM) $(patsubst %.3.ass,%.3,$(wildcard $(patsubst %,%.3.ass,$(MAN3_FILES)))) clean_man4_files: @$(RM) $(patsubst %.4.ass,%.4,$(wildcard $(patsubst %,%.4.ass,$(MAN4_FILES)))) clean_man5_files: @$(RM) $(patsubst %.5.ass,%.5,$(wildcard $(patsubst %,%.5.ass,$(MAN5_FILES)))) clean_man6_files: @$(RM) $(patsubst %.6.ass,%.6,$(wildcard $(patsubst %,%.6.ass,$(MAN6_FILES)))) clean_man7_files: @$(RM) $(patsubst %.7.ass,%.7,$(wildcard $(patsubst %,%.7.ass,$(MAN7_FILES)))) clean_man8_files: @$(RM) $(patsubst %.8.ass,%.8,$(wildcard $(patsubst %,%.8.ass,$(MAN8_FILES)))) ############################################################################## # # Installation dependencies and recipes # ############################################################################## # Function to define a generic installation dependency and recipe define install_template install: install_$(5)_files install_$(5)_files: @[ "X$(1)" = X ] || { \ MODESPEC="$(4)"; \ echo "installing $(2) ..." && \ $$(INSTALL_CMD) -D $(3) && \ case $$$$MODESPEC in \ UMASK:*) umask $$$${MODESPEC#UMASK:}; \ $$(INSTALL_CMD) $(2) $(3) ;; \ MODE:*) $$(INSTALL_CMD) -m $$$${MODESPEC#MODE:} $(2) $(3) ;; \ *) $$(INSTALL_CMD) -m $$$$MODESPEC $(2) $(3) ;; \ esac; \ } endef # Way up above are the recipes for *compiling* stuff; PERL_FILES, SHELL_FILES, etc. # Now we do the recipes for *installing* stuff. The variable names refer to # *where they are going*, not what type of file they are. BIN_FILES go to /usr/bin, # LIB_FILES go to /usr/lib or /usr/lib/module, etc. There is just one *cosmetic* # exception to this and that is MAN[1-8]_FILES, which defines *both* what to compile # *and* where to install it. # Function to define a {bin,share,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,$$$$(MAN$(1)_FILES),$$$$(patsubst %, %.$(1), $$$$(MAN$(1)_FILES)),$$$$($$(APP_UCNAME)_MAN$(1)_PREFIX),MODE:644,$(shell echo MAN$(1) | tr '[A-Z]' '[a-z]'))) endef # Generate the installation dependencies and recipes $(eval $(call install_xxx_template,BIN,MODE:755)) $(eval $(call install_xxx_template,SHARE,MODE:644)) $(eval $(call install_xxx_template,LIB,UMASK:022)) $(eval $(call install_man_template,1)) $(eval $(call install_man_template,2)) $(eval $(call install_man_template,3)) $(eval $(call install_man_template,4)) $(eval $(call install_man_template,5)) $(eval $(call install_man_template,6)) $(eval $(call install_man_template,7)) $(eval $(call install_man_template,8)) # etc files to be installed in _ETC_PREFIX. $(eval $(call install_template,$$(ETC_FILES),$$(ETC_FILES),$($(APP_UCNAME)_ETC_PREFIX),MODE:644,etc)) # doc files go in _DOC_PREFIX. $(eval $(call install_template,$$(DOC_FILES),$$(DOC_FILES),$($(APP_UCNAME)_DOC_PREFIX),MODE:644,doc))