为什么使用 shell 脚本目标调用 make 会创建可执行文件?



我写了一个简单的shell脚本(称为test.sh)来编译一个测试C++文件,并使用两个不同的编译器(g++和clang++)编译一个测试文件,并放入一些echo语句来比较输出。在命令行上,我不小心输入了make test,即使该目录中没有 Makefile。它没有抱怨没有 Makefile 或没有定义目标,而是执行了以下命令(我的系统正在运行带有 GNU Make 4.1 的 64 位 Debian stretch OS):

user@hostname test_dir$ make test
cat test.sh >test
chmod a+x test
user@hostname test_dir$

出于好奇,我制作了另一个 shell 脚本(other.sh)并做了同样的事情。

这是我other.sh文件:

#!/bin/bash
echo ""
echo "This is another test script!"
echo ""

命令行:

user@hostname test_dir$ make other
cat other.sh >other
chmod a+x other
user@hostname test_dir$

我的问题是为什么在终端中运行make命令时make自动创建可执行脚本(没有.sh扩展名)?这是正常/预期/标准行为吗?我可以在所有 Linux 计算机上依赖此行为吗?


附带问题/注意:是否有受支持的"隐式后缀"列表,make会自动为其创建可执行文件?

这是内置在 Gnu make 中的许多"隐式规则"之一。(每个 make 实现都会有一些隐式规则,但不能保证它们是相同的。

  1. 为什么 make 会自动创建没有.sh扩展名的可执行脚本?

有一个旧的源代码存储库系统称为源代码控制系统(SCCS)。虽然它不再有太多用途,但它曾经是维护源代码存储库的最常见方式。它有一个怪癖,它不保留文件权限,所以如果你在SCCS中保留一个(可执行的)shell脚本,后来把它签出来,它将不再是可执行的。Gnu make可以自动从SCCS仓库中提取文件;为了弥补消失的可执行权限问题,通常将.sh扩展与 shell 脚本一起使用; 然后,make可以执行两步提取,首先从存储库中提取foo.sh,然后将其复制到foo,添加可执行权限。

  1. 这是正常/预期/标准行为吗?我可以在所有 Linux 计算机上依赖此行为吗?

安装了开发工具集的 Linux 系统倾向于使用 Gnu make,因此您应该能够在用于开发的 Linux 系统上依靠这种行为。

BSD make 还附带了.sh的默认规则,但它只复制文件;它不会更改权限(至少在我的机器上的 bsdmake 发行版上)。所以这种行为并不普遍。

  1. 是否有受支持的"隐式后缀"列表,make 将自动为其创建可执行文件?

是的,有。您可以在制作手册中找到它:

默认后缀列表为:.out.a.ln.o.c.cc.C.cpp.p.f.F.m.r.y.l.ym.lm.s.S.mod.sym.def.h.info.dvi.tex.texinfo.texi.txinfo.w.ch.web.sh.elc.el

要获得更准确的隐式规则列表,可以使用以下命令

make -p -f/dev/null
# or, if you like typing, make --print-data-base -f /dev/null 

如创建选项摘要中所述。

make手册页:

make 实用程序的目的是自动确定 哪 大型程序的各个部分需要重新编译,并发出命令 以重新编译它们。 该手册GNU描述了 make,由理查德·斯托曼和罗兰·麦格拉思撰写,是 目前由保罗·史密斯维护。 我们的示例显示了C程序, 因为它们是最常见的,但您可以在任何编程中使用 make 其编译器可以使用 shell 命令运行的语言。 事实上,使 不限于程序。 您可以使用它来描述任何任务,其中 每当其他文件发生更改时,某些文件必须从其他文件自动更新。

make真的比大多数人想象的要多......

最新更新