Добавление каталога в PATH через Makefile


9

У меня возникли проблемы с экспортом ПУТИ, который я изменил в Makefile, в текущий Терминал. Я пытаюсь добавить в PATH папку bin внутри каталога Makefile.

Вот соответствующая полоса make-файла:

PATH := $(shell pwd)/bin:$(PATH)

install:
    mkdir -p ./bin 
    export PATH
    echo $(PATH)

Эхо печатает его правильно, но если я повторю эхо в терминале, PATH останется прежним.

Ответы:


16

Вы просто не можете этого сделать. Нет никакого способа… процесс make может изменить среду своего родителя (или его текущий каталог, о котором вы могли бы подумать дальше).

На самом деле, даже меньше, чем вы думаете.

  • Не все makeреализации отражают присваивание PATHпеременной make в среде; GNU make (встречается в Linux и других системах) делает, а BSD make - нет.
  • Каждая командная строка под целью запускается в отдельной подоболочке. (За исключением некоторых более старых BSD, которые могут быть реализованы.) Таким образом, export PATHстрока работает в оболочке, которая завершается сразу после этого. Не то, чтобы эта строка вообще что-то делала - если PATHона определена на этом этапе, это потому, что она уже находится в среде оболочки.

Make предназначен для создания вещей автоматически. Если вы хотите установить переменные для своей интерактивной среды, это не тот инструмент, на который вам следует обратить внимание. Вместо этого напишите фрагмент оболочки и поместите его в текущую оболочку:

. ./define-my-variables.sh

В вашем make-файле поставьте скрипт в каждой подоболочке . Вы можете использовать обратную косую черту, чтобы сделать длинную команду; помни это

  • Последовательность обратного слеша-новой строки удаляется командой make, поэтому оболочка не увидит там новую строку.
  • Не забудьте префикс каждой строки на вкладке, тем не менее.
  • Поведение ошибки make в случае сбоя команды прерывается. Оболочка не будет делать это по умолчанию, и сбой любой команды, кроме последней, по умолчанию останется незамеченным, поэтому вам нужно запустить set -e.
install:
    set -e; \
    . ./define-my-variables.sh; \
    mkdir -p bin; \
    …

¹ Обязательного примечание: нет разумного способа. Даже удаленный вызов chdirчерез ptraceотладчик не будет работать, как в большинстве оболочек, потому что им не нравится, когда их текущий каталог изменяется под их ногами.


Э-э, я думаю, что «Вы просто не можете этого сделать» неправильно. См. Ответ @Yeo: unix.stackexchange.com/a/291973/176350
XML

@XML Ответ Йео делает что-то другое, что не тот вопрос, о котором просит вопрос.
Жиль "ТАК ... перестать быть злым"

7

Ты не можешь Подпроцесс (например make) не может изменить среду своего родительского процесса.

Вы могли бы сделать что-то вроде

$ eval `make pathupdate`

Где pathupdateвыглядит цель:

pathupdate:
    @echo PATH=\"$(PATH)\"

6

Ваш ответ можно найти здесь: https://stackoverflow.com/a/8942216/367461

По сути, вы должны сделать это:

export PATH := $(shell pwd)/bin:$(PATH)

test:
    mkdir -p ./bin
    @echo $(PATH)

Я проверил это на Fedora 23 с GNU Make 4.0, и он отлично работает для меня.


1
Это правильный ответ для GNU Make. Для BSD Make вы можете использовать, .SHELL: name=sh path=/path/to/wrapper-scriptа затем создать скрипт-обертку, напримерexport FOO=bar; exec bash "$@"
rjh

2

Я собираюсь задать тот же вопрос, потому что я не смог заставить работать другой пример ответа.

Однако мне удалось добиться рабочего решения для меня с помощью evalкоманды. Я не слишком уверен, почему это не было опубликовано ранее.

do_something: 
    $(eval export PATH=$(shell pwd)/bin:$(PATH))
    @echo $(PATH)

Примечание: PATHизменения являются временными в самой программе. После выхода из make, PATH сбрасывается на более раннее значение.


Это не было опубликовано ранее, потому что это не то, что спрашивает вопрос: вопрос спрашивает, как получить измененный PATH после выхода из make. Кроме того, это может быть сделано гораздо проще: поставить export PATH=…на do_something:линию, вам не нужно eval.
Жиль "ТАК - перестать быть злым"

1

Вы можете заставить Make рекурсивно вызывать себя в измененной среде, например:

dummy: build_all

all: 
    PATH=/new/directory:$(PATH) $(MAKE) build_all

build_all:
    your make rules 

Если вы хотите использовать фрагмент оболочки:

dummy: build_all

all:
    . ./define-my-variables.sh ; $(MAKE) build_all

build_all:
   your make rules
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.