macos - 带有源的 Makefile 出现错误 `No such file or directory`

标签 macos makefile

我有一个非常简单的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。我不确定这是否会有所作为。

最佳答案

tldr;丢失,使用点(.),如下所示:

test:
        pytest -s

dev:
        . ./bin/authenticate.sh

下面是更长的解释...

它不起作用,因为make正在$PATH中寻找程序。这会失败,因为 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改变其策略;它不尝试查找并执行程序,而是将规则主体传递给系统 shell:

$ 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 类型决定了在每个 Makefile 规则中扩展哪些 shell 内置函数。您可以告诉 make 使用您选择的 shell,如下所示:

$ 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

引用文献:

关于macos - 带有源的 Makefile 出现错误 `No such file or directory`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44052093/

相关文章:

ios - 如何在不使用 sudo 的情况下从终端窗口关闭我的互联网连接?

makefile - 制作 : How to escape spaces in $(addprefix)?

makefile - 如果源文件存在,如何从一个目录构建,否则从另一个目录构建?

macos - AppleScript 创建 'link' 到特定的 Messages.app 对话?

c - [Makefile] 添加颜色在 OS X 上不起作用

mysql - 我可以使用 openssl s_client 来检索 MySQL 的 CA 证书吗?

具有用于单次调用的多个目标的 Makefile 规则

android - 使 : *** No targets specified and no makefile found. 停止

linux - 发出 "make"命令时发生错误

ruby-on-rails - OS X 10.8 上 Rails 应用程序中的段错误