Makefile ifeq logic hoặc


92

Làm thế nào để bạn thực hiện một logic HOẶC bằng cách sử dụng ifeqtoán tử make ?

ví dụ: tôi có (đơn giản hóa):

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

nhưng muốn hợp nhất những dòng này.

(vâng, vâng, tự động, cấu hình, v.v.; quá nặng tay so với tình hình hiện tại, tôi muốn giữ mọi thứ trong Makefile ở đây)

[đối lập logic với câu hỏi này: Cách sử dụng điều kiện nhiều trong câu lệnh 'ifeq' ]



1
Đừng nghĩ đó là một bản dupe, câu hỏi liên kết liên quan đến các ifdeftoán tử chuỗi , câu hỏi này liên quan đến các ifeqtoán tử chuỗi , tương tự, nhưng câu trả lời chắc chắn là khác nhau.
Pat

Câu trả lời:


103

Như được tìm thấy trong kho lưu trữ danh sách gửi thư,

người ta có thể sử dụng chức năng bộ lọc .

Ví dụ

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

lọc X, AB sẽ trả về A, B bằng X.

Một biến thể của điều này là

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

trong đó phép so sánh phủ định với một chuỗi trống được sử dụng thay thế ( bộ lọc sẽ trả về chuỗi rỗng nếu GCC_MINOR không khớp với các đối số)

Nhược điểm của các phương pháp đó là các đối số phải là các từ đơn.


7
Lưu ý cuối cùng: trong hai biến thể bạn có ở trên, biến thể đầu tiên sẽ chuyển thành true nếu $ (GCC_MINOR) để trống, trong khi biến thể thứ hai thì không (do đó, biến thể thứ hai nói chung là giải pháp tốt hơn).
John

1
Trên thực tế, nó phải là ifneq (,$(filter 4 5,$(GCC_MINOR))):)
Tuxdude

2
Có lẽ tốt hơn là để nguyên như vậy cho đơn giản?
Jason

Một lưu ý khác: Đây không hoạt động như một câu lệnh OR chung . Chúng tôi có một cái gì đó mà chúng tôi muốn kiểm tra if(flagA == TRUE || flagB == true), nhưng nếu bạn làm $(filter true, $(flagA) $(flagB)và cả hai đều đúng, bạn sẽ nhận đượcifeq(true, true true)
Charlie Su

27

Bạn có thể giới thiệu một biến khác. Nó không hợp nhất cả hai lần kiểm tra, nhưng ít nhất nó tránh phải đặt cơ thể vào hai lần:

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
Khả năng bảo trì của điều này trên quy mô có vẻ không tốt cho tôi: / Sau đó, một lần nữa, khi chúng tôi bắt đầu nói về quy mô, tôi đoán chúng tôi đang nói chuyện về tự động
Pat

2
@Pat: Tôi thích cách tiếp cận này hơn, nơi tôi có thể tách bài tập ở một nơi trong Makefile, có thể so sánh với nhiều giá trị hơn bằng cách sử dụng ifeq / else ifeq / else, hơn là sử dụng hàm bộ lọc có thể khiến các dòng khó đọc cực kỳ dài .
jcarballo

15

Tôi không nghĩ có một cách ngắn gọn và hợp lý để làm điều đó, nhưng có những cách dài dòng, hợp lý (chẳng hạn như của Foo Bah) và những cách ngắn gọn, bệnh hoạn, chẳng hạn như

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

(sẽ thực thi lệnh với điều kiện chuỗi $ (GCC_MINOR) xuất hiện bên trong chuỗi 4-5).


4
Đối với tốt hơn hoặc tệ hơn (có thể là tệ hơn), chỉ là loại hack bẩn thỉu mà tôi đang tìm kiếm; cảm ơn
Pat

1
Tôi không nghĩ điều này là bệnh lý, khác với thực tế là mọi thứ trong Makefile đều là bệnh lý. Nó thực sự khá thanh lịch. Tôi đã đọc bốn hoặc năm cách khác nhau để thực hiện điều này, và cách của bạn cho đến nay là cách dễ hiểu nhất.
Michael Geary

8

Đây là biến thể linh hoạt hơn: nó sử dụng trình bao bên ngoài, nhưng cho phép kiểm tra các điều kiện tùy ý:

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

Một cách khác mà bạn có thể cân nhắc sử dụng trong trường hợp này là:

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

Tôi thực sự sử dụng cùng một mã của mình vì tôi không muốn duy trì một confighoặc Configure.

Nhưng bạn phải sử dụng công cụ di động, không thiếu máu make, như GNU make ( gmake), và không phải của Posix make.

Và nó không giải quyết vấn đề logic ANDOR.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.