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
参考资料: