2010-08-27 24 views
12

Thật khó để tin, nhưng có vẻ như với tôi rằng thành ngữ Makefile phổ biến "> $ @" là sai. Đặc biệt, một mục tiêu có quy tắc có một lệnh thất bại nhưng sử dụng chuyển hướng này sẽ thất bại lần đầu tiên nhưng không phải lần sau. Điều này là bởi vì mặc dù lệnh không thành công, việc chuyển hướng "thành công" theo ý nghĩa tạo ra một mục tiêu cập nhật (mặc dù không có độ dài).

Dường như với tôi rằng điều đúng đắn cần làm là chuyển hướng đến tạm thời và thành công khi đổi tên tạm thời thành mục tiêu.

Dưới đây là ví dụ và Makefile:

bad-target: 
     command-that-will-fail > [email protected] 

good-target: 
     command-that-will-fail > [email protected] || (rm [email protected]; false) 
     mv [email protected] [email protected] 

clean: 
     rm -f bad-target good-target 

Và đây là một chuỗi các lệnh minh họa vấn đề và giải pháp của nó:

$ make clean 
rm -f bad-target good-target 

$ make bad-target 
command-that-will-fail > bad-target 
/bin/sh: command-that-will-fail: not found 
make: *** [bad-target] Error 127 

$ make bad-target 
make: `bad-target' is up to date. 

$ make good-target 
command-that-will-fail > good-target.tmp || (rm good-target.tmp; false) 
/bin/sh: command-that-will-fail: not found 
make: *** [good-target] Error 1 

$ make good-target 
command-that-will-fail > good-target.tmp || (rm good-target.tmp; false) 
/bin/sh: command-that-will-fail: not found 
make: *** [good-target] Error 1 

Trả lời

0

Vâng, điều này chắc chắn là một cái gì đó để ghi nhớ.

Nhưng đôi khi bạn ổn với lệnh không thành công và bạn không muốn thử lại, vì lỗi sẽ chỉ lặp lại chính nó.

Trong trường hợp đó, để trống kết quả là OK. Chỉ cần không thực hiện số lần xử lý tiếp theo khi có nội dung có ý nghĩa trong tệp đó.

15

Nếu bạn đang sử dụng GNU, bạn cũng có thể thêm mục tiêu đặc biệt .DELETE_ON_ERROR vào tệp makefile của mình. Điều này sẽ gây ra làm để xóa các tập tin đầu ra nếu có một lỗi trong quá trình thực hiện các lệnh cho tập tin đó:

all: foo.o 

foo.o: 
     echo bogus! > [email protected] 
     exit 1 

.DELETE_ON_ERROR: 

Dưới đây là một ví dụ về makefile này trong hành động:

$ gmake 
echo bogus! > foo.o 
exit 1 
gmake: *** [foo.o] Error 1 
gmake: *** Deleting file `foo.o' 

Đây là dễ dàng hơn để sử dụng hơn phiên bản của bạn, vì bạn không cần sửa đổi mọi quy tắc trong makefile.

+0

Rất tốt, cảm ơn bạn! .DELETE_ON_ERROR rất hữu ích. –

+1

Có cách nào để chỉ nhận hành vi DELETE_ON_ERROR cho các quy tắc cụ thể không? – Will

1

Có lẽ đây là giải pháp hiển nhiên, nhưng nhiều lệnh phổ biến cung cấp cờ -o hoặc tương tự. Vì vậy, thay vì chuyển hướng đầu ra, bạn nên sử dụng quy tắc:

target: target.dep 
    some_command target.dep -o [email protected] 

Nếu lệnh không thành công, tệp đầu ra sẽ không được tạo. Tôi đã không có nhiều dịp để sử dụng chuyển hướng đầu ra trong makefiles.

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