为啥在 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?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 ncat -exec 可以与 shell 脚本一起使用,但不能与 perl 脚本一起使用?