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.
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 scriptShell
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.
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
Disons que vous avez un fichier makefile comme ceci:
action:
echo argument is $(argument)
Vous l'appelleriez alors make action argument=something
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.
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:
make -r class02
;make
ou make all
;make -r
(supposez qu’ils contiennent tous un certain type d’affirmation et vous voulez juste les tester tous)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
export ROOT_DIR=<path/value>
Utilisez ensuite la variable $(ROOT_DIR)
dans le Makefile.