Makefile ifeq logis atau


94

Bagaimana Anda melakukan logika OR menggunakan ifeqoperator make ?

misalnya, saya telah (disederhanakan):

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

tetapi ingin mengkonsolidasikan garis-garis ini.

(ya, ya, autotools, configure, dll dll; terlalu berat untuk situasi saat ini, ingin menyimpan semuanya di dalam Makefile di sini)

[kebalikan logis dari pertanyaan ini: Bagaimana Menggunakan Kondisi Ganda dalam pernyataan 'ifeq' ]



1
Jangan mengira itu penipuan, pertanyaan terkait terkait ifdefoperator rantai , pertanyaan ini terkait ifeqoperator rantai , serupa, tetapi jawabannya pasti berbeda.
Tepuk

Jawaban:


104

Seperti yang ditemukan di arsip milis,

seseorang dapat menggunakan fungsi filter .

Sebagai contoh

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

filter X, AB akan mengembalikan A, B yang sama dengan X.

Variasi dari ini adalah

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

di mana perbandingan negatif terhadap string kosong digunakan sebagai gantinya ( filter akan mengembalikan string kosong jika GCC_MINOR tidak cocok dengan argumen)

Kelemahan dari metode tersebut adalah argumen harus berupa kata-kata tunggal.


7
Catatan terakhir: dalam dua variasi yang Anda miliki di atas, yang pertama akan menjadi true jika $ (GCC_MINOR) kosong, sedangkan yang kedua tidak (jadi yang kedua adalah solusi yang lebih baik secara umum).
Yohanes

1
Sebenarnya, seharusnya ifneq (,$(filter 4 5,$(GCC_MINOR))):)
Tuxdude

2
Mungkin lebih baik membiarkan apa adanya demi kesederhanaan?
Jason

Catatan lain: Ini tidak berfungsi sebagai pernyataan OR umum . Kami memiliki sesuatu yang ingin kami periksa if(flagA == TRUE || flagB == true), tetapi jika Anda melakukannya $(filter true, $(flagA) $(flagB)dan keduanya benar, Anda mendapatkanifeq(true, true true)
Charlie Su

27

Anda bisa memperkenalkan variabel lain. Ini tidak mengkonsolidasikan kedua pemeriksaan, tetapi setidaknya menghindari keharusan menempatkan tubuh dalam dua kali:

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
Pemeliharaan ini pada skala sepertinya tidak terlalu baik bagi saya: / Kemudian lagi, begitu kita mulai berbicara skala, saya kira kita berbicara tentang autotools
Pat

2
@Pat: Saya lebih suka pendekatan ini di mana saya dapat memisahkan tugas di satu tempat di Makefile, mungkin membandingkan dengan lebih banyak nilai menggunakan ifeq / else ifeq / else, daripada menggunakan fungsi filter yang bisa membuat sangat sulit untuk membaca baris .
jcarballo

15

Menurut saya tidak ada cara yang ringkas dan masuk akal untuk melakukan itu, tetapi ada cara yang bertele-tele dan masuk akal (seperti Foo Bah) dan cara patologis yang ringkas, seperti

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

(yang akan menjalankan perintah asalkan string $ (GCC_MINOR) muncul di dalam string 4-5).


4
Baik atau buruk (mungkin lebih buruk), jenis peretasan kotor yang saya cari; terima kasih
Tepuk

1
Saya tidak berpikir ini patologis sama sekali, selain fakta bahwa semua yang ada di Makefile bersifat patologis. Ini sangat elegan. Saya telah membaca empat atau lima cara berbeda untuk mencapai ini, dan cara Anda sejauh ini adalah yang paling mudah dipahami.
Michael Geary

8

Di sini varian yang lebih fleksibel: menggunakan shell eksternal, tetapi memungkinkan untuk memeriksa kondisi arbitrer:

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

Cara lain yang dapat Anda pertimbangkan untuk digunakan dalam kasus ini adalah:

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

Saya sebenarnya menggunakan yang sama dalam kode saya karena saya tidak ingin mempertahankan configatauConfigure .

Tetapi Anda harus menggunakan portabel, non-anemia make, seperti GNU make ( gmake), dan bukan milik Posix make.

Dan itu tidak membahas masalah logis ANDdan OR.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.