基于KitKat(KRT16S)、ARM平台配置进行描述。
一、基础概念
1、 sdk级别
高级别sdk:一般就是指android.jar,这个在做应用开发的时候可以直接导入;
低级别sdk:通过如“make sdk”命令生成的zip文件,包含platforms、platform-tools、tools等目录,以及模拟器、avd管理器、sdk管理器等;这个需要开发工具如eclipse进行配置方可使用;也是本文档所描述的sdk形式;
2、 android完整代码的编译
简单的来说,完整的编译过程是三个步骤:
步骤一:“source bulid/envsetup.sh”,配置通用的编译环境变量;
步骤二:“lunch”,选择product(或称device),配置平台相关的编译环境变量;
官方的代码如果未做任何修改一般是显示如下product(或称device)选择菜单:
1. aosp_arm-eng
2. aosp_x86-eng
3. aosp_mips-eng
4. vbox_x86-eng
5. aosp_manta-userdebug
6. mini_mips-userdebug
7. mini_armv7a_neon-userdebug
8. mini_x86-userdebug
9. aosp_deb-userdebug
10. aosp_grouper-userdebug
11. aosp_tilapia-userdebug
12. aosp_flo-userdebug
13. aosp_hammerhead-userdebug
14. aosp_mako-userdebug
选择不同的product(或称device)项,则用于编译的主要环境变量TARGET_PRODUCT、TARGET_BUILD_VARIANT、TARGET_BUILD_TYPE、TARGET_ARCH_VARIANT、TARGET_CPU_VARIANT均有所不同。例如,如果选择第7项,相关环境变量是:
TARGET_PRODUCT=mini_armv7a_neon
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_ARCH_VARIANT=armv7-a-neon
TARGET_CPU_VARIANT=cortex-a9
在官方实现的基础上可以通过自行定制来扩展 product(或称device),如vendor_test_eng,相关环境变量是:
TARGET_PRODUCT=vendor_test
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_ARCH_VARIANT=armv7-a-neon
TARGET_CPU_VARIANT=cortex-a7
步骤三:make [ -j N ]
如果跳过步骤二直接执行步骤三,则相关环境变量设置如下:
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_ARCH_VARIANT=armv7-a
TARGET_CPU_VARIANT=generic
3、 android的编译系统
用于android代码编译的配置文件都集中存放于build/core目录下,而官方提供的product(或称device)配置文件则集中存放于build/target目录下。通过lunch的选择,将相应的配置文件加载后即进入编译环节。编译系统如何搜寻到对应product(或称device)的配置文件是在build/core/config.mk中决定的:
board_config_mk := \
$(strip $(wildcard \
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
$(shell test -d device && find device -maxdepth 4 -path'*/$(TARGET_DEVICE)/BoardConfig.mk') \
$(shell test -d vendor && find vendor -maxdepth 4 -path'*/$(TARGET_DEVICE)/BoardConfig.mk') \
))
根据这些内容,可以得出搜索product(或称device)配置文件目录的优先级:
(1) build/target/board/$(TARGET_DEVICE)/BoardConfig.mk
这也是官方提供的系列product(或称device)的配置文件所在目录
(2) device/*/$(TARGET_DEVICE)/BoardConfig.mk
这也是自行定制product(或称device)存放的目录
(3) vendor/*/$(TARGET_DEVICE)/BoardConfig.mk
这个目录在官方代码中不存在,其它公司如高通的代码存在这个目录。
二、生成官方sdk的方式
1、 官方的文档介绍
在代码树中主要有三个文档描述了生成官方sdk的方式:
(1) sdk/README.txt
严格来说,这个文档只是描述要生成官方sdk的预备工作,以及如何更新sdk tools。值得关注的就是tools/base和tools/swt这两个仓库已经做为非缺省下载的仓库了,如果在repo init的时候不按要求进行,这两个仓库是不会下载的,也就无法完成官方sdk的生成工作。
对于大多数开发的公司来说,拿到的代码已经是上游芯片厂商做过修改的非官方原始版本了,有可能芯片厂商的代码仓库中已经不包含这两个仓库了。在生成官方sdk的实际过程中,从第三方开源项目(如codeaurora)中复制这两个仓库过来也顺利生成了官方sdk,这样就避免了无法从芯片厂商获取到仓库的问题。
(2) sdk/docs/howto_build_SDK.txt
这个文档描述了在linux下生成运行于linux或windows 平台的官方sdk的方法以及一些注意事项。很多人认为其中描述的方法不对是因为对于第一章节提及的基础概念理解不透彻,相关的问题是:
A) make sdk(或make win_sdk)会失败
此种情况一般是lunch选择了定制的product(或称device)后出现的错误,此时TARGET_PRODUCT和TARGET_CPU_VARIANT的值对应的是定制prodcut(或称device),也就是需要到device/*/$(TARGET_DEVICE)目录下配置文件去寻找的信息。
如果跳过lunch直接make sdk(或make win_sdk),则TARGET_PRODUCT是full,TARGET_CPU_VARIANT是generic,这个与官方的初衷是相违背的,原因见B)
B) make PRODUCT-sdk-sdk(或make PRODUCT-win_sdk)成功
文档中介绍的方法是lunch sdk-eng、make sdk,通过对比关键的环境变量发现两者其实是一致的,下面是最重要的两个环境变量值:
TARGET_PRODUCT=sdk
TARGET_CPU_VARIANT=generic
因此得出三点结论:
第一,生成官方sdk是需要TARGET_PRODUCT为sdk的(对应build/target/product/sdk.mk);
第二,不管执不执行lunch,make PRODUCT-sdk-sdk的环境变量都一样,所以它是将两步操作合二为一的操作,命令中第一个“sdk”关键字是指定product类型为sdk;
第三,官方没有提供生成自定制product(或称device)的sdk(下称vendor sdk)的方法,为此引出了问题C)
C) 此问题其实是问题A)的引申,即在定制vendor sdk后会出现错误:
build/core/main.mk:664:*** : Module 'bluetooth-health' in PRODUCT_PACKAGES has nothing toinstall!. Stop.
关于此问题的原因,最终在官方论坛上找到了正式说法:
Question:
Module 'bluetooth-health' inPRODUCT_PACKAGES has nothing to install
Answer:
This works as intended.
We intentionally made that be an error forsdk, for we want to make sure the SDK build installs everything in its productconfig.
Actually we want to enforce this check forall device builds as well, but unfortunately it takes much work to clean up thelegacy product configs.
You need to build the sdk in the sdkproduct config; or you should clean the dangling module names from the productconfig.
Anyway, we should remove those danglingmodule names (bluetooth-health hostapd wpa_supplicant.conf audio dhcpcd.confnetwork pand sdptool egl.cfg) from the build system.
也就是说这是有意为之,因为官方无法完全兼容所有vendor sdk的配置项,只能通过错误信息的方式来让vendor自行修改并生成vendor sdk。
D) 资源相关问题
框架的布局、图片、文字等资源信息是存放在frameworks/base/core/res下的,上游芯片厂商或下游开发公司在定制框架的时候也需要增加资源,但是出于某种目的会将资源以overlay的方式存放于product(或称device)的目录下,框架中仅做引用,这就会导致在生成官方sdk的时候出现资源缺失错误。遇到这种问题,办法一就是复制相关资源到框架中,办法二就是想办法生成vendor sdk(下有描述)。
(3) sdk/monitor/HOWTO-BUILD
严格来说,这个文档是与生成vendor sdk相关,对于官方sdk可忽略此部分。在sdk中有一个工具monitor(具体用法本文不探讨),在官方sdk方式下能生成,在vendor sdk方式下无法生成。通过查阅此文档发现生成monitor的配置文件sdk/monitor/Android.mk生效条件是:
# Expose the Monitor RCPonly for the SDK builds.
ifneq (,$(is_sdk_build)$(filtersdk sdk_x86 sdk_mips,$(TARGET_PRODUCT)))
即仅在product类型为sdk、sdk_x86、sdk_mips的情况下生成monitor,也就是官方sdk的方式。
三、生成厂商sdk的方式
其实生成官方sdk已经能满足应用开发需求,但是由于未包含厂商相关的内容,在联机调试时是否会有问题还有待考证。
根据前面二个章节的描述,生成vendor sdk除了要选择正确的product(或称device),还必须做一些配置文件的修改和调整,主要是针对几个错误进行:
错误一:
build/core/main.mk:664: *** : Module 'X' inPRODUCT_PACKAGES has nothing to install!. Stop.
遇到这种问题就是屏蔽此模块在配置文件中的引用。
错误二:
make[1]: *** No rule to make target`monitor', needed by `PRODUCT-vendor_test-aapt'. Stop.
解决办法见第二章节的相关说明。
错误三:
make[1]: Nothing to be done for `X'.
这个发生在生成zip文件时,主要是如aidl、adb、emulator等工具无法获取(实际已在out目录下生成),暂时的解决办法也是屏蔽。但为什么官方sdk无此错误,就需要比对product配置信息了。
四、引用
1、Android Makefile中是 如何识别 TARGET_PRODUCT 的
http://blog.csdn.net/stevenliyong/article/details/5285334
2、Android平台开发-Customize newdevice-定制新设备
http://blog.sina.com.cn/s/blog_60862cad0100wuaf.html
3、编译Android模拟器(make sdk),以及错误处理
http://blog.csdn.net/gaojinshan/article/details/9420869
4、Module 'bluetooth-health' inPRODUCT_PACKAGES has nothing to install
https://code.google.com/p/android/issues/detail?id=61210
5、Android编译系统详解(一)——build/envsetup.sh
http://www.cloudchou.com/android/post-134.html