在 Android 构建系统中,尤其是在使用传统的 Android.mk + make 构建流程(即 AOSP 的 legacy_android_build 模式)时,构建系统提供了一组内置的 Makefile 函数,用于帮助开发者自动查找、加载模块和处理路径。
这些函数由 AOSP 的构建框架定义,在 build/core/definitions.mk 和其他核心构建脚本中实现,是 Android 构建系统的“标准库”函数。以下是与你提到的 all-named-subdir-makefiles 类似的 常用内置函数列表及其作用说明:
1.模块编译阶段
一、目录扫描类函数(用于查找 Android.mk 文件,这个函数只用来加载模块定义!!!(如编译哪些 APK、so 库等),不加载 PRODUCT_SYSTEM_EXT_PROPERTIES += …,这是用于设备构建配置的变量)
函数名 |
参数 |
是否递归 |
描述 |
all-subdir-makefiles |
❌ 不需要参数 |
✅ 是 |
查找当前目录及所有子目录中的 Android.mk 文件 |
all-named-subdir-makefiles |
✅ 需要传入目录名列表 |
✅ 是 |
查找指定目录下的 Android.mk 文件(包括子目录) |
all-makefiles-under |
✅ 需要传入路径 |
✅ 是 |
查找指定路径及其子目录下的 Android.mk 文件 |
first-makefiles-under |
✅ 需要传入路径 |
❌ 否 |
查找指定路径下的第一层 Android.mk 文件(不递归) |
get-subdir-makefiles |
✅ 需要传入路径 |
❌ 否 |
获取当前目录下直接子目录中的 Android.mk 文件 |
二、路径操作类函数
函数名 |
描述 |
call my-dir |
返回当前 Android.mk 所在目录的路径 |
call intermediates-dir |
返回当前模块的中间文件输出目录(如 out/obj/…) |
call module-path |
返回某个模块的源码路径(用于跨模块引用) |
call host-path / call target-path |
转换路径格式,确保主机和目标平台兼容性 |
call word-list-file |
读取文件内容并作为单词列表返回(常用于配置文件解析) |
三、变量操作类函数
函数名 |
描述 |
call addprefix |
给列表每个元素添加前缀 |
call addsuffix |
给列表每个元素添加后缀 |
call filter |
过滤匹配模式的元素 |
call filter-out |
排除匹配模式的元素 |
call sort |
对列表排序 |
call wildcard |
匹配通配符路径(如 *.c) |
四、模块定义辅助函数
常见的 BUILD_XXX
模块类型
这些是 Android 构建系统中常用的构建模板,用于指定模块的输出形式。
Java 相关
类型 |
描述 |
BUILD_STATIC_JAVA_LIBRARY |
构建静态 Java 库(输出为 .jar 文件),供其他模块依赖。 |
BUILD_SHARED_JAVA_LIBRARY |
构建共享 Java 库(较少使用)。 |
BUILD_HOST_JAVA_LIBRARY |
构建主机端 Java 库(运行在 PC 上,如工具类)。 |
BUILD_DROIDDOC |
构建 Java API 文档。 |
✅ BUILD_STATIC_JAVA_LIBRARY
vs BUILD_JAVA_LIBRARY
对比项 |
BUILD_STATIC_JAVA_LIBRARY |
BUILD_JAVA_LIBRARY |
生成文件类型 |
.jar (Java 静态库) |
.jar (Java 动态库) |
用途 |
编译 Java 源码为 jar 包,仅用于编译时依赖 |
编译 Java 源码为 jar 包,并可被系统运行时加载 |
是否打包进系统镜像 |
❌ 不会直接打包到系统镜像中 |
✅ 可以安装到 /system/framework/ 等目录 |
典型使用场景 |
构建中间模块、SDK、内部依赖库 |
构建系统级 Java 库(如系统服务、Framework 类) |
输出路径示例 |
out/target/common/obj/JAVA_LIBRARIES/_intermediates/xxx.jar |
out/target/product//system/framework/*.jar |
补充说明
.jar
文件本身是 静态库或动态库的容器,但它本质上只是一个归档文件。
- 在 Android 构建系统中,“动态 Java 库”是指这个
.jar
文件会被 打包进系统镜像并作为运行时依赖加载,而不是指它包含 native 代码(那属于 .so
文件)。
总结一句话:
BUILD_STATIC_JAVA_LIBRARY
是用来构建 仅用于编译期依赖的 Java 静态库(.jar),不会被打包进系统;
而 BUILD_JAVA_LIBRARY
构建的是 可在系统运行时使用的 Java 动态库(.jar),最终会被打包进系统镜像(如 /system/framework/
)中。
APK 应用相关
类型 |
描述 |
BUILD_PACKAGE |
构建 Android APK 包(应用程序)。 |
BUILD_PRIV_APP |
构建特权应用(系统级应用,安装到 /system/priv-app )。 |
BUILD_EXECUTABLE |
构建可执行程序(通常是 Native 的 ELF 文件)。 |
Native / C++ 相关
类型 |
描述 |
BUILD_SHARED_LIBRARY |
构建动态链接库(.so 文件)。 |
BUILD_STATIC_LIBRARY |
构建静态链接库(.a 文件)。 |
BUILD_EXECUTABLE |
构建本地可执行文件(ELF 格式)。 |
BUILD_HOST_SHARED_LIBRARY |
构建主机端动态库(PC 上运行)。 |
BUILD_HOST_STATIC_LIBRARY |
构建主机端静态库。 |
资源和预编译相关
类型 |
描述 |
BUILD_PREBUILT |
构建预编译模块(复制已有的二进制文件)。 |
BUILD_MULTI_PREBUILT |
多个预编译模块一起构建。 |
BUILD_RAW_IMAGE |
构建原始镜像文件(如 boot.img)。 |
测试相关
类型 |
描述 |
BUILD_NATIVE_TEST |
构建 Native 测试模块。 |
BUILD_JAVA_TEST |
构建 Java 单元测试模块。 |
BUILD_CTS_TEST_PACKAGE |
构建 CTS 兼容性测试包。 |
示例说明
include $(CLEAR_VARS)
LOCAL_MODULE := mylib
LOCAL_SRC_FILES := mylib.cpp
include $(BUILD_SHARED_LIBRARY)
上面这段代码会构建一个名为 mylib.so
的动态链接库。
五、调试辅助函数
函数名 |
描述 |
$(warning …) |
输出警告信息到控制台 |
$(info …) |
输出普通信息 |
$(error …) |
报错并终止构建 |
$(shell …) |
执行 shell 命令 |
$(eval …) |
动态求值并赋值给变量 |
六、条件判断与逻辑函数
函数名 |
描述 |
if |
条件判断:$(if ,,) |
or / and |
逻辑或/与操作 |
filter / filter-out |
条件筛选 |
strip |
去除空白字符 |
word / words |
提取第 N 个词 / 获取词数 |
2.产品配置阶段
inherit-product
是 Android 构建系统中的一个 关键函数调用,用于在产品配置 .mk 文件中 继承另一个产品配置文件的定义内容。
一、基本含义
$(call inherit-product, path/to/other_product_config.mk)
这行代码的意思是:
把 path/to/other_product_config.mk 这个构建配置文件的内容“继承”进来,就像把它里面定义的所有变量和模块都复制到当前文件中一样。
二、典型使用场景
Android 构建系统采用“多层继承”的方式来组织设备配置。比如:
通用 Rockchip 平台配置(如 device/rockchip/common/device.mk)
具体芯片型号配置(如 device/rockchip/rk3588/device.mk)
具体设备厂商配置(如 device/rockchip/rk3588/topeet_rk3588.mk)
通过 inherit-product,你可以逐层继承这些配置,避免重复定义。
内容 |
描述 |
继承变量 |
如 PRODUCT_PACKAGES, PRODUCT_SYSTEM_EXT_PROPERTIES 等 |
继承模块 |
比如额外的 APK、so 库、驱动等 |
继承构建规则 |
比如分区大小、镜像生成方式等 |
总结说明
与 include 的区别
对比项 |
inherit-product |
include |
使用对象 |
Android 构建系统专用 |
Makefile 通用 |
是否处理 PRODUCT_* 变量 |
✅ 是 |
❌ 否(不会正确合并) |
推荐用途 |
继承其他产品配置文件 |
包含普通的 Makefile 片段(如函数定义) |
你可以把整个 Android 构建系统想象成两个部分:
构建阶段 |
作用 |
使用哪些机制 |
模块编译阶段 |
整体编译过程中编译 APK、so、bin 等模块 |
all-subdir-makefiles, include, Android.mk |
产品配置阶段 |
决定哪些模块被打包进系统镜像,设置系统属性等 |
PRODUCT_PACKAGES, PRODUCT_SYSTEM_EXT_PROPERTIES, inherit-product |
所以:
❗️include 和 all-named-subdir-makefiles 只负责“编译哪些模块”,但 不会决定这些模块是否被打包进最终镜像,也不会处理系统属性等产品级配置。
总结一句话:
include 和 all-named-subdir-makefiles 只让某些模块被编译出来;
要让它们或某些属性真正进镜像(如 system.img / system_ext.img),需要通过 inherit-product 把配置引入到产品 .mk 文件中。
编译流程的两个阶段
1.模块编译阶段:
只要你的 Android.mk 被 all-named-subdir-makefiles 加载了,就会被编译成目标文件(如 /out/target/product/…/system/priv-app/MyCustomApp.apk)
2.打包进镜像阶段:
如果没有通过 PRODUCT_PACKAGES 或 PRODUCT_PACKAGES_DEBUG 引入该模块,则不会被包含在系统镜像中