预编译本质是通过 Android 中 acp 命令来完成拷贝, 将一个文件从一个地方拷贝到另外一个地方, 并且源文件并不需要通过编译器进行编译, 一般都是针对一些二进制文件,比如没有源码的可执行程序,动态库,apk, 音乐,视频等各种文件。
常见的预编译模块有:
- 已经编译好的 C & CPP 可执行程序
- 已经编译好的 C & CPP 库
- 已经编译好的 Java 库
- 已经编译好的 Android 库
- 已经编译好的 apk
- 一些配置文件
在 aosp/device/mycompany/product 目录下,创建以下的文件结构:
.
├── AndroidProducts.mk
├── myaosp.mk
└── prebuilt
└── executable
├── Android.mk
└── busybox
其中 AndroidProducts.mk myaosp.mk 是 配置product 中添加的 product 配置文件。
busybox 文件是一个二进制可执行程序,通过以下命令下载
wget https://busybox.net/downloads/binaries/1.30.0-i686/busybox
其中 Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := busybox
LOCAL_MODULE := busyboxmk
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := optional
//LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/
include $(BUILD_PREBUILT)
接下来执行 mm 命令即可编译该模块。
我们也可以将 Android.mk 修改为 Android.bp:
cc_prebuilt_binary {
name: "busyboxbp",
srcs: ["busybox"],
}
通过 Anroid.bp 的方式来添加预编译模块。
在 上一节创建的 prebuild 目录下创建目录结构:
lib
├── Android.mk
└── libmymathbp.so
其中 libmymathbp.so 来自添加自定义模块之 C&CPP 库 的编译产物。
Android.mk 的具体内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libmymathpremk
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_SRC_FILES := libmymathbp.so
LOCAL_MULTILIB := 64
include $(BUILD_PREBUILT)
也可以将 Android.mk 修改为 Android.bp:
cc_prebuilt_library_shared {
name: "libmymathprebp,
srcs: ["libmymathbp.so"],
compile_multilib: "64",
}
预编译模块的引入都比较简单,后面的示例均为我从源码中搜索到的,看一下就明白了:
prebuilts/sdk/current/androidx/Android.bp 第 173 行处:
java_import {
name: "androidx.annotation_annotation-nodeps",
jars: ["m2repository/androidx/annotation/annotation/1.4.0-alpha03/annotation-1.4.0-alpha03.jar"],
sdk_version: "31",
host_supported: true,
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
],
min_sdk_version: "24",
}
prebuilts/sdk/current/androidx/Android.bp 第 201 行处:
android_library_import {
name: "androidx.appcompat_appcompat-resources-nodeps",
aars: ["m2repository/androidx/appcompat/appcompat-resources/1.7.0-alpha02/appcompat-resources-1.7.0-alpha02.aar"],
sdk_version: "31",
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
],
min_sdk_version: "14",
static_libs: [
"androidx.annotation_annotation",
"androidx.collection_collection",
"androidx.core_core",
"androidx.vectordrawable_vectordrawable",
"androidx.vectordrawable_vectordrawable-animated",
],
}
翻阅以下 prebuilts/sdk/current/androidx/Android.bp,会发现有很多“马甲”模块:
第 219 行:
android_library {
name: "androidx.appcompat_appcompat-resources",
sdk_version: "31",
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
],
min_sdk_version: "14",
manifest: "manifests/androidx.appcompat_appcompat-resources/AndroidManifest.xml",
static_libs: [
"androidx.appcompat_appcompat-resources-nodeps",
"androidx.annotation_annotation",
"androidx.collection_collection",
"androidx.core_core",
"androidx.vectordrawable_vectordrawable",
"androidx.vectordrawable_vectordrawable-animated",
],
java_version: "1.7",
}
这个模块 AndroidManifest.xml 文件中没有实际内容,他是 static_libs 内部模块的一个“马甲”而已
在系统中预装一些 apk 是很常见的操作,源码中可以找到很多示例:
external/chromium-webview/Android.bp
android_app_import {
name: "webview",
product_specific: true,
default_dev_cert: true,
required: [
"libwebviewchromium_loader",
"libwebviewchromium_plat_support",
],
arch: {
arm: {
apk: "prebuilt/arm//webview.apk",
},
arm64: {
apk: "prebuilt/arm64/webview.apk",
},
x86: {
apk: "prebuilt/x86/webview.apk",
},
x86_64: {
apk: "prebuilt/x86_64/webview.apk",
},
},
}
PRODUCT_COPY_FILES 变量值可以在 $product.mk 文件里面设置, 在我们这个例子里面是 myaosp.mk 文件。其作用是将源码中一些文件拷贝到输出目录中:
PRODUCT_COPY_FILES += \
system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
aosp 中默认带了这个值,表示将 system/core/rootdir/init.zygote32_64.rc 文件拷贝到 root/init.zygote32_64.rc,最终我们的模拟器中的 root 分区就会有这个 rc 文件了。