Jak mogę dodać katalog do $ PATH w Makefile?


87

Chcę napisać plik Makefile, który uruchamia testy. Testy znajdują się w katalogu „./tests”, a pliki wykonywalne do przetestowania w katalogu „./bin”.

Kiedy uruchamiam testy, nie widzą plików exec, ponieważ katalogu ./bin nie ma w $ PATH.

Kiedy robię coś takiego:

EXPORT PATH=bin:$PATH
make test

wszystko działa poprawnie. Jednak muszę zmienić $ PATH w Makefile.

Zawartość Simple Makefile:

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

Wyświetla ścieżkę poprawnie, jednak nie znajduje pliku x.

Kiedy robię to ręcznie:

$ export PATH=bin:$PATH
$ x

wszystko jest w porządku.

Jak mogłem zmienić $ PATH w Makefile?


Czy nie możesz po prostu wywołać testów z katalogu wykonywalnego ../test/test_to_run? Przepraszam, jeśli źle zrozumiałem pytanie.
— Chris,

Chcę, aby ten plik był normalnie widoczny dla testów. Nie chcę bawić się katalogami, ponieważ refaktoryzacja byłaby koszmarem.
— Szymon Lipiński

Jedynym sposobem, aby się do tego zbliżyć, jest wypisanie przez plik makefile skryptu powłoki zawierającego zmienną decls, a następnie posiadanie nadrzędnego źródła powłoki, z którym skrypt jest powiązany .. Jest to jednak prawdopodobnie niepraktyczne.
— Michael Smith

Uważam, że unix.stackexchange.com/questions/11530/… to zupełnie inne (głupie) pytanie, w przeciwieństwie do twojego.
— imz - Ivan Zakharyaschev

Odpowiedzi:


106

Czy próbowałeś exportdyrektywy Make samego (zakładając, że używasz GNU Make)?

export PATH := bin:$(PATH)

test all:
    x

W twoim przykładzie jest również błąd:

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

Po pierwsze, edytowana wartość echojest rozwinięciem PATHzmiennej wykonywanym przez Make, a nie powłokę. Jeśli wypisze oczekiwaną wartość, to myślę, że ustawiłeś PATHzmienną gdzieś wcześniej w swoim Makefile lub w powłoce, która wywołała Make. Aby temu zapobiec, powinieneś uciec od dolarów:

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

Po drugie, w żadnym wypadku to nie zadziała, ponieważ Make wykonuje każdy wiersz przepisu w oddzielnej powłoce . Można to zmienić, wpisując przepis w jednej linii:

test all:
    export PATH=bin:$$PATH; echo $$PATH; x

7
$(PATH)zostanie ustawiona na wartość PATHpowłoki wywołującej make. Zgodnie z instrukcją „Każda zmienna środowiskowa, która sprawia, że ​​widzi się po uruchomieniu, jest przekształcana w zmienną make o tej samej nazwie i wartości”.
— Emil Sit

Dyrektywa eksportowa zadziałała dla mnie (dzięki!), Ale dopiero po zainstalowaniu GNU Make 4.3. W wersji 3.81 (domyślnie na MacOS Catalina), zaktualizowany PATHzostał prawidłowo odzwierciedlone w zmiennych ( echo $(PATH)) oraz w środowiskach Polecenia ( env, which python, bash -c python), ale nie wydaje się być stosowany podczas lokalizowania wykonywalny dla polecenia: komenda pythonciągle uruchamia Plik wykonywalny Pythona na oryginale PATH.
— udokumentowano

27

Zgodnie z projektem makeparser wykonuje wiersze w oddzielnych wywołaniach powłoki, dlatego zmiana zmiennej (np. PATH) W jednej linii, zmiana może nie zostać zastosowana w kolejnych wierszach (zobacz ten post ).

Jednym ze sposobów obejścia tego problemu jest przekształcenie wielu poleceń w jeden wiersz (oddzielony znakiem ;) lub użycie specjalnego celu One Shell ( .ONESHELLod wersji GNU Make 3.82).

Alternatywnie możesz podać PATHzmienną w momencie wywołania powłoki. Na przykład:

PATH  := $(PATH):$(PWD)/bin:/my/other/path
SHELL := env PATH=$(PATH) /bin/bash

2
Podoba mi się to podejście!
— Alan Franzoni

2
To jest najlepsze, ponieważ działa nawet z $(shell)inwokacjami! : D Przykład: pastebin.com/Pii8pmkD
— PsychoX

Na dev.azure otrzymuję: env: 'env': Nie ma takiego pliku lub katalogu; Działa lokalnie; /
— Kamil Dziedzic

Nie działa na Debianie 10 z make 4.2: make: env PATH = <ścieżka> / bin / sh: nie znaleziono polecenia. Korzystanie z eksportu. Upewnij się, że używasz $ (HOME) a ​​nie ~ jako ścieżki w katalogu domowym.
— MKesper

25

Zmiany ścieżki wydają się być trwałe, jeśli najpierw ustawisz zmienną SHELL w pliku makefile:

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

test all:
    x

Nie wiem, czy jest to pożądane zachowanie, czy nie.


To rozwiązało problem, który miałem (używam zsh). Dzięki!
— Jezen Thomas,

Tak, to rzeczywiście robi to, czego chciał OP ... ale czy jest to funkcja czy błąd? Nawet po przeczytaniu działu SHELL w instrukcji make nie jestem pewien.
— pje

5
Dla mnie to też nie działa. whicha envteraz wybierz nową PATH, ale bezpośrednie wykonanie pliku binarnego nadal nie występuje w zmodyfikowanej PATH, tylko w oryginalnej.
— Konrad Rudolph

3

Zwykle jawnie podaję ścieżkę do pliku wykonywalnego:

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

Używam również tej techniki do uruchamiania nienatywnych plików binarnych w emulatorze, takim jak QEMU, jeśli kompiluję krzyżowo:

EXE = qemu-mips ./bin/

Jeśli make używa powłoki sh, to powinno działać:

test all:
    PATH=bin:$PATH x

Tak, fajne soulution, jednak mam testy napisane w perlu i muszę wywołać exe ze skryptu perla, a nie bezpośrednio z pliku makefile. Muszę przemyśleć cały test tego materiału :)
— Szymon Lipiński

Mam cię. A co powiesz na ustawienie PATH w samym wierszu poleceń? Zobacz edycję powyżej.
— Richard Pennington,

-2

Aby ustawić PATHzmienną, tylko w Makefile, użyj czegoś takiego:

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

test:
@echo my new PATH = $(PATH)

To nie działa tak, jak chcę. Zaktualizowałem pytanie o przykłady tego, co chcę osiągnąć.
— Szymon Lipiński
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.