安卓编译系统解析

最后更新于:2022-04-01 23:26:59

#安卓编译简记 qq群里 @随风破浪 编译安卓一星期未果,我之前的开发机上的lichee目录又不小心被覆盖了,所以抽空简单记录下如何在原始sdk的基础上 修改适配,成功编译出可以跑在荔枝派上的安卓系统。 ##1. 编译环境准备 ### 开发机系统要求 编译安卓需要64位linux系统,推荐**ubuntu 1404**或者**1604**, 开发机至少需要**4GB内存,40GB硬盘**;推荐**8GB内存,100GB硬盘**以上。 以下是开发过程中目录大小示意: ~~~ zp@ubuntu:~/develop$ du -lh --max-depth=1 v1.5.0/ 26G v1.5.0/android 6.8G v1.5.0/lichee 33G v1.5.0/ zp@ubuntu:~/develop$ du -lh --max-depth=1 a13_android4.1_v1.2/ 5.2G a13_android4.1_v1.2/lichee 23G a13_android4.1_v1.2/android4.1 28G a13_android4.1_v1.2/ ~~~ 开发机的CPU配置尽量高,笔者12线程并行编译,配以ssd,首次编译需要45分钟 网友双线程编译,耗时4小时左右。 ### 开发机软件环境 首先安装开发所需要的软件包和一些库。 下面的一些安装包可能有些过时的,遇到版本问题请自行解决。 在线安装 JDK6.0 ~~~ sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner" sudo add-apt-repository ppa:ferramroberto/java sudo apt-get update sudo apt-get install sun-java6-jdk sudo update-alternatives --c onfig java ~~~ 在线安装编译库 ~~~ sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev libc6-dev lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev g++-multilib mingw32 tofrodos python-markdown libxml2-utils ~~~ ### SDK下载 > 链接: http://pan.baidu.com/s/1pLnjfoZ 密码: cvnm 在SDK目录下 下载以下两个文件 ~~~ lichee-4.1-v1.2.tar.gz android4.1-v1.2.tar.gz ~~~ 这是安卓4.1的SDK,前面的是4.2的SDK, > 我手上的4.2 SDK的mali驱动ko和应用层库so版本对不上,换了从4.1里抠出的对应版本的so后,可以勉强启动系统,但是会不定时地出现缓冲队列满的问题导致ANR,所以暂时无法使用 在开发机上新建目录,如a13_android4.1 然后把两个sdk拷入,解压 把lichee对应的目录名改成lichee(即去掉版本号),目录如下所示 ~~~ zp@ubuntu:~/develop/a13_android4.1_v1.2$ ls android4.1 lichee ~~~ ##2. lichee编译 lichee是安卓系统的linux内核部分,需要首先编译,进入lichee目录执行: ~~~ ./build.sh -p a13_nuclear -k 3.0 ./build.sh pack ~~~ ### 编译错误解析 编译过程中会出错,每个人由于其开发环境以及执行步骤的不同,错误都可能不同,下面以我编译时遇到的错误为例进行解析 1. mali驱动编译出错 ~~~ make: Entering directory `/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0/modules/mali' /home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0 make -C DX910-SW-99002-r3p1-01rel0/driver/src/devicedrv/ump CONFIG=ca8-virtex820-m400-1 BUILD=release KDIR=/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0 make[1]: Entering directory `/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0/modules/mali/DX910-SW-99002-r3p1-01rel0/driver/src/devicedrv/ump' make -C /home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0 M=/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0/modules/mali/DX910-SW-99002-r3p1-01rel0/driver/src/devicedrv/ump modules make[2]: Entering directory `/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0' CC [M] /home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0/modules/mali/DX910-SW-99002-r3p1-01rel0/driver/src/devicedrv/ump/common/ump_kernel_common.o arm-none-linux-gnueabi-gcc: directory: No such file or directory arm-none-linux-gnueabi-gcc: directory": No such file or directory :0:16: warning: missing terminating " character make[3]: *** [/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0/modules/mali/DX910-SW-99002-r3p1-01rel0/driver/src/devicedrv/ump/common/ump_kernel_common.o] Error 1 make[2]: *** [_module_/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0/modules/mali/DX910-SW-99002-r3p1-01rel0/driver/src/devicedrv/ump] Error 2 make[2]: Leaving directory `/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0' make[1]: *** [all] Error 2 make[1]: Leaving directory `/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0/modules/mali/DX910-SW-99002-r3p1-01rel0/driver/src/devicedrv/ump' make: *** [build] Error 2 make: Leaving directory `/home/zp/develop/a13_android4.1_v1.2/lichee/linux-3.0/modules/mali' real 2m35.400s user 15m36.416s sys 0m35.740s ~~~ 进入排除可知是脚本里检查了SVN版本的问题,我们直接忽略SVN版本,将linux-3.0/modules/mali/DX910-SW-99002-r3p1-01rel0/driver/src/devicedrv/ump 目录下的SVN_REV直接赋值为0(在Kbuild和Makefile.common中) 重新编译,仍然是类似的错误,只是换了个目录,于是直接在mali驱动目录下全局搜索SVN_REV,将赋值的地方直接改为0 再重新编译成功 ~~~ mkdir: created directory ‘/home/zp/develop/a13_android4.1_v1.2/lichee/out’ ‘/home/zp/develop/a13_android4.1_v1.2/lichee/u-boot/u-boot.bin’ -> ‘/home/zp/develop/a13_android4.1_v1.2/lichee/out/android/u-boot.bin’ ############################### # compile success # ############################### real 0m51.177s user 1m1.324s sys 0m4.736s ~~~ ##3. 安卓编译 进入安卓目录,执行以下命令序列: ~~~ source build/envsetup.sh #导入一些环境变量 lunch #选择板型,直接选择10. nuclear_evb-eng,以后也直接在上面改 extract-bsp #将lichee中编译得到的内核镜像和模块拷贝过来 time make -j12 2>&1 | tee log.txt #编译system.img,这里-j12换成你电脑的线程数(核数*2)。12线程耗时约 pack #打包成刷机镜像 ~~~ 编译system.img成功的提示: ~~~ Creating filesystem with parameters: Size: 536870912 Block size: 4096 Blocks per group: 32768 Inodes per group: 8192 Inode size: 256 Journal blocks: 2048 Label: Blocks: 131072 Block groups: 4 Reserved block group size: 31 Created filesystem with 1443/32768 inodes and 102168/131072 blocks + '[' 0 -ne 0 ']' Running: mkuserimg.sh -s out/target/product/nuclear-evb/system out/target/product/nuclear-evb/obj/PACKAGING/systemimage_intermediates/system.img ext4 system 536870912 Install system fs image: out/target/product/nuclear-evb/system.img out/target/product/nuclear-evb/system.img+out/target/product/nuclear-evb/obj/PACKAGING/recovery_patch_intermediates/recovery_from_boot.p maxsize=548110464 blocksize=4224 total=412271984 reserve=5537664 real 36m1.948s user 350m4.772s sys 14m16.936s ~~~ pack打包成功的提示: ~~~ /home/zp/develop/a13_android4.1_v1.2/lichee/tools/pack/pctools/linux/eDragonEx//home/zp/develop/a13_android4.1_v1.2/lichee/tools/pack/outBuildImg 0 Dragon execute image.cfg SUCCESS ! CPlugin Free lib CPlugin Free lib ---------image is at------------- /home/zp/develop/a13_android4.1_v1.2/lichee/tools/pack/sun5i_android_a13-evb.img ~~~ ### 编译错误解析 1. 注意如果编译时突然中断,则可能出现文件截断的情况,需要先清空out 下子目录中的的obj目录,才好继续编译 例如下面错误就是: ~~~ target thumb C++: camera. <= device/softwinner/common/hardware/camera/HALCameraFactory.cpp In file included from device/softwinner/common/hardware/camera/CameraHardwareDevice.h:26:0, from device/softwinner/common/hardware/camera/HALCameraFactory.cpp:30: device/softwinner/common/hardware/camera/CameraHardware.h:29:23: fatal error: videodev2.h: No such file or directory compilation terminated. make: *** [out/target/product/generic/obj/SHARED_LIBRARIES/camera._intermediates/HALCameraFactory.o] Error 1 make: *** Waiting for unfinished jobs.... ~~~ 2. 在pack时遇到以下错误(虽然不导致编译失败,但是启动时会造成错误) ~~~ fail:/home/zp/develop/a13_android4.1_v1.2/lichee/tools/pack/out/bootfs/sprite 0 disk : c CopyRootToFS(/home/zp/develop/a13_android4.1_v1.2/lichee/tools/pack/out/bootfs) ~~~ 检查可以发现是lichee/tools/pack/pack中的打包脚本的这句出错: `fsbuild bootfs.ini split_xxxx.fex` 这个fsbuild在运行时貌似无法打包bootfs的二级目录,不知为何。。有些人却没有反馈有这个问题,应该是个人的环境不同。 由于fsbuild是二进制提供的,只能通过其作用揣测实际功能,经过试验,上面那句可以用以下脚本代替, 基本作用就是构造一个fat文件系统镜像。 ~~~ dd if=/dev/zero of=bootfs.fex bs=1M count=12 mkfs.vfat bootfs.fex sudo mount bootfs.fex /mnt sudo cp -r bootfs/* /mnt sync sudo umount /mnt cat split_xxxx.fex >> bootfs.fex ~~~ 3. 分区大小的问题(虽然不导致编译失败,但是启动时会造成错误) 如果往system.img里加入了太多东西,可能导致超出了默认的分区大小(512M),则需要修改默认分区规划 验证system.img的实际大小: `simg2img system.img system.bin` 如果生成的system.bin大小刚好是512M,并且可以挂载,那就是正常的。 如果大小超过了512M,或者挂载时出错,那么就需要修正分区配置。 配置文件在lichee/tools/pack/chips/sun5i/configs/android/a13-evb/sys_config.fex 修改大小即可。 ~~~ ;------------------------------>nandd, android real rootfs [partition3] class_name = DISK name = system size_hi = 0 size_lo = 524288 user_type = 1 ro = 0 ~~~ ##4. 镜像下载 前面pack打包完成后,会生成sun5i_android_a13-evb.img,这就是刷机镜像 镜像烧录工具是网盘中的PhoenixCard,打开后选择tf卡对应盘符,以及待烧录镜像,选择**卡启动**,进行烧录 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/77805d12cdca7a2c82220dc65501c9dc_762x500.png) ### 常见烧录错误 1.偶尔会出现'处理出错'的提示,这时候一般只要重新烧录即可 ##5. 启动系统的适配过程 通过以上步骤编译的img还是不能在荔枝派上启动的,前面只能算是编译过一遍evb的安卓,需要在荔枝派上启动,还得进行一系列适配工作。 ### 第一次启动(boot1跳转失败) 系统默认串口为UART1,接串口查看信息: ~~~ dram size =512 0xffffffff,0xffffffff super_standby_flag = 0 HELLO! BOOT0 is starting! boot0 version : 1.5.2 The size of Boot1 is 0x00036000. Fail in checking boot1. Ready to disable icache. Fail in loading Boot1. Jump to Fel. ~~~ 可见DDR已被识别,但是加载boot1失败。 这其中的原因是DDR虽然被识别,但是参数配置错误,导致运行出错,所以我们需要先配置正确的DDR参数。 DDR参数记录在sys_config1.fex中,这里不过多解释sys_config1.fex的字段,直接使用之前在debian中适配好的fex文件覆盖 lichee/tools/pack/chips/sun5i/configs/android/a13-evb/sys_config1.fex 然后重新进行安卓编译过程。 编译完成后,可以直接重新烧写完整镜像,也可以只更新uboot和bootfs,后者需要对编译系统比较了解,在此不详细展开。 重新烧录后,可以看到闪过了两个开机画面,说明已经可以启动到linux内核了。 ### 第二次启动(启动介质错误) 按前面修改后,启动会卡在第二张开机画面,查看串口信息: ~~~ [ 16.009615] init: buffer : /dev/block/nande [ 16.014564] init: do_umount: /data [ 16.018071] init: do_umount error = Invalid argument [ 17.390045] usb 2-1: device not accepting address 2, error -110 [ 17.450200] ehci_irq: port change detect [ 17.454145] ehci_irq: port change detect [ 21.007468] init: buffer : /dev/block/nandh [ 21.012161] init: do_umount: /cache [ 21.015755] init: do_umount error = Invalid argument [ 21.022007] init: open device error :No such file or directory [ 31.008863] init: buffer : /dev/block/nandi [ 31.013556] init: do_umount: /databk [ 31.017237] init: do_umount error = Invalid argument [ 31.029268] init: cannot find '/system/bin/sh', disabling 'console' [ 31.035766] init: cannot find '/system/bin/servicemanager', disabling 'servicemanager' [ 31.043742] init: cannot find '/system/bin/vold', disabling 'vold' [ 31.049968] init: cannot find '/system/bin/netd', disabling 'netd' [ 31.056192] init: cannot find '/system/bin/debuggerd', disabling 'debuggerd' [ 31.063282] init: cannot find '/system/bin/rild', disabling 'ril-daemon' [ 31.069987] init: cannot find '/system/bin/surfaceflinger', disabling 'surfaceflinger' [ 31.077943] init: cannot find '/system/bin/app_process', disabling 'zygote' [ 31.084939] init: cannot find '/system/bin/drmserver', disabling 'drm' [ 31.091502] init: cannot find '/system/bin/mediaserver', disabling 'media' [ 31.098387] init: cannot find '/system/bin/dbus-daemon', disabling 'dbus' [ 31.105211] init: cannot find '/system/bin/installd', disabling 'installd' [ 31.112125] init: cannot find '/system/etc/install-recovery.sh', disabling 'flash_recovery' [ 31.120541] init: cannot find '/system/bin/keystore', disabling 'keystore' [ 31.127432] init: cannot find '/system/bin/u3gmonitor', disabling 'u3gmonitor' [ 31.135780] init: cannot find '/system/bin/sh', disabling 'console' ~~~ 可见是tf卡启动与nand启动的不同造成linux内核挂载根文件系统出错,所以需要修改开机启动脚本,即 \*.rc文件 device/softwinner/nuclear-evb/init.sun5i.rc device/softwinner/nuclear-evb/ueventd.sun5i.rc 将其中的nandX按下面对应关系修改 ~~~ nanda —— mmcblk0p2 nandb —— mmcblk0p5 nandc —— mmcblk0p6 nandd —— mmcblk0p7 nande —— mmcblk0p8 nandf —— mmcblk0p9 nandg —— mmcblk0p10 nandh —— mmcblk0p11 nandi —— mmcblk0p12 ~~~ 其中有一句挂载剩余空间的替换也对应替换: ~~~ #format_userdata /dev/block/nandj NUCLEAR exec /system/bin/busybox mount -t vfat /dev/block/mmcblk0p1 /mnt/sdcard ~~~ 再修改vold.fstab,开机挂载方式,前面两行改成以下,即sd卡0作为sdcard,sd卡2作为外置sd卡 ~~~ dev_mount sdcard /mnt/sdcard auto /devices/platform/sunxi-mmc.0/mmc_host dev_mount extsd /mnt/extsd auto /devices/platform/sunxi-mmc.2/mmc_host ~~~ > 如果需要修改成sd卡2启动,则还需要修改uboot代码 > lichee\u-boot\include\configs中sun5i.a13.h文件中的卡启动定义 > `#define CONFIG_MMC_SUNXI_SLOT 2` 最后修改uboot的环境变量env.cfg (lichee/tools/pack/chips/sun5i/configs/android/default/env.cfg) 将mmc作为启动介质 ~~~ bootdelay=1 #default bootcmd, will change at runtime according to key press bootcmd=run setargs_mmc boot_normal#default nand boot #kernel command arguments console=ttyS0,115200 nand_root=/dev/system mmc_root=/dev/mmcblk0p7 init=/init loglevel=6 #set kernel cmdline if boot.img or recovery.img has no cmdline we will use this setargs_nand=setenv bootargs console=${console} root=${nand_root} init=${init} loglevel=${loglevel} partitions=${partitions} setargs_mmc=setenv bootargs console=${console} root=${mmc_root} init=${init} loglevel=${loglevel} partitions=${partitions} #nand command syntax: sunxi_flash read address partition_name read_bytes #0x40007800 = 0x40008000(kernel entry) - 0x800(boot.img header 2k) boot_normal=sunxi_flash read 40007800 boot;boota 40007800 boot_recovery=sunxi_flash read 40007800 recovery;boota 40007800 boot_fastboot=fastboot #recovery key recovery_key_value_max=0x13 recovery_key_value_min=0x10 #fastboot key fastboot_key_value_max=0x8 fastboot_key_value_min=0x2 ~~~ 修改完成后重新编译下安卓 为了省事,可以不下载整个镜像,只更新boot.fex和env.fex(lichee/tools/pack/out下) 在linux下,使用fdisk -l查看tf卡分区: ~~~ Device Boot Start End Blocks Id System /dev/sdb1 3448832 15595518 6073343+ b W95 FAT32 //剩余空间作为u盘 /dev/sdb2 * 73728 106495 16384 6 FAT16 //bootfs,含uboot /dev/sdb3 1 3448832 1724416 85 Linux extended /dev/sdb5 106496 139263 16384 83 Linux //env.fex /dev/sdb6 139264 204799 32768 83 Linux //boot.fex,含linux内核及ramdisk /dev/sdb7 204800 1253375 524288 83 Linux //system分区 /dev/sdb8 1253376 2301951 524288 83 Linux //data分区 /dev/sdb9 2301952 2334719 16384 83 Linux //misc分区 /dev/sdb10 2334720 2400255 32768 83 Linux //recovery分区 /dev/sdb11 2400256 2924543 262144 83 Linux //cache分区 /dev/sdb12 2924544 3448831 262144 83 Linux //databk分区 ~~~ 所以只需更新两个分区: ~~~ root@ubuntu64:/home/zp# dd if=env.fex of=/dev/sdb5 256+0 records in 256+0 records out 131072 bytes (131 kB) copied, 0.097856 s, 1.3 MB/s root@ubuntu64:/home/zp# dd if=boot.fex of=/dev/sdb6 19916+0 records in 19916+0 records out 10196992 bytes (10 MB) copied, 8.54376 s, 1.2 MB/s root@ubuntu64:/home/zp# sync ~~~ 更新之后即可成功进入到安卓系统~ ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/488a185c2d50f3f7447efb621d4d836e_2976x3968.jpg) 虽然此时可以进入系统,但是很多外设不能运行,这些外设的驱动适配见后面的外设适配解析。
';