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)ここではシェル コードの 1 行にすぎないため、複数行の変数は必要ありません。複数行の変数は、else ブロックでのみ使用されます。

パラメータが必要ない場合は、:= 割り当てを使用して、メソッドを拡張するだけです$(compile)(缶詰のレシピを参照してください) 。

注:バージョン 3.82 より前の make を使用すると、define ステートメントの最後にある = が認識されませんでした。define compile代わりに使用してこれを修正しました。

于 2012-12-22T02:17:34.077 に答える