52 votes

Fonctions dans le Makefile

Je suis en train d'écrire un Makefile avec beaucoup de trucs répétitifs, par exemple

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

où la cible 'syst' est défini, la variable 'UNAME' est défini (et est généralement de Linux, mais aussi par Cygwin ou OSF1) et les variables 'difort" et "err_arch" sont également définis. Ce bloc de code est utilisé plusieurs fois pour différents compilateur cibles (à l'aide d'un nom de convention de ''). Puisque c'est une énorme quantité de code redondant, j'aimerais être capable d'écrire de la plus simple manière. E. g., Je voudrais faire quelque chose comme ceci:

debug_ifort_Linux:
        compile(uname,compiler,flags,petsc_flags,target,lext)

où compiler pourrait être une fonction de code ci-dessus en fonction sur les arguments. Quelqu'un aurait-il une idée de comment je pourrais y arriver?

40voto

JonnyJD Points 1100

Il y a 3 concepts associés:

  1. call fonction
  2. multi-variables en ligne
  3. conditions

La refonte du résultat pourrait ressembler à ceci:

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

Que l'on \ qui reste, c'est de continuer l' $(MAKE) ligne pour le shell. Pas de multi-ligne variable est nécessaire ici, parce que c'est juste une ligne de code carapace. Multi-variables en ligne ne sont utilisées que dans le bloc else.

Si vous n'avez pas besoin de paramètres que vous pouvez utiliser : affectation= et étendre la méthode avec $(compile) (voir recettes de conserves)

[Edit] Note: à l'Aide rendre les versions antérieures à la version 3.82, l' = n'a pas été reconnu à la fin de l'instruction define pour moi. J'ai corrigé cela en utilisant define compile à la place.

39voto

ephemient Points 87003

Vous recherchez la fonction 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)
 

Si vous pouvez restructurer votre Makefile un peu, cependant, vous devriez voir si vous pouvez utiliser make 's conditionals au lieu de sh s'.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X