Wie könnte ich $ PATH in Makefile dir hinzufügen?

85

Ich möchte ein Makefile schreiben, das Tests ausführen würde. Der Test befindet sich in einem Verzeichnis './tests' und die zu testenden ausführbaren Dateien befinden sich im Verzeichnis './bin'.

Wenn ich die Tests ausführe, werden die exec-Dateien nicht angezeigt, da sich das Verzeichnis ./bin nicht im $ PATH befindet.

Wenn ich so etwas mache:

EXPORT PATH=bin:$PATH
make test

funktioniert alles. Allerdings muss ich den $ PATH im Makefile ändern.

Einfacher Makefile-Inhalt:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

Der Pfad wird korrekt gedruckt, die Datei x wird jedoch nicht gefunden.

Wenn ich das manuell mache:

$ export PATH=bin:$PATH
$ x

dann ist alles in ordnung.

Wie könnte ich den $ PATH im Makefile ändern?

Szymon Lipiński
quelle
Können Sie die Tests nicht einfach aus dem ausführbaren Verzeichnis wie aufrufen ../test/test_to_run? Entschuldigung, wenn ich die Frage falsch verstanden habe.
Chris
Ich möchte, dass diese Datei für die Tests normal sichtbar ist. Ich möchte nicht mit den Verzeichnissen spielen, da ich das umgestalten würde, wäre das ein Albtraum.
Szymon Lipiński
Die einzige Möglichkeit, dem nahe zu kommen, besteht darin, dass das Makefile ein Shell-Skript mit den Variablen decs schreibt und dann die übergeordnete Shell-Quelle mit diesem Skript erstellt .. Dies ist jedoch wahrscheinlich unpraktisch.
Michael Smith
Ich glaube, dass unix.stackexchange.com/questions/11530/… eine ganz andere (dumme) Frage ist als Ihre.
imz - Ivan Zakharyaschev

Antworten:

100

Haben Sie die exportDirektive von Make selbst ausprobiert (vorausgesetzt, Sie verwenden GNU Make)?

export PATH := bin:$(PATH)

test all:
    x

Außerdem gibt es in Ihrem Beispiel einen Fehler:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

Erstens ist der Wert, der echobearbeitet wird, eine Erweiterung der PATHVariablen, die von Make ausgeführt wird, nicht die Shell. Wenn der erwartete Wert ausgegeben wird, haben Sie vermutlich PATHirgendwo früher in Ihrem Makefile oder in einer Shell, die Make aufgerufen hat, eine Variable festgelegt. Um ein solches Verhalten zu verhindern, sollten Sie Dollars entkommen:

test all:
    PATH=bin:$$PATH
    @echo $$PATH
    x

Zweitens funktioniert dies in keinem Fall, da Make jede Zeile des Rezepts in einer separaten Shell ausführt . Dies kann geändert werden, indem das Rezept in eine einzelne Zeile geschrieben wird:

test all:
    export PATH=bin:$$PATH; echo $$PATH; x
Eldar Abusalimov
quelle
7
$(PATH)wird auf den Wert PATHder Shell gesetzt, die make aufruft. Im Handbuch heißt es: "Jede Umgebungsvariable, die make beim Start sieht, wird in eine make-Variable mit demselben Namen und Wert umgewandelt."
Emil Sit
Die Exportanweisung hat bei mir funktioniert (danke!), Aber erst nachdem ich GNU Make 4.3 installiert habe. In der Version 3.81 (die Standardeinstellung auf macOS Catalina), die aktualisiert PATHwird in Variablen korrekt wiedergegeben ( echo $(PATH)) und in Befehlen Umgebungen ( env, which python, bash -c python), aber scheint nicht verwendet zu werden , wenn die ausführbare Datei für den Befehl Ortung: Der Befehl pythonnoch läuft die Python ausführbar auf dem Original PATH.
Doktaphred
27

Durch den Design- makeParser werden Zeilen in separaten Shell-Aufrufen ausgeführt. Wenn Sie die Variable (z. B. PATH) in einer Zeile ändern, wird die Änderung möglicherweise nicht für die nächsten Zeilen angewendet (siehe diesen Beitrag ).

Eine Möglichkeit, dieses Problem zu umgehen, besteht darin, mehrere Befehle in eine einzige Zeile (getrennt durch ;) zu konvertieren oder ein spezielles One Shell- Ziel zu verwenden ( .ONESHELLab GNU Make 3.82).

Alternativ können Sie eine PATHVariable zum Zeitpunkt des Aufrufs der Shell angeben. Beispielsweise:

PATH  := $(PATH):$(PWD)/bin:/my/other/path
SHELL := env PATH=$(PATH) /bin/bash
Kenorb
quelle
2
Ich mag den Ansatz!
Alan Franzoni
2
Dies ist das Beste, weil es auch mit $(shell)Aufrufen funktioniert ! : D Beispiel: pastebin.com/Pii8pmkD
PsychoX
Auf dev.azure bekomme ich: env: 'env': Keine solche Datei oder kein solches Verzeichnis; Arbeitet vor Ort; /
Kamil Dziedzic
Funktioniert unter Debian 10 mit make 4.2 nicht: make: env PATH = <Pfad> / bin / sh: Befehl nicht gefunden. Export funktioniert. Stellen Sie sicher, dass Sie $ (HOME) und nicht ~ für einen Pfad im Home-Verzeichnis verwenden.
MKesper
25

Pfadänderungen scheinen dauerhaft zu sein, wenn Sie zuerst die SHELL-Variable in Ihrem Makefile festlegen:

SHELL := /bin/bash
PATH := bin:$(PATH)

test all:
    x

Ich weiß nicht, ob dies das gewünschte Verhalten ist oder nicht.

unterbestimmt
quelle
Dies hat das Problem behoben, das ich hatte (ich verwende zsh). Vielen Dank!
Jezen Thomas
Ja, das macht tatsächlich das, was das OP wollte ... aber ist es eine Funktion oder ein Fehler? Selbst nach dem Lesen des SHELL-Abschnitts des Make-Handbuchs bin ich mir nicht sicher.
pje
5
Das funktioniert auch bei mir nicht. whichund envjetzt den neuen PATH aufnehmen, aber die direkte Ausführung einer Binärdatei wird im modifizierten PATH immer noch nicht gefunden, sondern nur im ursprünglichen.
Konrad Rudolph
3

Normalerweise gebe ich den Pfad zur ausführbaren Datei explizit an:

EXE=./bin/
...
test all:
    $(EXE)x

Ich verwende diese Technik auch, um nicht native Binärdateien unter einem Emulator wie QEMU auszuführen, wenn ich Cross-Compilieren:

EXE = qemu-mips ./bin/

Wenn make die sh-Shell verwendet, sollte dies funktionieren:

test all:
    PATH=bin:$PATH x
Richard Pennington
quelle
Ja, coole Soulution, aber ich habe meine Tests in Perl geschrieben und ich muss die Exe aus dem Perl-Skript aufrufen, nicht direkt aus dem Makefile. Ich muss die ganze Prüfung dieses Zeuges überdenken :)
Szymon Lipiński
Erwischt. Wie wäre es, PATH in der Befehlszeile selbst festzulegen? Siehe die Bearbeitung oben.
Richard Pennington
-2

PATHVerwenden Sie zum Festlegen der Variablen nur im Makefile Folgendes:

PATH := $(PATH):/my/dir

test:
@echo my new PATH = $(PATH)
Karnhick
quelle
Es funktioniert nicht so, wie ich es will. Ich habe die Frage mit Beispielen aktualisiert, was ich erreichen möchte.
Szymon Lipiński