我正在编写一个包含大量重复内容的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
在定义目标'syst'的地方,定义了变量'UNAME'(通常是Linux,但也可能是Cygwin或OSF1),并且还定义了变量'difort'和'err_arch'.这段代码对于不同的编译器目标使用了很多次(使用名称约定'").由于这是一个庞大的冗余代码,我希望能够以更简单的方式编写它.例如,我想做这样的事情:
debug_ifort_Linux: compile(uname,compiler,flags,petsc_flags,target,lext)
其中compile可以是一个基于参数执行上述代码的函数.有谁知道我怎么能做到这一点?
有3个相关概念:
call
功能
多行变量
条件语句
重构的结果可能如下所示:
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),"...")
这一个\
剩下的就是继续$(MAKE)
为外壳线.这里不需要多行变量,因为它只是一行shell代码.多行变量仅用于else块.
如果您不需要参数,可以使用:=赋值,只需展开方法$(compile)
(参见罐装食谱)
[编辑] 注意:使用版本3.82之前的make,我在define语句的末尾无法识别=.我通过define compile
改为使用来修复此问题.
你正在寻找这个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)
如果你能调整你的Makefile
有点,但是,你应该看到,如果你能使用make
的条件句,而不是sh
的.