Makefile中的函数

时间:2009-02-03 15:47:53

标签: bash function makefile gnu-make

我正在编写一个包含大量重复内容的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可以是基于参数执行上述代码的函数。有谁知道我怎么能做到这一点?

2 个答案:

答案 0 :(得分:38)

您正在寻找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)

但是,如果您可以重新构建Makefile,那么您应该看看是否可以使用make的{​​{3}}代替sh

答案 1 :(得分:37)

有3个相关概念:

  1. call function
  2. multi-line variables
  3. conditionals
  4. 重构结果可能如下所示:

    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),"...")
    

    剩下的一个\是继续shell的$(MAKE)行。 这里不需要多行变量,因为它只是一行shell代码。 多行变量仅用于else块。

    如果您不需要参数,可以使用:=赋值,只需使用$(compile)扩展方法(参见canned recipes

    [编辑] 注意:使用版本3.82之前的make,我在define语句的末尾无法识别=。我使用define compile来修复此问题。