【问题标题】:Makefile with source get error `No such file or directory`带有源的 Makefile 得到错误“没有这样的文件或目录”
【发布时间】:2017-05-18 15:34:36
【问题描述】:

我有一个非常简单的Makefile 正在做source 来设置ENV 变量。但是如果我从Makefile调用它就行不通了

我收到此错误

make dev
source ./bin/authenticate.sh
make: source: No such file or directory
make: *** [dev] Error 1

脚本存在。

如果我在命令行中运行它,它可以工作。

source ./bin/authenticate.sh
Works!

这是我的Makefile

test:
    pytest -s

dev:
    source ./bin/authenticate.sh

我正在使用 OSX。我不确定这是否会有所作为。

【问题讨论】:

  • 猜测,您的 Make 使用的 shell 不支持内置 source。您可以使用 $(info $(SHELL)) 找出 Make 正在使用什么,echo $SHELL 找出您的命令行是什么,并使用 makefile 顶部的 SHELL := ... 将一个设置为另一个。
  • 如果您使用. ./bin/authenticate.sh,makefile 是否工作?点 (.) 是获取文件的 POSIX 方式。

标签: macos makefile


【解决方案1】:

tldr;失去source,使用点(.

下面是更长的解释......

它不起作用,因为make 正在$PATH 中寻找source 程序。这失败了,因为 source 是一个(非 POSIX)shell 内置,而不是任何传统的类 UNIX 系统上的可执行程序。

我能够复制问题中显示的失败;以下(大量删节)输出是在 Ubuntu 16.04 上使用 GNU Make v4.1 生成的:

$ strace -f -s65536 -- make dev 2>&1 | grep 'authenticate'
read(3, "test:\n\tpytest -s\n\ndev:\n\tsource ./bin/authenticate.sh\n", 4096) = 53
write(1, "source ./bin/authenticate.sh\n", 29source ./bin/authenticate.sh
[pid 32100] execve("/usr/local/sbin/source", ["source", "./bin/authenticate.sh"], [/* 82 vars */]) = -1 ENOENT (No such file or directory)
[pid 32100] execve("/usr/local/bin/source", ["source", "./bin/authenticate.sh"], [/* 82 vars */]) = -1 ENOENT (No such file or directory)
[pid 32100] execve("/usr/sbin/source", ["source", "./bin/authenticate.sh"], [/* 82 vars */]) = -1 ENOENT (No such file or directory)
[pid 32100] execve("/usr/bin/source", ["source", "./bin/authenticate.sh"], [/* 82 vars */]) = -1 ENOENT (No such file or directory)
[pid 32100] execve("/sbin/source", ["source", "./bin/authenticate.sh"], [/* 82 vars */]) = -1 ENOENT (No such file or directory)
[pid 32100] execve("/bin/source", ["source", "./bin/authenticate.sh"], [/* 82 vars */]) = -1 ENOENT (No such file or directory)

您可以看到make 进行了六次失败的尝试来查找source 程序;即,我的$PATH 的每个组件都有一个。

如果source改成.make改变策略;它不尝试查找和执行程序,而是将规则体传递给系统外壳:

$ strace -f -s65536 -- make dev 2>&1 | grep 'authenticate'
read(3, "test:\n\tpytest -s\n\ndev:\n\t. ./bin/authenticate.sh\n", 4096) = 48
write(1, ". ./bin/authenticate.sh\n", 24. ./bin/authenticate.sh
[pid 32122] execve("/bin/sh", ["/bin/sh", "-c", ". ./bin/authenticate.sh"], [/* 82 vars */]) = 0
[pid 32122] open("./bin/authenticate.sh", O_RDONLY) = 3

make 使用的 shell 类型决定了哪些 shell 内置函数在每个 Makefile 规则中得到扩展。您可以告诉make 使用您选择的外壳,如下所示:

$ cat Makefile
SHELL = /bin/bash
test:
        pytest -s

dev:
        source ./bin/authenticate.sh

由于bash 将内置source 定义为. 的同义词,因此使用source 的规则现在成功:

$ strace -f -s65536 -- make dev 2>&1 | grep 'authenticate'
read(3, "SHELL = /bin/bash\ntest:\n\tpytest -s\n\ndev:\n\tsource ./bin/authenticate.sh\n", 4096) = 71
write(1, "source ./bin/authenticate.sh\n", 29source ./bin/authenticate.sh
[pid 32573] execve("/bin/bash", ["/bin/bash", "-c", "source ./bin/authenticate.sh"], [/* 82 vars */]) = 0
[pid 32573] open("./bin/authenticate.sh", O_RDONLY) = 3

参考资料:

【讨论】:

  • 你如何从虚拟环境中停用,因为这在 make 中也不起作用
  • @Wayneio,如果您在 virtualenv 或类似的开发环境中遇到问题,那么我鼓励您针对您选择的工具提出一个新问题。
【解决方案2】:

cd bin && source authenticate.sh它有效

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-10
    • 1970-01-01
    • 2021-03-15
    • 2012-08-05
    • 1970-01-01
    • 2013-12-03
    • 1970-01-01
    相关资源
    最近更新 更多