1 环境背景
1.1 基础信息
Ubuntu系统版本:ubuntu 16.04 LTS
电脑主板CPU信息:Intel® Core™ i5-3470 CPU @ 3.20GHz × 4
电脑主板内存:15.6 GiB
需要编译的Android SDK版本:Android13
1.2 编译报错信息
1.2.1 make -j4 报错 log
============================================
[100% 1/1] analyzing Android.bp files and generating ninja file at out/soong/build.ninja
FAILED: out/soong/build.ninja
cd "$(dirname "out/host/linux-x86/bin/soong_build")" && BUILDER="$PWD/$(basename "out/host/linux-x86/bin/soong_build")" && cd / && env -i "$BUILDER" --top "$TOP" --soong_out "out/soong" --out "out" -o out/soong/build.ninja --globListDir build --globFile out/soong/globs-build.ninja -t -l out/.module_paths/Android.bp.list --available_env out/soong/soong.environment.available --used_env out/soong/soong.environment.used.build Android.bp
codec2-config: sdkVersion[33]
use aw hw vp9!
codec2-ic type : [a523]
registry_table has NOT been set. Please check it.
cedarx-config: sdkVersion[33], board[saturn], platformconfig[YES]
cedarx-ic type : [a523]
cedarc-config: sdkVersion[33], board[saturn], platformconfig[YES], cryptolevel[1], playreadytype[]
registry_table has NOT been set. Please check it.
/bin/sh: line 1: 23 Killed env -i "$BUILDER" --top "$TOP" --soong_out "out/soong" --out "out" -o out/soong/build.ninja --globListDir build --globFile out/soong/globs-build.ninja -t -l out/.module_paths/Android.bp.list --available_env out/soong/soong.environment.available --used_env out/soong/soong.environment.used.build Android.bp
19:14:04 soong bootstrap failed with: exit status 1
ninja: build stopped: subcommand failed.
#### failed to build some targets (09:26 (mm:ss)) ####
#### failed to build some targets (09:26 (mm:ss)) ####
1.2.2 Ubuntu系统dmesg报错 log
[ 974.660801] Out of memory: Kill process 8160 (soong_build) score 880 or sacrifice child
[ 974.661346] Killed process 8160 (soong_build) total-vm:16902592kB, anon-rss:15508200kB, file-rss:0kB, shmem-rss:0kB
[ 975.184685] oom_reaper: reaped process 8160 (soong_build), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
由以上log信息得知,SDK编译失败是由于系统内存不足,编译进程被系统kill掉导致编译中断。在Android高版本编译时经常会遇到framework一些相关任务编译时经常把内存吃满导致内存不足这种现象。
2 解决方法
2.1 增加主板物理内存
如果主机主板可以支持更大的内存,建议购买内存条来加大系统内存,提升主板性能。注意增加的内存条最好要跟之前主板所使用的内存条的型号跟频率要一致,以减少不必要的麻烦。由于我所使用的电脑主板最大内存容量只支持到16GB,所以此路不通,除非直接更换电脑主板。
2.2 减少编译线程
当你输入编译命令make -j4 的时候,会有以下提示,这是官方所建议的减少编译线程来解决编译时消耗内存过大的情况。
15:17:31 ************************************************************
15:17:31 You are building on a machine with 15.6GB of RAM
15:17:31
15:17:31 The minimum required amount of free memory is around 16GB,
15:17:31 and even with that, some configurations may not work.
15:17:31
15:17:31 If you run into segfaults or other errors, try reducing your
15:17:31 -j value.
15:17:31 ************************************************************
所以这个时候你就把:make -j4变成 make -j2或make -j1 (-j 1代表只用一个线程编译,会导致编译非常缓慢)
2.3 增加swap内存
Linux中Swap(即:交换分区),类似于Windows的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。Android是基于Linux的操作系统,所以也可以使用Swap分区来提升系统运行效率。
交换分区,英文的说法是swap,意思是“交换”、“实物交易”。它的功能就是在内存不够的情况下,操作系统先把内存中暂时不用的数据,存到硬盘的交换空间,腾出内存来让别的程序运行,和Windows的虚拟内存(pagefile.sys)的作用是一样的。
2.3.1 查看swap分区大小
chris@lc:/work2/SDK/A527/A527_Android13TableV1.2/android$ sudo fdisk -l
Disk /dev/sda: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x00016001
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 299999231 299997184 143.1G 83 Linux
/dev/sda2 300001278 1953523711 1653522434 788.5G 5 Extended
/dev/sda5 300001280 340000766 39999487 19.1G 83 Linux
/dev/sda6 340000768 343998463 3997696 1.9G 82 Linux swap / Solaris
/dev/sda7 344000512 345999359 1998848 976M 83 Linux
/dev/sda8 346001408 1953523711 1607522304 766.5G 83 Linux
chris@lc:/work2/SDK/A527/A527_Android13TableV1.2/android$ free -m
total used free shared buff/cache available
Mem: 15936 4655 149 2117 11131 8767
Swap: 1951 0 1951
2.3.2 创建文件
sudo dd if=/dev/zero of=/swapfile bs=1M count=20480
of:文件的保存路径
bs=1M count=20480:文件的大小为1MB*20480 = 20GB
在linux中,“/dev/zero”是一个特殊的设备文件,它会不断地产生二进制零值。在使用“dd”命令创建文件时,如果将输入文件(if)指定为“/dev/zero”,则会从该设备文件读取无限数量的二进制零值,以填充目标文件。
在创建Swap文件时,我们通常使用“/dev/zero”来填充文件中的内容,因为Swap文件中的内容在使用过程中并不重要,只需要占用一定的磁盘空间即可。而使用“/dev/zero”填充Swap文件可以确保文件中的所有位都被设置为零,从而避免在使用Swap文件时发生数据泄漏或错误。
因此,“sudo dd if=/dev/zero of=/swapfile bs=1M count=20480”命令中的“if=/dev/zero”参数的作用是从“if=/dev/zero”参数的作用是从“/dev/zero”设备文件中读取数据,并将其写入名为“/swapfile”的文件中,已创建一个大小为20GB的Swap文件。
2.3.3 将文件格式化为swap文件
sudo mkswap /swapfile
2.3.4 挂载swap文件
sudo swapon /swapfile
这样,虚拟内存就扩充好了,可以通过命令free -m查看内存情况:
chris@lc:/work2/SDK/A527/A527_Android13TableV1.2/android$ free -m
total used free shared buff/cache available
Mem: 15936 4675 168 2394 11092 8471
Swap: 22431 0 22431
Swap已经由之前的1951M(1.9GB)增加到现在的22431M(21.9GB)了,Swap虚拟内存增加成功。
2.3.4 设置剩余最小内存触发swap
sudo vi /etc/sysctl.conf
在末尾加入:
vm.min_free_kbytes=2048000
在空闲内存只剩2GB时触发使用虚拟内存。
2.3.5 开机自动挂载swap文件
系统重启的话,需要重新挂载swap文件,可以像挂载硬盘一样开机自动挂载:
sudo vim /etc/fstab
在末尾加入:
/swapfile none swap sw 0 0