web-dev-qa-db-fra.com

Utilisation de règles conditionnelles dans un makefile

Je capture l'intention du Makefile en pseudo-code, puis j'indique les problèmes que j'ai. Je recherche un Makefile plus convivial dans un environnement de test. L'utilisation correcte du Makefile est l'une des suivantes.

    make CATEGORY=parser TEST=basic.
    make ALL

Si un utilisateur donne à "JUST" les commandes comme indiqué ci-dessous, il doit imprimer un message disant "TEST défini par CATÉGORIE non défini" et vice-versa

    make CATEGORY=parser
    make TEST=basic

J'ai essayé d'écrire le Makefile de la manière suivante, mais il contient des erreurs:

    help:
        echo"Usage: make CATEGORY=<advanced|basic> TEST=<test-case>
        echo"       make ALL

    ifdef CATEGORY
        ifdef TEST
            CATEGORY_TEST_DEFINED = 1
        else
             echo "TEST not defined"
    else
        echo "CATEGORY not defined"
    endif



    ifeq ($(CATEGORY_TEST_DEFINED), 1)
    $(CATEGORY):
        cd $(PROJ)/$(CATEGORY)
        make -f test.mk $(TEST)
    endif

    ifdef ALL
    $(ALL):
         for i in `ls`
         cd $$(i)
         make all
    endif

Les questions que j'ai sont:

  1. Indique si les règles d'un Makefile peuvent être sélectives (en utilisant ifdef pour sélectionner les règles et les cibles).

  2. l'écho ne fonctionne pas. l'écho devrait aider l'utilisateur à utiliser correctement.

14
Mike

Le problème est que echo appartient au Shell; Make peut le passer au Shell dans une commande, mais Make ne peut pas l'exécuter. Utilisez à la place info:

ifdef CATEGORY
$(info CATEGORY defined)
else
$(info CATEGORY undefined)
endif

Si vous souhaitez que les règles soient conditionnelles:

ifdef CATEGORY
ifdef TEST
$(CATEGORY):
    whatever
else
$(info TEST not defined)
else
$(info CATEGORY not defined)
endif
20
Beta

Ces lignes sont douteuses:

help:
    echo"Usage: make CATEGORY=<advanced|basic> TEST=<test-case>
    echo"       make ALL

Vous avez besoin d'un espace entre echo et la chaîne, et la chaîne doit être terminée:

help:
    echo "Usage: make CATEGORY=<advanced|basic> TEST=<test-case>"
    echo "       make ALL"

Ces lignes sont douteuses:

ifdef CATEGORY
    ifdef TEST
        CATEGORY_TEST_DEFINED = 1
    else
         echo "TEST not defined"
else
    echo "CATEGORY not defined"
endif

Vous avez sûrement besoin d'un endif avant le deuxième else? (Même si ce n'est pas syntaxiquement obligatoire, je le recommanderais.)

ifdef CATEGORY
    ifdef TEST
        CATEGORY_TEST_DEFINED = 1
    else
         echo "TEST not defined"
    endif
else
    echo "CATEGORY not defined"
endif

De plus, make exécute uniquement des commandes telles que echo est censée être lors du traitement d'une cible (règle). Il n'y exécutera pas echo; il objectera simplement que vous ne pouvez pas définir de commandes sans qu'elles soient des actions pour une cible. Malgré tout ce que GNU Make ajoute à un makefile, le langage dans un makefile est un langage déclaratif et non un langage procédural.


Une autre façon de gérer cela est de définir des valeurs par défaut pour les macros:

CATEGORY = advanced
TEST     = all

Définissez des valeurs par défaut qui font quelque chose de semi-raisonnable; laissez l'utilisateur remplacer la valeur par défaut s'il le souhaite. Vous pouvez avoir une règle telle que:

${CATEGORY}/${TEST}: ...dependencies...
    ...actions...

Vous pouvez laisser help comme première règle. J'ai quelques répertoires où la première règle est:

null:
    @echo "You must specify a target with this makefile!"

C'est équivalent à ce que vous avez (sauf que make ne fait pas écho à la commande avant de l'exécuter, donc je ne vois que le message au lieu de la ligne de commande echo et le message; c'est le @ au travail). Le makefile dont il provient a également une règle all qui est généralement la première règle (par défaut) la plus sensée.

3
Jonathan Leffler