构建工具GNU make

在阅读GNU make构建工具相关资料的时候,一直在思考几个问题

  • “ build system ” 是翻译成构建系统还是编译系统 /li>
  • make是什么 make可能是构建系统,make也可能是是构建系统中的一部分构建工具。
  • make的使用场景 /li>

其实如果不回答上面三个问题,并不会对我们学习Makefile语言有什么障碍。但是笔者个性使然,就是想要把这些关系梳理清楚再去学习其中的语法。

先来回答第一个问题,阮一峰在他的博文中认为build叫做构建,compile叫做编译,参考这个Make 命令教程。所以我认为“ build system ” 叫做构建系统,而构建工具是构建系统中的一部分。构建工具有很多种 :成熟大型项目常用的make ,Android平台开发应用的gradle ,人工智能TensorFlow的bazel。

那么接下来回答第二个问题,make是什么 ake是构建系统中的一部分,是一种构建工具。用于规划如何编译项目。就好比汽车制造厂的组装器,调配汽车的各个零部件资源,并且进行合理的组装形成一辆完整的汽车。由于平台不同编译器不同等原因,它分为好多种 :GNU make,Visual C++的nmake ,cmake ,qmake 。想了解其差异,可以参考这个make makefile cmake qmake都是什么,有什么区别/p>

最后回答第三个问题,make相对于其他构建工具的历史来的悠久,其稳定性自然不言而喻。它是c/c++项目的必备工具,由于c/c++的语言特性导致很多大型项目的底层都离不开它,致使像“ Android Open Source Project ”这样的大型项目使用make来完成这个系统的编译、打包等工作 。就连阮一峰也在博文中推荐使用make来构建Node.js这种大型项目,参考这个使用 Make 构建 站

想要快速学习make这个构建工具,就需要从“熟悉Makefile的语法”和“Makefile在大型项目的使用“这两个方面来入手。

初步认识Makefile语言

如果是有ROM工作经验的工程师一定用过这条命令.它会重新打包生成system.img。执行后经过一系列的流程到达下面的代码。

build/core/Makefile

上面的代码基本说明了Makefile语言的使用。snod是一个标识,也是一个伪目标(phony target),与之相对的就是目标,是一个文件(目标文件、可执行文件)。而冒 右边,是左边的预备条件。他们的下一行就是编译指令或者是控制指令。比如这样

这个就是一个规则(rule),定义了如何编译的规则。可以用一个通用公式来表达,就是下面这个

当然Makefile语言也会有变量、函数。这个文章就不详细讲解Makefile语法了,因为已经有好多人都写过相关的文章,可以参考权威的”GNU make“,如果看不懂英文或者看英文吃力,可以参考这个中文文章”跟我一起写Makefile“。还有我最喜欢的博主老罗对Makefile的理解“Android编译系统简要介绍和学习计划”

make在Android平台的运用

为了加快AOSP项目的编译速度,Android团队在N版本添加了ninja构建工具,ninja构建工具相对于make构建工具更底层。通过开源项目kati(kati是项目名,但是最终编译生成的程序名却是叫做ckati,后续我们将使用ckati这个名字)将Makefile文件翻译成ninja文件。make和ninja的关系就像cmake和make。还有一点要注意的,由于7.1以后部分使用的是Soong+Buleprint这套构建工具,将bp文件转换成ninja文件,所以Makefile文件和Buleprint文件是混合使用的,分析Makefile文件要小心一点。不过Blueprint+Soong这套构建工具代替make、kati这套构建工具只是时间问题。 那么我们就来大致了解一下这个转换的流程

build/core/main.mk

当我们在项目顶级目录执行make命令时,在顶级目录有个Makefile文件include build/core/main.mk。所以主要的内容都在main.mk这个文件里面。由于KATI一开始并没有定义,所以会执行语句。makeparallel程序会fork出一个子进程执行soong_ui.bash,参数为。soong_ui.bash也很简单,就是执行soong_ui程序,该程序使用go语言写的。

我们来看看入库文件main.go
build/core/soong/cmd/soong_ui/main.go

build文件中Build函数就是执行ckati或者ninja程序的关键函数,

build/core/soong/ui/build/build.go

从main.go传过来的what参数为build.BuildAll,而BuildAll在build.go的定义就可以知道Build函数会一次执行run make、run Soong、run ckati、run ninja。每个工具的使用对应着一个go文件,比如run make,有make.go;run soong ,有soong.go。但是只有在run ckati时,ckati工具会再次执行build/core/main.mk文件。为什么要在这里执行main.mk,我们后面会讲到。先来看看看ckati的调用逻辑

build/soong/ui/build

很简单的几句话,就是执行ckati命令。

build/kati/main.cc

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年11月10日
下一篇 2022年11月10日

相关推荐