2012-03-13 13 views
23

Tôi đang sử dụng GNU tạo 3,81. Đây là một tệp thử nghiệm biểu thị sự cố:Làm cách nào để sử dụng các macro để tạo nhiều mục tiêu/quy tắc Makefile bên trong foreach? Hành vi bí ẩn

define BOZO 

a$(1): b c 
    touch a$(1) 

endef 

$(foreach i,1 2 3,$(call BOZO,$(i))) 

Ý tưởng ở đây là sử dụng mẫu macro (BOZO) để tạo quy tắc tuân theo mẫu có thể dự đoán được.

Vấn đề: khi tôi chạy thực hiện trên makefile này tôi nhận được một lỗi nói:

Makefile.fake:10: *** multiple target patterns. Stop. 

(nơi dòng 10 là phù hợp với foreach).

Bây giờ, tôi biết lỗi đó thường chỉ ra điều gì. Hãy xem dòng đó mở rộng ra bằng cách sử dụng hàm info để gửi mở rộng ra tiêu chuẩn. Tôi thay đổi dòng 10 là:

$(info $(foreach i,1 2 3,$(call BOZO,$(i)))) 

và tôi chạy:

$ make -n 

a1: b c 
    touch a1 

a2: b c 
    touch a2 

a3: b c 
    touch a3 

make: *** No targets. Stop. 

Lưu ý rằng "không có mục tiêu" thông điệp được mong đợi, kể từ khi $ (thông tin ...) chức năng đánh giá để trống nhưng nguyên nhân tạo thành in quy tắc được tạo.

Hãy chạy những quy tắc đó sau đó phải không?

$make -n > out.txt 
make: *** No targets. Stop. 
$make -f out.txt a1 a2 a3 
touch a1 
touch a2 
touch a3 
$ 

AAARGH! Các quy tắc hoạt động tốt. Vì vậy ... là lỗi trong thực hiện, hoặc trong sự hiểu biết của tôi?

Một đầu mối cuối cùng mà có thể giúp chẩn đoán: nếu tôi thay đổi dòng foreach để:

$(foreach i,1,$(call BOZO,$(i))) 

(nên foreach rằng chỉ có một lần lặp)

và sau đó làm

$make a1 

Tôi gặp lỗi khác:

make: *** No rule to make target `a1'. Stop. 

Tôi không biết cách nào để "nhìn thấy" việc mở rộng $(foreach) làm cho ngoại trừ $(info) và đầu ra của nó là hợp pháp, vì vậy tôi khá bối rối.

Trả lời

36
$(foreach i,1 2 3,$(eval $(call BOZO,$(i)))) 

eval function yêu cầu Phân tích cú pháp cấu trúc như cú pháp makefile để "thực hiện" chúng. Tôi không chắc chắn tại sao Hãy phản đối các quy tắc không được đánh giá theo cách đặc biệt này, nhưng đó là loại học tập.

+0

D'OH! Được rồi, tôi mới sử dụng các macro Makefile. Tôi vẫn không hiểu tại sao điều này là cần thiết, nhưng nó hoạt động nên tôi sẽ suy ngẫm về nó. Cảm ơn! – Joe

30

Câu trả lời của phiên bản beta là chính xác nhưng tôi muốn giải quyết nhận xét "Tôi không chắc chắn tại sao Hãy phản đối các quy tắc không được đánh giá".

Lý do các quy tắc không được đánh giá không hoạt động là một makefile cuối cùng là dựa trên dòng và các dòng được cắt nhỏ BEFORE biến được mở rộng. Vì vậy, nó chỉ là không thể cho một mở rộng của một biến để biến thành một kết quả multiline: ngay cả khi mở rộng có chứa newlines làm cho toàn bộ điều như một "dòng".Khi làm xong việc mở rộng foreach vòng lặp và phân tích các kết quả nó về cơ bản xem đây:

a1: b c touch a1 a2: b c touch a2 a3: b c touch b3 

đó là lý do tại sao bạn sẽ có được "nhiều mô hình mục tiêu" lỗi. Giá trị này làm cho việc diễn giải lại kết quả mở rộng ngay từ đầu như là một đoạn mã hoàn chỉnh của cú pháp makefile, bao gồm cả việc cắt dòng, v.v ..., và đó là lý do tại sao một mở rộng đa dòng hoạt động ở đó.

+0

Cảm ơn, rất hữu ích! – Joe

+0

Giải thích này rất hữu ích trong việc giúp tôi hiểu một tệp makefile phức tạp đặc biệt mà tôi đã gặp phải trong công việc. –

0

after using eval function still i am facing multiple pattern stop issue. I am recursively building target using foreach but i am facing this multiple target issue. while running make file on window 32 bit platform(which run correctly for linux machine)

define BOZO 
$(CWD)/$(1).o:$(CWD).$(1).def 
endef 
$(foreach target,$(basename $(list)),$(eval $(call BOZO,$(target)))) 

$(CWD)/%.def: a.out 
    @echo building [email protected] 
    a.out %.def 

Something như thế này. Bạn có thể đề nghị cho điều này ...!

+1

Cảm ơn bạn đã trích đoạn mã này, đoạn mã này có thể cung cấp một số trợ giúp ngay lập tức. Một lời giải thích thích hợp [sẽ cải thiện rất nhiều] (// meta.stackexchange.com/q/114762) giá trị giáo dục của nó bằng cách hiển thị * tại sao * đây là một giải pháp tốt cho vấn đề, và sẽ hữu ích hơn cho các độc giả tương lai tương tự, nhưng không giống nhau, câu hỏi. Vui lòng [sửa] câu trả lời của bạn để thêm giải thích và đưa ra chỉ dẫn về những giới hạn và giả định được áp dụng. –

Các vấn đề liên quan