为啥在 shell 脚本上使用 make?

Posted

技术标签:

【中文标题】为啥在 shell 脚本上使用 make?【英文标题】:Why use make over a shell script?为什么在 shell 脚本上使用 make? 【发布时间】:2011-04-17 10:44:34 【问题描述】:

在我看来,Make 只是一个 shell 脚本,对命令行参数的处理稍微容易一些。

为什么标准运行 make 而不是 ./make.sh

【问题讨论】:

对于相反的问题:为什么使用 shell 脚本而不是 make(因为显然更容易处理命令行参数),特别是对于系统管理员任务,请阅读此处:unix.stackexchange.com/a/497601/1170 【参考方案1】:

一般的想法是make 支持(合理地)最少的重建——也就是说,你告诉它你的程序的哪些部分依赖于其他部分。当您更新程序的某些部分时,它重建依赖它的部分。虽然您可以使用 shell 脚本来执行此操作,但这将是很多更多的工作(明确检查所有文件的最后修改日期等)。唯一明显的使用 shell 脚本的替代方法是每次都重建所有内容。对于小型项目,这是一种非常合理的方法,但对于大型项目,完全重建可能需要一个小时或更长时间——使用make,您可能会在一两分钟内轻松完成相同的事情......

我可能还应该补充一点,有很多替代品至少具有大致相似的功能。尤其是在大型项目中只重建少数文件的情况下,其中一些文件(例如,Ninja)通常比 make 快得多。

【讨论】:

【参考方案2】:

与上述一样,Make 是一种声明式(-ish)并行编程语言。

假设您有 4,000 个要转换的图形文件和 4 个 CPU。尝试编写一个 10 行的 shell 脚本(我在这里很慷慨),它会在使 CPU 饱和的同时可靠地执行此操作。

也许真正的问题是人们为什么要费心编写 shell 脚本。

【讨论】:

是的,您正在将总线性排序松散为更像树的排序。 这是我的用例。你能举个例子吗?【参考方案3】:

Make 确保在您对源文件进行更改时只重新编译所需的文件。

例如:

final : 1.o 2.o
    gcc -o final 1.o 2.o

1.o : 1.c 2.h
    gcc -c 1.c

2.o : 2.c 2.h
    gcc -c 2.c

如果我只更改文件2.h 并运行make,它将以相反的顺序执行所有 3 个命令。

如果我只更改文件1.c 并运行make,它只会以相反的顺序执行前两个命令。

尝试使用您自己的 shell 脚本完成此操作将涉及大量 if/else 检查。

【讨论】:

或者在shell中使用类似rsync -r -c -I $SOURCE $DEST_DIR的东西。【参考方案4】:

Make 是一个 expert system

有很多事情是用 shell 脚本很难做到的......

当然,它会检查什么是过时的,以便只构建它需要构建的东西 它执行 topological sort 或其他类型的树分析,以确定构建过时事物的依据和顺序,例如每个先决条件都在每个依赖项之前构建,并且只构建一次。 这是 declarative programming 的语言。无需将新元素合并到命令式控制流中即可添加新元素。 它包含 an inference engine 来处理规则、模式和日期,当与特定 Makefile 中的规则结合使用时,它会将 make 变成expert system。 它有一个宏处理器。 另请参阅:an earlier summary of make

【讨论】:

不过,它作为专家系统非常有限。例如。每个推理只能使用一次相同的规则。 只是为了详细说明第 2) 点,用更通俗的工程术语来说,shell 脚本强制执行线性排序,而 makefile 是树状文件。它消除了不必要的时间依赖性(尽管实际上 make 过程将线性执行)。 ...我认为 Makefiles 在 shell 脚本上的问题类似于 CSS 在 javascript 上的问题。每个节点执行的时间顺序几乎不那么明显。尽管至少使用 Makefiles 你仍然可以看到实际的 shell 命令。使用 CSS 甚至可以将其抽象出来。 我有一些 cmets,如果有人澄清它们,我将不胜感激。 1/你的第一点和两点不是相关的,从某种意义上说,拓扑排序是如何实现增量构建的? 2/你不能指出使用函数组合实现的第 3 点吗。 3/我想了解更多关于MakeFile最终用户4和5的优势,以及为什么这些优势不能通过组合shell命令来实现 这是我第一次遇到被描述为专家系统的 Make。作为构建专家系统的人,我不会考虑这件事。 Make 显然有一个推理引擎来推断如何通过 makefile 中指定的声明性规则来构建程序,但它是一个基于知识的系统不太明显,因为(叶)规则是要执行的 shell 命令而不是事实。而“专家系统”这个词是用来指一个系统,它成功地捕捉到了世界级专家的专业知识,事实并非如此。陪审团仍在等待我。【参考方案5】:

make 处理依赖关系:makefile 描述它们:二进制文件依赖于目标文件,每个目标文件依赖于一个源文件和头文件...运行 make 时,比较文件的日期以确定需要什么重新编译。

可以直接调用一个目标而不是构建 Makefile 中描述的所有内容。

此外,make 语法提供替换,vpath

所有这些都可以用 shell 脚本编写,让你已经拥有它。

【讨论】:

以上是关于为啥在 shell 脚本上使用 make?的主要内容,如果未能解决你的问题,请参考以下文章

为啥shell脚本比较经常使用x$VAR = xyes?

为啥shell脚本中不能执行cd 命令

为啥 ncat -exec 可以与 shell 脚本一起使用,但不能与 perl 脚本一起使用?

在本地进行shell脚本中执行svn命令,为啥提示bash: svn: command not found?

在shell脚本执行sql语句为啥会报错

Shell脚本——make命令和Makefile文件