52

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

4

2 回答 2

40

有3个相关概念:

  1. call功能
  2. 多行变量
  3. 条件句

重构后的结果可能如下所示:

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的行。这里不需要多行变量,因为它只是一行 shell 代码。多行变量仅在 else 块中使用。

如果您不需要参数,您可以使用 := 分配并使用扩展方法$(compile)(参见罐头食谱

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

于 2012-12-22T02:17:34.077 回答
39

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

于 2009-02-03T15:59:59.113 回答