在Android系统中修改Android.mk使其同时编译rgb2565和rgb2888(向out/host/linux-x86/bin/下新增加一个工具命令)
修改对应的Android.mk文件使其在源码编译时能够同时编译出rgb2565和rgb2888,rgb2888的源码文件已有,其实实现很简单,这里只是将我在具体测试中不同模块标签的模块在不同编译模式下的所采取的编译方式列举一下,因为我们的改动最好能和源码进行无缝的结合。
一、 Android系统的四种编译模式
Android系统有四种编译模式,分别是user、userdebug、eng、test。这个值由编译环境变量TARGET_BUILD_VARIANT保存,在源码编译之前需要我们手动指定。指定方式是,执行$ . build/envsetup.sh命令之后,执行lunch命令,系统会根据我们这一步的选择自动修改TARGET_BUILD_VARIANT的值。如果这个值未指定,系统则将其默认为eng。
不同的模式决定了不同的模块被安装到目标系统(system.img)中,并适用于不同的发布版本。这样可以使发布版本的系统更轻量,更简洁。下面看一下不同的编译模式之间的主要区别。
eng | This is the default flavor. A plain "make " is the same as "make eng ". droid is an alias foreng . · Installs modules tagged with: eng , debug , user , and/or development . · Installs non-APK modules that have no tags specified. · Installs APKs according to the product definition files, in addition to tagged APKs. · ro.secure=0 · ro.debuggable=1 · ro.kernel.android.checkjni=1 · adb is enabled by default. |
user | "make user " This is the flavor intended to be the final release bits. · Installs modules tagged with user . · Installs non-APK modules that have no tags specified. · Installs APKs according to the product definition files; tags are ignored for APK modules. · ro.secure=1 · ro.debuggable=0 · adb is disabled by default. |
userdebug | "make userdebug " The same as user , except: · Also installs modules tagged with debug . · ro.debuggable=1 · adb is enabled by default. |
tests | Installs modules tagged with user,debug,eng,tests。 |
上面的表格区分了不同编译模式中,编译系统所做的不同的事情。从上面的表格我们可以得知:
①并不是在对应的编译模式下,对应的编译模块才预装到目标系统中。例如上图中的eng。在eng编译模式下,会预装标签为eng、debug、user的模块。在tests编译模式下,会预装模块标签为user、debug、eng、tests的模块。这对于我们修改Android.mk并成功编译rgb2888来说是非常重要的信息。
②其中在user编译模式下,只会预装标签为user的模块。在userdebug模式下,预装的模块除了标签为user的还有标签为debug的模块。
③ 如果在执行编译时未指定编译模式,则系统将编译模式自动默认为eng模式。
④其他的区别对于编译rgb2888并没有影响。
二、 Android.mk文件中的模块标签
①Android.mk文件是Android源码中的编译配置文件,指定了对应的模块以怎样的方式进行编译。Android源码中的编译都是以模块进行的,一个Android.mk文件可以同时编译一个或多个模块。
② Android.mk中以include $(CLEAR_VARS)为开始,以include $(文件格式)为结束算作一个模块。我们可以在其之间指定这个模块的标签,模块的名称,需要的源文件,需要使用的库等等。
③ 每个模块标签的取值范围是user、eng、tests、optional、samples。系统会根据上面提到的TARGET_BUILD_VARIANT值将对应的模块编译到目标系统中。可以对模 块标签进行如下直观的理解:
user:指该模块在user模式下才编译。
eng:指该模块在eng模式下才编译。
tests:指该模块在tests模式下才编译
optional:指该模块在任何编译模式下都将编译。
samples:还不确定。
④上面官方给出的模块标签的理解,好想是不对的。因为在不同的编译模式下可能会预装不同的模块,比如,eng模式下,会预装标签为user、debug、eng的模块,所以在eng模式下也要编译标签为user,debug的模块。总之,我们可以理解为,编译模式和模块标签共同决定了在实际的编译中对应模块的编译方式,两者相互依赖。
⑤当模块标签未指定时,默认值是user。
三、 修改Android.mk使其同时编译rgb2565和rgb2888
①首先仿照Android.mk文件中rgb2565模块,编写rgb2888对应的编译配置。如下图所示:
②编写完Android.mk并选择eng模式编译。会出现如下的错误提示:
③上面提示user标签只支持传统的模块。如果在任何模式下编译该模块,需要指定模块的标签为optional。我们向Android.mk中rgb2888模块中添加对应的模块标签为 optional,然后重新编译,通过。
④将模块标签修改为optional后编译成功。当在对应的目录(out/host/linux-x86/bin/)中查找时,发现rgb2565命令已经生成,而rgb2888并未输出到该目录中。但是我们的编译已经通过,说明rgb2888的模块已经正确编译了。通过查看目录out/host/linux-x86/obj/EXECUTABLES/rgb2888_intermediates/,发现编译的中间生成物的确已经生成,说明我们的编译没有错误。从这一点可以说明,标签为optional的模块虽然在任何模式下都会编译,但是不会预装到目标系统中。
⑤当使用默认标签user时,提示user标签只支持传统的模块。通过测试发现,在eng模式下如果预装标签为user的模块时,必须显示指定user标签支持的模块。指定方式是修改源码中的build/core/user_tags.mk文件,在GRANDFATHERED_USER_MODULES +=中添加上模块的名称,即我们的rgb2888。然后编译,测试通过,对应的 rgb2888和rgb2565成功输出到了out/host/linux-x86/bin目录下。
⑥ 使用标签eng重新编译后,发现也会成功通过,rgb2888也成功输出到了对应的bin目录下(编译模式为eng)。
⑦通过比较发现,当使用编译模式为eng时,预装标签为user的模块时,要显示的指定,模块使用eng标签时,不需要显示的指定就可以预装该模块。对于eng模式下预装optional标签的模块,能否通过修改对应的支持才可以正确的预装,尚不明确。
⑧另外,将编译的模块预装到目标系统(system.img)貌似不能等价理解为对应的rgb2888在out/host/linux-x86/bin下正确输出了。这两者好像没有必然的联系。但是这并不影响我们解决问题。
四、 总结
综上所述,修改Android.mk文件使其同时编译出rgb2565和rgb2888,可以使用以下三种方式(eng编译模式):
②可以在rgb2565目录所在的位置下,新建rgb2888目录,拷贝对应的源码文件,编写rgb2888模块的编译文件Android.mk(使用默认模块标签),并修改build/core/user_tags.mk添加对rgb2888的支持。这种方式是源码更清晰简介。但也要修改user_tags.mk,这是关键。
③直接在rgb2888模块中显示使用eng标签。