2009-10-21 11 views
7

làm cho tập tin của chúng tôi biên dịch c file nguồn với một quy tắc mẫu tĩnh như thế này:Trong make gnu, điều kiện tiên quyết trong một quy tắc mẫu tĩnh có thể có hậu tố khác nhau

OBJECTS = foo.o bar.o baz.o 

$(OBJECTS): %.o: %.c 
    $(CC) $< $(C_OPTIONS) -c -o [email protected] 

tôi cần phải thay đổi một trong những c tập tin vào một tập tin Objective-C .m. Gọi trình biên dịch là như nhau cho cả hai loại nguồn, vì vậy tôi muốn sử dụng cùng một quy tắc và chỉ cần tinh chỉnh nó để linh hoạt hơn. Tôi không muốn thay đổi biến OPTIONS vì nó cũng được sử dụng cho bước liên kết, v.v.

Có cách nào để làm cho quy tắc ở trên linh hoạt hơn để chứa cả tệp .c và .m?

Cảm ơn

Trả lời

1

Không thực sự chỉ là sao chép vào

$(OBJECTS): %.o: %.m 
    $(CC) $< $(C_OPTIONS) -c -o [email protected] 
+0

Nó sẽ sinh ra lỗi. Đối với trường hợp đầu tiên, không tìm thấy tập tin '% .m' (lỗi!) Và thứ hai - không có'% .c' (một lỗi khác!) –

+0

Xin lỗi, hãy chỉ xem xét những gì đang tồn tại nếu không có. c tập tin sau đó nó sẽ không gọi quy tắc% .c – Mark

-1

Các cuộc gọi đến trình biên dịch cùng chỉ là một dịp vui. Thông thường bạn không biên dịch mã mục tiêu-c với $(CC). Điều đó chỉ cảm thấy kỳ lạ.

Nhưng kể từ khi bạn đi một cách khắc nghiệt, tôi sẽ không đăng giải pháp đúng, nơi bạn tách mục tiêu C mục tiêu từ mục tiêu C thành hai biến khác nhau $(OBJECTS) và thực hiện hai quy tắc (mà bạn thực sự nên làm). Quá chán. Thay vào đó, hãy hack!

OBJC_FILES:=$(subst $(wildcard *.m)) 

real_name = `(test -h $(1) && readlink $(1)) || echo $(1)` 

$(OBJECTS): %.o: %.c 
    $(GCC) $< $(C_OPTIONS) -c -o $(call real_name,[email protected]) 

$(OBJC_FILES): %.c: %.m 
    ln -s $< [email protected] 

Và Chúa giúp những người duy trì nó!

Btw, điều này rõ ràng sẽ không hoạt động nếu các tệp m của bạn được tạo.

7

Chúng tôi có thể thêm hành vi hoặc hành vi này vào danh sách những thứ Thực hiện có thể dễ dàng thực hiện, nhưng không phải. Đây là một cách để làm điều đó, bằng cách sử dụng "eval" để tạo ra một quy tắc riêng biệt cho từng đối tượng.

 
define RULE_template 
$(1): $(wildcard $(basename $(1)).[cm]) 
endef 

OBJECTS = foo.o bar.o baz.o 

$(foreach obj,$(OBJECTS),$(eval $(call RULE_template,$(obj)))) 

$(OBJECTS): 
    $(CC) $< $(C_OPTIONS) -c -o [email protected] 

Lưu ý rằng điều này phụ thuộc vào tệp nguồn đã có trước khi bạn chạy Make (foo.c hoặc foo.m, nhưng không phải cả hai). Nếu bạn đang tạo các nguồn đó trong cùng một bước, điều này sẽ không hoạt động.

Đây là một phương pháp ít thông minh hơn, mạnh mẽ hơn.

 
CPP_OBJECTS = foo.o bar.o 
OBJECTIVE_OBJECTS = baz.o 
OBJECTS = $(CPP_OBJECTS) $(OBJECTIVE_OBJECTS) 

$(CPP_OBJECTS): %.o: %.c 

$(OBJECTIVE_OBJECTS): %.o: %.m 

$(OBJECTS): 
    $(CC) $< $(C_OPTIONS) -c -o [email protected] 

CHỈNH SỬA: sửa chỉ định OBJECTS, nhờ Jonathan Leffler.

+1

Tôi đồng ý với phương pháp mạnh mẽ hơn - tôi sẽ sử dụng nó. Nhưng OBJECTS = macro cần một số $ (...) trên RHS. –

+0

Ack! Bạn nói đúng, tôi nên cẩn thận hơn. – Beta

+0

Làm ví dụ của bạn (ví dụ thứ hai) chỉ tệp foo.o đầu tiên đang được tạo. Có vấn đề gì? – BogdanSikach