2010-08-19 26 views
12

làm cho cú pháp được phân cách bằng dòng mới, nhưng $ (shell ...) thay thế dòng mới bằng khoảng trắng. Vì vậy, cách xấu xí nhất để làm

$ (eval $ (vỏ chương trình-that-phát ra-makefile-fragment))

mà không làm việc theo cách người ta có thể thích những gì.

Trả lời

13

Điều này có lẽ sẽ làm cho những gì bạn có trong tâm trí:

makefile_fragment: 
    program-that-emits-makefile-fragment > [email protected] 

include makefile_fragment 

Có phải đó là đủ? Có các thủ thuật bổ sung mà bạn có thể sử dụng nếu bạn cần chúng, chẳng hạn như quy tắc thêm ngữ cảnh xung quanh chương trình sản xuất, hoặc tạo đầu ra thông qua sed để đưa nó vào một dòng, sau đó phân tích cú pháp với các dấu gạch chéo ngược.

+3

+10 nếu có thể. Đó là một giải pháp thanh lịch và khá di động. –

+0

Không hoạt động .. _cho me_. Tôi chỉ nhận được các biến thể khi 'make:" makefile_fragment "được cập nhật.' –

+0

alex gray: thử [thêm một phụ thuộc vào' Makefile' chính nó] (http://make.mad-scientist.net/constructed-include- tập tin /) - 'makefile_fragment: $ (MAKEFILE_LIST)' – rampion

4

Vấn đề này đã được báo cáo với GNU làm cho bảo trì:

http://savannah.gnu.org/bugs/?28230

Nó được khép lại với những nhận xét sau đây:

Như Philip đề cập, điều này được dự định/hành vi tài liệu .
Tôi khuyên bạn nên sử dụng "bao gồm" thay vì eval; để tập lệnh của bạn viết ra một tệp, sau đó bao gồm tệp đó.

ADDED: Có giải pháp thay thế! Dưới đây là một GNUmakefile mẫu (thay thế 8 chỗ bởi các tab; vâng, có hai dòng trống sau khi define newline):

define newline 


endef 

$(eval $(subst #,$(newline),$(shell { echo 'war:'; echo '  echo "not love?"'; echo '  echo "Give peace a chance!"'; } | tr '\n' '#'))) 

Tổng quát hơn, đó là $(eval $(subst #,$(newline),$(shell myscript | tr '\n' '#')))

Bạn phải chọn một nhân vật sẽ không xuất hiện trong đầu ra của tập lệnh; # có vẻ là một ứng cử viên tốt.

+0

Viết ra các tập tin là một chút xấu xí --- phải sử dụng tempfile để ngăn chặn clobbering một cái gì đó, làm sạch, vv Sau đây hoạt động miễn là các dòng phát ra bởi tập lệnh không chứa khoảng trắng. $ (foreach line, $ (shell make-frag-maker), $ (eval $ (line))) – Bryan

+0

@colmode: Nếu bạn không thích lừa bao gồm, đây là một cái khác. Tôi không chắc chắn tôi thích nó: nó cảm thấy rất hacky, nhưng mặt khác nó làm như vậy những gì khác tôi đã mong đợi. Một điểm tốt là nó khá minh bạch; một điểm trong lợi của bao gồm là họ nên được một chút dễ dàng hơn để gỡ lỗi. – Gilles

+0

Cá nhân tôi thích phương pháp "bao gồm". Tính di động có thể không quan trọng trong trường hợp cụ thể của OP, nhưng "bao gồm" tránh sử dụng các cấu trúc không di động (chẳng hạn như '$ (shell) và' $ (eval) ') và do đó, IMHO, giải pháp tốt hơn. –

0

Dưới đây là một cách để thực hiện điều đó bằng cách chiếm đoạt ký tự thay thế%, vì vậy chúng tôi không cần phải dựa vào một ký tự không xuất hiện trong đầu ra của bản ghi.

define nl 


enddef 
$(foreach line, $(shell myscript | sed -e 's/%/\\%/' -e 's/$$/%/'), \ 
    $(eval $(patsubst %, $(line), $(nl)))) 
+0

Không làm việc cho tôi, ngay cả sau khi s/enddef/endef /: 'GNUmakefile: 5: *** dấu phân tách bị thiếu. Stop.' (GNU Make 3.81) – Gilles

+0

Tò mò. Tôi chỉ dán nó trở lại nguyên văn của makefile từ bài đăng này và nó hoạt động cho tôi. Cùng một phiên bản của make, quá. Có thể lỗi phân tích cú pháp này đến từ việc thực thi eval, tức là lỗi trong đầu ra của myscript không? – Bryan

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