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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:55:21  来源:igfitidea点击:

Functions in Makefile

bashfunctionmakefilegnu-make

提问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个相关概念:

  1. callfunction
  2. multi-line variables
  3. conditionals
  1. call功能
  2. 多行变量
  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 compileinstead.

[编辑]注意:使用 3.82 版之前的 make,在我的定义语句末尾无法识别 =。我通过使用define compile来解决这个问题。

回答by ephemient

You're looking for the callfunction.

您正在寻找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 Makefilea bit, though, you should see if you can use make's conditionalsinstead of sh's.

但是,如果您可以Makefile稍微重组一下,您应该看看是否可以使用make's条件而不是sh's。