วิธีตั้งค่าตัวแปรสภาพแวดล้อมของกระบวนการลูกใน 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(กระบวนการโหนดยังคงทำงานกับการเริ่มต้น

ฉันพลาดอะไร?


Unfortunatelyความคิดเห็นของคุณเกิดจากความเข้าใจผิดระหว่างตัวแปรสภาพแวดล้อมกับMakefileตัวแปร วิธีที่ดีที่สุดในการพิสูจน์ว่ามีการตั้งค่าตัวแปรสภาพแวดล้อมคือการสอบถามตัวแปรสภาพแวดล้อมนี้ภายในโปรแกรมอื่นที่จะmakeเรียกใช้ การทำecho $(BLAH)เพียงแค่ประเมินกลไกคีย์ / ค่าของ Makefile ภายใน Makefile เท่านั้น ใน python คุณสามารถprint(os.getenv("MURDOC")) ค้นหาตัวแปรสภาพแวดล้อมได้อย่างแท้จริง
truthadjustr

คำตอบ:


154

ทำให้ตัวแปรไม่ถูกส่งออกไปในสภาพแวดล้อมของกระบวนการทำให้เรียกใช้ ... ตามค่าเริ่มต้น อย่างไรก็ตามคุณสามารถใช้ 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 ช่องว่างรอบ ๆ=ให้ "ชื่อตัวแปรที่ไม่ถูกต้อง" สำหรับการส่งออก การมีแถวแรกเป็นสิ่งที่จำเป็นต้องมีในตัวอย่างของคุณจะทำให้ "คำสั่งเริ่มก่อนเป้าหมายแรก"
Gauthier

8
@Gauthier ใช่แน่นอน นั่นไม่ใช่สิ่งที่ฉันเขียน คุณเพิ่ม <\ n \ t> หลังall:ซึ่งไม่ได้อยู่ในตัวอย่างของฉัน ตัวอย่างของฉันตั้งใจจะใช้เป็นลายลักษณ์อักษร: เป็นการกำหนดตัวแปรเฉพาะเป้าหมายไม่ใช่การเพิ่มคำสั่งลงในสูตรอาหาร นอกจากนี้คุณไม่สามารถใช้สูตรอาหารและตัวแปรเฉพาะเป้าหมายกับเป้าหมายได้ในเวลาเดียวกันคุณต้องเขียนเป้าหมายสองครั้ง ดูตัวอย่างที่สองในคำถามและถามคำถามใหม่หากสิ่งนี้ไม่ช่วยอธิบายได้: มีพื้นที่หรือการจัดรูปแบบในความคิดเห็นไม่เพียงพอ
MadScientist

1
แล้วตัวแปรหลายตัวล่ะ?
Holms

1
ไม่เป็นไร แต่คุณเพิ่มไว้ที่หัวเป้าหมาย แค่แสดงรายการในบริบทของเป้าหมายจะไม่ทำงาน? เพราะมันไม่ได้ผลสำหรับฉัน
Holms

2
เพิ่มตัวแปรเฉพาะเป้าหมายใน GNU ทำให้ 3.77 สามารถส่งออกได้เมื่อ GNU ทำ 3.81 ดูgit.savannah.gnu.org/cgit/make.git/tree/NEWS
MadScientist

80

ดังที่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 export variable เข้าถึงได้เมื่อ$$MY_VAR
Sergei

มีประโยชน์ แต่ไม่สามารถหาวิธีส่งออกเฉพาะชุดของตัวแปรได้.
Eric Chen

14

ผมจำเป็นต้องมีเพียงตัวแปรสภาพแวดล้อมในท้องถิ่นเพื่อเรียกใช้คำสั่งการทดสอบของฉันที่นี่คือตัวอย่างการตั้งค่าสภาพแวดล้อมหลาย vars makeในเปลือกทุบตีและหลบหนีเครื่องหมายดอลลาร์ใน

SHELL := /bin/bash

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

6
โปรดแก้ไขคำตอบของคุณเพื่อให้มีคำอธิบายบางส่วน คำตอบแบบใช้โค้ดเท่านั้นที่จะให้ความรู้แก่ผู้อ่าน SO ในอนาคตน้อยมาก คำตอบของคุณอยู่ในคิวการกลั่นกรองเนื่องจากมีคุณภาพต่ำ
mickmackusa

ThorSummoner วิธีแก้ปัญหานี้ไม่ยืดหยุ่นเท่าวิธีการข้างต้น ตัวอย่างเช่นเราอาจต้องการมีกฎข้อเดียวสำหรับการเรียกใช้คำสั่งและจากนั้นกฎอื่น ๆ อีกหลายกฎที่ปรับเปลี่ยนพฤติกรรมนั้นโดยการตั้งค่าตัวแปรสภาพแวดล้อม ลองพิจารณา: test: cmd perf: export PERF = "yes" perf: test หาก 'cmd' มีความซับซ้อน (และมักจะเป็น) วิธีนี้จะง่ายกว่ามากในการดูแลรักษา แนวทางของคุณในการตั้งค่าตัวแปรสภาพแวดล้อมในกฎ cmd ทำให้ยากขึ้น
Keith Hanlan

1

ฉันจะเขียนการทดสอบเป้าหมายเดิมอีกครั้งโดยดูแลตัวแปรที่จำเป็นจะถูกกำหนดไว้ในกระบวนการย่อยเดียวกันเป็นแอปพลิเคชันที่จะเปิด:

test:
    ( NODE_ENV=test mocha --harmony --reporter spec test )
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.