源码编译完成后我们对源码目录中的文件结构进行详细的分析,便于我们在后期的工具使用,刷机,修改源码,查看所需要的系统镜像文件结构,系统源码编译完成后系统源码中自带的工具源码,c/c++库,java生成时的目录和关系,便于后续研究系统的源码和源码二次开发提供帮助.
Android源码目录结构
android编译顺序
Android编译系统
下面我们使用linux系统下的tree 工具来分析源码编译out目录结构:
1.tree -L N 查看多少级目录树,如果系统中没有安装tree:
sudo apt install treAndroid编译系统中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)/bin2.系统编译是会在源码目录下生成一个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 filesAndroid源代码在编译之前,要先对编译环境进行初始化,其中最主要就是指定编译的类型和目标设备的型号。
这个时候如果我们不选择任何类型,那么编译出来的就是模拟器使用的镜像文件,也就是: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 这是google nexus5x 打印处理的内容 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