学习Android的编译系统要重点关注以下三点:
--Non-Recursive Make,与之相反的是通过make命令的-C选项指定要哪些读取子目录中的Makefile,这样就要求逐一指定子目录名。Android.mk中使用include $(call all-makefiles-under,$(LOCAL_PATH))实现类似的功能
--使用Android.mk:它是简化了的Makefile--Build 系统代码: 编译的起源为build/core/main.mk
在kernel/lk/external中还可以看到传统的Makefile文件,高通平台的kernel/lk中还有一些特殊命名的.mk文件,这些makefile无法自动获取Android编译环境中的定义。一般都是通过Android.mk来包装这些Makefile文件。
main.mk中包含的envsetup.mk中包含product_config.mk文件,这里包含了product/device等产品相关的信息
编译过程会首先执行envsetup.sh,这里会遍历目录找出所有的Android.mk并合成
准备编译用环境变量,所以要用 source build/envsetup.sh,定义的典型变量有:ANDROID_EABI_TOOLCHAIN/ANDROID_TOOLCHAIN/ANDROID_QTOOLS/ANDROID_BUILD_PATHS/JAVA_HOME/ANDROID_JAVA_TOOLCHAIN/ANDROID_PRE_BUILD_PATHS/ANDROID_PRODUCT_OUT/OUT
还定义了一些命令lunch chooseproduct croot mm godir sgrep printconfig,所有定义内容可以通过set|less命令来查看
lunch定义的变量有TARGET_PRODUCT/TARGET_BUILD_VARIANT(user/debug/eng)/TARGET_BUILD_TYPE(release/debug)
Android.mk用到的定义
include $(CLEAR_VARS)清除所有其他模块的LOCAL_*变量定义
LOCAL_PATH/LOCAL_SRC_FILES/LOCAL_MODULE/LOCAL_MODULE_TAGS
include $(BUILD_EXECUTABLE)
build variants的含义
user
-installs modules tagged with user
-intalls non-packaged modules that have no tags specified
-ro.secure = 1
-ro.debuggable = 0
-ADB缺省为disabled
userdebug会另外增加
-installs modules tagged with debug
-ro.debuggable = 1
-ADB缺省为enabled
eng会另外增加
-installs modules tagged with eng and development
-ro.secure = 0
-ro.kernel.android.checkjni = 1
还有一种tag为optional,它不作为一个build variant,解析中为user
定义的相关变量可从build/core/clear_vars.mk中查看
定义的宏在build/core/definitions.mk中,可以用makefile中的call命令调用
对于tags为optional的module,在全编代码时不会被编译,除非将它的名字写在PRODUCT_PACKAGES变量中,位于/build/target/product/core.mk中。
BUILD_PREBUILT可用于处理系统编译前就已经编译好的库或配置文件(比如第三方厂家的),类似的还有处理多个预编译文件的BUILD_MULTI_PREBUILT。还可以使用简单的$(call add-prebuilt-files, ETC, pv_player.cfg)写法。可设定的类型有ETC,APPS,EXECUTABLES,SHARED_LIBRARIES,STATIC_LIBRARIES等。
可用的变量有LOCAL_MODULE_CLASS、LOCAL_MODULE_PATH、LOCAL_PREBUILT_LIBS等。
PRODUCT_COPY_FILES有类似功能,但不能用于预编译的apks
可以在make时通过设置环境变量做定制
export INIT_BOOTCHART=true
make
或者make INIT_BOOTCHART=true
$(warning Variable foo is $(foo))放在Makefile中方便调试
make <module> showcommands详细列出编译时调用的全命令行,寻找具体的编译报错原因时特别有用
make -B <module> 编译模块时先做make clean的动作
ninja是Android 7.0开始使用的代替make系统的Build 工具,原有的Makefile/*.mk 继续使用,但是由kati解析并转化成$OUT/build_$(TARGET_PRODUCT).ninja,然后由ninja解释并执行编译规则。
Android build team描述的Ninja的优点:
-更快的启动时间
-更快的增量编译 (Ninja 缓存了所有文件的mtime)
-更可靠的增量编译
注:ninja是日本忍者的英文词,读音为['nɪndʒə]。
['nɪndʒə]