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老皮!!!欢迎大家来找我探讨交流👀

相关推荐
皮皮高33 分钟前
itvbox绿豆影视tvbox手机版影视APP源码分享搭建教程
android·前端·后端·开源·tv
EnzoRay1 小时前
MotionEvent
android
玲小珑1 小时前
Auto.js 入门指南(七)定时任务调度
android·前端
墨狂之逸才2 小时前
adb常用命令调试
android
YoungForYou2 小时前
Android端部署NCNN
android
移动开发者1号2 小时前
Jetpack Compose瀑布流实现方案
android·kotlin
移动开发者1号2 小时前
Android LinearLayout、FrameLayout、RelativeLayout、ConstraintLayout大混战
android·kotlin
移动开发者1号2 小时前
ListView与RecyclerView区别总结
android·kotlin
移动开发者1号2 小时前
OkHttp 3.0源码解析:从设计理念到核心实现
android·kotlin
小草帽学编程6 小时前
鸿蒙Next开发真机调试签名申请流程
android·华为·harmonyos