2012-01-23 22 views
6

Tôi có một dự án C++ với các phần mở rộng khác nhau cho các tệp nguồn (.cpp, .c, .cc) và các phần mở rộng khác nhau cho các tệp tiêu đề (.hpp, .h, .hh). Các tập tin nguồn được đặt tại một thư mục gọi là SRC, và các tập tin tiêu đề là dự đoán trong một thư mục gọi là INC.Làm việc với nhiều phần mở rộng tệp nguồn trong một makefile

Tôi muốn dịch chương trình nguồn với một quy tắc như

vpath %.c $(SRC) 

%.o: %.c 
    $(COMPILER) $(FLAGS) $< $(INCFLAG)$(INC) 

Điều này tất nhiên hoạt động nếu Tôi biết tệp nguồn sẽ có dạng% .c, nhưng trong trường hợp có nhiều phần mở rộng tệp có thể, tôi cũng sẽ cần tạo một quy tắc tương tự cho% .cpp và% .cc. Tất nhiên ba quy tắc không phải là vấn đề lớn để viết, nhưng sẽ tốt hơn nếu có thể sử dụng tệp makefile này như là một kéo và thả cho bất kỳ dự án nào, thậm chí bằng một ngôn ngữ khác, mà không phải viết lại các quy tắc.

Vậy làm thế nào tôi có thể viết một quy tắc (hoặc một số cấu trúc khác mà hoàn thành mục tiêu giống nhau) hoạt động như:

SRC_EXT = cpp c cc 
vpath %.$(SRC_EXT) $(SRC) 

%.o: %.$(SRC_EXT) 
    $(COMPILER) $(FLAGS) $< $(INCFLAG)$(INC) 

Nhờ sự giúp đỡ của bạn.

Trả lời

3

Bạn không thể thực hiện tiêu chuẩn POSIX. Tuy nhiên kể từ khi bạn đề cập đến vpath tôi sẽ giả sử bạn đang sử dụng GNU thực hiện. Nếu bạn có một phiên bản đầy đủ mới (3,81 hoặc mới hơn), bạn có thể làm điều này một cách dễ dàng đủ với cuộc gọi và eval:

SRC_EXT = cpp c cc 

define compile_rule 
%.o : %.$1 
     $$(COMPILER) $$(FLAGS) $$< $$(INCFLAG)$$(INC) 
endef  
$(foreach EXT,$(SRC_EXT),$(eval $(call compile_rule,$(EXT)))) 

Nếu bạn không có đủ mới GNU thực hiện, hoặc muốn một giải pháp thay thế, bạn có thể làm điều tương tự với các tệp makefiles được tạo.

+0

aha! tuyệt quá! Tôi đã tự hỏi làm thế nào để gọi một quy tắc biên dịch, nhưng làm thế nào foreach được gọi là ở nơi đầu tiên? Là nó chỉ ngồi đó trong tập tin, như trong nó được gọi là ngay sau khi bạn đặt biến SRC_EXT? Điều này sẽ buộc việc biên dịch lại tất cả các tệp nguồn ngay cả khi tệp .o được cập nhật? – user487100

+1

Phân tích cú pháp Makefile là tất cả về việc mở rộng mọi thứ. Bất cứ khi nào thực hiện gặp một biến hoặc chức năng trong một "bối cảnh ngay lập tức" (xem "Làm thế nào để đọc một Makefile" trong GNU làm cho hướng dẫn sử dụng), nó sẽ mở rộng nó. Điều đó có thể liên quan đến nhiều bước của khóa học. Khi việc mở rộng hoàn tất, bất kỳ thứ gì còn lại được phân tích cú pháp dưới dạng một tệp makefile. Hàm eval là đặc biệt. Về cơ bản vòng lặp foreach này được mở rộng và phân tích cú pháp bằng cách thực hiện khi nó đọc trong makefile, và nó định nghĩa các quy tắc giống như cách bạn đã viết chúng ra. Vì vậy, nó hoạt động giống như bất kỳ quy tắc nào khác (sẽ không buộc biên dịch lại). – MadScientist

+0

rất hay. Cảm ơn! – user487100

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