Як я можу додати dir до $ PATH у Makefile?


87

Я хочу написати Makefile, який би запускав тести. Тест знаходиться в каталозі './tests', а виконувані файли, що перевіряються, знаходяться в каталозі './bin'.

Коли я запускаю тести, вони не бачать файли exec, оскільки каталог ./bin відсутній у $ PATH.

Коли я роблю щось подібне:

EXPORT PATH=bin:$PATH
make test

все працює. Однак мені потрібно змінити $ PATH у Makefile.

Простий вміст Makefile:

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

Він правильно друкує шлях, проте не знаходить файл x.

Коли я роблю це вручну:

$ export PATH=bin:$PATH
$ x

тоді все гаразд.

Як я можу змінити $ PATH у Makefile?


Чи не можете ви просто викликати тести з виконуваного каталогу як ../test/test_to_run? Вибачте, якщо я неправильно зрозумів питання.
Кріс

Я хочу, щоб цей файл був нормально видимим для тестів. Я не хочу грати з каталогами, оскільки я переробляю це, що було б дуже важливо.
Szymon Lipiński

Єдиний спосіб наблизитись до цього - це зробити makefile виписати скрипт оболонки, що містить змінну decls, а потім мати батьківське джерело оболонки, з яким сценарій .. Однак це, мабуть, недоцільно.
Michael Smith

Я вважаю, що unix.stackexchange.com/questions/11530/… - це зовсім інше (дурне) питання, на відміну від вашого.
imz - Іван Захарящев

Відповіді:


106

Ви пробували exportдирективу Makeself (припускаючи, що ви використовуєте GNU Make)?

export PATH := bin:$(PATH)

test all:
    x

Крім того, у вашому прикладі є помилка:

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

По-перше, значення, яке echoредагується, є розширенням PATHзмінної, що виконується Make, а не оболонкою. Якщо він друкує очікуване значення, то, я думаю, ви встановили PATHзмінну десь раніше у вашому файлі Make або в оболонці, яка викликала Make. Щоб запобігти такій поведінці, вам слід уникати доларів:

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

По-друге, у будь-якому випадку це не спрацює, оскільки Make виконує кожен рядок рецепта в окремій оболонці . Це можна змінити, написавши рецепт в один рядок:

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

7
$(PATH)встановить значення PATHоболонки, що викликає make. Відповідно до посібника , "кожна змінна середовища, яка make бачить, коли вона запускається, перетворюється у змінну make з однаковим іменем та значенням".
Еміль Сіт

Директива про експорт працювала для мене (дякую!), Але лише після того, як я встановив GNU Make 4.3. У версії 3.81 (за замовчуванням на MacOS Catalina), оновлений PATHправильно відображено в змінних ( echo $(PATH)) і в середовищі команд ( env, which python, bash -c python), але , здається, не буде використовуватися при пошуку виконуваного файлу для команди: команда pythonвсе ще біжить Python, виконуваний на оригіналі PATH.
підписаний

27

За задумом makeпарсер виконує рядки в окремих викликах оболонки, тому, змінюючи змінну (наприклад PATH) в одному рядку, зміна може не застосовуватися до наступних рядків (див. Цей пост ).

Одним із способів вирішити цю проблему є перетворення декількох команд в один рядок (розділені ;) або використання спеціальної цілі One Shell ( .ONESHELL, станом на GNU Make 3.82).

В якості альтернативи ви можете вказати PATHзмінну під час виклику оболонки. Наприклад:

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

2
Мені подобається підхід!
Алан Францоні,

2
Це найкраще, тому що воно працює навіть із $(shell)викликами! : D Приклад: pastebin.com/Pii8pmkD
PsychoX

На dev.azure я отримую: env: 'env': Немає такого файлу чи каталогу; Працює на місцях; /
Каміль Дзедзіч

Не працює на Debian 10 з make 4.2: make: env PATH = <path> / bin / sh: Команду не знайдено. Використання експортних робіт. Обов’язково використовуйте $ (HOME), а не ~ для шляху в домашній директорії.
MKesper

25

Зміни шляху виявляються постійними, якщо спочатку ви встановите змінну SHELL у своєму файлі make:

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

test all:
    x

Я не знаю, бажана це поведінка чи ні.


Це вирішило проблему, з якою я стикався (я запускаю zsh). Дякую!
Jezen Thomas

Так, це справді робить те, що хотів ОП ... але це функція чи помилка? Навіть прочитавши розділ SHELL в інструкції з виготовлення, я не впевнений.
пі

5
Це теж не працює у мене. whichі envтепер підберіть новий PATH, але безпосереднє виконання двійкового файлу все ще не знайдено у зміненому PATH, лише в оригінальному.
Конрад Рудольф

3

Що я зазвичай роблю, це явно надаю шлях до виконуваного файлу:

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

Я також використовую цю техніку для запуску чужих двійкових файлів під емулятором, як QEMU, якщо я перехресно компілюю:

EXE = qemu-mips ./bin/

Якщо make використовує оболонку sh, це має спрацювати:

test all:
    PATH=bin:$PATH x

Так, круте рішення, проте я тести написав на perl, і мені потрібно зателефонувати до exe зі скрипта perl, а не безпосередньо з makefile. Я повинен переглянути все тестування цього матеріалу :)
Szymon Lipiński

Маю Як щодо встановлення PATH у самому командному рядку? Дивіться редагування вище.
Річард Пеннінгтон,

-2

Щоб встановити PATHзмінну, лише в Makefile, використовуйте щось на зразок:

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

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

Це працює не так, як я хочу. Я оновив запитання на прикладах того, чого хочу досягти.
Szymon Lipiński
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.