it-swarm.dev

So drucken Sie eine Variable im Makefile aus

In meinem Makefile habe ich eine Variable 'NDK_PROJECT_PATH'. Meine Frage ist, wie ich sie beim Kompilieren ausdrucken kann.

Ich habe gelesen Make file echo display "$ PATH" string und ich habe versucht:

@echo $(NDK_PROJECT_PATH)
@echo $(value NDK_PROJECT_PATH)

Beides gibt mir

"build-local.mk:102: *** missing separator.  Stop."

Weiß jemand, warum es bei mir nicht funktioniert?

217
michael

Sie können Variablen beim Lesen des Makefiles ausdrucken (vorausgesetzt, GNU make, da Sie diese Frage entsprechend markiert haben), indem Sie diese Methode verwenden (mit einer Variablen namens "var"):

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

Sie können dieses Konstrukt zu jedem Rezept hinzufügen, um zu sehen, welche Marke an die Shell übergeben wird:

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

Was hier passiert, ist, dass make das gesamte Rezept ($(info $$var is [${var}])echo Hello world) als einzelne rekursiv erweiterte Variable speichert. Wenn make beschließt, das Rezept auszuführen (wenn Sie es beispielsweise anweisen, all zu erstellen), erweitert es die Variable und übergibt dann jede resultierende Zeile separat an die Shell.

Also, in schmerzhaften Details:

  • Es erweitert $(info $$var is [${var}])echo Hello world
  • Dazu wird zunächst $(info $$var is [${var}])
    • $$ wird wörtlich $
    • ${var} wird :-) (say)
    • Der Nebeneffekt ist, dass $var is [:-)] bei Standardausgabe erscheint
    • Die Erweiterung von $(info...) ist jedoch leer
  • Make bleibt mit echo Hello world
    • Erstellen Sie zuerst Ausdrucke echo Hello world auf stdout, um Sie darüber zu informieren, was die Shell tun soll
  • Die Shell druckt Hello world auf stdout.
195
bobbogo

von einem "Mr. Make Post" https://www.cmcrossroads.com/article/printing-value-makefile-variable

Fügen Sie Ihrem Makefile die folgende Regel hinzu:

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

Wenn Sie den Wert einer Makefile-Variablen herausfinden möchten, gehen Sie wie folgt vor:

make print-VARIABLE

und es wird zurückkehren:

VARIABLE = the_value_of_the_variable
140

Als 'bobbogo' in der obigen Antwort wies und gemäß GNU Make manual , können Sie info/warning/error verwenden, um Text anzuzeigen.

$(error   text…)
$(warning text…)
$(info    text…)

Variablen drucken,

$(error   VAR is $(VAR))
$(warning VAR is $(VAR))
$(info    VAR is $(VAR))

wenn Sie 'error' verwenden, wird die Ausführung von make gestoppt, nachdem die Fehlerzeichenfolge angezeigt wurde

134
tsenapathy

Wenn Sie nur eine Ausgabe wünschen, möchten Sie $(info) für sich verwenden. Sie können dies überall in einem Makefile tun, und es wird angezeigt, wenn diese Zeile ausgewertet wird:

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

Gibt VAR="<value of VAR>" aus, wenn make diese Zeile verarbeitet. Dieses Verhalten ist sehr positionsabhängig, daher müssen Sie sicherstellen, dass die $(info) -Erweiterung erfolgt, nachdem alles, was $(VAR) ändern könnte, bereits geschehen ist!

Eine allgemeinere Option besteht darin, eine spezielle Regel zum Drucken des Werts einer Variablen zu erstellen. Im Allgemeinen werden Regeln ausgeführt, nachdem Variablen zugewiesen wurden, sodass der tatsächlich verwendete Wert angezeigt wird. (Es ist jedoch es ist möglich, dass eine Regel eine Variable ändert .) Eine gute Formatierung verdeutlicht, worauf eine Variable eingestellt ist, und die Funktion $(flavor) gibt Auskunft darüber, um welche Art von Variable es sich handelt etwas ist. Also in dieser Regel:

print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
  • $* erweitert sich zu dem Stamm, der dem % Muster in der Regel entspricht.
  • $($*) wird auf den Wert der Variablen erweitert, deren Name durch $* angegeben wird.
  • Der [ und ] begrenzen die Variablenerweiterung klar. Sie können auch " und " oder ähnliches verwenden.
  • $(flavor $*) gibt an, um welche Art von Variable es sich handelt. HINWEIS: $(flavor) akzeptiert einen Variablennamen und nicht dessen Erweiterung. Wenn Sie also make print-LDFLAGS sagen, erhalten Sie $(flavor LDFLAGS), was Sie wollen.
  • $(info text) liefert die Ausgabe. Make druckt text als Nebeneffekt der Erweiterung auf die Standardausgabe. Die Erweiterung von $(info) ist jedoch leer. Sie können es sich wie @echo vorstellen, aber wichtig ist, dass es die Shell nicht verwendet, sodass Sie sich nicht um Shell-Anführungsregeln kümmern müssen.
  • @true gibt nur einen Befehl für die Regel aus. Ohne das gibt make auch print-blah is up to date aus. Ich fühle, dass @true es klarer macht, dass es ein No-Op sein soll.

Laufen Sie, Sie bekommen

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

Alle Versionen von make erfordern, dass Befehlszeilen mit einem TAB (nicht Leerzeichen) als erstes Zeichen in der Zeile eingerückt werden. Wenn Sie uns die gesamte Regel anstatt nur der zwei fraglichen Zeilen zeigen würden, könnten wir eine klarere Antwort geben, aber es sollte ungefähr so ​​aussehen:

myTarget: myDependencies
        @echo hi

dabei muss das erste Zeichen in der zweiten Zeile TAB sein.

6
MadScientist

@echo $ (NDK_PROJECT_PATH) ist der gute Weg, dies zu tun. Ich glaube nicht, dass der Fehler von dort kommt. Im Allgemeinen tritt dieser Fehler auf, wenn Sie die Absicht falsch eingegeben haben: Ich denke, Sie haben Leerzeichen, in denen Sie einen Tabulator haben sollten.

6
user1746732

Führen Sie make -n aus; es zeigt Ihnen den Wert der Variablen ..

Makefile ...

all:
        @echo $(NDK_PROJECT_PATH)

Befehl:

export NDK_PROJECT_PATH=/opt/ndk/project
make -n 

Ausgabe:

echo /opt/ndk/project
4
ivandcl

Dieses makefile generiert die Fehlermeldung "Fehlendes Trennzeichen":

all
    @echo NDK_PROJECT_PATH=$(NDK_PROJECT_PATH)

done:
        @echo "All done"

Vor dem @echo "All done" steht ein Tabulator (obwohl die done: -Regel und -Aktion weitgehend überflüssig sind), jedoch nicht vor dem @echo PATH=$(PATH).

Das Problem ist, dass die Zeile, die mit all beginnt, entweder einen Doppelpunkt : oder den Wert = haben sollte, um anzuzeigen, dass es sich um eine Zielzeile oder eine Makrozeile handelt, und dass es keine von beiden gibt Trennzeichen fehlt.

Die Aktion, die den Wert einer Variablen wiedergibt, muss einem Ziel zugeordnet werden, möglicherweise einem Dummy- oder PHONEY-Ziel. Und auf dieser Ziellinie muss ein Doppelpunkt stehen. Wenn Sie im Beispiel all einen : nach makefile einfügen und die führenden Leerzeichen in der nächsten Zeile durch einen Tabulator ersetzen, funktioniert dies einwandfrei.

Sie haben wahrscheinlich ein analoges Problem in der Nähe von Zeile 102 im ursprünglichen makefile. Wenn Sie vor den fehlgeschlagenen Echooperationen 5 nicht leere, kommentarlose Zeilen angezeigt haben, ist es wahrscheinlich möglich, die Diagnose zu beenden. Da die Frage jedoch im Mai 2013 gestellt wurde, ist es unwahrscheinlich, dass das defekte makefile noch verfügbar ist (August 2014), sodass diese Antwort nicht formal validiert werden kann. Es kann nur verwendet werden, um eine plausible Art und Weise zu veranschaulichen, in der das Problem aufgetreten ist.

3

Das Makefile muss nicht geändert werden.

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

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

Das Problem ist, dass das Echo nur unter einem Ausführungsblock funktioniert. irgendetwas nach "xx:"

Alles über dem ersten Ausführungsblock ist also nur eine Initialisierung, sodass kein Ausführungsbefehl verwendet werden kann.

Erstellen Sie also einen Ausführungsblock

2
Andy

Dies kann generisch erfolgen und beim Debuggen eines komplexen Makefiles sehr hilfreich sein. Nach der gleichen Technik wie in eine andere Antwort beschrieben, können Sie Folgendes in jedes Makefile einfügen:

# 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

Dann können Sie einfach "make print" ausführen, um den Wert einer Variablen zu sichern:

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

Um den Wert einer Variablen auszudrucken, können Sie Folgendes verwenden:

rule:
<tab>@echo $(VAR_NAME)

Wenn die Regel ausgeführt wird, wird die Variable gedruckt.

1
Samuel

wenn Sie Android make (mka) @echo $(NDK_PROJECT_PATH) verwenden, funktioniert dies nicht und Sie erhalten den Fehler *** missing separator. Stop." Verwenden Sie diese Antwort , wenn Sie versuchen, Variablen in _ zu drucken.Android make

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

das hat bei mir geklappt

0
mjalil

Wenn Sie das Makefile selbst nicht ändern möchten, können Sie mit --eval ein neues Ziel hinzufügen und dann das neue Ziel ausführen, z.

make --eval='print-tests: @echo TESTS $(TESTS) ' print-tests

Sie können das erforderliche TAB-Zeichen mit CTRL-V, TAB in die Befehlszeile einfügen.

beispiel Makefile von oben:

all: do-something

TESTS=
TESTS+='a'
TESTS+='b'
TESTS+='c'

do-something:
        @echo "doing something"
        @echo "running tests $(TESTS)"
        @exit 1
0
Wade

Ich gebe normalerweise eine Fehlermeldung aus, wenn ich den Variablenwert sehen wollte. (Nur wenn Sie den Wert sehen wollten. Die Ausführung wird gestoppt.)

@echo $ (Fehler NDK_PROJECT_PATH = $ (NDK_PROJECT_PATH))

0
Abdul Jaleel