Як встановити змінну середовища дочірнього процесу в Makefile


135

Я хотів би змінити цей Makefile:

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

boot:
    @supervisor         \
      --harmony         \
      --watch etc,lib       \
      --extensions js,json      \
      --no-restart-on error     \
        lib

test:
    NODE_ENV=test mocha         \
      --harmony             \
      --reporter spec       \
        test

clean:
    @rm -rf node_modules

.PHONY: test clean

до:

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

boot:
    @supervisor         \
      --harmony         \
      --watch etc,lib       \
      --extensions js,json      \
      --no-restart-on error     \
        lib

test: NODE_ENV=test
test:
    mocha                   \
      --harmony             \
      --reporter spec       \
        test

clean:
    @rm -rf node_modules

.PHONY: test clean

На жаль, другий не працює (процес вузла все ще працює за замовчуванням NODE_ENV .

Що я пропустив?

Відповіді:


153

Зробити змінні не експортовані в середовище процесів, робити виклики ... за замовчуванням. Однак ви можете використовувати make's, exportщоб змусити їх робити це. Змінити:

test: NODE_ENV = test

до цього:

test: export NODE_ENV = test

(за умови, що у вас є досить сучасна версія GNU make> = 3,77).


3
У мене GNU складає 3.81, і all: <\n\t>export PROJ_ROOT=$(CURDIR)<\n\t>echo $(PROJ_ROOT)<\n>виводить правильне розширення для першого ряду, але тільки echoдля другого. PROJ_ROOTне встановлюється після запуску make. Проміжки навколо =дають "неправильну назву змінної" для експорту. Перший рядок, який є обов'язковою умовою, як у вашому прикладі, дає "команди починаються перед першою ціллю"
— Готьє

8
@ Goauthier так, звичайно. Це не те, що я написав. Ви додали <\ n \ t> після all:, що не в моєму прикладі. Мій приклад призначений для використання як написаний: це визначення цільової змінної, НЕ додавання команди до рецепту. Крім того, ви не можете одночасно використовувати рецепт та змінну, орієнтовану на ціль, для цілі: вам потрібно написати ціль двічі. Дивіться другий приклад у запитанні та задайте нове запитання, якщо це не допомагає пояснити це: у коментарях недостатньо місця та форматування.
— MadScientist

1
А як щодо кількох змінних?
— Холмс

1
Це добре, але ви додали його до голови мішені. Просто перерахувати їх у контексті цілі не вийде? Тому що це не працює для мене
— розбивається

2
Цільові змінні додані в GNU складають 3,77. Вони можуть експортуватися станом на ВНП 3,81. Дивіться git.savannah.gnu.org/cgit/make.git/tree/NEWS
— MadScientist

79

Як зазначив MadScientist , ви можете експортувати окремі змінні за допомогою:

export MY_VAR = foo  # Available for all targets

Або експортувати змінні для конкретної цілі ( конкретні змінні ):

my-target: export MY_VAR_1 = foo
my-target: export MY_VAR_2 = bar
my-target: export MY_VAR_3 = baz

my-target: dependency_1 dependency_2
  echo do something

Ви також можете вказати .EXPORT_ALL_VARIABLESціль, яку - ви здогадалися! —ЕКСПОРТ ВСІХ РЕЧІВ:

.EXPORT_ALL_VARIABLES:

MY_VAR_1 = foo
MY_VAR_2 = bar
MY_VAR_3 = baz

test:
  @echo $$MY_VAR_1 $$MY_VAR_2 $$MY_VAR_3

див. .EXPORT_ALL_VARIABLES


2
Як не дивно, я тестував його раніше, що показав, що він працював .. (не впевнений, чому зараз ..) Я можу повернутися назад і видалити коментар, я здогадуюсь ..
— AnthonyC

3
@AnthonyC Це працює тому, що є два MY_VARs: одна змінна makefile доступна як, ${MY_VAR}а інша є експортною змінною bash, доступ до якої$$MY_VAR
— Сергій

Корисно. Але не можна знайти спосіб експортувати лише набір змінних.
— Ерік Чен

15

Мені потрібні були лише мінливі середовища локально, щоб викликати мою тестову команду, ось приклад встановлення кількох варіантів середовища в оболонці bash та уникнення знака долара make.

SHELL := /bin/bash

.PHONY: test tests
test tests:
    PATH=./node_modules/.bin/:$$PATH \
    JSCOVERAGE=1 \
    nodeunit tests/

6
Відредагуйте свою відповідь, щоб включити пояснення. Відповіді, що стосуються лише коду, дуже мало навчають майбутніх читачів ЗП. Ваша відповідь знаходиться в черзі на помірність, оскільки вона низька.
— mickmackusa

ThorSummoner, це рішення не є настільки гнучким, як підхід вище. Наприклад, можна мати одне правило для виклику команди, а потім кілька інших правил, які змінюють таку поведінку, встановлюючи змінні середовища. Поміркуйте: test: cmd perf: export PERF = "так" perf: test Якщо "cmd" складний (і він зазвичай є), то такий підхід набагато простіше дотримуватися. Ваш підхід до встановлення змінної середовища в правилі cmd ускладнює це.
— Кіт Ханлан

1

Я б переписав оригінальний цільовий тест, піклуючись про те, щоб потрібна змінна визначена в ІДНІЙ ПІДПРИЄМЦІ як програма для запуску:

test:
    ( NODE_ENV=test mocha --harmony --reporter spec test )
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.