编译android源码的make命令解析
2012-01-09 09:02
344 查看
摘要:
本文描述了编译android源码时,make命令后面隐藏的玄机,通过一步步的分析,你会发现,实际上不是想象的那么复杂(肯定比编hello world复杂,哈)。
正文:
最近编译了一下android 1.6,同时也分析了一下android的build system。build system对我来说实在太大,要想了解这个系统的细节不是一两天可以完成的,于是我就退而求其次,去了解编译android源码的命令make。还是那句话,一切都是从编译开始的。
1. make命令执行后,编译的入口在哪里?
虽然我的最终目的是研究android源码之间的关系,但是,当我编完android源码后,这是我想到的第一个问题。根据makefile的规则,make若不加参数会默认执行目录下的makefile文件,而这里的makefile文件include了main.mk文件。同时,makefile会执行main.mk中的第一条规则。根据这个原则,你会发现main.mk中的第一条规则在main.mk的第45行,但是它什么也不做,目的只是占个位置。
# This is the default target. It must be the first declared target.DEFAULT_GOAL := droid$(DEFAULT_GOAL):
真正的定义在第681行,这里的定义覆盖了上面的定义。往下走一步是droidcore规则,它的定义为:
.PHONY: droidcoredroidcore: files \ systemimage \ $(INSTALLED_BOOTIMAGE_TARGET) \ $(INSTALLED_RECOVERYIMAGE_TARGET) \ $(INSTALLED_USERDATAIMAGE_TARGET) \ $(INTERNAL_DEFAULT_DOCS_TARGETS) \ $(INSTALLED_FILES_FILE)
这个规则显然是我们想要的,但问题是其中的变量值是多少呢?要解决这个问题也很容易。make在解析makefile文件时,大致流程如下:首先会解析makefile文件,这一步主要是进行规则的展开工作,根据make后面的参数来解析出规则实际要执行的动作(action)。解析完整个文件后,就开始执行指定的规则后面的动作了,此时,就只剩下一个动作列表,挨个执行就可以了。根据这个原则,加上droidcore规则位于文件的末尾,所以我们可以在文件的最后输出这些参数。这里我们要用到makefile的函数info和error,info的作用是在第一遍解析时,输出信息,然后继续解析,error则是输出信息后退出,具体可以参考make的文档。比如,这里我们要查看上面几个变量的值,可以在main.mk的最后添加如下语句。最后一句用来标识main.mk已经解析完。
上面几个变量的值实际上是相对于android源码的相对目标文件路径,比如INSTALLED_BOOTIMAGE_TARGET为out/target/product/generic/ramdisk.img。这里我们很容易猜到systemimage的值(out/target/product/generic/system.img)是什么了。
到这里,我们可以认为,像out/target/product/generic/ramdisk.img的值,实际上就是一条makefile确定的规则,无论这条规则是怎么来的,使用make out/target/product/generic/ramdisk.img是可以编译ramdisk.img文件的,在后面我们可以看到,知道这一点很重要,android的build system就是靠这一点工作的,我认为是核心。
2. droidcore规则完全展开后是什么样子的?
有了上面的工作,这个问题就变的容易许多。我本来的目的是想要研究android源代码之间的依赖关系,而这个依赖关系通过makefile中获取,是最直观和可靠的。要想获得droidcore的所有动作列表也不难,make命令有个参数-n,它的目的是“只输出规则下的动作(编译命令)语句,而不执行规则”。比如,要想获得droidcore的所有动作序列,可以使用如下命令:(输出结果太长了,可以将它输出到文件)
make -n 我将这个命令的结果输出到文件,由于等的时间太长,就放弃了,估计起码有几十兆,几万行命令。
也可以用如下命令来获取编译ramdisk.img所需要的命令序列:
make -n out/target/product/generic/ramdisk.img
编译ramdisk.img命令大概有5600行。还是有点大,那该如何?这个输出的最后一行你会发现,ramdisk.img是通过将目录out/target/product/generic/root打包而成的。所以,你可以去研究这个包里的每个文件是怎么编出来的。有了上面的例子,应该不难。
后面该怎么样进行下去,我还没想好,先研究ramdisk.img下每个文件是怎么来的再说。
本文描述了编译android源码时,make命令后面隐藏的玄机,通过一步步的分析,你会发现,实际上不是想象的那么复杂(肯定比编hello world复杂,哈)。
正文:
最近编译了一下android 1.6,同时也分析了一下android的build system。build system对我来说实在太大,要想了解这个系统的细节不是一两天可以完成的,于是我就退而求其次,去了解编译android源码的命令make。还是那句话,一切都是从编译开始的。
1. make命令执行后,编译的入口在哪里?
虽然我的最终目的是研究android源码之间的关系,但是,当我编完android源码后,这是我想到的第一个问题。根据makefile的规则,make若不加参数会默认执行目录下的makefile文件,而这里的makefile文件include了main.mk文件。同时,makefile会执行main.mk中的第一条规则。根据这个原则,你会发现main.mk中的第一条规则在main.mk的第45行,但是它什么也不做,目的只是占个位置。
# This is the default target. It must be the first declared target.DEFAULT_GOAL := droid$(DEFAULT_GOAL):
真正的定义在第681行,这里的定义覆盖了上面的定义。往下走一步是droidcore规则,它的定义为:
.PHONY: droidcoredroidcore: files \ systemimage \ $(INSTALLED_BOOTIMAGE_TARGET) \ $(INSTALLED_RECOVERYIMAGE_TARGET) \ $(INSTALLED_USERDATAIMAGE_TARGET) \ $(INTERNAL_DEFAULT_DOCS_TARGETS) \ $(INSTALLED_FILES_FILE)
这个规则显然是我们想要的,但问题是其中的变量值是多少呢?要解决这个问题也很容易。make在解析makefile文件时,大致流程如下:首先会解析makefile文件,这一步主要是进行规则的展开工作,根据make后面的参数来解析出规则实际要执行的动作(action)。解析完整个文件后,就开始执行指定的规则后面的动作了,此时,就只剩下一个动作列表,挨个执行就可以了。根据这个原则,加上droidcore规则位于文件的末尾,所以我们可以在文件的最后输出这些参数。这里我们要用到makefile的函数info和error,info的作用是在第一遍解析时,输出信息,然后继续解析,error则是输出信息后退出,具体可以参考make的文档。比如,这里我们要查看上面几个变量的值,可以在main.mk的最后添加如下语句。最后一句用来标识main.mk已经解析完。
1: $(info INSTALLED_BOOTIMAGE_TARGET = $(INSTALLED_BOOTIMAGE_TARGET))
2: $(info INSTALLED_RECOVERYIMAGE_TARGET = $(INSTALLED_RECOVERYIMAGE_TARGET))
3: $(info INSTALLED_USERDATAIMAGE_TARGET = $(INSTALLED_USERDATAIMAGE_TARGET))
4: $(info INTERNAL_DEFAULT_DOCS_TARGETS = $(INTERNAL_DEFAULT_DOCS_TARGETS))
5: $(info INSTALLED_FILES_FILE = $(INSTALLED_FILES_FILE))
6: $(error >>>>>>> end of the main.mk)
上面几个变量的值实际上是相对于android源码的相对目标文件路径,比如INSTALLED_BOOTIMAGE_TARGET为out/target/product/generic/ramdisk.img。这里我们很容易猜到systemimage的值(out/target/product/generic/system.img)是什么了。
到这里,我们可以认为,像out/target/product/generic/ramdisk.img的值,实际上就是一条makefile确定的规则,无论这条规则是怎么来的,使用make out/target/product/generic/ramdisk.img是可以编译ramdisk.img文件的,在后面我们可以看到,知道这一点很重要,android的build system就是靠这一点工作的,我认为是核心。
2. droidcore规则完全展开后是什么样子的?
有了上面的工作,这个问题就变的容易许多。我本来的目的是想要研究android源代码之间的依赖关系,而这个依赖关系通过makefile中获取,是最直观和可靠的。要想获得droidcore的所有动作列表也不难,make命令有个参数-n,它的目的是“只输出规则下的动作(编译命令)语句,而不执行规则”。比如,要想获得droidcore的所有动作序列,可以使用如下命令:(输出结果太长了,可以将它输出到文件)
make -n 我将这个命令的结果输出到文件,由于等的时间太长,就放弃了,估计起码有几十兆,几万行命令。
也可以用如下命令来获取编译ramdisk.img所需要的命令序列:
make -n out/target/product/generic/ramdisk.img
编译ramdisk.img命令大概有5600行。还是有点大,那该如何?这个输出的最后一行你会发现,ramdisk.img是通过将目录out/target/product/generic/root打包而成的。所以,你可以去研究这个包里的每个文件是怎么编出来的。有了上面的例子,应该不难。
后面该怎么样进行下去,我还没想好,先研究ramdisk.img下每个文件是怎么来的再说。
相关文章推荐
- 编译android源码的make命令解析
- 编译android源码的make命令解析
- 编译android源码的make命令解析
- 编译android源码的make命令解析
- 编译完android源码并且已经make sdk之后,重启不能调用emulator命令解决方案
- Android源码编译——Ubuntu 14.10的make3.8、gcc-4.4.7和g++-4.4.7安装方法
- 利用源码编译Android系统的APK和可执行命令的方法
- android源码编译错误make ***[out/host/linux-x86/obj/EXECUTABLE/llvm-rs-cc_intermediates/llvm-rs-cc] Error 1
- Android源码内部编译过程总结(Make)(转)
- Android源码编译完重启电脑后emulator命令报错
- Android源码编译之:KeyError: 'ui_strings.grd' make: *** [out/target/product/generic/obj/GYP/shared_interme
- Android 源码编译 make sdk ADT
- Android源码编译make的各类错误解决方案汇总
- DM3730上。android2.3源码编译过程,问题解析。(方便以后自己用)
- Android源码编译make的错误处理
- android平台的三个编译命令----make,mm,mmm
- 解决:Android编译源码根目录下/system/vold后,通过push命令将编译生成的vold文件push至system/bin下无法正常开机
- 编译android源码时用到的几个命令m、mm、mmm
- ubuntu12.04 64bit 编译android源码时遇到的问题"make: *** [out/host/linux-x86/obj/EXECUTABLES/adb_intermediates"
- ubuntu下mtk6573平台android源码编译命令