2012-01-20 24 views
54

Tôi muốn viết một Makefile sẽ chạy thử nghiệm. Kiểm tra nằm trong thư mục './tests' và các tệp thi hành được kiểm tra nằm trong thư mục './bin'.

Khi tôi chạy thử nghiệm, họ không thấy tệp exec, dưới dạng thư mục ./bin không nằm trong $ PATH.

Khi tôi làm một cái gì đó như thế này:

EXPORT PATH=bin:$PATH 
make test 

mọi thứ hoạt động. Tuy nhiên tôi cần phải thay đổi $ PATH trong Makefile.

đơn giản nội dung Makefile:

test all: 
    PATH=bin:${PATH} 
    @echo $(PATH) 
    x 

It in con đường một cách chính xác, tuy nhiên nó không tìm thấy tập tin x.

Khi tôi làm điều này bằng tay:

$ export PATH=bin:$PATH 
$ x 

tất cả mọi thứ là OK rồi.

Làm cách nào để thay đổi $ PATH trong Makefile?

+0

Bạn có thể không chỉ gọi các kiểm tra từ thư mục thực thi như '../ test/test_to_run'? Xin lỗi nếu tôi đã hiểu sai câu hỏi. – Chris

+0

Tôi muốn tệp này hiển thị cho các bài kiểm tra bình thường. Tôi không muốn chơi với các thư mục, vì tôi tái cấu trúc nó sẽ là một cơn ác mộng. –

+0

Cách duy nhất bạn có thể tiến gần đến điều này là để makefile viết ra một kịch bản lệnh shell chứa biến đó và sau đó có nguồn gốc của trình bao cha với tập lệnh '.'. Điều này có lẽ là không thực tế. –

Trả lời

65

Bạn đã thử export directive make tự (giả định rằng bạn sử dụng GNU Make)?

export PATH := bin:$(PATH) 

test all: 
    x 

Ngoài ra, có một lỗi trong bạn ví dụ:

test all: 
    PATH=bin:${PATH} 
    @echo $(PATH) 
    x 

Thứ nhất, giá trị là echo ed là một mở rộng của PATH biến được thực hiện bởi Make, không vỏ. Nếu nó in giá trị dự kiến ​​sau đó, tôi đoán, bạn đã thiết lập PATH biến ở đâu đó trước đó trong Makefile của bạn, hoặc trong một vỏ mà gọi Make. Để ngăn chặn hành vi như vậy, bạn nên thoát USD:

test all: 
    PATH=bin:$$PATH 
    @echo $$PATH 
    x 

Thứ hai, trong mọi trường hợp này sẽ không làm việc vì Make thực hiện mỗi dòng của công thức trong một separate shell.Điều này có thể được thay đổi bằng cách viết các công thức trong một dòng duy nhất:

test all: 
    export PATH=bin:$$PATH; echo $$PATH; x 
+4

'$ (PATH)' sẽ được đặt thành giá trị 'PATH' của trình bao gọi thực hiện. Theo [hướng dẫn] (http://www.gnu.org/software/make/manual/html_node/Environment.html), "Mọi biến môi trường tạo ra khi thấy nó bắt đầu được biến thành một biến làm với cùng một biến tên và giá trị. " –

-2

Để đặt biến PATH, trong Makefile chỉ, sử dụng một cái gì đó như:

PATH := $(PATH):/my/dir 

test: 
@echo my new PATH = $(PATH) 
+0

Nó không hoạt động theo cách tôi muốn. Tôi đã cập nhật câu hỏi với các ví dụ về những gì tôi muốn đạt được. –

2

Những gì tôi thường làm là cung cấp đường dẫn đến thực thi một cách rõ ràng:

EXE=./bin/ 
... 
test all: 
    $(EXE)x 

tôi cũng sử dụng này kỹ thuật chạy các tệp nhị phân không phải gốc trong trình giả lập như QEMU nếu tôi đang biên dịch chéo:

EXE = qemu-mips ./bin/ 

Nếu làm được bằng cách sử dụng vỏ sh, điều này sẽ làm việc:

test all: 
    PATH=bin:$PATH x 
+0

Vâng, soulution mát mẻ, tuy nhiên tôi đã có các bài kiểm tra của tôi bằng văn bản trong perl và tôi cần phải gọi exe từ kịch bản perl, không trực tiếp từ makefile. Tôi đã phải suy nghĩ lại toàn bộ thử nghiệm của công cụ này :) –

+0

Gotcha. Làm thế nào về thiết lập PATH trên dòng lệnh chính nó? Xem chỉnh sửa ở trên. –

+0

Ồ, tôi hiểu rồi. Xin lỗi vì thông tin sai lạc. –

18

thay đổi con đường dường như dai dẳng nếu bạn đặt biến SHELL trong makefile của bạn đầu tiên:

SHELL := /bin/bash 
PATH := bin:$(PATH) 

test all: 
    x 

Tôi không biết nếu đây là hành vi mong muốn hay không.

+0

Điều này khắc phục được sự cố mà tôi gặp phải (tôi đang chạy zsh). Cảm ơn! –

+0

Vâng, điều này thực sự làm những gì OP muốn ... nhưng nó là một tính năng hay một lỗi? Ngay cả sau khi đọc phần [make manual's SHELL] (http://www.gnu.org/software/make/manual/make.html#Choosing-the-Shell) Tôi không chắc chắn. – pje

+2

Điều này cũng không phù hợp với tôi. 'which' và' env' bây giờ lấy PATH mới, nhưng trực tiếp thực thi một nhị phân vẫn không được tìm thấy trong PATH đã sửa đổi, chỉ trong PATH đã sửa đổi. –

8

Theo thiết kế make phân tích cú pháp thực thi dòng trong một lời gọi vỏ riêng biệt, đó là lý do tại sao thay đổi biến (ví dụ PATH) trong một dòng, sự thay đổi có thể không được áp dụng cho các dòng tiếp theo (xem này post).

Một cách để workaround vấn đề này, là để chuyển đổi nhiều lệnh thành một dòng duy nhất (cách nhau bằng ;), hoặc sử dụng One Shell mục tiêu đặc biệt (.ONESHELL, tính đến GNU Make 3,82).

Hoặc bạn có thể cung cấp PATH biến tại thời điểm khi trình bao được gọi. Ví dụ:

PATH := $(PATH):$(PWD)/bin:/my/other/path 
SHELL := env PATH=$(PATH) /bin/bash 
+1

Tôi thích cách tiếp cận! –

+1

Điều này là tốt nhất, bởi vì nó hoạt động ngay cả với lời gọi '$ (shell)'! : D Ví dụ: https://pastebin.com/Pii8pmkD – PsychoX

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