web-dev-qa-db-fra.com

Passer des variables supplémentaires depuis la ligne de commande pour créer

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

519
Pablo

Vous avez plusieurs options pour configurer des variables en dehors de votre makefile:

  • De l'environnement - chaque variable d'environnement est transformée en une variable makefile de même nom et de même valeur.

    Vous pouvez également vouloir définir l’option -e (alias --environments-override) sur, et vos variables d’environnement remplaceront les assignations effectuées dans le fichier makefile (à moins que ces assignations elles-mêmes utilisent la directive override] . mieux et flexible pour utiliser ?= assignation (l'opérateur d'affectation de variable conditionnelle 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
    • Shell est soit défini dans un fichier makefile, soit par défaut à /bin/sh (justification: les commandes sont spécifiées dans le fichier makefile et sont spécifiques à Shell).
  • À partir de la ligne de commande - make peut prendre des assignations de variables comme partie de sa ligne de commande, mélangées à des cibles:

    make target FOO=bar
    

    Mais alors toutes les assignations à la variable FOO du makefile seront ignorées sauf si vous utilisez la directive override dans assignation. (L'effet est identique à celui de l'option -e pour les variables d'environnement).

  • Exporter depuis le parent Make - si vous appelez Make depuis un Makefile, vous ne devriez généralement pas écrire explicitement des affectations de variables comme celles-ci:

    # 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 le fait dans l'environnement de chaque appel du shell et les appels à partir de ces commandes sélectionnent 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 argument.

645
P Shved

Le moyen le plus simple est:

make foo=bar target

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

Si vous utilisez des sous-marques, consultez cet article: Communication de variables en sous-marque

170
Mark Byers

Disons que vous avez un fichier makefile comme ceci:

action:
    echo argument is $(argument)

Vous l'appelleriez alors make action argument=something

59
nc3b

Du manuel :

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

Donc, vous pouvez faire (à partir de bash):

FOOBAR=1 make

résultant dans une variable FOOBAR dans votre Makefile.

19
Thomas

Une autre option non citée ici est incluse dans le GNU Make book 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. Par exemple, supposons que vous étudiez les threads dans c ++ 11 et que vous ayez divisé votre étude en plusieurs fichiers (class01, ..., classNM) et que vous souhaitiez: compiler puis tout et exécuter individuellement ou en compiler un à la fois et exécutez-le si un indicateur est spécifié (-r, par exemple). Donc, vous pourriez arriver avec le Makefile suivant:

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

SOURCES = class01 class02 class03

%: %.cxx
    $(CXX) $(CXXFLAGS) -o [email protected] $^ $(LDLIBS)
ifneq (,$(findstring r,  $(MAKEFLAGS)))
    ./[email protected]
endif

all: $(SOURCES)

.PHONY: clean

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

Ayant cela, vous auriez:

  • construire et exécuter un fichier w/make -r class02;
  • construisez tous w/make ou make all;
  • construisez et exécutez tous les w/make -r (supposez qu’ils contiennent tous un certain type d’affirmation et vous voulez juste les tester tous)
4
Ciro Costa

Si vous créez un fichier appelé Makefile et ajoutez une variable comme ceci $ (unittest), 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), je pourrai alors utiliser une expression régulière pour filtrer le test que je souhaite exécuter avec mon Makefile

3
serup
export ROOT_DIR=<path/value>

Utilisez ensuite la variable $(ROOT_DIR) dans le Makefile.

3
parasrish