Question Passer des variables supplémentaires à partir de la ligne de commande pour faire


Puis-je transmettre des variables à un fichier Make GNU sous forme d'arguments de ligne de commande? En d'autres termes, je veux passer des arguments qui finiront par devenir des variables dans le Makefile.


422
2018-05-13 10:31


origine


Réponses:


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 avec le même nom et la même valeur.

    Vous pouvez également définir -e option (aka --environments-override), et vos variables d’environnement remplaceront les affectations effectuées dans le fichier makefile (à moins que ces affectations ne override directif . Cependant, il n'est pas recommandé, et il est beaucoup mieux et flexible d'utiliser ?= affectation (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
    • SHELL est soit défini dans un makefile, soit défini par défaut sur /bin/sh (justification: les commandes sont spécifiées dans le fichier makefile, et elles sont spécifiques au shell).
  • De la ligne de commande - make peut prendre des affectations variables dans le cadre de sa ligne de commande, mélangé avec des cibles:

    make target FOO=bar
    

    Mais alors toutes les affectations à FOO variable dans le makefile sera ignorée sauf si vous utilisez le override directif en affectation. (L'effet est le même qu'avec -e option pour les variables d'environnement).

  • Exporter depuis le parent - Si vous appelez Make à partir d'un Makefile, vous ne devriez généralement pas écrire explicitement des 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 le fait dans l'environnement de chaque invocation de shell, et les appels à partir de ces commandes choisissent ces variables d'environnement comme indiqué ci-dessus.

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

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


524
2018-05-13 10:57



Le moyen le plus simple est:

make foo=bar target

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

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


133
2018-05-13 10:38



Disons que vous avez un makefile comme celui-ci:

action:
    echo argument is $(argument)

Tu l'appellerais alors make action argument=something


43
2018-05-13 10:38



Du Manuel:

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

Donc vous pouvez faire (depuis bash):

FOOBAR=1 make

résultant en une variable FOOBAR dans votre Makefile.


16
2018-05-13 10:38



Si vous créez un fichier appelé Makefile et ajoutez une variable comme this $ (unittest) alors 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) alors je serai en mesure d'utiliser l'expression régulière pour filtrer le test que je veux mon Makefile courir


2
2018-03-08 13:29



export ROOT_DIR=<path/value>

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


2
2018-01-07 16:03



Il y a une autre option non citée ici qui est incluse dans le livre Make de GNU par 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 de c ++ 11 et que vous ayez divisé votre étude en plusieurs fichiers (class01, ..., classNM) et que vous voulez: compiler tout et exécuter individuellement ou en compiler un à la fois et l'exécuter si un indicateur est spécifié (-r, par exemple). Donc, vous pourriez venir avec 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 auriez:

  • construire et exécuter un fichier w / make -r class02;
  • construire tout w / make ou make all;
  • construire et courir tout w / make -r (supposons que tous contiennent un certain type d’affirmation et que vous voulez juste les tester tous)

1
2018-05-21 02:53