Thay thế quy trình trong GNU Makefiles


11

Trên dấu nhắc bash, người ta có thể thực thi diff bằng các tệp giả:

diff <(echo test) <(echo test)

Thêm phần này vào Makefile không thành công:

all:
        diff <(echo test) <(echo test)

Lỗi (gợi ý: / bin / sh trỏ đến / bin / bash trên hệ thống này):

/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `diff <(echo test) <(echo test)'

Điều đó có nghĩa là gì, và có cách nào để vẫn khác hai đầu ra mà không sử dụng các tệp tạm thời không?

Câu trả lời:


20

/bin/shcó thể bashtrên hệ thống của bạn, nhưng khi được gọi là sh, bashsẽ chạy ở chế độ POSIX (như thể POSIXLY_CORRECTđã được xác định hoặc được bắt đầu bằng --posix).

Trong chế độ này, quá trình thay thế không tồn tại.

Các giải pháp:

all:
    command1 >file1
    command2 >file2
    diff file1 file2
    rm -f file1 file2

Thay thế:

all:
    bash -c "diff <(command1) <(command2)"

Hoặc chỉ định nghĩa biến Makefile SHELL/bin/bash:

SHELL=/bin/bash

Nếu bạn muốn tính di động, hãy đi với giải pháp đầu tiên. Nếu bạn ổn với sự phụ thuộc vào bash, hãy chọn cái thứ hai. Nếu bạn cũng không cần quan tâm đến makeviệc triển khai không phải GNU , hãy sử dụng phần ba.


Về cài đặt SHELL: Các tiêu chuẩn POSIX nói rằng thực thi trong Makefiles nên được gọi với system()chức năng thư viện C bằng make. Hàm này không được đảm bảo để sử dụng SHELLbiến môi trường (trên thực tế, làm như vậy không được khuyến khích bởi tiêu chuẩn). Tiêu chuẩn cũng đi đến một số độ dài để nói rằng việc đặt biến Makefile SHELLsẽ không ảnh hưởng đến biến môi trường SHELL . makeTuy nhiên, trong hầu hết các triển khai mà tôi biết, biến Makefile SHELLsẽ được sử dụng để thực thi các lệnh.

Gợi ý trong Cơ sở lý luận cho maketiện ích là sử dụng bash -c:

MAKESHELLTính năng lịch sử và các tính năng liên quan được cung cấp bởi các maketriển khai khác đã bị bỏ qua. Trong một số triển khai, nó được sử dụng để cho phép người dùng ghi đè lên trình bao được sử dụng để chạy makecác lệnh. Điều này thật khó hiểu; Đối với một thiết bị cầm tay make, vỏ nên được lựa chọn bởi nhà văn makefile. Hơn nữa, một nhà văn makefile không thể yêu cầu một vỏ thay thế được sử dụng và vẫn xem xét makefile xách tay. Mặc dù có thể tiêu chuẩn hóa một cơ chế để chỉ định một vỏ thay thế, nhưng các triển khai hiện tại không đồng ý với cơ chế đó và các nhà văn makefile có thể đã gọi một vỏ thay thế bằng cách chỉ định tên shell trong quy tắc cho mục tiêu; ví dụ:

python -c "foo"


Có cách nào để gọi bashtrong Makefile hoặc bất kỳ giải pháp nào khác cho vấn đề khác mà không sử dụng các tệp tạm thời không?
Johannes

Chỉ cần sử dụng hai tệp tạm thời, đây ít nhiều là phương thức thay thế quy trình sẽ làm gì dưới mui xe.
Kusalananda

3
Bạn cũng có thể thiết lập SHELLđể /bin/bashtrong Makefile.
Stephen Kitt

1
@Johannes Kusalananda đã thêm thông tin vào câu trả lời của anh ấy, điều này thật tuyệt vì nó đưa ra một số tùy chọn và hoàn cảnh mà chúng có thể được sử dụng. Tôi muốn bạn chấp nhận câu trả lời này ... (Nhưng tôi đánh giá cao tình cảm!)
Stephen Kitt

2
Thông tin sử dụng biến SHELL không phù hợp POSIX là rất hữu ích. Có lẽ nó vẫn tốt hơn để sử dụng bash -c.
Johannes
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.