Dans mon makefile, j’ai une variable ‘NDK_PROJECT_PATH’, ma question est: comment puis-je l’imprimer quand il comstack?
J’ai lu le fichier Make écho affichant la chaîne “$ PATH” 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 cela ne fonctionne pas pour moi?
Vous pouvez imprimer des variables au fur et à mesure de la lecture du fichier makefile (en supposant que GNU make a correctement balisé cette question) en utilisant cette méthode (avec une variable nommée “var”):
$(info $$var is [${var}])
Vous pouvez append cette construction à n’importe quelle recette pour voir ce que passera au shell:
.PHONY: all all: ; $(info $$var is [${var}])echo Hello world
Maintenant, ce qui se passe ici est que make stocke la recette entière ( $(info $$var is [${var}])echo Hello world
) en tant que variable unique récursivement étendue. Lorsque make décide d’exécuter la recette (par exemple lorsque vous lui dites de générer all
), il étend la variable, puis transmet chaque ligne résultante séparément au shell.
Donc, dans les détails douloureux:
$(info $$var is [${var}])echo Hello world
$(info $$var is [${var}])
$$
devient littéral $
${var}
devient :-)
(dis) $var is [:-)]
apparaît sur la sortie standard $(info...)
est vide echo Hello world
echo Hello world
sur stdout d’abord pour vous faire savoir ce qu’il va demander au shell de faire Hello world
sur stdout. à partir d’un “M. Make post” https://www.cmcrossroads.com/article/printing-value-makefile-variable
Ajoutez la règle suivante à votre fichier Makefile:
print-% : ; @echo $* = $($*)
Ensuite, si vous souhaitez connaître la valeur d’une variable makefile, il vous suffit de:
make print-VARIABLE
et il reviendra:
VARIABLE = the_value_of_the_variable
Comme ‘bobbogo’ dans la réponse ci-dessus a indiqué et selon le manuel GNU Make , vous pouvez utiliser info / warning / error pour afficher le 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 “erreur”, l’exécution de la commande s’arrête après l’affichage de la chaîne d’erreur
Si vous voulez simplement une sortie, vous voulez utiliser $(info)
par lui-même. Vous pouvez le faire n’importe où dans un fichier Makefile, et cela montrera quand cette ligne est évaluée:
$(info VAR="$(VAR)")
Produira VAR="
chaque fois que make traitera cette ligne. Ce comportement est très dépendant de la position, vous devez donc vous assurer que l’extension $(info)
se produit APRÈS que tout ce qui pourrait modifier $(VAR)
ait déjà eu lieu!
Une option plus générique consiste à créer une règle spéciale pour imprimer la valeur d’une variable. En règle générale, les règles sont exécutées une fois les variables affectées, ce qui vous indique la valeur réellement utilisée. (Cependant, il est possible pour une règle de changer une variable .) Un bon formatage aidera à clarifier à quoi une variable est définie, et la fonction $(flavor)
vous dira quel type de variable est quelque chose. Donc, dans cette règle:
print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
$*
s’étend à la racine correspondant au motif %
dans la règle. $($*)
développe à la valeur de la variable dont le nom est donné par $*
. [
et ]
délimiter clairement l’expansion de la variable. Vous pouvez également utiliser "
et "
ou similaire. $(flavor $*)
vous indique quel type de variable c’est. REMARQUE: $(flavor)
prend un nom de variable et non son extension. Donc, si vous dites make print-LDFLAGS
, vous obtenez $(flavor LDFLAGS)
, ce que vous voulez. $(info text)
fournit une sortie. Faire des impressions de text
sur sa sortie standard comme effet secondaire de l’extension. L’expansion de $(info)
est vide. Vous pouvez penser à cela comme @echo
, mais surtout, il n’utilise pas le shell, vous n’avez donc pas à vous soucier des règles de citation du shell. @true
est là juste pour fournir une commande pour la règle. Sans cela, make affichera aussi print-blah is up to date
. Je pense que @true
rend plus clair que c’est censé être un non-op. En cours d’exécution, vous obtenez
$ make print-LDFLAGS LDFLAGS is a recursive variable set to [-L/Users/...]
Toutes les versions de make
nécessitent que les lignes de commande soient en retrait avec une tabulation (pas d’espace) comme premier caractère de la ligne. Si vous nous monsortingez la règle entière au lieu des deux lignes en question, nous pourrions vous donner une réponse plus claire, mais cela devrait ressembler à ceci:
myTarget: myDependencies @echo hi
où le premier caractère de la deuxième ligne doit être TAB.
@echo $ (NDK_PROJECT_PATH) est le bon moyen de le faire. Je ne pense pas que l’erreur vienne de là. Généralement, cette erreur apparaît lorsque vous avez mal écrit l’intention: je pense que vous avez des espaces où vous devriez avoir un onglet.
Exécuter make -n
; il vous montre la valeur de la variable ..
Makefile …
all: @echo $(NDK_PROJECT_PATH)
Commander:
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 soient largement superflues), mais pas avant le @echo PATH=$(PATH)
.
Le problème est que la ligne commençant par all
devrait avoir un signe deux-points ou un égal =
pour indiquer qu’il s’agit d’une ligne cible ou d’une macro-ligne, et que le séparateur est absent.
L’action faisant écho à la valeur d’une variable doit être associée à une cible, éventuellement une cible factice ou PHONEY. Et cette ligne cible doit avoir un deux-points. Si vous ajoutez un :
après all
dans l’exemple makefile
et remplacez les blancs en début de ligne sur la ligne suivante par un onglet, cela fonctionnera de manière très sécurisée.
Vous avez probablement un problème analogue près de la ligne 102 dans le makefile
origine. Si vous avez affiché 5 lignes non vides et sans commentaire avant les opérations d’écho qui échouent, il serait probablement possible de terminer le diagnostic. Cependant, étant donné que la question a été posée en mai 2013, il est peu probable que le makefile
soit toujours disponible (août 2014). Cette réponse ne peut donc pas être validée officiellement. Il ne peut être utilisé que pour illustrer une manière plausible dans laquelle le problème est survenu.
Le problème est que echo ne fonctionne que sous un bloc d’exécution. c’est-à-dire après “xx:”
Donc, tout ce qui est au-dessus du premier bloc d’exécution est juste une initialisation, donc aucune commande d’exécution ne peut être utilisée.
Donc, créez un bloc d’exécution
Pour imprimer la valeur d’une variable, vous pouvez utiliser:
rule: @echo $(VAR_NAME)
Lorsque la règle s’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 fichier makefile complexe. En suivant la même technique que celle décrite dans une autre réponse , vous pouvez insérer ce qui suit dans un fichier 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
Vous pouvez alors faire “make print” pour vider 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 append 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 requirejs dans la ligne de commande en utilisant CTRL-V, TAB
exemple Makefile from above:
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 (mka) @echo $(NDK_PROJECT_PATH)
ne fonctionnera pas et vous donnera une erreur *** missing separator. Stop."
*** missing separator. Stop."
Utilisez cette réponse si vous essayez d’imprimer des variables dans Android
NDK_PROJECT_PATH := some_value $(warning $(NDK_PROJECT_PATH))
ça a fonctionné pour moi