在我看来,Make 只是一个 shell 脚本,对命令行参数的处理稍微容易一些。
为什么运行 make 而不是 ./make.sh 是标准的
一般的想法是 make
支持(合理地)最少的重建——即,你告诉它你的程序的哪些部分依赖于其他部分。当您更新程序的某些部分时,它仅重建依赖于它的部分。虽然您可以使用 shell 脚本来执行此操作,但这将是很多更多的工作(明确检查所有文件的最后修改日期等)。唯一明显的使用 shell 脚本的替代方法是每次都重建所有内容。对于小型项目,这是一种非常合理的方法,但对于大型项目,完全重建可能需要一个小时或更长时间——使用 make
,您可能在一两分钟内轻松完成相同的事情......
我可能还应该补充一点,有很多替代品至少具有大致相似的功能。尤其是在大型项目中只有少数文件被重建的情况下,其中一些文件(例如,Ninja)通常比 make 快得多。
Make是一个专家系统
有很多事情是用 shell 脚本很难做到的......
当然,它会检查什么是过时的,以便只构建它需要构建的东西
它执行拓扑排序或某种其他类型的树分析,以确定什么依赖于什么以及构建过时事物的顺序,这样每个先决条件都在每个依赖项之前构建,并且只构建一次。
它是一种用于声明式编程的语言。可以添加新元素,而无需将它们合并到命令式控制流中。
它包含一个推理引擎来处理规则、模式和日期,当与特定 Makefile 中的规则结合使用时,它就变成了一个专家系统。
它有一个宏处理器。
另请参阅:make 的早期摘要。
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
,它只以相反的顺序执行前 2 个命令。
尝试使用您自己的 shell 脚本完成此操作将涉及大量 if/else
检查。
rsync -r -c -I $SOURCE $DEST_DIR
的东西。
除了上述之外,Make 是一种声明性(-ish)并行编程语言。
假设您有 4,000 个要转换的图形文件和 4 个 CPU。尝试编写一个 10 行的 shell 脚本(我在这里很慷慨),它会在你的 CPU 饱和的同时可靠地完成它。
也许真正的问题是人们为什么要费心编写 shell 脚本。
make 处理依赖关系:makefile 描述它们:二进制文件依赖于目标文件,每个目标文件依赖于一个源文件和头文件...运行 make 时,比较文件的日期以确定需要重新编译的文件.
可以直接调用一个目标,而不是构建 Makefile 中描述的所有内容。
此外,make 语法提供替换,vpath
所有这些都可以用 shell 脚本编写,让你已经拥有它。