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?

170
demandé sur Community 2013-05-09 21:35:20

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 $(info $$var is [${var}])echo Hello world
  • 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
  • le shell imprime Hello world sur stdout.
158
répondu bobbogo 2018-06-20 18:35:57

à 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
107
répondu Anthony Earl Wong 2014-09-12 22:46:16

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

100
répondu tsenapathy 2018-09-12 10:16:57

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 dites make print-LDFLAGS , vous obtenez $(flavor LDFLAGS) , qui est ce que vous voulez.
  • $(info text) fournit la sortie. Make prints text 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 aussi print-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/...]
38
répondu Jim Nasby 2017-11-01 15:24:28

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.

6
répondu MadScientist 2013-05-09 23:35:43

@echo $(NDK_PROJECT_PATH) est la bonne façon de le faire. Je ne pense pas que l'erreur vient de là. Généralement, cette erreur apparaît lorsque vous avez mal tapé l'intendation : je pense que vous avez des espaces où vous devriez avoir un onglet.

5
répondu 2013-05-09 17:45:31

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
5
répondu ivandcl 2014-08-12 23:32:19

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.

3
répondu Jonathan Leffler 2014-08-12 23:28:59

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

2
répondu Andy 2015-12-04 17:56:56

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.

1
répondu Samuel 2014-12-31 00:33:14

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
1
répondu Idelic 2017-05-23 12:10:46

pas besoin de modifier le Makefile.

$ cat printvars.mak
print-%:
        @echo '$*=$($*)'

$ cd /to/Makefile/dir
$ make -f ~/printvars.mak -f Makefile print-VARIABLE
1
répondu Talespin_Kit 2018-02-14 07:49:28

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
0
répondu Wade 2017-03-06 23:00:12

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

0
répondu mjalil 2017-05-23 12:34:51