ฉันจะเพิ่ม dir ใน $ PATH ใน Makefile ได้อย่างไร


91

ฉันต้องการเขียน Makefile ซึ่งจะเรียกใช้การทดสอบ การทดสอบอยู่ในไดเร็กทอรี "./tests" และไฟล์ปฏิบัติการที่จะทดสอบอยู่ในไดเร็กทอรี "./bin"

เมื่อฉันเรียกใช้การทดสอบพวกเขาไม่เห็นไฟล์ exec เนื่องจากไดเร็กทอรี. / bin ไม่อยู่ใน $ PATH

เมื่อฉันทำสิ่งนี้:

EXPORT PATH=bin:$PATH
make test

ทุกอย่างใช้งานได้ อย่างไรก็ตามฉันต้องการเปลี่ยน $ PATH ใน Makefile

เนื้อหา Makefile อย่างง่าย:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

มันพิมพ์เส้นทางอย่างถูกต้อง แต่ไม่พบไฟล์ x

เมื่อฉันทำสิ่งนี้ด้วยตนเอง:

$ export PATH=bin:$PATH
$ x

ทุกอย่างเรียบร้อยแล้ว

ฉันจะเปลี่ยน $ PATH ใน Makefile ได้อย่างไร


คุณไม่สามารถเรียกการทดสอบจากไดเร็กทอรีปฏิบัติการเช่น../test/test_to_run? ขออภัยหากฉันเข้าใจคำถามผิด
คริส

ฉันต้องการให้การทดสอบมองเห็นไฟล์นี้ได้ตามปกติ ฉันไม่ต้องการเล่นกับไดเร็กทอรีเพราะฉันปรับโครงสร้างใหม่ซึ่งจะเป็นเรื่องใกล้
Szymon Lipiński

วิธีเดียวที่คุณสามารถมาใกล้นี้คือการมีการเขียน Makefile ออกเชลล์สคริปต์ที่มี decls .ตัวแปรแล้วมีแหล่งเปลือกผู้ปกครองว่าสคริปต์ด้วย อย่างไรก็ตามอาจเป็นไปไม่ได้
Michael Smith

ผมเชื่อว่าunix.stackexchange.com/questions/11530/...เป็นแตกต่างกันมาก (โง่) คำถามของคุณแตกต่างจาก
imz - Ivan Zakharyaschev

คำตอบ:


108

คุณลองใช้exportคำสั่ง Make yourself (สมมติว่าคุณใช้ GNU Make) หรือไม่?

export PATH := bin:$(PATH)

test all:
    x

นอกจากนี้ยังมีข้อบกพร่องในตัวอย่างของคุณ:

test all:
    PATH=bin:${PATH}
    @echo $(PATH)
    x

ประการแรกค่าที่echoed คือการขยายPATHตัวแปรที่ดำเนินการโดย Make ไม่ใช่เชลล์ หากพิมพ์ค่าที่คาดไว้ฉันเดาว่าคุณได้ตั้งค่าPATHตัวแปรไว้ก่อนหน้านี้ใน Makefile ของคุณหรือในเชลล์ที่เรียกใช้ Make เพื่อป้องกันพฤติกรรมดังกล่าวคุณควรหลบหนีดอลลาร์:

test all:
    PATH=bin:$$PATH
    @echo $$PATH
    x

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

test all:
    export PATH=bin:$$PATH; echo $$PATH; x

7
$(PATH)จะได้รับการตั้งค่าเป็นค่าของPATHเชลล์ที่เรียกใช้ make ตามคู่มือ "ตัวแปรสภาพแวดล้อมทุกตัวที่เห็นเมื่อเริ่มทำงานจะถูกเปลี่ยนเป็นตัวแปร make ที่มีชื่อและค่าเดียวกัน"
Emil Sit

คำสั่งการส่งออกใช้ได้ผลสำหรับฉัน (ขอบคุณ!) แต่หลังจากฉันติดตั้ง GNU Make 4.3 แล้วเท่านั้น ในรุ่น 3.81 (ค่าเริ่มต้นบน MacOS Catalina), การปรับปรุงPATHจะสะท้อนให้เห็นอย่างถูกต้องในตัวแปร ( echo $(PATH)) และอยู่ในสภาพแวดล้อมที่มีคำสั่ง ( env, which python, bash -c python) แต่ดูเหมือนจะไม่ถูกนำมาใช้เมื่อตำแหน่งปฏิบัติการสำหรับคำสั่ง: คำสั่งpythonยังคงทำงาน PATHปฏิบัติการหลามในต้นฉบับ
บรรยาย

30

ด้วยการออกแบบmakeparser รันบรรทัดในการเรียกใช้เชลล์แยกต่างหากนั่นคือเหตุผลที่การเปลี่ยนตัวแปร (เช่นPATH) ในบรรทัดเดียวการเปลี่ยนแปลงอาจไม่ถูกนำไปใช้กับบรรทัดถัดไป (ดูโพสต์นี้)

วิธีหนึ่งในการแก้ไขปัญหานี้คือการแปลงคำสั่งหลายคำสั่งเป็นบรรทัดเดียว (คั่นด้วย;) หรือใช้เป้าหมายพิเศษOne Shell ( .ONESHELLตาม GNU Make 3.82)

หรือคุณสามารถระบุPATHตัวแปรในเวลาที่เรียกใช้เชลล์ ตัวอย่างเช่น:

PATH  := $(PATH):$(PWD)/bin:/my/other/path
SHELL := env PATH=$(PATH) /bin/bash

2
ฉันชอบแนวทางนี้!
Alan Franzoni

2
นี่เป็นวิธีที่ดีที่สุดเพราะใช้งานได้แม้จะมี$(shell)การเรียกร้องก็ตาม! : D ตัวอย่าง: pastebin.com/Pii8pmkD
PsychoX

ใน dev.azure ฉันได้รับ: env: 'env': ไม่มีไฟล์หรือไดเร็กทอรีดังกล่าว ทำงานในพื้นที่; /
Kamil Dziedzic

ไม่ทำงานบน Debian 10 ด้วย make 4.2: make: env PATH = <path> / bin / sh: ไม่พบคำสั่ง ใช้งานส่งออก ตรวจสอบให้แน่ใจว่าใช้ $ (HOME) ไม่ใช่ ~ สำหรับเส้นทางในบ้าน
MKesper

25

การเปลี่ยนแปลงเส้นทางดูเหมือนจะคงอยู่หากคุณตั้งค่าตัวแปร SHELL ใน makefile ของคุณก่อน:

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

test all:
    x

ฉันไม่รู้ว่านี่เป็นพฤติกรรมที่ต้องการหรือไม่


สิ่งนี้แก้ไขปัญหาที่ฉันพบ (ฉันใช้ zsh) ขอบคุณ!
Jezen Thomas

ใช่นี่ทำในสิ่งที่ OP ต้องการจริงๆ ... แต่มันเป็นคุณสมบัติหรือข้อบกพร่อง แม้ว่าหลังจากอ่านส่วน SHELL ของ make manualแล้วฉันก็ไม่แน่ใจ
pje

5
สิ่งนี้ใช้ไม่ได้กับฉันเช่นกัน whichและenvตอนนี้รับ PATH ใหม่ แต่ยังไม่พบการเรียกใช้ไบนารีโดยตรงใน PATH ที่แก้ไขเฉพาะในเส้นทางเดิม
Konrad Rudolph

3

สิ่งที่ฉันมักจะทำคือระบุเส้นทางไปยังไฟล์ปฏิบัติการอย่างชัดเจน:

EXE=./bin/
...
test all:
    $(EXE)x

ฉันยังใช้เทคนิคนี้เพื่อเรียกใช้ไบนารีที่ไม่ใช่เจ้าของภาษาภายใต้โปรแกรมจำลองเช่น QEMU หากฉันรวบรวมข้าม:

EXE = qemu-mips ./bin/

หาก make ใช้ sh shell สิ่งนี้ควรใช้งานได้:

test all:
    PATH=bin:$PATH x

ใช่ Soulution ที่ยอดเยี่ยม แต่ฉันได้รับการทดสอบที่เขียนด้วยภาษา perl และฉันต้องเรียก exe จากสคริปต์ perl ไม่ใช่โดยตรงจาก makefile ฉันต้องทบทวนการทดสอบทั้งหมดของสิ่งนี้ใหม่ :)
Szymon Lipiński

Gotcha วิธีการตั้งค่า PATH บนบรรทัดคำสั่งเอง? ดูการแก้ไขด้านบน
Richard Pennington

-3

ในการตั้งค่าPATHตัวแปรภายใน Makefile เท่านั้นให้ใช้สิ่งต่อไปนี้

PATH := $(PATH):/my/dir

test:
@echo my new PATH = $(PATH)

มันไม่ได้ผลอย่างที่ฉันต้องการ ฉันได้อัปเดตคำถามพร้อมตัวอย่างสิ่งที่ฉันต้องการบรรลุ
Szymon Lipiński
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.