Puis-je transmettre des variables à un Makefile GNU comme arguments de ligne de commande? En d'autres termes, je veux passer des arguments qui finiront par devenir des variables dans le Makefile.Passer des variables supplémentaires de la ligne de commande à
Répondre
Vous avez plusieurs options pour configurer des variables de l'extérieur de votre makefile:
De l'environnement - chaque variable d'environnement est transformé en une variable makefile avec le même nom et la valeur.
Vous pouvez également définir l'option
-e
(alias--environments-override
) sur, et vos variables d'environnement redéfinirez cessions effectuées dans makefile (à moins que ces affectations utilisent eux-mêmes leoverride
directive. Cependant, on ne recommande pas, et il est beaucoup mieux et flexible utiliser?=
affectation (l'opérateur d'affectation variable conditionnelle, il a seulement un effet si la variable 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 fixée dans un makefile, ou par défaut/bin/sh
(justification: les commandes sont spécifiées au sein du makefile, et ils sont spécifiques à la coquille).
ligne de commande-
make
peut accepter des affectations variables dans le cadre de sa ligne de commande, mêlée à des cibles:make target FOO=bar
Mais toutes les affectations à la variable
FOO
dans le makefile seront ignorés sauf si vous utilisez leoverride
directive dans l'affectation. (L'effet est le même que pour l'option-e
pour les variables d'environnement).Exportation du parent Faire - si vous appelez faire à partir d'un Makefile, vous écrivez doit généralement pas explicitement les affectations de variables comme celui-ci:
# Don't do this! target: $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
Au lieu de cela, une meilleure solution pourrait consister à 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 toutes les variables à l'aide
export
sans arguments.
La façon la 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: Communicating Variables to a Sub-make
par sous-fait vous voulez dire aux makefiles 'inclus' dans le makefile principal? – Pablo
@Michael: Cela signifie appeler make depuis l'intérieur du makefile. J'ai mis à jour ma réponse puisque vous semblez être intéressé par ce détail. –
De l'manual:
Les variables de la marque 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.
Alors vous pouvez faire (de bash):
FOOBAR=1 make
entraînant une variable FOOBAR
dans votre Makefile.
Si vous faites un fichier appelé Makefile et ajouter une variable comme cette $ (unittest) alors vous serez en mesure d'utiliser cette variable dans le Makefile même avec des jokers
exemple:
make unittest=*
J'utilise BOOST_TEST et en donnant un caractère générique au paramètre --run_test = $ (unittest) alors, je vais pouvoir utiliser une expression régulière pour filtrer le test que je veux que mon Makefile courir
Il existe 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 donne l'exemple:
archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
+touch archive.a
+ranlib -t archive.a
else
ranlib archive.a
endif
Il consiste à vérifier si un paramètre donné apparaît dans MAKEFLAGS
. Par exemple ... supposons que vous étudiez des threads en 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 compiler un à la fois et exécutez-le si un drapeau est spécifié (-r
, par exemple).Ainsi, vous pourriez trouver la Makefile
suivante:
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 avez:
- construire et exécuter un fichier w/
make -r class02
; - construire tout w/
make
oumake all
; - construire et exécuter tous les w/
make -r
(supposons que tous contiennent une certaine sorte de assert choses et vous voulez juste les tester)
export ROOT_DIR=<path/value>
utiliser la variable, $(ROOT_DIR)
dans le Makefile .
pour passer de la ligne de commande quelque chose avec des espaces faire '' faire A = '' comme df '' ' –
On dirait que vous demandez des problèmes si vous vous souciez des variables d'environnement. D'une part, c'est un cauchemar de débogage si cela fonctionne à l'endroit A et non à l'endroit B, juste parce qu'ils ont des environnements différents. –
Il est en fait orthographié --environment-overrides – user7610