赞
踩
刚才有个朋友问我,博主发生什么事了,给我发了几张截图,我一看,哦,原来是有个大帅哔看了文章,说是,博主,我能白嫖你的文章,我说年轻人,点个赞再走,他说不点,我说点一个,他说不点,我说点一个,他说不点,我说我这文章对你有用,他不服气,说要先看看。我说可以,很快啊,看完后,就是一个复制,一个粘贴,一个网页关闭,我大意了啊,没有删除文章。按传统博客的有用为止,他说已经输了啊。 后来他说他是乱点的,这可不是乱点的啊,训练有素。我劝年轻人好好点赞,耗子尾汁,谢谢朋友们
一直想下载、编译、调试一下Android源码 ,加强对一些framework的理解,搞了好多次,终于可以正常调试了。这里进行一些总结和分享。
Android源码到模拟器运行,主要有的四个步骤:
我使用的环境是Ubuntu16.04 、openJDK8、Android 8.0.0
官方文档:要求
我的电脑是双系统,ubuntu 空间划分不集中,分区空间不够,导致编译失败。我在实践过程中,发现不需要官方声明的那么多空间,下载初始化包.repo 40G左右,检出代码(Android 8.0.0),又占用了40G左右,编译用了60G左右。总共算下来160G的分区空间应该是够用了。
Android 源码是非常庞大的,而且每个模块都是用git来进行管理 ,整个Android源码是由很多个git项目构成,Google对Android代码的更新也是更新到相应模块的git项目上。
那对于需要编译Android的开发者来说,要分别clone 每个git项目而且还要放到固定的位置确实是件惨绝人寰的事,所以Google就开发了一个基于Python编写的帮助开发者管理多个项目的工具,这个工具就叫repo,repo就是封装了git命令的python脚本。
由于国内网络的原因,我们使用国内的清华源下载源码和repo工具
下面的命令,是从清华源下载repo工具,这样脚本中的路径就是指向清华源的aosp
mkdir ~/bin # 在home下创建bin文件夹
PATH=~/bin:$PATH # 把bin文件夹加入环境变量的
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo #下载repo脚本
chmod a+x ~/bin/repo #添加权限
我们有个非常庞大的项目Pre,该项目由很多个子项目R1,R2,…Rn等组成,为了方便管理和协同开发,我们为每个子项目创立自己的仓库,整个项目的结构如下:
项目Pre进行分库的好处就是,只需要创建需要开发的模块分支,代码量减少了很多。检出的时候也可以只检出某一模块的代码。
会遇到这么一个问题:如果我们想要创建Pre分支来做feature开发,这就意味着,我们需要到每个子项目中分别创建对应的分支,这个过程如果纯粹靠手工做,那简直是个灾难,于是会写个自动化处理程序(我们假设这个工具叫做RepoUtil)来帮助我们解决这个问题。这个RepoUtil也会有版本管理之类的需求,因此我们也用Git对其管理,并为其创建对应的仓库。此时整个项目的结构如下:
这里RepoUtil知道整个项目Pre下的每个子项目(即维护子项目的列表),同时提供对这些子项目的管理功能,比如统一创建分支等。但是从"单一职责"角度来看,RepoUitl这个工具的功能过于复杂,我们完全可以将维护子项目列表这个功能抽取出来作为一个新项目sub_projects,因为子项目也会变化。因此,为其创建对应的仓库,并用Git管理,RepoUtil只需要通过简单的对ub_projects进行依赖即可,此时整个项目的结构如下:
AOSP项目结构
在mainfest文件夹中,执行git branch -a
就可以看到所有的分支
下载源码有两种方法:
官方文档:下载源代码
初始化包每月都会进行更新,由于首次同步需要下载约 30GB 数据,如果上面的方法,过程中任何网络故障都可能造成同步失败,我第一次是使用官方的方法,失败过一次。后来都是用这个方法。
下载 https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar,下载完成后记得根据 checksum.txt 的内容校验一下。
由于所有代码都是从隐藏的 .repo 目录中 checkout 出来的,所以我们只保留了 .repo 目录,下载后解压 再 repo sync 一遍即可得到完整的目录。
使用方法如下:
wget -c https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar # 下载初始化包
tar xf aosp-latest.tar
cd AOSP # 解压得到的 AOSP 工程目录
# 这时 ls 的话什么也看不到,因为只有一个隐藏的 .repo 目录
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-8.0.1_r1 # 可选命令,指定版本,如果未指定,则使用最新的版本
repo sync # 正常同步一遍即可得到完整目录
# 或 repo sync -l 仅checkout代码
Android各版本列表:https://source.android.google.cn/setup/start/build-numbers.html#source-code-tags-and-builds
官方文档:搭建编译环境
sudo apt-get update
sudo apt-get install openjdk-8-jdk
官方文档没有介绍Ubuntu 16.04所需的软件包。使用Ubuntu 16.04的小伙伴,需要安装下面的软件
sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib
sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386
sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386
sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev
sudo apt-get install git-core gnupg flex bison gperf build-essential
sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib
sudo apt-get install libc6-dev-i386
sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev
sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
sudo apt-get install lib32z-dev ccache
使用 envsetup.sh 脚本初始化环境。请注意,将 source 替换成 .(一个点)可以省去一些字符,这种简写形式在文档中更为常用。
source build/envsetup.sh
或者
. build/envsetup.sh
使用 lunch 选择要编译的目标。确切的配置可作为参数进行传递。例如,以下命令表示针对模拟器进行完整编译,并且所有调试功能均处于启用状态。
lunch aosp_arm-eng
直接运行 lunch
(没有参数),会列出所有支持的类型,输入对应的序号来进行选择。
所有编译目标都采用 BUILD-BUILDTYPE 形式,其中 BUILD 是表示特定功能组合的代号。BUILDTYPE 是以下类型之一:
编译类型 | 使用情况 |
---|---|
user | 权限受限;适用于生产环境 |
userdebug | 与“user”类似,但具有 root 权限和可调试性;是进行调试时的首选编译类型 |
eng | 具有额外调试工具的开发配置 |
您可以使用 make 编译任何代码。GNU make 可以借助 -jN 参数处理并行任务,通常使用的任务数 N 介于编译时所用计算机上硬件线程数的 1-2 倍之间。例如,在一台双核 E5520 计算机(2 个 CPU,每个 CPU 4 个内核,每个内核 2 个线程)上,要实现最快的编译速度,可以使用介于 make -j16 到 make -j32 之间的命令。
make -j4
如果编译完一个版本后想重新编译一个,可以使用 make clobber
清除之前编译生成的文件。我们编译产生的文件都在 out文件夹下。
编译成功后,输入emulator
可启动模拟器
每次执行完lunch后下次进入基本就忘记上次编译的参数设置,可以使用printconfig
命令显示当前的设置
1、 从代码中查看当前版本,找到如下文件
build\make\core\version_defaults.mk
搜索关键字 PLATFORM_VERSION
# This is the canonical definition of the platform version,
# which is the version that we reveal to the end user.
# Update this value when the platform version changes (rather
# than overriding it somewhere else). Can be an arbitrary string.
# When you add a new PLATFORM_VERSION which will result in a new
# PLATFORM_SDK_VERSION please ensure you add a corresponding isAtLeast*
# method in the following java file:
# frameworks/support/compat/gingerbread/android/support/v4/os/BuildCompat.java
# When you change PLATFORM_VERSION for a given PLATFORM_SDK_VERSION
# please add that PLATFORM_VERSION to the following text file:
# cts/tests/tests/os/assets/platform_versions.txt
PLATFORM_VERSION.OPR1 := 8.0.0
由于在Ubuntu上开发,很多常用软件都没有,所以后来又在mac上编译源码,遇到不少问题,下面来分享一下
两种解决方法:
具体操作,下载地址,可以参考这里
这篇文章 也遇到这个错误,但是报错细节、Android版本号 和我的不一样,所以我暂时没有去尝试
在苹果官网看到 关于bad cpu type in executable 回复 的,
想了一下,既然Mac 10.15 支持64位,不支持32位,那就用新版Android吧,免得Android 8.0.0_r1 上越改问题越多
Android10.0.0_r1 是支持64位的,但是在编译过程中一定会遇到这个错误
FAILED: build out/target/product/generic_x86_64/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests
Outputs: out/target/product/generic_x86_64/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests
Error: exited with code: 1
Command: /bin/bash -c "(out/host/darwin-x86/bin/sepolicy_tests -l out/host/darwin-x86/lib64/libsepolwrap.dylib -f out/target/product/generic_x86_64/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts -f out/target/product/generic_x86_64/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts -p out/target/product/generic_x86_64/obj/ETC/sepolicy_intermediates/sepolicy ) && (touch out/target/product/generic_x86_64/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests )"
Output:
/bin/bash: line 1: 28159 Segmentation fault: 11 ( out/host/darwin-x86/bin/sepolicy_tests -l out/host/darwin-x86/lib64/libsepolwrap.dylib -f out/target/product/generic_x86_64/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts -f out/target/product/generic_x86_64/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts -p out/target/product/generic_x86_64/obj/ETC/sepolicy_intermediates/sepolicy )
这个错误是与mac 10.15 兼容问题,可通过这个临时解决
make SELINUX_IGNORE_NEVERALLOWS=true
还有个官方方案,打上下面的patch:(我是使用这个方法解决的)
1f944107a3341ab593c93bbdf09e22436cc0e3d3
官方就是修改 system/sepolicy/tests/Android.bp 去掉stl: “libc++_static”,
下面这个是Catalina MacOS SDK 10.15的patch:
89dad60ed5ec30b0f732b612d454151abdb4e449
出自这篇文章:AOSP SELinux error
注意在mac 上编译,磁盘格式最好使用 Mac OS扩展(区分大小写,日志式),我在APFS 上解压aosp-laster.rar、同步代码、编译,完整操作了两次都不行。遇到同样的错误,也没再网上找到答案。也有可能是其它原因,按照官方的最好
注意:执行命令的时候,需要在bash 环境下,不能再zsh 环境下
请点赞、收藏,感谢大家的支持,有任何疑问可在评论区回复
参考:
官方文档:准备编译
自己动手编译Android源码(超详细)
Android 源码下载 到 编译全过程
从源码中查看当前android版本
android aosp编译的一些辅助命令
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。