Cách đặt biến môi trường của tiến trình con trong Makefile


134

Tôi muốn thay đổi Makefile này:

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

đến:

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

Thật không may, cái thứ hai không hoạt động (quá trình nút vẫn chạy với mặc định NODE_ENV.

Tôi đã bỏ lỡ cái gì?

Câu trả lời:


153

Làm cho các biến không được xuất vào môi trường của các tiến trình thực hiện các lệnh gọi ... theo mặc định. Tuy nhiên, bạn có thể sử dụng make exportđể buộc họ làm như vậy. Thay đổi:

test: NODE_ENV = test

đến đây:

test: export NODE_ENV = test

(giả sử bạn có phiên bản GNU đủ hiện đại, tạo> = 3,77).


3
Tôi có GNU tạo 3,81 và all: <\n\t>export PROJ_ROOT=$(CURDIR)<\n\t>echo $(PROJ_ROOT)<\n>xuất ra bản mở rộng chính xác cho hàng đầu tiên, nhưng chỉ echocho hàng thứ hai. PROJ_ROOTkhông được đặt sau khi chạy make. Khoảng cách xung quanh =cho "tên biến xấu" để xuất. Có hàng đầu tiên là điều kiện tiên quyết như trong ví dụ của bạn sẽ cho "các lệnh bắt đầu trước mục tiêu đầu tiên"
Gauthier

8
@Gauthier có tất nhiên. Đó không phải là những gì tôi đã viết. Bạn đã thêm <\ n \ t> sau all:, không có trong ví dụ của tôi. Ví dụ của tôi dự định sẽ được sử dụng như văn bản: nó xác định một biến cụ thể đích, KHÔNG thêm lệnh vào công thức. Ngoài ra, bạn không thể sử dụng một công thức và một biến cụ thể cho mục tiêu cùng một lúc: bạn phải viết mục tiêu hai lần. Xem ví dụ thứ hai trong câu hỏi và hỏi một câu hỏi mới nếu điều này không giúp giải thích nó: không có đủ không gian hoặc định dạng trong các bình luận.
MadSellectist

1
Còn nhiều biến số thì sao?
thánh

1
Điều đó tốt nhưng bạn đã thêm nó vào đầu mục tiêu. Chỉ liệt kê chúng trong bối cảnh mục tiêu sẽ không hoạt động? Bởi vì nó không hoạt động với tôi
holms

2
Các biến đặc trưng cho mục tiêu đã được thêm vào trong GNU make 3.77. Chúng có thể xuất được như GNU tạo ra 3,81. Xem git.savannah.gnu.org/cgit/make.git/tree/NEWS
MadSellectist

79

Như MadSellectist đã chỉ ra , bạn có thể xuất các biến riêng lẻ bằng:

export MY_VAR = foo  # Available for all targets

Hoặc xuất các biến cho một mục tiêu cụ thể ( các biến cụ thể theo mục tiêu ):

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

Bạn cũng có thể chỉ định .EXPORT_ALL_VARIABLESmục tiêu để bạn đoán nó! Bạn có thể đoán được tất cả những điều đó !!!

.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

xem .EXPORT_ALL_VARIABLES


2
Thật kỳ lạ là tôi đã kiểm tra nó sớm hơn cho thấy nó hoạt động .. (không hiểu tại sao bây giờ ..) Tôi có thể quay lại và xóa nhận xét tôi đoán ..
AnthonyC

3
@AnthonyC Nó hoạt động vì có hai MY_VARs: một là biến makefile được truy cập ${MY_VAR}và một biến khác là biến xuất bash, được truy cập dưới dạng$$MY_VAR
Sergei

Hữu ích. Nhưng không thể tìm ra cách chỉ xuất một tập hợp các biến.
Eric Chen

15

Tôi chỉ cần các biến môi trường cục bộ để gọi lệnh thử nghiệm của mình, đây là một ví dụ thiết lập nhiều lọ môi trường trong vỏ bash và thoát khỏi ký hiệu đô la make.

SHELL := /bin/bash

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

6
Vui lòng chỉnh sửa câu trả lời của bạn để bao gồm một số lời giải thích. Các câu trả lời chỉ có mã làm rất ít để giáo dục các độc giả SO tương lai. Câu trả lời của bạn là trong hàng đợi kiểm duyệt vì chất lượng thấp.
mickmackusa

ThorSummoner, giải pháp này không linh hoạt như cách tiếp cận ở trên. Ví dụ, người ta có thể muốn có một quy tắc duy nhất để gọi một lệnh và sau đó một số quy tắc khác sửa đổi hành vi đó bằng cách đặt các biến môi trường. Xem xét: test: cmd perf: export PERF = "yes" perf: test Nếu 'cmd' phức tạp (và thường là như vậy), thì cách tiếp cận này dễ duy trì hơn rất nhiều. Cách tiếp cận của bạn để thiết lập biến môi trường trong quy tắc cmd làm cho điều này trở nên khó khăn hơn.
Keith Hanlan

1

Tôi sẽ viết lại bài kiểm tra mục tiêu ban đầu, quan tâm đến biến cần thiết được xác định trong QUY TRÌNH CÙNG như là ứng dụng để khởi chạy:

test:
    ( NODE_ENV=test mocha --harmony --reporter spec test )
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.