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


87

我想编写一个可以运行测试的Makefile。测试位于目录“ ./tests”中,而要测试的可执行文件位于目录“ ./bin”中。

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

当我做这样的事情:

EXPORT PATH=bin:$PATH
make test

一切正常。但是我需要更改Makefile中的$ PATH。

简单的Makefile内容:

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

它可以正确打印路径,但是找不到文件x。

当我手动执行此操作时:

$ export PATH=bin:$PATH
$ x

一切都很好。

如何更改Makefile中的$ PATH?


您不仅可以从可执行目录中调用测试../test/test_to_run吗?抱歉,如果我误解了这个问题。
克里斯

我希望该文件对测试正常可见。我不想玩目录,因为我重构那是件麻烦事。
SzymonLipiński2012年

接近此方法的唯一方法是,使makefile编写一个包含变量decls的shell脚本,然后使用该脚本的父shell源.。但是,这可能是不切实际的。
迈克尔·史密斯

我相信unix.stackexchange.com/questions/11530/…是一个非常不同的(愚蠢的)问题,与您的不同。
imz –伊万·扎哈拉里舍夫(Ivan Zakharyaschev)

Answers:


105

您是否尝试过Make本身的export指令(假设您使用的是GNU Make)?

export PATH := bin:$(PATH)

test all:
    x

此外,您的示例中还有一个错误:

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

首先,echoed的值是PATH由Make而不是shell执行的变量的扩展。如果可以打印期望值,那么我猜您已经PATH在Makefile或调用Make的shell中的某个位置设置了变量。为了防止这种行为,您应该避免美元:

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

其次,在任何情况下这都不行,因为Make在单独的shell中执行配方的每一行。可以通过在单行中编写配方来更改它:

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

7
$(PATH)将被设置为PATH调用make的shell的值。按照手册,“ make每次启动时看到的每个环境变量都将转换为具有相同名称和值的make变量。”
埃米尔(Emil Sit)2013年

导出指令对我有用(谢谢!),但是只有在我安装了GNU Make 4.3之后。在3.81版本(在MacOS卡塔利娜默认值),更新后的PATH正确反映变量(echo $(PATH))和命令的环境(内envwhich pythonbash -c python),但似乎并没有定位该命令的可执行文件时使用:命令python仍然运行Python可执行文件在原始文件上PATH
摄于

27

通过设计make解析器,可以在单独的shell调用中执行行,这就是为什么PATH在一行中更改变量(例如)的原因,该更改可能不适用于下一行(请参见本文章)。

解决此问题的一种方法是将多个命令转换为单行(由 ;),或使用一个Shell特殊目标(.ONESHELL从GNU Make 3.82开始,)。

另外,您可以PATH在调用shell时提供变量。例如:

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

2
我喜欢这种方法!
艾伦·弗朗佐尼

2
这是最好的,因为它甚至可以在$(shell)调用中起作用!:D示例:pastebin.com/Pii8pmkD
PsychoX

在dev.azure上,我得到:env:'env':没有这样的文件或目录;在本地工作; /
Kamil Dziedzic

在使用make 4.2的Debian 10上不起作用:make:env PATH = <path> / bin / sh:找不到命令。使用出口作品。确保在主目录中使用$(HOME)而不是〜。
MKesper

25

如果首先在makefile中设置SHELL变量,则路径更改似乎是持久的:

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

test all:
    x

我不知道这是否是所需的行为。


这解决了我遇到的问题(我正在运行zsh)。谢谢!
Jezen Thomas

是的,这确实可以执行OP所希望的……但这是功能还是错误?即使阅读了制造手册的外壳部分,我也不确定。
2014年

5
这对我也不起作用。whichenv现在拿起新的路径,而是直接执行的二进制仍然没有在经修改的路径发现,仅在原有的一个。
Konrad Rudolph 2014年

3

我通常要做的是显式提供可执行文件的路径:

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

如果我交叉编译,我还使用此技术在QEMU之类的模拟器下运行非本机二进制文件:

EXE = qemu-mips ./bin/

如果make使用的是sh shell,这应该可以工作:

test all:
    PATH=bin:$PATH x

是的,很酷的解决方案,但是我已经用perl编写了我的测试,我需要从perl脚本而不是直接从makefile调用exe。我必须重新考虑对这些东西的整个测试:)
SzymonLipiński2012年

知道了 如何在命令行本身上设置PATH?参见上面的编辑。
理查德·彭宁顿

-2

要设置PATH变量,仅在Makefile中,使用类似以下内容的方法:

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

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

它不能按我想要的方式工作。我已经用我想要实现的示例更新了这个问题。
SzymonLipiński2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.