Cara mengatur variabel lingkungan proses anak di Makefile

135

Saya ingin mengubah Makefile ini:

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

untuk:

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

Sayangnya yang kedua tidak berfungsi (proses simpul masih berjalan dengan default NODE_ENV.

Apa yang saya lewatkan?

Bodokaiser
sumber

Jawaban:

153

Jadikan variabel tidak diekspor ke lingkungan proses buat panggil ... secara default. Namun Anda dapat menggunakan make exportuntuk memaksa mereka melakukannya. Perubahan:

test: NODE_ENV = test

untuk ini:

test: export NODE_ENV = test

(dengan asumsi Anda memiliki versi GNU modern yang cukup membuat> = 3,77).

Ilmuwan gila
sumber
3
Saya memiliki GNU make 3.81, dan all: <\n\t>export PROJ_ROOT=$(CURDIR)<\n\t>echo $(PROJ_ROOT)<\n>menampilkan ekspansi yang benar untuk baris pertama, tetapi hanya echountuk yang kedua. PROJ_ROOTtidak diatur setelah menjalankan make. Spasi sekitar =memberi "nama variabel buruk" untuk ekspor. Memiliki baris pertama sebagai prasyarat seperti pada contoh Anda memberikan "perintah dimulai sebelum target pertama"
Gauthier
8
@Authier ya tentu saja. Bukan itu yang saya tulis. Anda menambahkan <\ n \ t> setelah all:, yang tidak ada dalam contoh saya. Contoh saya dimaksudkan untuk digunakan sebagai tertulis: itu mendefinisikan variabel target-spesifik, BUKAN menambahkan perintah ke resep. Anda juga tidak dapat menggunakan resep dan variabel khusus target pada target secara bersamaan: Anda harus menulis target dua kali. Lihat contoh kedua dalam pertanyaan, dan ajukan pertanyaan baru jika ini tidak membantu menjelaskannya: tidak ada cukup ruang atau format dalam komentar.
MadScientist
1
Bagaimana dengan banyak variabel?
holms
1
Itu bagus tapi Anda menambahkannya ke kepala target. Hanya daftar mereka dalam konteks target tidak akan berhasil? Karena itu tidak berhasil untuk saya
holms
2
Variabel spesifik target ditambahkan dalam GNU make 3.77. Mereka dapat diekspor pada GNU make 3.81. Lihat git.savannah.gnu.org/cgit/make.git/tree/NEWS
MadScientist
79

Seperti yang ditunjukkan MadScientist , Anda dapat mengekspor variabel individual dengan:

export MY_VAR = foo  # Available for all targets

Atau ekspor variabel untuk target spesifik ( variabel target-spesifik ):

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

Anda juga dapat menentukan .EXPORT_ALL_VARIABLEStarget untuk — Anda dapat menebaknya! —Ekspor SEMUA HAL !!!

.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

lihat .EXPORT_ALL_VARIABLES

Shammel Lee
sumber
2
Anehnya saya melakukan tes sebelumnya yang menunjukkan itu berhasil .. (tidak yakin mengapa sekarang ..) Saya dapat kembali dan menghapus komentar saya kira ..
AnthonyC
3
@AnthonyC Ini bekerja karena ada dua MY_VARs: satu adalah variabel makefile diakses sebagai ${MY_VAR}dan satu lagi adalah variabel bash diekspor, diakses sebagai$$MY_VAR
Sergei
Berguna. Tetapi tidak dapat menemukan cara untuk mengekspor hanya satu set variabel.
Eric Chen
15

Saya hanya perlu variabel lingkungan secara lokal untuk menjalankan perintah pengujian saya, inilah contoh pengaturan beberapa vars lingkungan dalam bash shell, dan lolos dari dolar masuk make.

SHELL := /bin/bash

.PHONY: test tests
test tests:
    PATH=./node_modules/.bin/:$$PATH \
    JSCOVERAGE=1 \
    nodeunit tests/
ThorSummoner
sumber
6
Harap edit jawaban Anda untuk memasukkan beberapa penjelasan. Jawaban hanya kode tidak banyak membantu mendidik pembaca SO masa depan. Jawaban Anda ada dalam antrian moderasi karena berkualitas rendah.
mickmackusa
ThorSummoner, solusi ini tidak sefleksibel pendekatan di atas. Sebagai contoh, seseorang mungkin ingin memiliki satu aturan tunggal untuk menjalankan perintah dan kemudian beberapa aturan lain yang memodifikasi perilaku itu dengan menetapkan variabel lingkungan. Pertimbangkan: test: cmd perf: export PERF = "yes" perf: test Jika 'cmd' rumit (dan biasanya memang demikian), maka pendekatan ini jauh lebih mudah untuk dipertahankan. Pendekatan Anda untuk mengatur variabel lingkungan di aturan cmd membuat ini lebih sulit.
Keith Hanlan
1

Saya akan menulis ulang tes target asli, mengurus variabel yang diperlukan didefinisikan DALAM PROSES SUB SAMA sebagai aplikasi untuk memulai:

test:
    ( NODE_ENV=test mocha --harmony --reporter spec test )
Guiyo M
sumber