bash Makefile 中的函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/507641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Functions in Makefile
提问by Karl Yngve Lerv?g
I am writing a Makefile with a lot of repetitive stuff, e.g.
我正在编写一个包含很多重复内容的 Makefile,例如
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 ''). Since this is a huge amount of redundant code, I would like to be able to write it in a more simple manner. E.g., I would like to do something like this:
在定义目标 'syst' 的地方,定义了变量 'UNAME'(通常是 Linux,但也可能是 Cygwin 或 OSF1)并且还定义了变量 'difort' 和 'err_arch'。这段代码被多次用于不同的编译器目标(使用命名约定 '')。由于这是大量的冗余代码,我希望能够以更简单的方式编写它。例如,我想做这样的事情:
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?
其中 compile 可能是一个函数,根据参数执行上面的代码。有谁知道我怎么能做到这一点?
采纳答案by JonnyJD
There are 3 related concepts:
有3个相关概念:
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.
这一个\
剩下的就是继续$(MAKE)
为外壳线。这里不需要多行变量,因为它只是一行 shell 代码。多行变量仅在 else 块中使用。
If you don't need parameters you can use := assignment and just expand the method with $(compile)
(see canned recipes)
如果您不需要参数,您可以使用 := assignment 并使用$(compile)
(参见罐头食谱)扩展方法
[Edit]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.
[编辑]注意:使用 3.82 版之前的 make,在我的定义语句末尾无法识别 =。我通过使用define compile
来解决这个问题。
回答by ephemient
You're looking for the call
function.
您正在寻找call
功能。
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 conditionalsinstead of sh
's.
但是,如果您可以Makefile
稍微重组一下,您应该看看是否可以使用make
's条件而不是sh
's。