Functions in Makefile
BashFunctionMakefileGnu MakeBash Problem Overview
I am writing a Makefile with a lot of repetitive stuff, e.g.
debug_ifort_Linux:
if [ $(UNAME) = Linux ]; then \
$(MAKE) FC=ifort FFLAGS=$(difort) PETSC_FFLAGS="..." \
TARGET=$@ LEXT="ifort_$(UNAME)" -e syst; \
else \
echo $(err_arch); \
exit 1; \
fi
where the target 'syst' is defined, the variable 'UNAME' is defined (and is usually Linux, but might also by Cygwin or OSF1) and the variables 'difort' and 'err_arch' are also defined. This block of code is used very many times for different compiler targets (using a name convention of '
debug_ifort_Linux:
compile(uname,compiler,flags,petsc_flags,target,lext)
where compile could be a function doing the code above based on the arguments. Does anyone have any idea how I could accomplish this?
Bash Solutions
Solution 1 - Bash
There are 3 related concepts:
The refactored result could look like this:
ifeq ($(UNAME),Linux)
compile = $(MAKE) FC=$(1) FFLAGS=$(2) PETSC_FFLAGS=$(3) \
TARGET=$@ LEXT="$(1)_$(UNAME)" -e syst
else
define compile =
echo $(err_arch)
exit 1
endef
endif
debug_ifort:
$(call compile,ifort,$(difort),"...")
That one \
that is left is to continue the $(MAKE)
line for the shell.
No multi-line variable is necessary here, because it is just one line of shell code.
Multi-line variables are only used in the else block.
If you don't need parameters you can use := assignment and just expand the method with $(compile)
(see canned recipes)
Note: Using make prior to version 3.82, the = was not recognized at the end of the define statement for me. I fixed this by using define compile
instead.
Solution 2 - Bash
You're looking for the http://www.gnu.org/software/make/manual/html_node/Call-Function.html">`call` function.
compile = \
if [ $(UNAME) = $(1) ]; then \
$(MAKE) FC=$(2) FFLAGS=$(3) PETSC_FFLAGS="..." \
TARGET=$@ LEXT="$(4)_$(UNAME)" -e syst; \
else \
echo $(err_arch); \
exit 1; \
fi
debug_ifort_Linux:
$(call compile,Linux,ifort,$(difort),ifort)
If you can restructure your Makefile
a bit, though, you should see if you can use make
's http://www.gnu.org/software/make/manual/html_node/Conditional-Syntax.html">conditionals</a> instead of sh
's.