如何在 Makefile 将 dir 添加到 $PATH?

我想编写一个 Makefile 来运行测试。测试在目录中’。/test’和要测试的可执行文件位于’目录中。我是宾。

当我运行测试时,他们没有看到 exec 文件,因为目录./bin 不在 $PATH 中。

当我做这样的事情:

EXPORT PATH=bin:$PATH
make test

一切工作。然而,我需要更改生成文件中的 $PATH。

简单生成文件内容:

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

它正确地打印了路径,但是没有找到文件 x。

当我手动执行此操作时:

$ export PATH=bin:$PATH
$ x

那就没事了。

如何更改 Makefile 中的 $PATH?

127840 次浏览

To set the PATH variable, within the Makefile only, use something like:

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


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

What I usually do is supply the path to the executable explicitly:

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

I also use this technique to run non-native binaries under an emulator like QEMU if I'm cross compiling:

EXE = qemu-mips ./bin/

If make is using the sh shell, this should work:

test all:
PATH=bin:$PATH x

Did you try export directive of Make itself (assuming that you use GNU Make)?

export PATH := bin:$(PATH)


test all:
x

Also, there is a bug in you example:

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

First, the value being echoed is an expansion of PATH variable performed by Make, not the shell. If it prints the expected value then, I guess, you've set PATH variable somewhere earlier in your Makefile, or in a shell that invoked Make. To prevent such behavior you should escape dollars:

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

Second, in any case this won't work because Make executes each line of the recipe in a separate shell. This can be changed by writing the recipe in a single line:

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

Path changes appear to be persistent if you set the SHELL variable in your makefile first:

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


test all:
x

I don't know if this is desired behavior or not.

By design make parser executes lines in a separate shell invocations, that's why changing variable (e.g. PATH) in one line, the change may not be applied for the next lines (see this post).

One way to workaround this problem, is to convert multiple commands into a single line (separated by ;), or use One Shell special target (.ONESHELL, as of GNU Make 3.82).

Alternatively you can provide PATH variable at the time when shell is invoked. For example:

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