2012-12-13 31 views
10

Đây là một phiên bản thu gọn của Makefile của tôi:phụ thuộc Makefile không làm việc cho mục tiêu giả mạo

.PHONY: all 

all: src/server.coffee 
    mkdir -p bin 
    ./node_modules/.bin/coffee -c -o bin src/server.coffee 

Tôi muốn chạy make và chỉ có nó biên dịch lại khi src/server.coffee đã thay đổi. Tuy nhiên, nó recompiles mỗi khi tôi chạy make:

$ make 
mkdir -p bin 
./node_modules/.bin/coffee -c -o bin src/server.coffee 
$ make 
mkdir -p bin 
./node_modules/.bin/coffee -c -o bin src/server.coffee 

Nếu tôi thay đổi Makefile của tôi không sử dụng một đối tượng giả mạo, nó hoạt động như mong đợi. New Makefile:

bin/server.js: src/server.coffee 
    mkdir -p bin 
    ./node_modules/.bin/coffee -c -o bin src/server.coffee 

Kết quả:

$ make 
mkdir -p bin 
./node_modules/.bin/coffee -c -o bin src/server.coffee 
$ make 
make: `bin/server.js' is up to date. 

Tại sao sẽ không tôn trọng nó phụ thuộc của tôi với một mục tiêu giả mạo? Lý do tôi hỏi là bởi vì trong thực tế, tôi sẽ không chỉ biên dịch một tệp đơn lẻ thành một tệp khác, vì vậy tôi không muốn phải theo dõi tên của tất cả các tệp đầu ra để sử dụng làm mục tiêu.

Trả lời

8

Thay vì một mục tiêu giả mạo (mà như @cmotley chỉ ra, đang làm việc một cách chính xác như mong muốn) những gì bạn có thể sử dụng khi bạn muốn tránh thêm công việc là một "empty target":

Mục tiêu rỗng là một biến thể của mục tiêu giả tạo; nó được sử dụng để giữ công thức nấu ăn cho một hành động mà bạn yêu cầu một cách rõ ràng theo thời gian. Không giống như một mục tiêu giả mạo, tệp đích này thực sự tồn tại; nhưng nội dung của tệp không quan trọng và thường trống.

Mục đích của tệp đích rỗng là để ghi lại, với thời gian sửa đổi cuối cùng của nó, khi công thức của quy tắc được thực hiện lần cuối. Nó làm như vậy bởi vì một trong các lệnh trong công thức là một lệnh cảm ứng để cập nhật tệp đích.

Tuy nhiên, trong trường hợp này có thực sự không cần thiết phải bổ sung thêm một tập tin đầu ra sản phẩm nào - bạn đã có đầu ra của biên soạn CoffeeScript của bạn! Điều đó phù hợp với mẫu Makefile điển hình hơn, như bạn đã trình bày trong câu hỏi của mình. Những gì bạn có thể làm là tái cấu trúc theo cách tiếp cận này:

.PHONY: all 
all: bin/server.js 

bin/server.js: src/server.coffee 
    mkdir -p bin 
    ./node_modules/.bin/coffee -c -o bin src/server.coffee 

Bây giờ bạn có hai điều: một mục tiêu "tất cả" thông thường đúng là giả nhưng không làm việc thêm. Bạn cũng đang ở trong một vị trí tốt hơn để làm điều này chung chung hơn, do đó bạn có thể dễ dàng thêm nhiều file:

.PHONY: all 
all: bin/server.js bin/other1.js bin/other2.js 

bin/%.js: src/%.coffee 
    mkdir -p bin 
    ./node_modules/.bin/coffee -c -o bin $< 
+3

Chỉ cần rõ ràng, một mục tiêu ** trống ** phải là một tệp và thực sự chỉ được sử dụng cho dấu thời gian của nó? Có loại nào khác của '.PHONY' cho phép quy tắc đích có một phần tử công thức (với các lệnh được thực thi) * và * chỉ chạy khi các phụ thuộc có cần cập nhật không? Nó có vẻ khá vỡ vì nó có '. PHONY' làm những thứ khác nhau tùy thuộc vào việc nó có một cơ thể công thức hay không. – jozxyqk

4

Có cần phải có một số tệp đích để so sánh với thời gian sửa đổi của tệp server.coffee. Vì bạn không có mục tiêu cụ thể, make không thể biết liệu đầu ra có mới hơn hay không thì phụ thuộc hay không, vì vậy nó sẽ luôn luôn xây dựng all.

+0

Ah, cảm ơn. Tôi đã không nhận ra rằng làm thế nào để tính toán các tập tin cần thiết để được biên dịch lại. Rất hữu ích –

9

Theo tài liệu Make:

The prerequisites of the special target .PHONY are considered 
to be phony targets. When it is time to consider such a target, 
make will run its recipe unconditionally, regardless of whether 
a file with that name exists or what its last-modification time is. 

http://www.gnu.org/software/make/manual/html_node/Special-Targets.html

Make chạy lộ trong các mục tiêu giả mạo vô điều kiện - điều kiện tiên quyết không thành vấn đề.

+0

Được rồi, điều đó khá đơn giản. Bạn có biết cách giải quyết tốt nào để đạt được mục tiêu không phải khai báo rõ ràng các tệp đầu ra phụ thuộc vào một tập hợp các tệp nguồn không? –

+0

Bạn có thể khai báo một số biến để theo dõi tệp nguồn và tệp đối tượng. Ví dụ: SRC = $ (ký tự đại diện ./src/*.c) và OBJECTS = $ (patsubst% .c,% .o, $ (SRC)). Sau đó, $ (OBJECTS) có thể là điều kiện tiên quyết cho mục tiêu của bạn. Tôi nghĩ đó là những gì bạn đang cố gắng làm. – cmotley

1

Như những người khác đã đề cập, làm cho vẻ tại timestamps của các tập tin để tìm hiểu xem sự phụ thuộc đã thay đổi.

Nếu bạn muốn "mô phỏng" mục tiêu giả với phụ thuộc, bạn sẽ phải tạo tệp thực bằng tên đó và sử dụng lệnh touch (trên hệ thống Unix).

Tôi cần một giải pháp để chỉ làm sạch thư mục nếu các makefiles bị thay đổi (tức là các cờ biên dịch đã được thay đổi, do đó các tệp đối tượng cần được biên dịch lại).

Đây là những gì tôi đã sử dụng (và chạy trước mỗi biên soạn) với một file có tên makefile_clean:

makefile_clean: makefile 
    @rm '*.o' 
    @sudo touch makefile_clean 

Lệnh touch cập nhật các dấu thời gian sửa đổi lần cuối đến thời điểm hiện tại.

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