Dưới đây là một ví dụ từ GNU Make manual section on Secondary Expansion (hơi đơn giản):
foo_SRCS := bar.c baz.c
.SECONDEXPANSION:
# [email protected] expands to the target ("foo" in this case)
foo: $$(patsubst %.c,%.o,$$([email protected]_SRCS))
này hoạt động tuyệt vời; nó được xây dựng bar.o
và baz.o
:
cc -c -o bar.o bar.c
cc -c -o baz.o baz.c
Nhưng nếu tôi tinh chỉnh ví dụ này chỉ hơi, các patsubst
dừng làm việc:
all: foo.a
foo_SRCS := bar.c baz.c
.SECONDEXPANSION:
# $$* expands to the stem of the match ("foo" in this case).
%.a: $$(patsubst %.c,%.o,$$($$*_SRCS))
ar rcs [email protected] $^
Nó không còn xây dựng bar.o
và baz.o
, và thay vào đó là sử dụng *.c
file trực tiếp như điều kiện tiên quyết!
ar rcs foo.a bar.c baz.c
Xin lưu ý rằng phần $$($$*_SRCS)
đang làm việc rõ ràng, bằng chứng thực tế là nó tìm thấy foo_SRCS
và sử dụng mà là điều kiện tiên quyết. Nhưng vì lý do nào đó, phần patsubst
đã trở thành no-op! Thay vì thay thế %.c
bằng %.o
, chỉ cần sử dụng trực tiếp foo_SRCS
.
Điều gì đang xảy ra ở đây? Làm thế nào tôi có thể có được ví dụ của tôi để làm việc?
EDIT: Tôi đã có một giả thuyết cho rằng %
ký tự bên trong patsubst
đã bị đánh giá sớm, bằng cách sử dụng phù hợp với gốc (foo), do đó patsubst bản thân đang tìm kiếm một cái gì đó như thế này:
$(patsubst foo.c,foo.o,bar.c baz.c)
Để kiểm tra lý thuyết này, tôi đã thêm một tập tin gọi foo.c
để foo_SRCS
:
all: foo.a
foo_SRCS := foo.c bar.c baz.c
.SECONDEXPANSION:
# $$* expands to the stem of the match ("foo" in this case).
%.a: $$(patsubst %.c,%.o,$$($$*_SRCS))
ar rcs [email protected] $^
Đó dẫn đến một cái gì đó thậm chí lạ:
make: *** No rule to make target `foo.a', needed by `all'. Stop.
Cảm ơn! Tôi không chắc mình hiểu 100% những gì đang diễn ra, nhưng tôi có thể xác nhận rằng công việc sửa chữa của bạn. –
Trình phân tích cú pháp của Make không phải là rất thông minh. Khi thực hiện thấy nỗ lực của bạn nó unescapes '$$' vào '$' và kết thúc với dòng được chỉ ra ở trên. Sau đó nó thấy rằng như là một quy luật mẫu bình thường. Các quy tắc mẫu lấy mẫu đích, khớp với tên tệp đích đối với nó để trích xuất một gốc và sau đó thay thế gốc đó trong danh sách điều kiện tiên quyết thay cho mỗi '%'. Điều này phá vỡ patsubst vì nó không còn chứa bất kỳ ký tự '%' nào khi mở rộng thứ cấp mở rộng nó. Việc thoát các ký tự '%' cho phép chỉ xem chúng khi mở rộng thứ cấp đang diễn ra chứ không phải khi quy tắc mẫu được kết hợp với gốc. –
Tất cả những điều đó hợp lý với tôi. Phần tôi không hiểu sau đó là lý do tại sao ví dụ ban đầu (từ Make manual) làm việc ở tất cả. Tại sao nó sẽ không thất bại trong cùng một cách? –