通过Makefile将目录添加到PATH


9

将我在Makefile中修改的PATH导出到当前终端中时遇到一些麻烦。我试图将Makefile目录所在的bin文件夹添加到PATH中。

这是makefile的相关部分:

PATH := $(shell pwd)/bin:$(PATH)

install:
    mkdir -p ./bin 
    export PATH
    echo $(PATH)

回显可以正确打印,但是如果我在终端中重做回显,则PATH保持不变。

Answers:


16

您根本无法做到这一点。make方法无法改变其父级环境(或当前目录,您可能会想到下一个)。

实际上,发生的事情比您想象的要少。

  • 并非所有的make实现都反映PATH了环境中对make 变量的分配。GNU make(可以在Linux和其他系统上找到)可以,但是BSD make不能。
  • 目标下的每个命令行都在单独的子Shell中运行。(除了某些较早的BSD make实施方案。)因此,该export PATH行在shell中运行,该shell随后立即终止。并不是说这行首先要做任何事情-如果PATH在那时定义,那是因为它已经在shell的环境中了。

Make是用于自动构建事物的。如果要为交互式环境设置变量,那么这不是您应该使用的工具。相反,写一个shell代码片段,以及是在当前shell:

. ./define-my-variables.sh

在您的makefile中,在每个subshel​​l中提供脚本源。您可以使用反斜杠发出长命令;记住

  • 反斜杠-换行符序列由make剥离,因此shell不会在其中看到换行符。
  • 尽管如此,请记住为每行加上一个标签作为前缀。
  • Make的错误行为是如果命令失败则中止。默认情况下,shell不会执行此操作,默认情况下,任何命令的失败(但最后一个命令都会失败)都不会被注意到,因此您需要运行set -e
install:
    set -e; \
    . ./define-my-variables.sh; \
    mkdir -p bin; \
    …

¹ 强制性说明:不可理智。即使chdir通过ptrace调试器进行远程调用也无法像大多数Shell一样工作,因为它们不希望将当前目录更改到他们的脚下。


嗯,我认为“您根本做不到”是不正确的。参见@Yeo答案:unix.stackexchange.com/a/291973/176350
XML

@XML Yeo的答案做了一些不同的事情,这不是问题所要的。
吉尔斯(Gilles)'所以别再邪恶了'

7

你不能 子流程(如make)无法更改其父流程的环境。

你可以做类似的事情

$ eval `make pathupdate`

pathupdate目标是这样的:

pathupdate:
    @echo PATH=\"$(PATH)\"

6

您的答案可以在这里找到:https : //stackoverflow.com/a/8942216/367461

基本上,您应该这样做:

export PATH := $(shell pwd)/bin:$(PATH)

test:
    mkdir -p ./bin
    @echo $(PATH)

我在Fedora 23上使用GNU Make 4.0对此进行了测试,它对我来说很好用。


1
这是GNU Make的正确答案。对于BSD Make,您可以使用.SHELL: name=sh path=/path/to/wrapper-script然后制作一个包装器脚本,例如export FOO=bar; exec bash "$@"
rjh '18

2

我将要问同样的问题,因为我无法使其他答案示例正常工作。

但是,我设法通过使用eval命令为我实现了可行的解决方案。我不太确定为什么以前没有发布。

do_something: 
    $(eval export PATH=$(shell pwd)/bin:$(PATH))
    @echo $(PATH)

注意:PATH更改是make自身内部的临时操作。从make退出后,PATH将重置为较早的值。


之前没有发布过,因为它不是问题要问的问题:问题询问从make退出后如何获取更改的PATH。此外,这可以在一个更简单的方式来完成:将export PATH=…do_something:线,你不需要eval
吉尔斯(Gilles)'所以别再邪恶了'

1

您可以使Make在修改后的环境中递归调用自身,例如:

dummy: build_all

all: 
    PATH=/new/directory:$(PATH) $(MAKE) build_all

build_all:
    your make rules 

如果要使用外壳程序片段:

dummy: build_all

all:
    . ./define-my-variables.sh ; $(MAKE) build_all

build_all:
   your make rules
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.