Android系统编译常用配置及指令

有时间来整理一下Android系统编译的内容,本文从三方面展开:编译过程、常用的编译配置和命令

一. 编译过程步骤

1.初始化编译环境

source ./build/envsetup.sh它主要作用:

  • 定义m\mm\mmm\lunch 等函数

  • 添加编译目标:将以下文件搜索并source进来

    device//vendorsetup.sh
    vendor/
    /vendorsetup.sh

    product/*/vendorsetup.sh

2. 选择编译目标 lunch xxtarget

  • 可新建device/company/product/AndroidProducts.mk文件并在AndroidProducts.mk中通过COMMON_LUNCH_CHOICES新增编译目标选项,注意:编译目标需要有合法的配置信息。

  • lunch xxtarget选择编译目标后,会确定TARGET_PRODUCT、TARGET_BUILD_VARIANT、TARGET_PLATFORM_VERSION、TARGET_BUILD_TYPE等变量的值

3. 编译 make -j8

Android根目录的Makefile include进来一个编译核心文件:build/make/core/main.mk

main.mk主要功能:

  • include 包含众多mk文件;
  • include config.mk, config.mk 中定义了在Android.mk中编译目标时会用到的常量
  • include /build/core/envsetup.sh,然后通过include product_config.mk检索所有Product,并做目标有效性检查,然后根据lunch时选择的目标设置TARGET_DEVICE,然后在envsetup.sh中根据TARGET_DEVICE查找BoardConfig.mk文件进行Board相关配置,查找KERNEL_HEADER,配置编译工具链
  • definitions.mk中定义了all_makefiles_under等用来检索文件的函数
  • 将所有子目录下的Android.mk文件收集 并include进来,将相应的Android.mk中定义的目标包含进编译模块中。
  • include build/core/Makefile文件,定义bootimage,systemimage等依赖目标,然后通过make编译目标就可以编译系统了。

二. 常用配置

Android 7.0 之后逐渐用 Android.bp 替换 Android.mk

1.编译动态库

java 复制代码
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
cJSON.c
LOCAL_MODULE:= libmycjson
include $(BUILD_SHARED_LIBRARY)
  • Android.bp
java 复制代码
cc_library_shared { //编译成动态库,类似于 Android.mk 中的 BUILD_SHARED_LIBRARY
name: "libcamera_client",
aidl: {
export_aidl_headers: true, //是否导出 aidl 头文件路径
local_include_dirs: ["aidl"], //将[指定的目录列表]加入 aidl 搜索头文件路径。
// ["aidl"]表示当前目录下的 aidl 目录
include_dirs: [ //指定搜索外部 aidl 头文件的路径
"frameworks/native/aidl/gui",
],
},
srcs: [ //源文件,类似于 Android.mk 中的 LOCAL_SRC_FILES
// AIDL files for camera interfaces
// The headers for these interfaces will be available to any modules that
// include libcamera_client, at the path "aidl/package/path/BnFoo.h"
":libcamera_client_aidl", //引用了另外一个模块中定义的源文件。在当前 bp 文件的第 81 行
// Source for camera interface parcelables, and manually-written interfaces
"Camera.cpp",
"CameraMetadata.cpp",
"CameraParameters.cpp",
"CaptureResult.cpp",
"CameraParameters2.cpp",
"ICamera.cpp",
"ICameraClient.cpp",
"ICameraRecordingProxy.cpp",
"ICameraRecordingProxyListener.cpp",
"camera2/CaptureRequest.cpp",
"camera2/OutputConfiguration.cpp",
"camera2/SessionConfiguration.cpp",
"camera2/SubmitInfo.cpp",
"CameraBase.cpp",
"CameraUtils.cpp",
"VendorTagDescriptor.cpp",
],
shared_libs: [ //编译所依赖的动态库,类似于 Android.mk 中的 LOCAL_SHARED_LIBRARIES
"libcutils",
"libutils",
"liblog",
"libbinder",
"libgui",
"libcamera_metadata",
"libnativewindow",
],
include_dirs: [//用户指定的头文件查找路径,类似于 Android.mk 中的 LOCAL_C_INCLUDES
"system/media/private/camera/include",
"frameworks/native/include/media/openmax",
],
export_include_dirs: [//将当前的路径导出,如果有其他模块引用当前模块,就不需要指定头文件路径
"include",
"include/camera"
],
export_shared_lib_headers: ["libcamera_metadata"],//将 libcamera_metadata 模块对应的头文件路径列表导出
cflags: [//编译 flag,类似于 Android.mk 中的 LOCAL_CFLAGS
"-Werror",
"-Wall",
"-Wextra",
],
}

2. 编译可执行程序

java 复制代码
LOCAL_PATH:= $(call my-dir)
curdir=$(LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
main.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/libcjson
LOCAL_SHARED_LIBRARIES += \
libmycjson \
LOCAL_CFLAGS += \
-Wno-error \
-Wno-unused-parameter
LOCAL_MODULE:= cjson_test
LOCAL_MODULE_TAGS := optional
LOCAL_MULTILIB := 64
include $(BUILD_EXECUTABLE)
include $(curdir)/libcjson/Android.mk
  • Android.bp
java 复制代码
cc_binary {
name: "reboot",
srcs: ["reboot.c"],
shared_libs: ["libcutils"],
cflags: ["-Werror"],
}

3.编译Java动态库

java 复制代码
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_JAVA_LIBRARIES := libmytest
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := TestDemo
include $(BUILD_JAVA_LIBRARY)
  • Android.bp
java 复制代码
java_library { //编译成 java 库
name: "services",//编译出的模块的名称
dex_preopt: {
app_image: true, //是否为当前模块生成 app image(.art)文件
profile: "art-profile",//指定与当前 Android.bp 相关的配置文件路径
},
srcs: [ //源文件
"java/**/*.java",
],
// The convention is to name each service module 'services.$(module_name)'
static_libs: [
//编译所依赖的静态库
"services.core",
"services.accessibility",
"services.appwidget",
"services.autofill",
"services.backup",
"services.companion",
"services.coverage",
"services.devicepolicy",
"services.midi",
"services.net",
"services.print",
"services.restrictions",
"services.usage",
"services.usb",
"services.voiceinteraction",
"android.hidl.base-V1.0-java",
],
libs: [//链接的动态库
"android.hidl.manager-V1.0-java",
],
// Uncomment to enable output of certain warnings (deprecated, unchecked)
//javacflags: ["-Xlint"],
}

4. apk(含源码,不含源码的可参考预编译)

java 复制代码
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, app/src/main/java)
LOCAL_PACKAGE_NAME := StorageTest
LOCAL_SDK_VERSION := current
#LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_CERTIFICATE := platform
LOCAL_USE_AAPT2 := true
# 指定 Manifest 文件
LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml
LOCAL_RESOURCE_DIR := \
$(addprefix $(LOCAL_PATH)/, app/src/main/res)
# 需要的 jar,否则无法找到系统相关资源
LOCAL_STATIC_JAVA_LIBRARIES := \
androidx.appcompat_appcompat \
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
  • Android.bp
java 复制代码
android_app {
name: "Music",
srcs: [
"src/**/*.java",
"src/com/android/music/IMediaPlaybackService.aidl",
],
sdk_version: "current",
product_specific: true, //安装到 product 分区
optimize: {
proguard_flags_files: ["proguard.flags"],
},
certificate: "platform",
}

5.预编译

java 复制代码
#预编译配置文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := Vendor_5135_Product_0005.idc
LOCAL_SRC_FILES := Vendor_5135_Product_0005.idc
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/idc
include $(BUILD_PREBUILT)
java 复制代码
# 预编译动态库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES :=libglib-2.0.so
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE := libglib-2.0
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MULTILIB := 32
include $(BUILD_PREBUILT)
java 复制代码
# 预编译可执行程序
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := busybox_aarch64
LOCAL_MODULE := busybox_aarch64
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := optional
include $(BUILD_PREBUILT)
java 复制代码
#预编译APK
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Hello
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
#定义编译完成之后的类型:除了APPS,还有ETC,EXECUTABLES(.bin)SHARED_LIBRARIES(.so) 等选择值 
LOCAL_MODULE_CLASS := APPS

#定义编译完成之后模块的后缀
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)

#定义使用原app签名可用选择项platform,shared,media
LOCAL_CERTIFICATE := PRESIGNED

#将apk编进"/system/priv-app/目录",如果为false,或者不加这句话,就会编进"/system/app" 目录, 二者区别在于前者的权限要高于后者,即不可卸载
LOCAL_PRIVILEGED_MODULE := true

#不进行odex化
LOCAL_DEX_PREOPT := false

# 定义编译出来的目标文件,如动态库,静态库,jar包以及apk
include $(BUILD_PREBUILT)
  • Android.bp
java 复制代码
//预编译etc配置文件
prebuilt_etc {
name: "Vendor_my_idc",
src: "Vendor_5135_Product_0005.idc",
filename_from_src: true,
sub_dir:"usr",
}
java 复制代码
//预编译可执行文件
cc_prebuilt_binary {
name: "logpersist.start",
srcs: ["logpersist"],
init_rc: ["logcatd.rc"],
required: ["logcatd"],
symlinks: [
"logpersist.stop",
"logpersist.cat",
],
strip: {
none: true,
},
}
java 复制代码
//预编译动态库
cc_prebuilt_library_shared {
name: "libmycjson-pre.so",
srcs: ["x86_64/libmycjson-pre.so"],
compile_multilib : "64",
}

三. 常用命令

1. 编译命令

1.1 m命令

  • m 源码树的根目录执行编译,编译的是根目录下所有的代码;
  • mm 编译当前路径下所有模块,但不包含依赖关系的模块;
  • mmm [module_path] 编译指定路径下的所有模块,但不包含依赖关系的模块;
  • mma 编译当前路径下所有模块,且包含依赖关系的模块;
  • mmma [module_path] 编译指定路径下的所有模块,且包含依赖关系的模块;

1.2make命令

  • make [module_name] 无参数,则表示编译整个Android代码,如果有module_name,是会遍历module,编译指定的module;
    常见module编译例:
    {模块} make命令 | mmm命令
    {init} make init | mmm system/core/init
    {zygote} make app_process | mmm frameworks/base/cmds/app_process
    {system_server} make services | mmm frameworks/base/services
    {java framework} make framework | mmm frameworks/base
    {framework资源} make framework-res | mmm frameworks/base/core/res
    {jni framework} make libandroid_runtime | mmm frameworks/base/core/jni
    {binder} make libbinder | mmm frameworks/native/libs/binder
    {RefBase等} make libutils | mmm framworks/base/libs/utils
    {Looper等} make framework | mmm framworks/base
    {AudioTrack} make libmedia | mmm framworks/base/media/kibmedia
    {AudioFlinger} make libaudiofliginger | mmm framworks/base/libs/audioflinger
    {AudioPolicyService} make libaudiopolicy | mmm hardware/msm7k/libaudio-qsd8k
    {SurfaceFlinger} make libsurfaceflinger | mmm frameworks/base/libs/surfaceflinger
    {Vold} make vold | mmm system/vold
    {Rild} make rild | mmm hardware/ril/rild
    {MediaProvider} make MediaProvider | mmm packages/providers/MediaProvider
    {Phone} make phone | mmm packages/apps/Phone
  • make clean:执行清理操作,等价于 rm -rf out/
  • make update-api:更新API,在framework API改动后需执行该指令,Api记录在目录frameworks/base/api;
  • make sdk 编译出 Android 的 SDK;
  • make clean-sdk 清理 SDK 的编译产物;
  • make help 帮助信息,显示主要的 make 目标;
  • make snod 从已经编译出的包快速重建系统镜像;
  • make clean- 清理一个指定模块的编译结果;
  • make dump-products 显示所有产品的编译配置信息;
  • make libandroid_runtime 编译所有 JNI framework 内容
  • make framework 编译所有 Java framework 内容
  • make services 编译系统服务和相关内容。
  • make bootimage 生成 boot.img
  • make systemimage 编译生成system.img
  • make recoveryimage 生成 recovery.img
  • make userdataimage 生成 userdata.img
  • make cacheimage 生成 cache.img
  • make otapackage 生成升级包
  • make dist 执行 Build,并将 MAKECMDGOALS 变量定义的输出文件拷贝到 /out/dist 目录。

2. 编译配置和搜索命令

  • add_lunch_combo [product] 将某个产品加入到用户选项中
  • print_lunch_menu 查询lunch可选的product
  • check_product [product] 检查产品是否有效
  • printconfig 打印当前选择的产品配置
  • get_build_var [build_var] 查找编译时各种变量值;
  • get_abs_build_var [build_var] 获取系统中的编译变量的值
  • cgrep [keyword] 所有 C/C++文件执行搜索操作
  • jgrep [keyword] 所有 Java 文件执行搜索操作
  • ggrep [keyword] 所有 Gradle 文件执行搜索操作
  • mgrep [keyword] 所有 Android.mk 文件执行搜索操作
  • mangrep [keyword] 所有AndroidManifest.xml文件执行搜索操作
  • sepgrep [keyword] 所有 sepolicy 文件执行搜索操作
  • resgrep [keyword] 所有本地res/*.xml文件执行搜索操作

3. 导航命令

  • croot 切换至Android根目录

  • godir [filename] 跳转到包含某个文件的目录

👀关注公众号:Android老皮!!!欢迎大家来找我探讨交流👀

相关推荐
拭心11 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王13 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡14 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道14 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库15 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道15 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe16 小时前
Android Hook - 动态加载so库
android
居居飒16 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He19 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗19 小时前
Android笔试面试题AI答之Android基础(1)
android