คุณสามารถสร้าง Makefiles ที่ถูกต้องโดยไม่มีอักขระแท็บได้หรือไม่?


114
target: dependencies
    command1
    command2

ในระบบของฉัน (Mac OS X) makeดูเหมือนว่าจะกำหนดให้ Makefiles มีอักขระแท็บที่นำหน้าเนื้อหาของแต่ละcommandบรรทัดหรือแสดงข้อผิดพลาดทางไวยากรณ์

นี่เป็นสิ่งที่น่ารำคาญเมื่อสร้างหรือแก้ไข Makefiles เพราะฉันตั้งค่าตัวแก้ไขให้เป็น all-space-all-the-time

คุณสามารถสร้าง Makefiles ที่ถูกต้องโดยไม่มีอักขระแท็บได้หรือไม่?


4
ฉันยังได้กำหนดค่าตัวแก้ไขของฉันให้เลียนแบบแท็บด้วยช่องว่าง แต่ตัวแก้ไขของฉันยังอนุญาตให้ฉันพิมพ์ Ctrl-Tab ในโอกาสที่หายากเมื่อฉันต้องมีแท็บในเชิงบวกเช่นเดียวกับใน Makefiles บางทีบรรณาธิการของคุณก็ทำได้เช่นกัน
เครื่องมือ

คำตอบ:


118

นี่คือเหตุการณ์ที่แปลกประหลาดไวยากรณ์ / ความต้องการของmakeมันมีอะไรจะทำอย่างไรกับ Mac OS X ได้ makeแต่มีอะไรที่คุณสามารถทำกับมันถ้าคุณจะไปกับการใช้งาน

แก้ไข : GNU Make รองรับคำนำหน้าสูตรที่กำหนดเองแล้ว ดูคำตอบนี้

คุณไม่ใช่คนแรกที่ไม่ชอบแง่มุมmakeนี้ หากต้องการอ้างอิงคู่มือ Unix Haters ' :

ปัญหาเกี่ยวกับ Makefile ของ Dennis คือเมื่อเขาเพิ่มบรรทัดความคิดเห็นเขาแทรกช่องว่างก่อนอักขระแท็บที่จุดเริ่มต้นของบรรทัดที่ 2 โดยไม่ได้ตั้งใจอักขระแท็บเป็นส่วนที่สำคัญมากของไวยากรณ์ของ Makefiles บรรทัดคำสั่งทั้งหมด (บรรทัดที่ขึ้นต้นด้วย cc ในตัวอย่างของเรา) ต้องขึ้นต้นด้วยแท็บ หลังจากที่เขาทำการเปลี่ยนแปลงบรรทัดที่ 2 ไม่ได้เกิดข้อผิดพลาด

“ แล้วไง” คุณถามว่า "นั่นมันอะไรกัน"

ไม่มีอะไรผิดปกติกับมันโดยตัวมันเอง เป็นเพียงแค่ว่าเมื่อคุณพิจารณาว่าเครื่องมือการเขียนโปรแกรมอื่น ๆ ทำงานอย่างไรใน Unix การใช้แท็บเป็นส่วนหนึ่งของไวยากรณ์ก็เหมือนกับหนึ่งในกับดัก pungee stick ใน The Green Berets: เด็กที่น่าสงสารจากแคนซัสกำลังเดินไปข้างหน้าจอห์นเวย์นและทำไม่ได้ มองไม่เห็นสายการเดินทาง ท้ายที่สุดไม่มีสายการเดินทางที่ต้องระวังในไร่ข้าวโพดแคนซัส ตี!


5
ปัญหาเกี่ยวกับแท็บเป็นสิ่งแรก ๆ ที่ทุกคนใช้ make learns - ฉันไม่เคยพบว่ามันเป็นปัญหาจริง

2
@ นีลฉันไม่: ฉันไม่เคยบอกว่าฉันเห็นด้วยกับ UHH ฉันแค่บอกว่าบางคนไม่ชอบมัน :-)
Alok Singhal

2
ดูเหมือนปลั๊กที่ดีสำหรับการใช้ cmake ไม่ใช่สิ่งเดียวที่น่าผิดหวังในการสร้างไวยากรณ์
orodbhen

3
ฉันเพิ่งพบgnu.org/software/make/manual/html_node/Special-Variables.html (ดู.RECIPEPREFIX) หนึ่งในคำตอบด้านล่างยังระบุว่าและควรทำเครื่องหมายว่า "ถูกต้อง" แทนคำตอบของฉัน stackoverflow.com/a/21920142
Alok Singhal

3
ไม่ใช่ปัญหาใหญ่ แต่สร้างความรำคาญใจ ทุกครั้ง มันน่ารำคาญอย่างน่าเชื่อถือและมันน่ารำคาญใน \ omicron linear time
Parthian Shot

60

ในช่วงเวลาที่ถามคำถามนี้ในตอนแรก GNU Make เวอร์ชันได้รับการเผยแพร่ซึ่งช่วยให้คุณสามารถใช้สิ่งอื่นที่ไม่ใช่Tabอักขระนำหน้าได้ จากประกาศรายชื่อผู้รับจดหมาย :

ตัวแปรพิเศษใหม่: .RECIPEPREFIX ช่วยให้คุณสามารถรีเซ็ตอักขระแนะนำสูตรอาหารจากค่าเริ่มต้น (TAB) เป็นอย่างอื่นได้ อักขระตัวแรกของค่าตัวแปรนี้คืออักขระแนะนำสูตรอาหารใหม่ ถ้าตัวแปรถูกตั้งค่าเป็นสตริงว่าง TAB จะถูกใช้อีกครั้ง สามารถตั้งค่าและรีเซ็ตได้ตามต้องการ สูตรอาหารจะใช้ค่าที่ใช้งานอยู่เมื่อมีการแยกวิเคราะห์ครั้งแรก ในการตรวจจับคุณสมบัตินี้ให้ตรวจสอบค่า $ (. RECIPEPREFIX)

ฟีเจอร์นี้ถูกเพิ่มใน GNU Make 3.82 ซึ่งเปิดตัวในเดือนกรกฎาคม 2010 (หกเดือนหลังจากวันที่ถามเดิมของคำถามนี้) เนื่องจากเป็นเวลาสามปีและมีการเปลี่ยนแปลงตั้งแต่นั้นจึงมีแนวโน้มว่า Make รสชาติอื่น ๆ จะตาม GNU Make


51

มีวิธีที่ซับซ้อนในการมี makefile ที่ถูกต้องโดยไม่มีแท็บ

หากคุณเปลี่ยน makefile เป็นอ่าน:

target: dependencies; command1; command2

ถ้าจะทำงาน. หากคุณต้องการมากกว่าหนึ่งบรรทัดคุณสามารถทำได้:

target: dependencies; \
command1; \
command2

ยุ่ง แต่ได้ผล


การอัปเกรดเป็นเวอร์ชันของ Make ที่รองรับ.RECIPEPREFIXน่าจะเป็นแนวทางที่ดีที่สุด อย่างไรก็ตามเนื่องจากฉันไม่รู้สึกอยากทำเช่นนั้นฉันจึงใช้วิธีแก้ปัญหาตามวิธีนี้ บรรทัดที่ 1 target:\ :, บรรทัดที่ 2: [การเยื้องสี่ช่องว่าง] ตามด้วย;command
LS

33

หากคุณมี vimrc ในโปรไฟล์ของคุณคุณสามารถเพิ่มบรรทัดนี้เพื่อป้องกันไม่ให้ vim เปลี่ยนเป็นช่องว่าง:

autocmd FileType make setlocal noexpandtab

ฉันก็กำลังดิ้นรนกับเรื่องนี้เช่นกันและสิ่งนี้ได้รับการแก้ไขแล้วสำหรับฉัน กระจายคำดี!


19

สำหรับฉันถ้าคุณต้องการใช้ช่องว่าง

.RECIPEPREFIX +=

ตัวอย่าง


รุ่นใดรองรับสิ่งนี้ สิ่งนี้ใช้ไม่ได้ใน GNU Make 4.1
Cerin

2
GNU Make 4.1 สร้างขึ้นสำหรับ x86_64-pc-linux-gnu ฉันขอโทษ แต่มันใช้งานได้
neok

อาจจำเป็นต้องมีการกล่าวถึงตัวแปรนี้จะต้องมีการประกาศภายใน make file เอง (จุดนำหน้าไม่ง่ายที่จะมองเห็น)
urusai_na

อย่างน้อยในเวอร์ชัน 4.2 สิ่งนี้ควรใช้งานได้ เอกสารระบุในคำอธิบาย.RECIPEPREFIXว่า "หากตัวแปรว่างเปล่า ( ตามค่าเริ่มต้น ) อักขระนั้นคืออักขระแท็บมาตรฐาน" ซึ่งหมายความว่าตัวแปรถูกกำหนดโดยค่าเริ่มต้น ifeq ($(origin .RECIPEPREFIX), undefined)มันได้รับการยืนยันโดยใช้ เนื่องจาก+=ผนวกช่องว่างเดียวและ rhs เข้ากับ lhs จึงvar +=ตั้งค่าvarเป็นช่องว่างเดียว (บวกสตริงว่าง) ตราบเท่าที่varได้กำหนดไว้แล้ว (หากvarไม่ได้กำหนดไว้+=จะเหมือนกับ=)
ynn

1
คำตอบนี้ใช้ไม่ได้อีกต่อไป ดูคำตอบของฉันสำหรับโซลูชันล่าสุด
YNN

11

ในโหมดแทรกของกลุ่มหนึ่งสามารถใช้Ctrl-v <TAB>เพื่อแทรกแท็บตัวอักษรได้แม้ว่าคุณจะตั้งค่าแป้นแท็บเพื่อแทรกช่องว่างก็ตาม แน่นอนว่านี่ไม่ได้ตอบคำถามของคุณ แต่อาจเป็นอีกทางเลือกหนึ่งสำหรับวิธีการที่มีเพื่อหลีกเลี่ยงการใช้แท็บตามตัวอักษร


10

หากคุณใช้EditorConfigคุณสามารถเพิ่มบรรทัดต่อไปนี้ใน.editorconfigไฟล์ของคุณเพื่อบังคับให้ IDE ของคุณใช้แท็บสำหรับการเยื้องแทนช่องว่างในMakefile:

[Makefile]
indent_style = tab

4

ถึง GNU Make 4.2

คำตอบของ Steven Penny ได้ผล

.RECIPEPREFIX +=

เหตุผลที่ว่าทำไมงานนี้ได้อธิบายไว้ในความคิดเห็นของฉัน


ตั้งแต่ GNU Make 4.3 (เผยแพร่เมื่อ 19 ม.ค. 2020)

พฤติกรรมของ+=ตัวดำเนินการได้รับการเปลี่ยนแปลงในลักษณะที่ไม่สามารถใช้ร่วมกันได้ ถ้าตัวถูกดำเนินการด้านซ้ายมีค่าว่างช่องว่างจะไม่ถูกเพิ่มอีกต่อไป

คุณสามารถใช้ไฟล์

.RECIPEPREFIX := $(.RECIPEPREFIX)<space>

ซึ่ง<space>เป็นพื้นที่เดียว แม้ว่าจะ$(.RECIPEPREFIX)มีการขยายเป็นค่าว่างส่วนนี้เป็นสิ่งจำเป็นที่จะไม่ให้ GNU <space>ทำให้ไม่สนใจ โปรดทราบว่ารหัสนี้ใช้งานได้แม้ใน GNU Make เก่ากว่าเวอร์ชัน 4.3


1

ใน ubuntu: vi Makefiles แทนที่ช่องว่างตามแท็บ (หรือสิ่งอื่นที่คุณต้องการ):

:%s/<space chars>/^I/g

สำหรับ ex แทนที่ 8 ช่องว่างโดยแท็บ:

:%s/        /^I/g

ให้ความสนใจ: ^ ฉันแทรกด้วยแป้นแท็บไม่ใช่^และฉันอักขระ: D


-6

ไม่สามารถพกพาได้ รสชาติบางอย่างของการทำต้องใช้อักขระแท็บอย่างแน่นอน อีกเหตุผลหนึ่งที่เลือกใช้แท็บมากกว่าช่องว่าง :-)

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