Функции в Makefile - PullRequest
       9

Функции в Makefile

47 голосов
/ 03 февраля 2009

Я пишу 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 ]

38 голосов
/ 03 февраля 2009

Вы ищете функцию 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.

37 голосов
/ 22 декабря 2012

Есть 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) для оболочки. Здесь не требуется многострочная переменная, потому что это всего лишь одна строка кода оболочки. Многострочные переменные используются только в блоке else.

Если вам не нужны параметры, вы можете использовать: = назначение и просто расширить метод с помощью $(compile) (см. консервированные рецепты )

[Редактировать] Примечание: При использовании make до версии 3.82 символ = не был распознан в конце оператора define для меня. Я исправил это, используя define compile.

...