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

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 deviendront éventuellement des variables dans le Makefile.

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 l’option -e (aka --environments-override ) et vos variables d’environnement remplaceront les affectations faites dans makefile (à moins que ces affectations elles-mêmes n’utilisent la directive override . Cependant, ce n’est pas recommandé et c’est beaucoup mieux et flexible pour utiliser ?= assignation (l’opérateur d’assignation de variable conditionnelle, cela 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 défini par défaut sur /bin/sh (justification: les commandes sont spécifiées dans le fichier Make, et elles sont spécifiques au shell).
  • A partir de la ligne de commandemake peut prendre des assignations de variables dans le cadre de sa ligne de commande, avec des cibles:

     make target FOO=bar 

    Cependant, toutes les affectations à la variable FOO dans le fichier Make seront ignorées à moins que vous n’utilisiez la directive de override dans l’affectation. (L’effet est le même qu’avec l’option -e pour les variables d’environnement).

  • Exportation à partir du parent Make – si vous appelez Make depuis un Makefile, vous ne devez 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 entre dans l’environnement de chaque invocation de shell, et les appels à partir de ces commandes sélectionnent la variable d’environnement spécifiée ci-dessus.

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

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

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 propagera pas automatiquement aux sous-marques.

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

Disons que vous avez un makefile comme celui-ci:

 action: echo argument is $(argument) 

Vous appelez alors cela make action argument=something

A partir du manuel :

Les variables de make peuvent provenir de l’environnement dans lequel make est exécuté. Chaque variable d’environnement qui fait apparaître lorsqu’elle est démarrée est transformée en une variable make avec 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 (de bash):

 FOOBAR=1 make 

résultant en une variable FOOBAR dans votre Makefile.

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

 export ROOT_DIR= 

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

Il existe une autre option non citée 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 (,$(findssortingng 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: comstackr tous et exécuter individuellement ou en comstackr un à la fois et l’exécuter si un indicateur est spécifié ( -r , par exemple). Donc, vous pouvez créer le Makefile suivant:

 CXX=clang++-3.5 CXXFLAGS = -Wall -Werror -std=c++11 LDLIBS = -lpthread SOURCES = class01 class02 class03 %: %.cxx $(CXX) $(CXXFLAGS) -o $@.out $^ $(LDLIBS) ifneq (,$(findssortingng 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 exécuter tous les w / make -r (supposons que tous contiennent un certain type de choses d’affirmation et que vous voulez juste les tester toutes)