Definieren Sie eine Makefile-Variable mit einer ENV-Variablen oder einem Standardwert

77

Ich versuche eine einfache Sache zu tun:

TMPDIR ?= /tmp

test:
    @echo $(TMPDIR)

Das funktioniert, wenn ich laufe:

$ make test
/tmp

Es funktioniert auch, wenn ich laufe:

$ make test -e TMPDIR=~/tmp
/home/user/tmp

Was kann ich tun, damit es auch funktioniert:

$ TMPDIR=~/tmp make test
/home/user/tmp
Natim
quelle
4
Erhm ... was Sie haben, funktioniert (wenn Sie ?=eine Umgebungsvariable verwenden und festgelegt haben, wird stattdessen der Wert der Umgebungsvariablen verwendet). Was genau ist das Problem (warum funktioniert es Ihrer Meinung nach nicht)?
MadScientist
1
Auch nur zu Ihrer Information: Das Hinzufügen von Anführungszeichen zu Variablenwerten in einem Makefile ist normalerweise keine gute Idee.
MadScientist
Ja , ich doppelt geprüft und ich arbeite mit TMPDIR ?= "/tmp"und echo $(TMPDIR)das einzige , was nicht die Klammer um die Variablennamen zu vergessen.
Natim
1
Sie haben Ihre Verwendung von -erückwärts. -eDamit env- Variablen Variablen überschreiben können, die im Makefile definiert sind, wirken sie sich nicht auf die Variablenzuweisung aus, die von Befehlszeilenargumenten ausgeht.
Etan Reisner
1
Sorry Natim, aber ?= funktioniert . Wenn es nicht das tut, was Sie wollen, ist entweder Ihre obige Erklärung verwirrend und wir verstehen nicht, was Sie wollen, oder es gibt etwas an Ihrer realen Umgebung, das sich in Ihrer obigen Frage nicht widerspiegelt.
MadScientist

Antworten:

129

Um meinen obigen Kommentaren nachzugehen, hier ein Beispiel:

T ?= foo
all:
        : '$(T)'

Wenn ich das Makefile nun auf verschiedene Arten ausführe, verhält es sich wie erwartet (ich bekomme es foonur, wenn ich es Tweder in der Befehlszeile noch in der Umgebung festgelegt habe):

$ make
: 'foo'

$ make T=bar
: 'bar'

$ T=bar make
: 'bar'
Verrückter Wissenschaftler
quelle
Was ist das : all:;:?
Xiphias
3
all:erstellt eine Regel für ein Ziel alle . Das Semikolon beendet die Liste der Voraussetzungen und beginnt die erste Rezeptzeile. Das letzte :ist das Rezept; Ein Doppelpunkt ist ein spezieller POSIX-Shell-Operator, der im Grunde bedeutet "nichts tun". Dies definiert also eine vollständige Regel für das allZiel, die ein Rezept hat, das nichts tut.
MadScientist
Ich bevorzuge eigentlich das Originalformat, da es funktioniert, ohne Leerzeichen in Tabulatoren konvertieren zu müssen (es ist schwierig, ein hartes TAB in ein Beispiel in SO einzufügen). Aber ich denke, andere Leute haben die Bearbeitung so genehmigt ...
MadScientist
35

In der Befehlszeile von make angegebene Variablen überschreiben die in makefile zugewiesenen Werte :

TMPDIR := "/tmp"
test:
    @echo $(TMPDIR)

Und dann:

make TMPDIR=whatever
whatever

Es ist im Allgemeinen eine schlechte Praxis, dass Makefiles von Umgebungsvariablen abhängen. Aus diesem Grund wird die Übergabe von Variablen in der make-Befehlszeile bevorzugt.


Eine andere Möglichkeit ist die Verwendung der make- orFunktion:

X := $(or ${X},${X},abc)

all :
    @echo ${X}

make
abc

X=def make 
def

Eigentlich sollten Sie sich nur an die ?=Zuweisung halten.

Maxim Egorushkin
quelle
1
Ok, das ist gut zu wissen, aber wie kann ich die Umgebungsvariable als Standardwert verwenden, wenn sie festgelegt ist?
Natim
In diesem speziellen Fall ist TMPDIR eine Variable, die existieren könnte und die ich verwenden möchte, wenn dies der Fall ist.
Natim
Ich habe es versucht, TMPDIR := $(or $$TMPDIR,$$TMPDIR,"/tmp")aber es scheint nicht zu funktionieren.
Natim
@ Natim Warum setzen Sie zusätzliche Dollarzeichen?
Maxim Egorushkin
1
Diese $(orAufrufe scheinen mehr zu sein als nötig. Funktioniert das nicht $(or $X,abc) ?
Ned Batchelder
4

Hier ist eine einfache Lösung:

SHELL  := env TMPDIR=$(TMPDIR) $(SHELL)
TMPDIR ?= "/tmp"

all:
  @echo $(TMPDIR)

Das funktioniert für beide Szenarien: TMPDIR=new/path makeund make TMPDIR=new/path.

Kenorb
quelle
0

Eines der Dinge, die Sie tun könnten, ist:

TMPDIR := "/tmp"

ifdef $$TMPDIR
TMPDIR := $$TMPDIR
endif

test:
    echo $(TMPDIR)
Natim
quelle
Es funktioniert nicht als TMPDIR=~/tmp make, nur wenn es als läuft make TMPDIR=~/tmp , aber die Frage war, ob es für beide funktioniert.
Kenorb