Bagaimana saya bisa menambahkan dir ke $ PATH di Makefile?

91

Saya ingin menulis Makefile yang akan menjalankan tes. Tes ada di direktori './tests' dan file yang dapat dieksekusi untuk diuji ada di direktori './bin'.

Ketika saya menjalankan tes, mereka tidak melihat file exec, karena direktori ./bin tidak ada di $ PATH.

Ketika saya melakukan sesuatu seperti ini:

EXPORT PATH=bin:$PATH
make test

semuanya bekerja. Namun saya perlu mengubah $ PATH di Makefile.

Konten Makefile sederhana:

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

Ini mencetak jalur dengan benar, namun tidak menemukan file x.

Ketika saya melakukan ini secara manual:

$ export PATH=bin:$PATH
$ x

semuanya baik-baik saja.

Bagaimana saya bisa mengubah $ PATH di Makefile?

Szymon Lipiński
sumber
Bisakah Anda tidak hanya memanggil tes dari direktori yang dapat dieksekusi seperti ../test/test_to_run? Maaf jika saya salah paham dengan pertanyaannya.
Chris
Saya ingin file ini terlihat oleh pengujian secara normal. Saya tidak ingin bermain-main dengan direktori, karena saya melakukan refactoring itu akan menjadi mimpi buruk.
Szymon Lipiński
Satu-satunya cara Anda bisa mendekati ini adalah dengan membuat makefile menulis skrip shell yang berisi variabel mendeklarasikan dan kemudian memiliki sumber shell induk yang digunakan skrip tersebut .. Namun ini mungkin tidak praktis.
Michael Smith
Saya percaya bahwa unix.stackexchange.com/questions/11530/… adalah pertanyaan yang sangat berbeda (bodoh), tidak seperti pertanyaan Anda.
imz - Ivan Zakharyaschev

Jawaban:

108

Apakah Anda mencoba exportdirektif Make sendiri (dengan asumsi Anda menggunakan GNU Make)?

export PATH := bin:$(PATH)

test all:
    x

Juga, ada bug dalam contoh Anda:

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

Pertama, nilai yang sedang echodiedit adalah perluasan PATHvariabel yang dilakukan oleh Make, bukan shell. Jika mencetak nilai yang diharapkan maka, saya kira, Anda telah menetapkan PATHvariabel di suatu tempat sebelumnya di Makefile Anda, atau di shell yang memanggil Make. Untuk mencegah perilaku seperti itu, Anda harus menghindari dolar:

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

Kedua, bagaimanapun juga ini tidak akan berhasil karena Make mengeksekusi setiap baris resep di shell terpisah . Ini dapat diubah dengan menulis resep dalam satu baris:

test all:
    export PATH=bin:$$PATH; echo $$PATH; x
Eldar Abusalimov
sumber
7
$(PATH)akan disetel ke nilai dari PATHshell yang memanggil make. Sesuai manual , "Setiap variabel lingkungan yang membuat melihat saat dijalankan diubah menjadi variabel make dengan nama dan nilai yang sama."
Emil Sit
Perintah ekspor berfungsi untuk saya (terima kasih!), Tetapi hanya setelah saya menginstal GNU Make 4.3. Dalam versi 3.81 (default di MacOS Catalina), yang diperbarui PATHdengan benar tercermin dalam variabel ( echo $(PATH)) dan dalam lingkungan perintah ( env, which python, bash -c python), tetapi tampaknya tidak digunakan saat menemukan executable untuk perintah: perintah pythonmasih menjalankan Python dapat dieksekusi pada aslinya PATH.
doctaphred
30

Dengan desain makeparser mengeksekusi baris dalam pemanggilan shell terpisah, itulah mengapa mengubah variabel (misalnya PATH) dalam satu baris, perubahan mungkin tidak diterapkan untuk baris berikutnya (lihat posting ini ).

Salah satu cara untuk mengatasi masalah ini, adalah dengan mengubah beberapa perintah menjadi satu baris (dipisahkan oleh ;), atau menggunakan target khusus Satu Shell ( .ONESHELL, seperti GNU Make 3.82).

Sebagai alternatif, Anda dapat memberikan PATHvariabel pada saat shell dipanggil. Sebagai contoh:

PATH  := $(PATH):$(PWD)/bin:/my/other/path
SHELL := env PATH=$(PATH) /bin/bash
kenorb
sumber
2
Saya suka pendekatannya!
Alan Franzoni
2
Ini adalah yang terbaik, karena berfungsi bahkan dengan $(shell)pemanggilan! : D Contoh: pastebin.com/Pii8pmkD
PsychoX
Pada dev.azure saya mendapatkan: env: 'env': Tidak ada file atau direktori seperti itu; Bekerja secara lokal; /
Kamil Dziedzic
Tidak berfungsi pada Debian 10 dengan make 4.2: make: env PATH = <path> / bin / sh: Perintah tidak ditemukan. Menggunakan karya ekspor. Pastikan untuk menggunakan $ (HOME) dan bukan ~ untuk jalur di direktori home.
MKesper
25

Perubahan jalur tampaknya tetap jika Anda menyetel variabel SHELL di makefile Anda terlebih dahulu:

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

test all:
    x

Saya tidak tahu apakah ini perilaku yang diinginkan atau tidak.

tidak ditentukan
sumber
Ini memperbaiki masalah yang saya alami (saya menjalankan zsh). Terima kasih!
Jezen Thomas
Ya, ini memang melakukan apa yang diinginkan OP ... tetapi apakah itu fitur atau bug? Bahkan setelah membaca bagian SHELL manual make saya tidak yakin.
pje
5
Ini juga tidak berhasil untuk saya. whichdan envsekarang ambil PATH baru, tetapi secara langsung mengeksekusi biner masih tidak ditemukan di PATH yang dimodifikasi, hanya di yang asli.
Konrad Rudolph
3

Apa yang biasanya saya lakukan adalah menyediakan jalur ke yang dapat dieksekusi secara eksplisit:

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

Saya juga menggunakan teknik ini untuk menjalankan biner non-native di bawah emulator seperti QEMU jika saya melakukan kompilasi silang:

EXE = qemu-mips ./bin/

Jika make menggunakan shell sh, ini seharusnya berfungsi:

test all:
    PATH=bin:$PATH x
Richard Pennington
sumber
Ya, soulution keren, namun tes saya tertulis dalam perl dan saya perlu memanggil exe dari skrip perl, bukan langsung dari makefile. Saya harus memikirkan kembali seluruh pengujian hal ini :)
Szymon Lipiński
Kena kau. Bagaimana dengan pengaturan PATH pada baris perintah itu sendiri? Lihat edit di atas.
Richard Pennington
-3

Untuk mengatur PATHvariabel, di dalam Makefile saja, gunakan sesuatu seperti:

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

test:
@echo my new PATH = $(PATH)
karnhick.dll
sumber
Ini tidak bekerja seperti yang saya inginkan. Saya telah memperbarui pertanyaan dengan contoh apa yang ingin saya capai.
Szymon Lipiński