分析Android源码编译输出(out)目录结构
源码编译完成后我们对源码目录中的文件结构进行详细的分析,便于我们在后期的工具使用,刷机,修改源码,查看所需要的系统镜像文件结构,系统源码编译完成后系统源码中自带的工具源码,c/c++库,java生成时的目录和关系,便于后续研究系统的源码和源码二次开发提供帮助.
下面我们使用linux系统下的tree 工具来分析源码编译out目录结构:
1.tree -L N 查看多少级目录树,如果系统中没有安装tree:
sudo apt install tre
Android编译系统中envsetup.mk文件定义了输出文件的路径和说明:
ifeq (,$(strip $(OUT_DIR)))
ifeq (,$(strip $(OUT_DIR_COMMON_BASE)))
OUT_DIR := $(TOPDIR)out
else
OUT_DIR := $(OUT_DIR_COMMON_BASE)/$(notdir $(PWD))
endif
endif
DEBUG_OUT_DIR := $(OUT_DIR)/debug
# Move the host or target under the debug/ directory
# if necessary.
TARGET_OUT_ROOT_release := $(OUT_DIR)/target
TARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/target
TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))
HOST_OUT_ROOT_release := $(OUT_DIR)/host
HOST_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/host
HOST_OUT_ROOT := $(HOST_OUT_ROOT_$(HOST_BUILD_TYPE))
# We want to avoid two host bin directories in multilib build.
HOST_OUT_release := $(HOST_OUT_ROOT_release)/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
HOST_OUT_debug := $(HOST_OUT_ROOT_debug)/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
HOST_OUT := $(HOST_OUT_$(HOST_BUILD_TYPE))
# TODO: remove
BUILD_OUT := $(HOST_OUT)
HOST_CROSS_OUT_release := $(HOST_OUT_ROOT_release)/windows-$(HOST_PREBUILT_ARCH)
HOST_CROSS_OUT_debug := $(HOST_OUT_ROOT_debug)/windows-$(HOST_PREBUILT_ARCH)
HOST_CROSS_OUT := $(HOST_CROSS_OUT_$(HOST_BUILD_TYPE))
TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product
TARGET_COMMON_OUT_ROOT := $(TARGET_OUT_ROOT)/common
HOST_COMMON_OUT_ROOT := $(HOST_OUT_ROOT)/common
PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)
OUT_DOCS := $(TARGET_COMMON_OUT_ROOT)/docs
BUILD_OUT_EXECUTABLES := $(BUILD_OUT)/bin
2.系统编译是会在源码目录下生成一个out文件夹:文件夹中包括两部分的内容:host:本机(ubunt上使用的工具和一些库),target:就是我们要的内容,源码编译时和手机相关的内容,(与电脑相关的文件放在host中,与手机相关的放在target文件夹中):out目录下的目录树:
out
├── casecheck.txt
├── CaseCheck.txt
├── host //与电脑相关的一些工具
│ ├── common //是编译是用到的一些公共的jar(javalib.jar)包
│ │ └── obj
│ └── linux-x86 //这是是编译主机的类型
│ ├── bin //有一部分是Android开发工具的工具:例如打包,混淆,对齐,创建文件系统,打包镜像等工具
│ ├── framework //加密的jar包,签名/认证等一系列的jar包
│ ├── gen //一些中间文件
│ ├── lib //在编译/打包时使用到的一些库
│ ├── lib64
│ ├── obj
│ ├── obj32
│ ├── previous_prebuilt_tools_config.mk
│ └── usr
├── target //与手机相关的的文件
│ ├── common
│ │ ├── docs
│ │ ├── gen
│ │ ├── obj
│ │ └── R
│ └── product
│ ├── bullhead
│ └── generic
└── versions_checked.mk
21 directories, 4 files
下面对host中的工具和库做一个简单的说明:
当我们源码编译完成后会产生几个*.img文件,system/priv-app/*.apk是怎么产生的,就可以弄明白在编译时为什么会生成一个主机文件,一个文件夹下是手机相关.下面是host目录中的一些工具:Android apk打包过程
.
├── common
│ └── obj
│ └── JAVA_LIBRARIES
└── linux-x86
├── bin
│ ├── aapt
│ ├── adb
│ ├── aidl
│ ├── dex2oat
│ ├── dx
│ ├── mkbootfs
│ ├── mkbootimg
│ ├── mkuserimg.sh
│ ├── verity_signer
│ └── zipalign
├── framework
│ ├── BootSignature.jar
│ ├── dx.jar
│ ├── hierarchyviewer.jar
│ ├── host-libprotobuf-java-nano.jar
│ ├── signapk.jar
│ └── VeritySigner.jar
接下来就开始分析编译产生的和手机相关的一些目录:
开始学习编译android系统源码时,总是弄不明白,为什么编译目录会是这个样子,压根不知道问什么这样设计,相信大家在编译系统是总会遇到最头痛的事情:估计就是编译时间过长,初次编译需要好几个小时才能搞定,第二次编译时耗时大大缩短.这个与目录结构和编译系统息息相关.
.
├── common
│ ├── docs
│ │ ├── apache-http-stubs-gen-timestamp
│ │ ├── api-stubs-timestamp
│ │ └── system-api-stubs-timestamp
│ ├── gen
│ │ └── conscrypt
│ ├── obj
│ │ ├── all-event-log-tags.txt
│ │ ├── APPS //系统生成的apk零时文件,通过后面的打包工具可以生成不同签名的apk
│ │ ├── ETC
│ │ ├── framework.aidl
│ │ ├── JAVA_LIBRARIES
│ │ ├── PACKAGING
│ │ └── previous_aidl_config.mk
│ └── R
│ ├── android
│ ├── androidx
│ ├── com
│ ├── jp
│ └── rsexample
└── product
├── bullhead //android6.0的版本nexusX系列手机使用到的文件
│ ├── boot.img
│ ├── cache.img
│ ├── ramdisk.img
│ ├── recovery.img
│ ├── system.img
│ ├── userdata.img
└── generic //模拟器使用到的镜像文件
├── cache.img
├── ramdisk.img
├── system.img
└── userdata.img
39 directories, 28 files
上面看到的主要三个目录进行说明:
common:目录主要是在编译是使用到的中间文件,这些文件和系统,平台,用户的信息没有联系,例如生成的app并没有被打包成为*.apk的格式,还没有被签名,在后续的操作中我们可以使用当个的文件进行打包,而不用在重新去编译*.java->*.class->dex的转换,但的二次编译的时候,就只修改变动的地方,从而大大提高编译速度.如果你手工编译过apk或者反编译过apk那么对下面的内容不会很陌生,我没方便易之后就会失去签名文件,这就是为什么会产生这些文件,当我编译同一份代码给两个不同的版本需要有各种的签名文件时,是不是可以缩短编译时间,只需要修改重新编译不同的部分,相关的不会就会有缓存了,这样就可以大大缩短编译时间,这个和下面要介绍的两个目录有很大的关系:
target/common/obj/APPS/Launcher3_intermediates/
├── classes
│ ├── android
│ │ └── support
│ └── com
│ ├── android
│ └── google
├── classes.dex
├── classes-full-debug.jar
├── classes.jack
├── classes.jar
├── classes-jarjar.jar
├── classes.noshrob.jack
├── emma_out
│ └── lib
│ └── classes-jarjar.jar
├── jack-noshrob-rsc
├── jack-noshrob-rsc.java-source-list
├── jack-rsc
├── jack-rsc.java-source-list
├── proguard_dictionary
├── proguard_options
├── public_resources.xml
├── src
│ ├── android
│ │ └── support
│ ├── com
│ │ └── android
│ ├── proto
│ │ ├── Proto.stamp
│ │ └── src
│ └── R.stamp
└── with-local
├── classes.dex
└── classes.dex.flags
18 directories, 16 files
Android源代码在编译之前,要先对编译环境进行初始化,其中最主要就是指定编译的类型和目标设备的型号。
这个时候如果我们不选择任何类型,那么编译出来的就是模拟器使用的镜像文件,也就是:generic文件夹中的镜像文件
当我们选择:
18. aosp_bullhead-userdebug 时就会生成时候nexusX使用的进行文件 下图是google官方的编译设备型号对于的文件CodeName
如果现在我们还要在编译一个nexus 6P的刷机镜像文件,那么在product文件夹下还好生成一个:angler的文件夹,这个时候就会从common使用编译好的缓存文件来编译,修改带不同的部分,这样就会大大减小编译的时间.
~/androidsource/WORKING_DIRECTORY/out$ lunch
You're building on Linux
Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_mips-eng
4. aosp_mips64-eng
5. aosp_x86-eng
6. aosp_x86_64-eng
7. aosp_deb-userdebug
8. aosp_flo-userdebug
9. full_fugu-userdebug
10. aosp_fugu-userdebug
11. mini_emulator_arm64-userdebug
12. m_e_arm-userdebug
13. mini_emulator_mips-userdebug
14. mini_emulator_x86_64-userdebug
15. mini_emulator_x86-userdebug
16. aosp_flounder-userdebug
17. aosp_angler-userdebug
18. aosp_bullhead-userdebug
19. aosp_hammerhead-userdebug
20. aosp_hammerhead_fp-userdebug
21. aosp_shamu-userdebug
Which would you like? [aosp_arm-eng]
接下来才是我们要介绍的重点:
bullhead/
├── android-info.txt
├── boot.img 包含了系统ramdisk.img和系统镜像,也就是系统最小的运行单元,这个时候就这有linux 内核和一些系统工具,也就是根目录的文件系统
├── cache //缓存文件的目录结构
├── cache.img //带有格式的文件
├── clean_steps.mk
├── data //这个目录对于系统中的/data/data 目录
├── dex_bootjars
├── fake_packages
├── gen
├── installed-files.txt
├── kernel //这是系统内核目录会被打包到boot.img中去
├── obj
├── obj_arm
├── previous_build_config.mk
├── ramdisk.img //这里包含了最小的文件系统,是boot.img的组成部分,根文件系统
├── ramdisk-recovery.img //这个是也是一个能够独立运行的系统,相当于一个没有用户空间的android系统
├── recovery
├── recovery.id
├── recovery.img
├── root
├── split_bootimg.pl
├── symbols
├── system //这个对于的 系统的/system
├── system.img
├── userdata.img
└── vendor
上面介绍的内容可以参考linux文件系统就可以很好理解:
这个时候我们就可以使用下列工具刷入镜像文件:
fastboot flash boot out/target/product/bullhead/boot.img
fastboot flash recovery out/target/product/bullhead/recovery.img
fastboot flash system out/target/product/bullhead/system.img
fastboot flash userdata out/target/product/bullhead/userdata.img
fastboot flash cache out/target/product/bullhead/cache.img
上面就是我们编译处理的镜像文件,编译出来之后,如果直接在模拟器上运行,那么就运行emulator就可以启动模拟器了,模拟器还可以跟上参数:
emulator -kernel ./prebuilt/android-arm/kernel/kernel-qemu -sysdir ./out/target/product/generic -system system.img -data userdata.img -ramdisk ramdisk.img
上面是在模拟其中使用,如果要在真机上使用那么我们应该怎么处理呢:
编译android源码并且刷入真机
通过上面的文章,你已经刷入了手机真机,这个时候突然有个想法,为什么fastboot flash ....这么多东西进去,到底是放在哪里,处理这些之外还有那些分区:
我们可以通过很多方法来查看:查看手机分区
下面是我们查看到系统所有的分区,在linux系统下所以的设备都看做文件,所以这个地方有一些不是实际的物理设备,但是到这,目的差不多达成了,现在我们已经看到了我们打出来的源码镜像文件问什么是那样的.现在我们使用fastboot flash 命令和分析源码编译输出目录文件是否跟着明白.
ls -l /dev/block/platform/soc.0/f9824900.sdhci/by-name/ <
lrwxrwxrwx root root 1970-01-08 17:35 boot -> /dev/block/mmcblk0p37
lrwxrwxrwx root root 1970-01-08 17:35 cache -> /dev/block/mmcblk0p40
lrwxrwxrwx root root 1970-01-08 17:35 oem -> /dev/block/mmcblk0p36
lrwxrwxrwx root root 1970-01-08 17:35 recovery -> /dev/block/mmcblk0p38
lrwxrwxrwx root root 1970-01-08 17:35 system -> /dev/block/mmcblk0p41
lrwxrwxrwx root root 1970-01-08 17:35 userdata -> /dev/block/mmcblk0p45
lrwxrwxrwx root root 1970-01-08 17:35 vendor -> /dev/block/mmcblk0p39
ls -l /dev/block/platform/soc.0/f9824900.sdhci/by-name/ < lrwxrwxrwx root root 1970-01-08 17:35 DDR -> /dev/block/mmcblk0p28 lrwxrwxrwx root root 1970-01-08 17:35 aboot -> /dev/block/mmcblk0p8 lrwxrwxrwx root root 1970-01-08 17:35 abootbak -> /dev/block/mmcblk0p14 lrwxrwxrwx root root 1970-01-08 17:35 apdp -> /dev/block/mmcblk0p17 lrwxrwxrwx root root 1970-01-08 17:35 boot -> /dev/block/mmcblk0p37 lrwxrwxrwx root root 1970-01-08 17:35 cache -> /dev/block/mmcblk0p40 lrwxrwxrwx root root 1970-01-08 17:35 cmnlib -> /dev/block/mmcblk0p33 lrwxrwxrwx root root 1970-01-08 17:35 cmnlibbak -> /dev/block/mmcblk0p35 lrwxrwxrwx root root 1970-01-08 17:35 config -> /dev/block/mmcblk0p16 lrwxrwxrwx root root 1970-01-08 17:35 devinfo -> /dev/block/mmcblk0p43 lrwxrwxrwx root root 1970-01-08 17:35 dpo -> /dev/block/mmcblk0p19 lrwxrwxrwx root root 1970-01-08 17:35 fsc -> /dev/block/mmcblk0p20 lrwxrwxrwx root root 1970-01-08 17:35 fsg -> /dev/block/mmcblk0p27 lrwxrwxrwx root root 1970-01-08 17:35 grow -> /dev/block/mmcblk0p46 lrwxrwxrwx root root 1970-01-08 17:35 hyp -> /dev/block/mmcblk0p6 lrwxrwxrwx root root 1970-01-08 17:35 hypbak -> /dev/block/mmcblk0p12 lrwxrwxrwx root root 1970-01-08 17:35 imgdata -> /dev/block/mmcblk0p29 lrwxrwxrwx root root 1970-01-08 17:35 keymaster -> /dev/block/mmcblk0p32 lrwxrwxrwx root root 1970-01-08 17:35 keymasterbak -> /dev/block/mmcblk0p34 lrwxrwxrwx root root 1970-01-08 17:35 keystore -> /dev/block/mmcblk0p44 lrwxrwxrwx root root 1970-01-08 17:35 laf -> /dev/block/mmcblk0p31 lrwxrwxrwx root root 1970-01-08 17:35 limits -> /dev/block/mmcblk0p15 lrwxrwxrwx root root 1970-01-08 17:35 metadata -> /dev/block/mmcblk0p30 lrwxrwxrwx root root 1970-01-08 17:35 misc -> /dev/block/mmcblk0p23 lrwxrwxrwx root root 1970-01-08 17:35 modem -> /dev/block/mmcblk0p1 lrwxrwxrwx root root 1970-01-08 17:35 modemst1 -> /dev/block/mmcblk0p25 lrwxrwxrwx root root 1970-01-08 17:35 modemst2 -> /dev/block/mmcblk0p26 lrwxrwxrwx root root 1970-01-08 17:35 msadp -> /dev/block/mmcblk0p18 lrwxrwxrwx root root 1970-01-08 17:35 oem -> /dev/block/mmcblk0p36 lrwxrwxrwx root root 1970-01-08 17:35 persist -> /dev/block/mmcblk0p24 lrwxrwxrwx root root 1970-01-08 17:35 persistent -> /dev/block/mmcblk0p42 lrwxrwxrwx root root 1970-01-08 17:35 pmic -> /dev/block/mmcblk0p2 lrwxrwxrwx root root 1970-01-08 17:35 pmicbak -> /dev/block/mmcblk0p10 lrwxrwxrwx root root 1970-01-08 17:35 recovery -> /dev/block/mmcblk0p38 lrwxrwxrwx root root 1970-01-08 17:35 rpm -> /dev/block/mmcblk0p7 lrwxrwxrwx root root 1970-01-08 17:35 rpmbak -> /dev/block/mmcblk0p13 lrwxrwxrwx root root 1970-01-08 17:35 sbl1 -> /dev/block/mmcblk0p3 lrwxrwxrwx root root 1970-01-08 17:35 sbl1bak -> /dev/block/mmcblk0p9 lrwxrwxrwx root root 1970-01-08 17:35 sdi -> /dev/block/mmcblk0p5 lrwxrwxrwx root root 1970-01-08 17:35 sec -> /dev/block/mmcblk0p22 lrwxrwxrwx root root 1970-01-08 17:35 ssd -> /dev/block/mmcblk0p21 lrwxrwxrwx root root 1970-01-08 17:35 system -> /dev/block/mmcblk0p41 lrwxrwxrwx root root 1970-01-08 17:35 tz -> /dev/block/mmcblk0p4 lrwxrwxrwx root root 1970-01-08 17:35 tzbak -> /dev/block/mmcblk0p11 lrwxrwxrwx root root 1970-01-08 17:35 userdata -> /dev/block/mmcblk0p45 lrwxrwxrwx root root 1970-01-08 17:35 vendor -> /dev/block/mmcblk0p39