Hinzufügen eines Verzeichnisses zu PATH über Makefile

9

Ich habe Probleme beim Exportieren des Pfads, den ich im Makefile geändert habe, in das aktuelle Terminal. Ich versuche, dem Ordner PATH den Ordner bin hinzuzufügen, in dem sich das Makefile-Verzeichnis befindet.

Hier ist der relevante Streifen des Makefiles:

PATH := $(shell pwd)/bin:$(PATH)

install:
    mkdir -p ./bin 
    export PATH
    echo $(PATH)

Das Echo druckt es korrekt aus, aber wenn ich das Echo im Terminal wiederhole, bleibt der PFAD gleich.

Tshepang
quelle

Antworten:

15

Das kann man einfach nicht. Der make-Prozess kann auf keinen Fall¹ die Umgebung des übergeordneten Elements (oder das aktuelle Verzeichnis, an das Sie möglicherweise als Nächstes denken) ändern.

In der Tat passiert noch weniger als Sie denken.

  • Nicht alle makeImplementierungen spiegeln die Zuordnung zur PATHVariablen make in der Umgebung wider . GNU make (auf Linux und anderen Systemen verfügbar) tut dies, BSD make jedoch nicht.
  • Jede Befehlszeile unter einem Ziel wird in einer separaten Unterschale ausgeführt. (Außer in einigen älteren BSD-Implementierungen.) Die export PATHLeitung läuft also auf einer Shell, die unmittelbar danach endet. Nicht, dass diese Zeile überhaupt etwas tun würde - wenn PATHsie an diesem Punkt definiert ist, liegt es daran, dass sie sich bereits in der Umgebung der Shell befindet.

Make dient zum automatischen Erstellen von Dingen. Wenn Sie Variablen für Ihre interaktive Umgebung festlegen möchten, ist dies nicht das Tool, das Sie sich ansehen sollten. Stattdessen schreibt einen Shell - Schnipsel und Quelle es in der aktuellen Shell:

. ./define-my-variables.sh

Geben Sie in Ihrem Makefile das Skript in jeder Subshell ein . Sie können einen Backslash verwenden, um einen langen Befehl auszuführen. erinnere dich daran

  • Die Backslash-Newline-Sequenz wird von make entfernt, sodass die Shell dort keine Newline sieht.
  • Denken Sie daran, jeder Zeile dennoch eine Registerkarte voranzustellen.
  • Das Fehlerverhalten von Make besteht darin, den Vorgang abzubrechen, wenn ein Befehl fehlschlägt. Die Shell macht das standardmäßig nicht und der Fehler eines Befehls, aber der letzte, bleibt standardmäßig unbemerkt, sodass Sie ihn ausführen müssen set -e.
install:
    set -e; \
    . ./define-my-variables.sh; \
    mkdir -p bin; \
    …

¹ Obligatorische Anmerkung: kein vernünftiger Weg. Selbst das Remote-Aufrufen von chdirvia über ptraceeinen Debugger funktioniert nicht wie bei den meisten Shells, da sie nicht möchten, dass ihr aktuelles Verzeichnis unter ihren Füßen geändert wird.

Gilles 'SO - hör auf böse zu sein'
quelle
Ähm, ich denke "Das kann man einfach nicht" ist falsch. Siehe @ Yeo Antwort: unix.stackexchange.com/a/291973/176350
XML
Die Antwort von @XML Yeo macht etwas anderes, was in der Frage nicht gefragt ist.
Gilles 'SO - hör auf böse zu sein'
7

Das kannst du nicht. Es ist nicht möglich, dass ein Unterprozess (wie make) die Umgebung seines übergeordneten Prozesses ändert.

Sie könnten so etwas tun

$ eval `make pathupdate`

Wo das pathupdateZiel aussieht:

pathupdate:
    @echo PATH=\"$(PATH)\"
cjm
quelle
6

Ihre Antwort finden Sie hier: https://stackoverflow.com/a/8942216/367461

Grundsätzlich sollten Sie dies tun:

export PATH := $(shell pwd)/bin:$(PATH)

test:
    mkdir -p ./bin
    @echo $(PATH)

Ich habe dies auf Fedora 23 mit GNU Make 4.0 getestet und es funktioniert gut für mich.

Dan Jones
quelle
1
Dies ist die richtige Antwort für GNU Make. Für BSD Make können Sie .SHELL: name=sh path=/path/to/wrapper-scriptein Wrapper-Skript wieexport FOO=bar; exec bash "$@"
rjh
2

Ich werde die gleiche Frage stellen, weil ich das andere Antwortbeispiel nicht zum Laufen bringen konnte.

Es gelang mir jedoch, die funktionierende Lösung für mich mithilfe eines evalBefehls zu erreichen. Ich bin mir nicht sicher, warum dies nicht früher gepostet wurde.

do_something: 
    $(eval export PATH=$(shell pwd)/bin:$(PATH))
    @echo $(PATH)

Hinweis: Die PATHÄnderungen sind vorübergehend innerhalb des Make selbst. Nach dem Verlassen des make wird der PATH auf den früheren Wert zurückgesetzt.

Yeo
quelle
Dies wurde nicht früher gepostet, da es nicht das ist, was die Frage stellt: Die Frage fragt, wie der geänderte PFAD nach dem Beenden von make abgerufen werden soll. Auch könnte dies in einer viel einfacheren Weise erfolgen: setzen export PATH=…auf der do_something:Linie, die Sie nicht benötigen eval.
Gilles 'SO - hör auf böse zu sein'
1

Sie können dazu führen, dass Make sich rekursiv in einer geänderten Umgebung aufruft:

dummy: build_all

all: 
    PATH=/new/directory:$(PATH) $(MAKE) build_all

build_all:
    your make rules 

Wenn Sie ein Shell-Snippet verwenden möchten:

dummy: build_all

all:
    . ./define-my-variables.sh ; $(MAKE) build_all

build_all:
   your make rules
Sam B.
quelle