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.
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 leoverride
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 utilisezoverride
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.
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
Dites que vous avez un makefile comme ceci:
action:
echo argument is $(argument)
Vous l'appelleriez alors make action argument=something
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.
export ROOT_DIR=<path/value>
Ensuite, utilisez la variable, $(ROOT_DIR)
dans le Makefile.
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
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
oumake 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)