Passer des variables supplémentaires de la ligne de commande à make

Puis-je passer des variables à un Makefile GNU en tant qu'arguments de ligne de commande? En d'autres termes, je veux passer quelques arguments qui deviendront éventuellement des variables dans le Makefile.

438
demandé sur pillravi 2010-05-13 14:31:50

7 réponses

Vous avez plusieurs options pour configurer des variables à partir de l'extérieur de votre makefile:

  • From environment - chaque variable d'environnement est transformée en une variable makefile avec le même nom et la même valeur.

    Vous pouvez également définir l'option -e (aka --environments-override) sur, et vos variables d'environnement remplaceront les affectations faites dans makefile (à moins que ces affectations elles-mêmes utilisent le override directive . Cependant, il n'est pas recommandé, et c'est beaucoup meilleur et flexible à utiliser ?= assignment (l'opérateur d'affectation de variable conditionnelle, il n'a d'effet que si la variable n'est pas encore définie):

    FOO?=default_value_if_not_set_in_environment
    

    Notez que certaines variables ne sont pas héritées de l'environnement:

    • MAKE est obtenu à partir du nom du script
    • {[9] } est défini dans un makefile, ou par défaut /bin/sh (justification: les commandes sont spécifiées dans le makefile, et elles sont spécifiques au shell).
  • À Partir de ligne de commande - make peut prendre des affectations de variables dans le cadre de sa ligne de commande, mêlée à des cibles:

    make target FOO=bar
    

    Mais alors toutes les affectations à la variable FOO dans le makefile seront ignorées sauf si vous utilisez override directive {[26] } en cession. (L'effet est le même qu'avec l'option -e pour les variables d'environnement).

  • Exporter à partir du parent Make - si vous appelez Make à partir D'un Makefile, vous ne devriez généralement pas explicitement écrivez les affectations de variables comme ceci:

    # Don't do this!
    target:
            $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
    

    Au lieu de cela, une meilleure solution pourrait être d'exporter ces variables. L'exportation d'une variable la rend dans l'environnement de chaque appel de shell, et faire des appels à partir de ces commandes choisir ces variables d'environnement comme spécifié ci-dessus.

    # Do like this
    CFLAGS=-g
    export CFLAGS
    target:
            $(MAKE) -C target
    

    Vous pouvez également exporter toutes les variables en utilisant export sans arguments.

543
répondu P Shved 2013-09-20 21:44:01

Le moyen le plus simple est:

make foo=bar target

, Puis dans votre makefile, vous pouvez vous référer à $(foo). Notez que cela ne se propagera pas automatiquement aux sous-marques.

Si vous utilisez des sous-marques, consultez cet article: communiquer des Variables à une sous-marque

138
répondu Mark Byers 2010-05-13 10:55:40

Dites que vous avez un makefile comme ceci:

action:
    echo argument is $(argument)

Vous l'appelleriez alors make action argument=something

44
répondu nc3b 2010-05-13 10:38:10

Du manuel :

Les Variables de make peuvent provenir de l'environnement dans lequel make est exécuté. Chaque variable d'environnement que make voit au démarrage est transformée en une variable make avec le même nom et la même valeur. Cependant, une affectation explicite dans le makefile, ou avec un argument de commande, remplace l'environnement.

Donc vous pouvez faire (de bash):

FOOBAR=1 make

Résultant en une variable FOOBAR dans votre Makefile.

16
répondu Thomas 2010-05-13 10:38:17
export ROOT_DIR=<path/value>

Ensuite, utilisez la variable, $(ROOT_DIR) dans le Makefile.

3
répondu parasrish 2016-01-07 16:03:31

Si vous créez un fichier appelé Makefile et ajoutez une variable comme celle-ci $(unittest) ensuite, vous pourrez utiliser cette variable dans le Makefile même avec des caractères génériques

Exemple :

make unittest=*

J'utilise BOOST_TEST et en donnant un caractère générique au paramètre --run_test=$(unittest) ensuite, je serai en mesure d'utiliser l'expression régulière pour filtrer le test que je veux mon Makefile pour exécuter

2
répondu serup 2014-03-08 13:29:37

Il y a une autre option non citée ici qui est incluse dans le livre GNU Make de Stallman et McGrath (voir http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_7.html ). Il fournit l'exemple:

archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
        +touch archive.a
        +ranlib -t archive.a
else
        ranlib archive.a
endif

Cela implique de vérifier si un paramètre donné apparaît dans MAKEFLAGS. Exemple .. supposons que vous étudiez les threads en C++11 et que vous avez divisé votre étude sur plusieurs fichiers (class01, ... , classNM) et vous voulez: compiler puis tout et exécuter individuellement ou compiler et l'exécuter si un indicateur est spécifié (-r, par exemple). Donc, vous pouvez trouver ce qui suit Makefile:

CXX=clang++-3.5
CXXFLAGS = -Wall -Werror -std=c++11
LDLIBS = -lpthread

SOURCES = class01 class02 class03

%: %.cxx
    $(CXX) $(CXXFLAGS) -o $@.out $^ $(LDLIBS)
ifneq (,$(findstring r,  $(MAKEFLAGS)))
    ./$@.out
endif

all: $(SOURCES)

.PHONY: clean

clean:
    find . -name "*.out" -delete

Ayant cela, vous feriez:

  • construire et exécuter un fichier w/ make -r class02;
  • construire tous les w/ make ou make all;
  • construisez et exécutez tous w / make -r (supposons que tous contiennent un certain type de choses assert et que vous voulez juste les tester tous)
1
répondu Ciro Costa 2015-05-21 02:53:20