Android系统编译

  • 简介
  • 搭建编译环境
  • 系统编译命令
  • 常见小知识点
    • Android编译版本
    • Android.mk文件
    • 编译系统中的变量和宏
    • native layer
  • 编译碰到的问题
    • 安装lib32bz2-1.0出问题
    • add-apt-repository命令不存在
    • Jack server installation not found
    • subcommand failed问题
    • 内核目录下存在.config文件导致编译错误
  • 输出目录中的重要目录
  • 编译模块
  • 系统属性相关目标和依赖文件的定义
    • 编译时确定系统属性值
  • 打包新添加的模块至system.img

简介

Android系统源码将Makefile划分成一个个Makefile片段,通过Makefileinclude指令将这些片段组装成一个Makefile,因此Android.mk编译脚本其实是整个Android编译系统的一个Makefile片段,编译时编译系统会遍历每个目录下的Android.mk文件。

搭建编译环境

sudo apt-get install u-boot-toolssudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev lib32ncurses5 lib32z1 x11proto-core-dev libx11-dev lib32z1-devsudo apt-get install build-essential subversion git-core libncurses5-dev zlib1g-dev gawk flex quilt libssl-dev xsltproc libxml-parser-perl mercurial bzr ecj cvs unzip lib32z1 lib32ncurses5 lib32bz2-1.0sudo apt-get install libxml2-utilssudo apt-get install subversion openssh-client openssh-server samba git-core git-gui vimsudo add-apt-repository ppa:git-core/ppasudo apt-get updatesudo apt-get upgradesudo apt-get install libswitch-perlsudo apt-get install rar unrarsudo apt-get install gawksudo apt-get install bc

搭建编译环境官方文档(有关JDK要求)

系统编译命令

  1. source build/envsetup.sh
  • 此命令会将vendor和device目录中厂商指定的envsetup.sh加载到当前shell中,获取厂商提供的产品配置信息。脚本文件build/envsetup.sh提供编译所需的重要命令用于编译Android源码。build/envsetup.sh脚本中的函数
    add_lunch_combo会被多次调用,用来添加Android编译选项。
  1. lunch
  • 用于初始化编译环境,指定目标产品类型和编译类型。第二件事是通过make命令执行build/core/config.mk脚本,并且加载另一个脚本build/core/dumpvar.mk来打印出当前的编译环境配置信息。
  1. m
  • 相当于make命令
  1. mm和mmm
  • 用于模块编译
  1. 查看编译命令
  • mmm ./ showcommands

常见小知识点

Android编译版本

  • user :权限受限;适用于生产环境
  • userdebug: 与“user”类似,但具有 root 权限和可调试性;是进行调试时的首选编译类型
  • eng : 具有额外调试工具的开发配置

Android.mk文件

Android.mk是编译系统解析一次或多次的微小Makefile片段。Android.mk的语法支持将源文件分组为模块。模块是静态库、动态库或独立的可执行程序。可在每个Android.mk中定义一个或多个模块,也可在多个模块中使用同一个源文件。

LOCAL_PATH := $(call my-dir)
//表示源文件在开发树中的位置,my-dir是编译系统提供的宏函数,返回当前目录的路径

LOCAL_MODULE:= service_manager_my
// 指定生成的模块名,不能包含空格

include $(BUILD_EXECUTABLE)
// BUILD_EXECUTABLE表示我们要编译的是可执行程序

include $(CLEAR_VARS)
// 清空编译环境的变量,会清除许多LOCAL_XXX变量

LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_CFLAGS += -Wno-unused-variable
LOCAL_CFLAGS += -Wno-unused-function
LOCAL_CFLAGS += -Wincompatible-pointer-types
// 指定忽略一些未使用的变量或函数

LOCAL_SRC_FILES:= test_server.c binder.c
// 指定源文件,包含要编译到模块中的C/C++源文件列表

LOCAL_C_INCLUDES += system/core/libcutils/include/
// 指定头文件路径,指定的路径是相对于NDK编译系统根目录的路径

LOCAL_MODULE_TAGS := user eng optional test
// 各项具体说明如下:
1、user:只有在user版本时该模块才被编译进去;
2、eng:只有在eng版本时该模块才被编译进去;
3、test:只有在tests版本时该模块才被编译进去;
4、optional:在所有版本中都编译该模块进去。

用于设置该app是否要安装到priv-app下
LOCAL_PRIVILEGED_MODULE = true

不开启odex,不生成APP的dex文件,不进行预先优化,节省空间,可编译出完整的apk
LOCAL_DEX_PREOPT = false

如果预置的APK,要覆盖原生apk,则需在android.mk中添加以下选项,此变量可以使其他的模块不加入编译。
LOCAL_OVERRIDES_PACKAGES

  • 特别注意不要在Android.mk文件中添加无谓的空格,编译报错找不到原因很痛苦的!

编译系统中的变量和宏

编译系统提供了许多可在Android.mk中使用的变量。NDK编译系统保留了下列变量名称:

以 LOCAL_ 开头的名称,例如 LOCAL_MODULE。
以 PRIVATE_、NDK_ 或 APP 开头的名称。编译系统在内部使用这些变量名。
小写名称,例如 my-dir。编译系统也是在内部使用这些变量名。

指向用于指定预编译共享库的编译脚本。与 BUILD_SHARED_LIBRARYBUILD_STATIC_LIBRARY 的情况不同,这里的 LOCAL_SRC_FILES 值不能是源文件,而必须是指向预编译共享库的一个路径,例如 foo/libfoo.so。使用此变量的语法为:

include $(PREBUILT_SHARED_LIBRARY)

指定生成的模块名称。例如,如果LOCAL_MODULE 的名称为 foo,可以强制系统将它生成的文件命名为 libnewfoo。

LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo

native layer

本地应用程序指的是可以直接运行在操作系统上,并且处理器直接执行机器码的程序。比如windows上的各种*.exe的程序,而linux上的是各种bin程序。
在Android上,OS是linux,因此各种bin程序就是所谓natvie application了,比如**/system/bin**目录下的所有文件。
这些应用程序都是由GCC(c/c++)编译生成。在Android软件架构里,这些应用程序组成了native layer。

编译碰到的问题

安装lib32bz2-1.0出问题

解决方法:

sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libbz2-1.0:i386

add-apt-repository命令不存在

解决方法:

apt-get install software-properties-common

Jack server installation not found

解决方法:在prebuilts/sdk/tools 目录下执行以下命令

./jack-admin install-server jack-launcher.jar jack-server-4.11.ALPHA.jar

  • Jack编译器工具是一套新的Android编译工具用来将Java代码转换为Android dex字节代码。Jack服务器无法启动原因:$HOME目录下无.jack文件

subcommand failed问题

编译Android系统时经常都是使用多线程编译,有时甚至用到了58个线程,启用太多线程的话,由于Makefile的目标与文件或其它目标的依赖关系,会导致编译目标时需要的源还未编译完成,会提示ninja: build stopped: subcommand failed,这时就需要减少线程数来编译。

  • 在切换编译目标时需要执行make installclean,用以清除之前编译生成的文件。

内核目录下存在.config文件导致编译错误

Using /mnt/kernel-4.4 as source for kernel
/mnt/kernel-4.4 is not clean, please run ‘make mrproper’
in the ‘/mnt/kernel-4.4’ directory.
/mnt/kernel-4.4/Makefile:1033: recipe for target ‘prepare3’ failed
make[1]: *** [prepare3] Error 1
make[1]: *** Waiting for unfinished jobs…
[DCT_INFO]: DWS file path is /mnt/kernel-4.4/drivers/misc/mediatek/dws/m
t6771/8p1_64_bsp.dws
[DCT_INFO]: Gen files path is /mnt/out/target/product/8p1_64_bsp/ob
j/KERNEL_OBJ/arch/arm64/boot/dts/8p1_64_bsp
[DCT_INFO]: Log files path is /mnt/out/target/product/8p1_64_bsp/ob
j/KERNEL_OBJ/arch/arm64/boot/dts/8p1_64_bsp
[DCT_INFO]: Parameter is cust_dtsi
[DCT_INFO]: chip id: MT6771
[DCT_INFO]: Chip ID : MT6771
[DCT_INFO]: Project Info: 8p1_64_bsp
[DCT_INFO]: Start to generate cust_dtsi file…
[DCT_INFO]: Generate cust_dtsi file successfully!
make[1]: *** wait: No child processes. Stop.
Makefile:152: recipe for target ‘sub-make’ failed
make: *** [sub-make] Error 2
make: Leaving directory ‘/mnt/kernel-4.4’

在kernel-4.4目录下搜索“is not clean”会发现导致错误的原因是当kernel-4.4目录下存在.config文件或kernel-4.4/include/目录下存在config目录时,就会报错,因此删除掉这两个对象就可以了。
因为之前有去修改过kernel-4.4目录中的文件,并执行过make menuconfig命令,这在Android系统源码中是不可以的。

输出目录中的重要目录

  • Android系统预装的APP所在目录为:
    out/target/product/$(PROJECT_NAME))/system/app/

  • C编译的可执行文件所在目录为:
    out/target/product/$(PROJECT_NAME))/system/bin/

  • 动态链接库所在目录为:
    out/target/product/$(PROJECT_NAME))/system/lib/

  • 硬件抽象层接口文件所在目录:
    out/target/product/$(PROJECT_NAME))/system/lib/hw/

编译模块

  • init模块

mmm system/core/init/
编译完成:
[100% 201/201] Copy: out/target/product/88p1_64_bsp/testcases/init_tests/arm/init_tests

  • 单独编译framework的services模块

先在framework/base目录下执行
mmm core/res/生成framework-res.apk

如果framework/base/services/下也有修改,也要编译:
mmm framework/base/services

然后再单独编译framework
mmm frameworks/base

相关的输出文件在输出目录下的system/framework中,包含:
services.jar
framework-res.apk
framework.jar

可利用adb命令将这些文件push到设备端的system/framework目录下。若需测试这两个新模块,需先杀掉所有使用该模块的进程,进程重启后会重新加载模块。
系统服务被杀掉后一般都会自动重启(由init控制)

系统属性相关目标和依赖文件的定义

  • build/make/core/Makefile

intermediate_system_build_prop := $(call intermediates-dir-for,ETC,
system_build_prop)/build.prop
猜想intermediate_system_build_prop 展开即为:
out/target/product/8p1_64_bsp/obj/ETC/system_build_prop_intermediates/build.prop

BUILDINFO_SH := build/make/tools/buildinfo.sh
INTERNAL_BUILD_ID_MAKEFILE := $(wildcard $(BUILD_SYSTEM)/build_id.mk)
即为:build/make/core/build_id.mk

system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
展开即为:device/mediateksample/8p1_64_bsp/system.prop

INSTALLED_ANDROID_INFO_TXT_TARGET := $(PRODUCT_OUT)/android-info.txt
展开即为:out/target/product/8p1_64_bsp/android-info.txt

  • 最后将包括build/make/tools/buildinfo.sh中设置的属性一并写入build.prop文件中,并在out目录下生成build.prop文件。位于输出目录的system目录下。
    build.prop记录的都是系统设置,是个属性文件。init进程将会加载/system/build.prop中定义的属性。
  • 系统源码中的property_service.cpp源文件中的load_properties_from_file函数就是用于init进程加载存储属性值的文件。
bool load_properties_from_file(const char* filename, const char* filter) {Timer t;auto file_contents = ReadFile(filename);if (!file_contents) {PLOG(WARNING) << "Couldn't load property file '" << filename<< "': " << file_contents.error();return false;}file_contents->push_back('\n');LoadProperties(file_contents->data(), filter, filename);LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";return true;
}

编译时确定系统属性值

在device.mk中添加,例如:
PRODUCT_PROPERTY_OVERRIDES += persist.sys.Notification=1

打包新添加的模块至system.img

device.mk中的PRODUCT_PACKAGES选项中加入该模块如果将新添加的PRODUCT_PACKAGES选项放入新创建的Makefile中,需要在build/target/product/core.mk末尾追加一行
例如在build/target/product目录下创建一个新的Makefile文件mytest.mk
build/target/product/core.mk末尾追加:$(call inherit-product, $(SRC_TARGET_DIR)/product/mytest.mk)

Android系统编译小总结相关推荐

  1. Android系统编译优化:使用Ninja加快编译

    背景 环境 关键编译阶段和耗时分析 阶段一:Soong bootstrap 阶段二:Kati遍历.mk搜集与ninja生成 阶段三:Ninja编译 编译优化 对比汇总 背景 Android系统模块代码 ...

  2. Android系统编译时集成三方APK

    1. 前言 最近在学习Android系统开发,在开发过程中可能要到将三方apk集成到系统中的需求.目前我了解的方法有两种. 一种是在系统编译完毕之后,再将三方apk文件放置到系统目录之下.参考如何将a ...

  3. Android系统编译aosp

    Android系统编译 公号文字版本:https://mp.weixin.qq.com/s/y6ReUNd3EDUctNVO_x3ZwQ 博客文字版本:http://liuwangshu.cn/bat ...

  4. Android系统编译

    Android系统编译 先执行环境初始化: source build/envsetup.sh && lunch aosp-eng 再执行make 模块名,模块根据需求自选,例如: ma ...

  5. 全志A40i开发板Android系统编译

    Android系统编译 A40i &T3 板卡用户可以通过飞凌嵌入式提供的网盘链接获取OKA40i-C开发板软件和硬件的文档及源码.软件和硬件的文档及源码下载方法不清楚的可联系飞凌嵌入式客服索 ...

  6. Android 系统编译环境设置及源代码编译

    一. 摘要    虽然已经在Android系统工作了一段时间, 但是每次需要重新setup环境的时候,都需要花一点时间, 所以就想借着这次在ubuntu 12.04 64bits系统上重新安装的机会, ...

  7. 有用的博客整理(Android系统编译相关)

    //在Ubuntu18.04中Android Studio开发环境搭建 http://baijiahao.baidu.com/s?id=1604117887374452787&wfr=spid ...

  8. Linux常用基本命令Android系统编译命令

    Linux命令: touch 创建文件 touch framework/base/Android.mk // 创建文件夹 mkdir 创建文件夹 cat 显示文件所有内容(合并文件) cat aa文件 ...

  9. Android系统编译过程

    Android系统build分类 1.build/core 目录下的文件,这是Android Build的系统框架核心: 2.device目录下的文件,存放的是具体的产品配置文件: 3.各个模块的编译 ...

最新文章

  1. Redis 有序集合(zset)取交集(zinterstore)操作耗时测试
  2. Codeforces 528A Glass Carving STL模拟
  3. 【Kylin】60-20-040-集成-Kylin集成LDAP
  4. powerdesigner显示工具面板_Adobe After Effects:如何使用木偶工具
  5. 十七条黄金定律!(心态是命运的控制塔)
  6. Shell脚本实战:日志关键字监控+自动告警
  7. RTB竞价中的cookie mapping技术
  8. Atiitt 自我学习法流程 1.预先阶段 1.1.目标搜索 资料搜索 1.2. 1.3.通过关联关键词 抽象 等领域 拓展拓宽体系树 1.4. 2.分析整理阶段 2.1.找出重点 压缩要学会
  9. 一网打尽位图与矢量图
  10. Struts1 面试题目总结
  11. 微信小程序.阿里巴巴矢量图标库iconfont使用
  12. 软件版本 —— Alpha、Beta、RC版本的区别
  13. 高效能人士的七个习惯 读书笔记
  14. java毕业设计青岛滨海药店管理系统的设计与实现源码+lw文档+mybatis+系统+mysql数据库+调试
  15. MMD导入unity中使用
  16. 基于Vue移动音乐webapp跨域获取QQ音乐歌单接口
  17. svn分支介绍和使用
  18. 极大似然估计原理思想
  19. 11_FreeRTOS时间片调度实验
  20. C/C++ 实现一个简单的文本编辑器(windows程序设计)

热门文章

  1. c语言位运算的妙用-程序优化
  2. R语言随机森林报错The response has five or fewer unique values. Are you sure you want to do regression原因及解决办法
  3. 怎样将微信热门文章采集到自己的公众号中?
  4. Smmu硬件寄存器—V2
  5. Android中实现红绿灯动画,android红绿灯制作
  6. Installshield 安装包安装过程中遇到的报错(一)
  7. linux如何测试IP和端口是否能访问
  8. docker 垃圾清理命令
  9. 基于FPGA的数字钟设计实验报告
  10. xp系统计算机怎么连接到网络打印机,WinXP电脑如何添加网络打印机?WinXP添加网络打印机的步骤...