กระบวนการทดแทนใน GNU Makefiles


11

ในการพร้อมท์ bash เราสามารถเรียกใช้ diff โดยใช้ไฟล์หลอก:

diff <(echo test) <(echo test)

การเพิ่มสิ่งนี้ตามที่เป็นลงใน Makefile ล้มเหลว:

all:
        diff <(echo test) <(echo test)

ข้อผิดพลาด (คำใบ้: / bin / sh ชี้ไปที่ / bin / bash ในระบบนี้):

/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `diff <(echo test) <(echo test)'

มันหมายความว่าอย่างไรและมีวิธีที่จะยังคงแตกต่างสองเอาต์พุตโดยไม่ใช้ไฟล์ชั่วคราวหรือไม่?

คำตอบ:


20

/bin/shอาจจะเป็นbashในระบบของคุณ แต่เมื่อเรียกว่าเป็นsh, bashจะทำงานในโหมด POSIX (เช่นถ้าPOSIXLY_CORRECTถูกกำหนดหรือมันเริ่มต้นด้วย--posix)

ในโหมดนี้การทดแทนกระบวนการไม่มีอยู่

Solutions:

all:
    command1 >file1
    command2 >file2
    diff file1 file2
    rm -f file1 file2

ทางเลือก:

all:
    bash -c "diff <(command1) <(command2)"

หรือเพียงแค่กำหนดตัวแปร Makefile SHELLเป็น/bin/bash:

SHELL=/bin/bash

ถ้าคุณต้องการพกพาไปด้วยวิธีแรก หากคุณตกลงกับการพึ่งพาbashให้เลือกที่สอง หากคุณไม่จำเป็นต้องสนใจเกี่ยวกับmakeการใช้งานที่ไม่ใช่ของ GNU ให้ใช้ส่วนที่สาม


การตั้งค่าเกี่ยวกับSHELL: มาตรฐาน POSIX กล่าวว่า executables ใน Makefiles ควรจะเรียกด้วยsystem()ฟังก์ชั่นห้องสมุด C makeโดย ฟังก์ชั่นนี้ไม่รับประกันว่าจะใช้SHELLตัวแปรสภาพแวดล้อม (อันที่จริงแล้วการทำเช่นนั้นถูกทำให้หมดกำลังใจโดยมาตรฐาน) มาตรฐานยังไปกับความยาวบางส่วนที่จะบอกว่าการตั้งค่าตัวแปร Makefile SHELLไม่ควรส่งผลกระทบต่อตัวแปรสภาพแวดล้อม SHELLในการใช้งานส่วนใหญ่ของmakeที่ฉันรู้ แต่ตัวแปร Makefile SHELLจะถูกใช้ในการดำเนินการคำสั่ง

คำแนะนำในRationale สำหรับmakeยูทิลิตี้คือการใช้bash -c:

MAKESHELLคุณลักษณะประวัติและคุณลักษณะที่เกี่ยวข้องที่จัดเตรียมโดยmakeการนำไปใช้งานอื่นถูกละเว้น ในการใช้งานบางอย่างมันถูกใช้เพื่อให้ผู้ใช้แทนที่เชลล์ที่จะใช้ในการเรียกใช้makeคำสั่ง นี่คือความสับสน; สำหรับพกพาmakeเชลล์ควรเลือกโดยผู้เขียน makefile เพิ่มเติมตัวเขียน makefile ไม่สามารถต้องการเชลล์สำรองที่จะใช้และยังคงพิจารณา makefile portable ในขณะที่มันเป็นไปได้ที่จะสร้างมาตรฐานกลไกสำหรับการระบุเชลล์สำรองการใช้งานที่มีอยู่ไม่เห็นด้วยกับกลไกดังกล่าวและผู้เขียน makefile สามารถเรียกเชลล์สำรองแล้วโดยระบุชื่อเชลล์ในกฎสำหรับเป้าหมาย; ตัวอย่างเช่น:

python -c "foo"


มีวิธีที่จะเรียกใช้bashใน Makefile หรือวิธีแก้ไขปัญหาอื่น ๆ ของ diff โดยไม่ต้องใช้ไฟล์ชั่วคราวหรือไม่?
โยฮันเนส

เพียงใช้ไฟล์ชั่วคราวสองไฟล์นี่เป็นวิธีการทดแทนกระบวนการที่จะทำภายใต้ประทุนมากขึ้นหรือน้อยลง
Kusalananda

3
คุณสามารถตั้งค่าSHELLเป็น/bin/bashใน Makefile ได้เช่นกัน
สตีเฟ่น Kitt

1
@Johannes Kusalananda เพิ่มข้อมูลลงในคำตอบของเขาซึ่งยอดเยี่ยมมากเพราะมันมีตัวเลือกมากมายและสถานการณ์ที่สามารถใช้งานได้ ฉันอยากให้คุณยอมรับคำตอบนี้ ... (แต่ฉันรู้สึกซาบซึ้งในความรู้สึก!)
สตีเฟ่น Kitt

2
ข้อมูลที่ใช้ตัวแปร SHELL นั้นไม่สอดคล้องกับ POSIX มีประโยชน์มาก bash -cบางทีมันอาจจะยังคงดีกว่าที่จะใช้
โยฮันเนส
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.