Як встановити змінну середовища дочірнього процесу в 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.