Makefile ifeq ตรรกะหรือ


95

คุณดำเนินการตรรกะหรือโดยใช้ifeqตัวดำเนินการของ make ได้อย่างไร

เช่นฉันมี (ตัวย่อ):

ifeq ($(GCC_MINOR), 4)
    CFLAGS += -fno-strict-overflow
endif
ifeq ($(GCC_MINOR), 5)
    CFLAGS += -fno-strict-overflow
endif

แต่ต้องการรวมบรรทัดเหล่านี้

(ใช่ใช่เครื่องมืออัตโนมัติกำหนดค่า ฯลฯ ฯลฯ มือหนักเกินไปสำหรับสถานการณ์ปัจจุบันต้องการเก็บทุกอย่างไว้ใน Makefile ที่นี่)

[ตรรกะตรงข้ามกับคำถามนี้: วิธีใช้หลายเงื่อนไขในคำสั่ง 'ifeq' ]



1
อย่าคิดว่ามันเป็นการหลอกลวงคำถามที่เชื่อมโยงเกี่ยวข้องกับifdefตัวดำเนินการแบบโซ่คำถามนี้เกี่ยวข้องกับifeqตัวดำเนินการโซ่คล้ายกัน แต่คำตอบนั้นแตกต่างกันอย่างแน่นอน
แพ็ต

คำตอบ:


105

ตามที่พบในที่เก็บรายชื่ออีเมล

สามารถใช้filterฟังก์ชันนี้ได้

ตัวอย่างเช่น

ifeq ($(GCC_MINOR),$(filter $(GCC_MINOR),4 5))

filter X, A Bจะส่งคืนค่า A, B ที่เท่ากับ X หมายเหตุแม้ว่าจะไม่เกี่ยวข้องกับตัวอย่างข้างต้น แต่เป็นการดำเนินการ XOR เช่นถ้าคุณมีสิ่งที่ต้องการแทน:

ifeq (4, $(filter 4, $(VAR1) $(VAR2)))

แล้วทำเช่นmake VAR1=4 VAR2=4กรองจะกลับซึ่งไม่เท่ากับ4 44

รูปแบบที่ดำเนินการ OR แทนคือ:

ifneq (,$(filter $(GCC_MINOR),4 5))

ซึ่งใช้การเปรียบเทียบเชิงลบกับสตริงว่างแทน ( filterจะส่งคืนสตริงว่างหากGCC_MINORไม่ตรงกับอาร์กิวเมนต์) การใช้VAR1/ VAR2ตัวอย่างจะมีลักษณะดังนี้:

ifneq (, $(filter 4, $(VAR1) $(VAR2)))

ข้อเสียของวิธีการเหล่านั้นคือคุณต้องแน่ใจว่าอาร์กิวเมนต์เหล่านี้จะเป็นคำเดียวเสมอ ตัวอย่างเช่น if VAR1is 4 fooผลลัพธ์ตัวกรองยังคงเป็น4และifneqนิพจน์ยังคงเป็นจริง ถ้าVAR1เป็น4 5ผลการกรองจะเป็น4 5และifneqนิพจน์เป็นจริง

ทางเลือกหนึ่งที่ง่ายคือการดำเนินการเดียวกันทั้งในifeqและelse ifeqสาขาเช่นนี้:

ifeq ($(GCC_MINOR),4)
    @echo Supported version
else ifeq ($(GCC_MINOR),5)
    @echo Supported version
else
    @echo Unsupported version
endif

7
หมายเหตุ: ในสองรูปแบบที่คุณมีข้างต้นตัวแรกจะเปลี่ยนเป็นจริงถ้า $ (GCC_MINOR) ว่างเปล่าในขณะที่ตัวที่สองจะไม่ (ดังนั้นอันที่สองเป็นวิธีการแก้ปัญหาที่ดีกว่าโดยทั่วไป)
จอห์น

1
ที่จริงมันควรจะเป็นifneq (,$(filter 4 5,$(GCC_MINOR))):)
Tuxdude

2
บางทีอาจจะดีกว่าที่จะปล่อยให้เป็นไปเพื่อความเรียบง่าย?
Jason

หมายเหตุอื่น: สิ่งนี้ใช้ไม่ได้เป็นคำสั่ง OR ทั่วไป เรามีบางอย่างที่อยากตรวจสอบif(flagA == TRUE || flagB == true)แต่ถ้าคุณทำ$(filter true, $(flagA) $(flagB)และทั้งสองอย่างเป็นจริงคุณจะได้รับifeq(true, true true)
Charlie Su

27

คุณสามารถแนะนำตัวแปรอื่นได้ มันไม่ได้รวมการตรวจสอบทั้งสอง แต่อย่างน้อยก็หลีกเลี่ยงที่จะต้องใส่เนื้อหาสองครั้ง:

do_it = 
ifeq ($(GCC_MINOR), 4)
    do_it = yes
endif
ifeq ($(GCC_MINOR), 5)
    do_it = yes
endif
ifdef do_it
    CFLAGS += -fno-strict-overflow
endif

7
ความสามารถในการบำรุงรักษาในระดับนี้ดูเหมือนจะไม่ค่อยดีสำหรับฉัน: / จากนั้นอีกครั้งเมื่อเราเริ่มพูดถึงมาตราส่วนฉันเดาว่าเรากำลังพูดถึงเครื่องมืออัตโนมัติ
แพต

2
@ แพท: ฉันชอบวิธีนี้มากกว่าที่ฉันสามารถแยกงานออกจากที่เดียวใน Makefile ซึ่งอาจจะเปรียบเทียบกับค่าที่มากกว่าโดยใช้ ifeq / else ifeq / else แทนที่จะใช้ฟังก์ชันตัวกรองที่ทำให้อ่านบรรทัดได้ยากมาก .
jcarballo

15

ฉันไม่คิดว่าจะมีวิธีที่รัดกุมและสมเหตุสมผลในการทำเช่นนั้น แต่มีวิธีที่ละเอียดและสมเหตุสมผล (เช่นของ Foo Bah) และวิธีที่กระชับและเป็นพยาธิวิทยาเช่น

ifneq (,$(findstring $(GCC_MINOR),4-5))
    CFLAGS += -fno-strict-overflow
endif

(ซึ่งจะดำเนินการคำสั่งโดยที่สตริง $ (GCC_MINOR) ปรากฏภายในสตริง 4-5)


4
ให้ดีขึ้นหรือแย่ลง (อาจแย่กว่านั้น) ก็แค่แฮ็คสกปรกที่ฉันกำลังมองหา ขอบคุณ
พาท

1
ฉันไม่คิดว่านี่เป็นพยาธิสภาพเลยนอกจากข้อเท็จจริงที่ว่าทุกอย่างใน Makefile เป็นพยาธิสภาพ มันค่อนข้างสง่างามจริงๆ ฉันได้อ่านสี่หรือห้าวิธีในการทำสิ่งนี้ให้สำเร็จและของคุณเป็นวิธีที่เข้าใจง่ายที่สุด
Michael Geary

8

ตัวแปรที่ยืดหยุ่นกว่านี้: ใช้เชลล์ภายนอก แต่อนุญาตให้ตรวจสอบเงื่อนไขโดยพลการ:

ifeq ($(shell test ".$(GCC_MINOR)" = .4  -o  \
                   ".$(GCC_MINOR)" = .5  -o  \
                   ".$(TODAY)"     = .Friday  &&  printf "true"), true)
    CFLAGS += -fno-strict-overflow
endif

1
ifeq ($(GCC_MINOR), 4)
    CFLAGS += -fno-strict-overflow
endif
ifeq ($(GCC_MINOR), 5)
    CFLAGS += -fno-strict-overflow
endif

อีกอย่างที่คุณสามารถพิจารณาใช้ในกรณีนี้คือ:

GCC42_OR_LATER = $(shell $(CXX) -v 2>&1 | $(EGREP) -c "^gcc version (4.[2-9]|[5-9])")

# -Wstrict-overflow: http://www.airs.com/blog/archives/120
ifeq ($(GCC42_OR_LATER),1)
  CFLAGS += -Wstrict-overflow
endif

จริงๆแล้วฉันใช้รหัสเดียวกันนี้ในรหัสของฉันเพราะฉันไม่ต้องการแยกต่างหากconfigหรือConfigure.

แต่คุณต้องใช้แบบพกพาที่ไม่ใช่โรคโลหิตจางmakeเช่น GNU แต่งหน้า ( gmake) และไม่ makePosix

และไม่ได้กล่าวถึงปัญหาของตรรกะANDและOR.

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