web-dev-qa-db-fra.com

Comment imprimer une variable dans le makefile

Dans mon makefile, j'ai une variable 'NDK_PROJECT_PATH', ma question est de savoir comment puis-je l'imprimer quand il est compilé?

J'ai lu Faire que le fichier echo affiche "$ 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 cela ne fonctionne pas pour moi?

217
michael

Vous pouvez imprimer des variables au fur et à mesure que le makefile est lu (en supposant que GNU make puisque vous avez balisé cette question correctement) en utilisant cette méthode (avec une variable nommée "var"):

$(info $$var is [${var}])

Vous pouvez ajouter cette construction à n'importe quelle recette pour voir ce que make transmettra au shell:

.PHONY: all
all: ; $(info $$var is [${var}])echo Hello world

Maintenant, ce qui se passe ici, c'est que make stocke la recette entière ($(info $$var is [${var}])echo Hello world) sous la forme d'une variable unique développée récursivement. Lorsque make décide d'exécuter la recette (par exemple, lorsque vous lui indiquez de créer all), il développe la variable, puis transmet chaque ligne résultante séparément au shell.

Donc, en détail douloureux:

  • Il se développe $(info $$var is [${var}])echo Hello world
  • Pour ce faire, il étend d'abord $(info $$var is [${var}])
    • $$ devient littéral $
    • ${var} devient :-) (par exemple)
    • L'effet secondaire est que $var is [:-)] apparaît en sortie standard
    • L'expansion de la $(info...) si est vide
  • Make reste avec echo Hello world
    • Faites des impressions echo Hello world sur stdout en premier pour vous dire ce que vous allez demander à Shell de faire.
  • Le shell imprime Hello world sur la sortie standard.
195
bobbogo

à partir d'un "M. Make post" https://www.cmcrossroads.com/article/printing-value-makefile-variable

Ajoutez la règle suivante à votre Makefile:

print-%  : ; @echo $* = $($*)

Ensuite, si vous voulez connaître la valeur d'une variable de makefile, il suffit de:

make print-VARIABLE

et il reviendra:

VARIABLE = the_value_of_the_variable
140
Anthony Earl Wong

Comme 'bobbogo' dans la réponse ci-dessus pointait et conformément au 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 'error', l'exécution du make s'arrête après l'affichage de la chaîne d'erreur

134
tsenapathy

Si vous voulez simplement une sortie, vous voulez utiliser $(info) par lui-même. Vous pouvez le faire n'importe où dans un Makefile, et cela montrera quand cette ligne est évaluée:

$(info VAR="$(VAR)")

Générera VAR="<value of 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) soit déjà arrivé!

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 après l’affectation des variables, ce qui vous indique la valeur réellement utilisée. (Bien que ce soit possible pour une règle de changer une variable .) Une bonne mise en forme aidera à clarifier le paramétrage d'une variable, et la fonction $(flavor) vous indiquera le type de variable. quelque chose est. Donc dans cette règle:

print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
  • $* étend à la tige le modèle % correspondant dans la règle.
  • $($*) étend la valeur de la variable dont le nom est donné par $*.
  • Les [ et ] délimitent clairement le développement des variables. Vous pouvez également utiliser " et " ou similaire.
  • $(flavor $*) vous indique de quel type de variable il s'agit. NOTE: $(flavor) prend une variable nom et non son développement. Donc, si vous dites make print-LDFLAGS, vous obtenez $(flavor LDFLAGS), ce que vous voulez.
  • $(info text) fournit une sortie. Make imprime text sur sa sortie standard en tant qu'effet secondaire de l'expansion. Le développement de $(info) si 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 de shell.
  • @true est là juste pour fournir une commande pour la règle. Sans cela, make make affichera également print-blah is up to date. Je pense que @true indique plus clairement que c'est censé être un no-op.

En cours d'exécution, vous obtenez

$ make print-LDFLAGS
LDFLAGS is a recursive variable set to [-L/Users/...]
39
Jim Nasby

Toutes les versions de make nécessitent que les lignes de commande soient en retrait avec une tabulation (et non de l'espace) comme premier caractère de la ligne. Si vous nous montriez la règle entière au lieu des deux lignes en question, nous pourrions donner une réponse plus claire, mais cela devrait ressembler à quelque chose comme:

myTarget: myDependencies
        @echo hi

où le premier caractère de la deuxième ligne doit être TAB.

6
MadScientist

@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 saisi l’intention: je pense que vous avez des espaces où vous devriez avoir un onglet.

6
user1746732

Exécutez 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
4
ivandcl

Cette 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 par all devrait avoir un signe deux-points : ou un égal à = pour indiquer qu’il s’agit d’une ligne cible ou d’une ligne macro. le séparateur est manquant.

L'action qui fait écho à la valeur d'une variable doit être associée à une cible, éventuellement une cible factice ou PHONEY. Et cette ligne cible doit avoir deux points dessus. Si vous ajoutez un : après all dans l'exemple makefile et que vous remplacez les blancs de la ligne suivante par un onglet, cela fonctionnera sans problème.

Vous avez probablement un problème analogue près de la ligne 102 dans l'original makefile. Si vous montriez cinq lignes non vides, sans commentaire avant les opérations d'écho qui échouaient, il serait probablement possible de terminer le diagnostic. Cependant, depuis que la question a été posée en mai 2013, il est peu probable que la version cassée makefile soit encore disponible (août 2014), aussi cette réponse ne peut-elle pas être validée formellement. Il ne peut être utilisé que pour illustrer une manière plausible dont le problème est survenu.

3
Jonathan Leffler

Pas besoin de modifier le Makefile.

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

$ cd /to/Makefile/dir
$ make -f ~/printvars.mak -f Makefile print-VARIABLE
2
Talespin_Kit

Le problème est que l'écho ne fonctionne que sous un bloc d'exécution. c'est-à-dire n'importe quoi après "xx:"

Donc, tout ce qui se trouve au-dessus du premier bloc d’exécution n’est qu’une initialisation et aucune commande d’exécution ne peut être utilisée.

Alors créez un bloc d'exécution

2
Andy

Cela peut être fait de manière générique et peut être très utile lors du débogage d'un fichier Make complexe. En suivant la même technique que celle décrite dans autre réponse , vous pouvez insérer les éléments suivants dans n’importe quel fichier Make:

# 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

Ensuite, vous pouvez juste faire "make print" pour dump la valeur de toute variable:

$ make print CXXFLAGS
CXXFLAGS = -g -Wall
1
Idelic

Pour imprimer la valeur d'une variable, vous pouvez utiliser:

rule:
<tab>@echo $(VAR_NAME)

Lorsque la règle est exécutée, la variable sera imprimée.

1
Samuel

si vous utilisez Android make (mka) @echo $(NDK_PROJECT_PATH) ne fonctionnera pas et vous donnera l'erreur *** missing separator. Stop." use cette réponse si vous essayez d'imprimer des variables dans Android marque

NDK_PROJECT_PATH := some_value
$(warning $(NDK_PROJECT_PATH))

cela a fonctionné pour moi

0
mjalil

Si vous ne souhaitez 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 de tabulation requis dans la ligne de commande à l'aide de 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
Wade

Je fais habituellement écho avec une erreur si je voulais voir la valeur de la variable. (Seulement si vous vouliez voir la valeur. Cela arrêtera l'exécution.)

@echo $ (erreur NDK_PROJECT_PATH = $ (NDK_PROJECT_PATH))

0
Abdul Jaleel