Comment imprimer une variable dans makefile
dans mon makefile, j'ai une variable 'NDK_PROJECT_PATH', ma question Est Comment puis-je l'imprimer quand il compile?
j'ai lu Faire fichier affichage echo "$PATH" chaîne et j'ai essayé:
@echo $(NDK_PROJECT_PATH)
@echo $(value NDK_PROJECT_PATH)
les deux me donne
"build-local.mk:102: *** missing separator. Stop."
Quelqu'un sait pourquoi ça ne marche pas pour moi?
14 réponses
vous pouvez imprimer des variables comme le makefile est lu (en supposant que GNU make comme vous avez étiqueté cette question correctement) en utilisant cette méthode (avec une variable appelée "var"):
$(info $$var is [${var}])
vous pouvez ajouter cette construction à n'importe quelle recette pour voir ce que faire passera à la coquille:
.PHONY: all
all: ; $(info $$var is [${var}])echo Hello world
maintenant, ce qui se passe ici est que faire des magasins la recette entière ( $(info $$var is [${var}])echo Hello world
) comme une seule variable étendue récursivement. Quand faire décide d'exécuter la recette (par exemple quand vous lui dites de construire all
), il étend la variable, puis passe chaque ligne résultante séparément à l'interpréteur de commandes.
ainsi, dans les détails douloureux:
- "1519240920 Elle" étend
- pour ce faire, il se dilate d'abord
$(info $$var is [${var}])
-
$$
devient littéral$
-
${var}
devient:-)
(say) - l'effet secondaire est que
$var is [:-)]
apparaît sur la sortie standard - l'expansion du
$(info...)
bien qu'il soit vide
-
- Faire est de gauche avec
echo Hello world
- Faire des tirages
echo Hello world
sur la sortie standard stdout premiers à vous faire savoir ce qu'il va demander au shell de faire
- Faire des tirages
- le shell imprime
Hello world
sur stdout.
$(info $$var is [${var}])echo Hello world
à partir d'un "M. Faire de post" https://www.cmcrossroads.com/article/printing-value-makefile-variable
ajouter la règle suivante à votre Makefile:
print-% : ; @echo $* = $($*)
alors, si vous voulez connaître la valeur d'une variable makefile, juste:
make print-VARIABLE
et il reviendra:
VARIABLE = the_value_of_the_variable
comme "bobbogo" dans la réponse ci-dessus pointée et selon le GNU Make manual , vous pouvez utiliser info / avertissement / d'erreur pour afficher du texte.
$(error text…)
$(warning text…)
$(info text…)
pour imprimer des variables,
$(error VAR is $(VAR))
$(warning VAR is $(VAR))
$(info VAR is $(VAR))
lorsque vous utilisez 'error' l'exécution de make s'arrête après avoir affiché la chaîne d'erreur
si vous voulez simplement une sortie, vous voulez utiliser $(info)
par lui-même. Vous pouvez faire cela n'importe où dans un Makefile, et il affichera quand cette ligne est évaluée:
$(info VAR="$(VAR)")
affichera VAR="<value of VAR>"
chaque fois que make traite cette ligne. Ce comportement est très dépendant de la position, donc vous devez vous assurer que l'expansion $(info)
se produit après tout ce qui pourrait modifier $(VAR)
a déjà eu lieu!
un plus générique option est de créer une règle spéciale pour l'impression de la valeur d'une variable. Généralement parlant, les règles sont exécutées après que les variables sont attribuées, donc cela vous montrera la valeur qui est réellement utilisée. (Bien que, il est possible pour une règle de changer une variable .) Un bon formatage vous aidera à clarifier à quoi une variable est définie, et la fonction $(flavor)
vous indiquera quel type de variable est quelque chose. Ainsi dans cette règle:
print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
-
$*
s'étend à la tige que le%
motif correspond dans la règle. -
$($*)
s'étend à la valeur de la variable dont le nom est donné par$*
. - les
[
et]
délimitent clairement l'expansion de la variable. Vous pouvez également utiliser"
et"
ou similaire. -
$(flavor $*)
vous dit quel type de variable il être. NOTE:$(flavor)
prend une variable nom , et non son expansion. Donc si vous ditesmake print-LDFLAGS
, vous obtenez$(flavor LDFLAGS)
, qui est ce que vous voulez. -
$(info text)
fournit la sortie. Make printstext
sur son stdout comme effet secondaire de l'expansion. L'extension de$(info)
est cependant vide. Vous pouvez y penser comme@echo
, mais surtout, il n'utilise pas la coquille, si vous n'avez pas à vous inquiéter sur les règles de citation de shell. -
@true
est là juste pour fournir une commande pour la règle. Sans que, make produira aussiprint-blah is up to date
. Je pense que@true
rend plus clair que c'est censé être un no-op.
L'exécuter, vous obtenez
$ make print-LDFLAGS
LDFLAGS is a recursive variable set to [-L/Users/...]
toutes les versions de make
exigent que les lignes de commande soient marquées d'un onglet (et non d'un espace) comme premier caractère de la ligne. Si vous nous avez montré toute la règle au lieu de seulement les deux lignes en question nous pourrions donner une réponse plus claire, mais il devrait être quelque chose comme:
myTarget: myDependencies
@echo hi
où le premier caractère de la deuxième ligne doit être TAB.
Exécuter make -n
, il vous montre la valeur de la variable..
Makefile...
all:
@echo $(NDK_PROJECT_PATH)
commande:
export NDK_PROJECT_PATH=/opt/ndk/project
make -n
sortie:
echo /opt/ndk/project
ce makefile
générera le message d'erreur "séparateur manquant":
all
@echo NDK_PROJECT_PATH=$(NDK_PROJECT_PATH)
done:
@echo "All done"
il y a un onglet avant le @echo "All done"
(bien que la règle et l'action done:
soient largement superflues), mais pas avant le @echo PATH=$(PATH)
.
le problème est que la ligne commençant all
devrait avoir soit un deux-points :
ou un égal =
pour indiquer qu'il s'agit d'une ligne cible ou d'une macro ligne, et il n'a ni l'un ni l'autre, donc le séparateur a disparu.
l'action qui fait écho à la valeur d'une variable doit être associée à une cible, peut-être une cible fictive ou fictive. Et cette ligne de cible doit avoir un côlon. Si vous ajoutez un :
après all
dans l'exemple makefile
et remplacez les blancs de tête sur la ligne suivante par un onglet, cela fonctionnera parfaitement.
vous avez probablement un problème analogue près de la ligne 102 dans l'original makefile
. Si vous montré 5 non-blanc, non-commentaire lignes avant les opérations d'écho qui ne fonctionnent pas, il serait probablement possible de terminer le diagnostic. Cependant, puisque la question a été posée en mai 2013, il est peu probable que le makefile
cassé soit encore disponible maintenant (août 2014), de sorte que cette réponse ne peut pas être validée formellement. Elle ne peut être utilisée que pour illustrer une manière plausible dont le problème s'est produit.
le problème est que echo ne fonctionne que sous un bloc d'exécution. c'est-à-dire tout ce qui suit "xx: "
donc tout ce qui se trouve au-dessus du premier bloc d'exécution n'est qu'une initialisation, donc aucune commande d'exécution ne peut être utilisée.
alors créer un bloc d'exécution
Pour imprimer la valeur d'une variable, vous pouvez utiliser:
rule:
<tab>@echo $(VAR_NAME)
quand la règle exécute la variable sera imprimée.
cela peut être fait de manière générique et peut être très utile lors du débogage d'un makefile complexe. Suivant la même technique que celle décrite dans une autre réponse , vous pouvez insérer ce qui suit dans n'importe quel makefile:
# if the first command line argument is "print"
ifeq ($(firstword $(MAKECMDGOALS)),print)
# take the rest of the arguments as variable names
VAR_NAMES := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
# turn them into do-nothing targets
$(eval $(VAR_NAMES):;@:))
# then print them
.PHONY: print
print:
@$(foreach var,$(VAR_NAMES),\
echo '$(var) = $($(var))';)
endif
alors vous pouvez simplement faire "make print" pour Dumper la valeur de n'importe quelle variable:
$ make print CXXFLAGS
CXXFLAGS = -g -Wall
pas besoin de modifier le Makefile.
$ cat printvars.mak
print-%:
@echo '$*=$($*)'
$ cd /to/Makefile/dir
$ make -f ~/printvars.mak -f Makefile print-VARIABLE
si vous ne voulez pas modifier le Makefile lui-même, vous pouvez utiliser --eval
pour ajouter une nouvelle cible, puis exécuter la nouvelle cible, par exemple
make --eval='print-tests:
@echo TESTS $(TESTS)
' print-tests
vous pouvez insérer le caractère TAB requis dans la ligne de commande en utilisant CTRL-V, TAB
exemple de Makefile d'en haut:
all: do-something
TESTS=
TESTS+='a'
TESTS+='b'
TESTS+='c'
do-something:
@echo "doing something"
@echo "running tests $(TESTS)"
@exit 1
si vous utilisez android make (mka) @echo $(NDK_PROJECT_PATH)
ne fonctionnera pas et vous donne erreur *** missing separator. Stop."
utilisez cette réponse si vous essayez d'imprimer des variables dans Android make
NDK_PROJECT_PATH := some_value
$(warning $(NDK_PROJECT_PATH))
qui a fonctionné pour moi