Come posso aggiungere dir a $ PATH in Makefile?


91

Voglio scrivere un Makefile che esegua i test. I test si trovano nella directory "./tests" e i file eseguibili da testare si trovano nella directory "./bin".

Quando eseguo i test, non vedono i file exec, poiché la directory ./bin non è in $ PATH.

Quando faccio qualcosa del genere:

EXPORT PATH=bin:$PATH
make test

tutto funziona. Tuttavia ho bisogno di cambiare $ PATH nel Makefile.

Contenuto Makefile semplice:

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

Stampa correttamente il percorso, tuttavia non trova il file x.

Quando lo faccio manualmente:

$ export PATH=bin:$PATH
$ x

allora va tutto bene.

Come posso cambiare $ PATH nel Makefile?


Non puoi semplicemente chiamare i test dalla directory eseguibile come ../test/test_to_run? Scusa se ho frainteso la domanda.
Chris,

Voglio che questo file sia normalmente visibile ai test. Non voglio giocare con le directory, dato che rifattorizzare sarebbe un incubo.
Szymon Lipiński

L'unico modo per avvicinarsi a questo è far scrivere al makefile uno script di shell contenente la variabile decls e quindi avere il sorgente della shell genitore con cui lo script .. Questo probabilmente è comunque poco pratico.
Michael Smith,

Credo che unix.stackexchange.com/questions/11530/… sia una domanda molto diversa (stupida), a differenza della tua.
imz - Ivan Zakharyaschev

Risposte:


108

Hai provato la exportdirettiva di Make stesso (assumendo che tu usi GNU Make)?

export PATH := bin:$(PATH)

test all:
    x

Inoltre, c'è un bug nel tuo esempio:

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

Primo, il valore che viene echoed è un'espansione della PATHvariabile eseguita da Make, non dalla shell. Se stampa il valore atteso, immagino che tu abbia impostato la PATHvariabile da qualche parte in precedenza nel tuo Makefile o in una shell che ha invocato Make. Per prevenire tale comportamento dovresti sfuggire ai dollari:

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

Secondo, in ogni caso questo non funzionerà perché Make esegue ogni riga della ricetta in una shell separata . Questo può essere modificato scrivendo la ricetta in una sola riga:

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

7
$(PATH)verrà impostato sul valore della PATHshell che richiama make. Come da manuale , "Ogni variabile d'ambiente che make vede quando si avvia viene trasformata in una variabile make con lo stesso nome e valore".
Emil Sit

La direttiva export ha funzionato per me (grazie!), Ma solo dopo aver installato GNU Make 4.3. Nella versione 3.81 (il default su MacOS Catalina), la versione aggiornata PATHsi riflette correttamente nel variabili ( echo $(PATH)) e all'interno degli ambienti comandi ( env, which python, bash -c python), ma non sembra essere utilizzato quando localizzare l'eseguibile per il comando: il comando pythonviene eseguito ancora il Eseguibile Python sull'originale PATH.
doctaphred

30

In base alla progettazione, il makeparser esegue le righe in invocazioni di shell separate, ecco perché cambiando variabile (ad esempio PATH) in una riga, la modifica potrebbe non essere applicata per le righe successive (vedere questo articolo ).

Un modo per ovviare a questo problema è convertire più comandi in una singola riga (separata da ;), oppure utilizzare il target speciale One Shell ( .ONESHELL, a partire da GNU Make 3.82).

In alternativa puoi fornire una PATHvariabile nel momento in cui viene invocata la shell. Per esempio:

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

2
Mi piace l'approccio!
Alan Franzoni

2
Questo è il migliore, perché funziona anche con le $(shell)invocazioni! : D Esempio: pastebin.com/Pii8pmkD
PsychoX

Su dev.azure ottengo: env: 'env': nessun file o directory di questo tipo; Funziona localmente; /
Kamil Dziedzic

Non funziona su Debian 10 con make 4.2: make: env PATH = <path> / bin / sh: comando non trovato. Utilizzo di opere di esportazione. Assicurati di usare $ (HOME) e non ~ per un percorso nella directory home.
MKesper

25

Le modifiche al percorso sembrano essere persistenti se imposti prima la variabile SHELL nel tuo makefile:

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

test all:
    x

Non so se questo sia un comportamento desiderato oppure no.


Questo ha risolto il problema che stavo avendo (sto eseguendo zsh). Grazie!
Jezen Thomas

Sì, questo fa davvero quello che voleva l'OP ... ma è una caratteristica o un bug? Anche dopo aver letto la sezione SHELL del manuale di make non sono sicuro.
pje

5
Anche questo non funziona per me. whiche envora prendi il nuovo PATH, ma l'esecuzione diretta di un binario non si trova ancora nel PATH modificato, solo in quello originale.
Konrad Rudolph

3

Quello che di solito faccio è fornire esplicitamente il percorso all'eseguibile:

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

Uso anche questa tecnica per eseguire binari non nativi con un emulatore come QEMU se sto eseguendo la compilazione incrociata:

EXE = qemu-mips ./bin/

Se make usa la shell sh, dovrebbe funzionare:

test all:
    PATH=bin:$PATH x

Sì, cool soulution, tuttavia ho i miei test scritti in perl e ho bisogno di chiamare l'exe dallo script perl, non direttamente dal makefile. Devo ripensare all'intero test di questa roba :)
Szymon Lipiński

Gotcha. Che ne dici di impostare PATH sulla riga di comando stessa? Vedi la modifica sopra.
Richard Pennington

-3

Per impostare la PATHvariabile, solo all'interno del Makefile, usa qualcosa come:

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

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

Non funziona come voglio. Ho aggiornato la domanda con esempi di ciò che voglio ottenere.
Szymon Lipiński
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.