小米4是Cyanogenmod官方支持的Device,所以编译无需我们做Device specific适配,我们只需要提取代码(Android 与Kernel),获取proprietary binary files即可编译。
小米4以及小米3的设备名字都是cancro,CM对于这两款设备的WIki位于:
https://wiki.cyanogenmod.org/w/Build_for_cancro
1. breakfast VS proprietary files
先获取proprietary binary files然后再breakfast,否则会出现错误。
2. 提取proprietary file的错误解决
提取有两种方法:
一种是手机刷入cm12.1系统后使用adb pull获取
一种是直接解压cm编译的ota包,然后从里面的system.new.dat中获取
其中第二种方法更为方便,但是我们需要将system.new.dat转换成system.img
sparse
主要在于一个是为了减小size而对内部中的内容进行了压缩,而system.img则没有压缩。
因为是zip包,在linux下面我们使用unzip来完成
unzip -d cm12.1 cm-12.1-20151117-SNAPSHOT-YOG7DAO1K6-cancro.zip
Archive: cm-12.1-20151117-SNAPSHOT-YOG7DAO1K6-cancro.zip
signed by SignApk
extracting: cm12.1/system.patch.dat
inflating: cm12.1/META-INF/com/android/metadata
inflating: cm12.1/META-INF/com/google/android/update-binary
inflating: cm12.1/META-INF/com/google/android/updater-script
inflating: cm12.1/META-INF/org/cyanogenmod/releasekey
inflating: cm12.1/boot.img
inflating: cm12.1/file_contexts
inflating: cm12.1/install/bin/backuptool.functions
inflating: cm12.1/install/bin/backuptool.sh
inflating: cm12.1/install/bin/nfcchecker.sh
inflating: cm12.1/install/bin/otasigcheck.sh
inflating: cm12.1/install/bin/resize2fs_static
inflating: cm12.1/system.new.dat
inflating: cm12.1/system.transfer.list
inflating: cm12.1/system/build.prop
inflating: cm12.1/META-INF/com/android/otacert
inflating: cm12.1/META-INF/MANIFEST.MF
inflating: cm12.1/META-INF/CERT.SF
inflating: cm12.1/META-INF/CERT.RSA
使用python脚本sdat2img来完成
sdat2img.py system.transfer.list system.new.dat system.img
Skipping command erase
Copying 32767 blocks into position 0...
Copying 2 blocks into position 32768...
Copying 2 blocks into position 32809...
Copying 32212 blocks into position 33323...
Copying 2 blocks into position 65536...
Copying 20457 blocks into position 66050...
Copying 2 blocks into position 98304...
Copying 2 blocks into position 98345...
Copying 32212 blocks into position 98859...
Copying 2 blocks into position 131072...
Done! Output image: /home/hexiongjun/android/CM_XiaoMi4/cm12.1/system.img
这样就有了我们需要的system.img文件了
sudo mount -t ext4 system.img system
脚本extract-files.sh本身就有从local directory拷贝的功能,但是实际上我们运行的时候会有错误
./extract-files.sh -d /home/hexiongjun/android/CM_XiaoMi4/cm12.1/system
cp: cannot stat ‘/home/hexiongjun/android/CM_XiaoMi4/cm12.1/system/system/vendor/lib/libthermalioctl.so’: No such file or directory
$ find -name libthermalioctl.so
./system/vendor/lib/libthermalioctl.so
因此我们更改前面使用的方式
]$ ./extract-files.sh -d /home/hexiongjun/android/CM_XiaoMi4/cm12.1/
cp: cannot stat ‘/home/hexiongjun/android/CM_XiaoMi4/cm12.1//system/vendor/lib/rfsa/adsp/libscveT2T_skel.so’: No such file or directory
当然还有更为容易解决的方式
查看脚本,我们可以知道它的路径都是按照实机来的,而实机中像vendor这种目录是位于/vendor中,且这个vendor是/system/vendor的soft link,同样的还有etc等目录:
shell@flo:/ $ ll /
drwxr-xr-x root root 2016-05-31 15:30 acct
drwxrwx--- system cache 2016-04-18 22:59 cache
lrwxrwxrwx root root 1969-12-31 13:00 charger -> /sbin/healthd
dr-x------ root root 2016-05-31 15:30 config
lrwxrwxrwx root root 2016-05-31 15:30 d -> /sys/kernel/debug
drwxrwx--x system system 2016-05-31 15:30 data
-rw-r--r-- root root 297 1969-12-31 13:00 default.prop
drwxr-xr-x root root 2016-05-31 15:30 dev
lrwxrwxrwx root root 2016-05-31 15:30 etc -> /system/etc
-rw-r--r-- root root 19494 1969-12-31 13:00 file_contexts
drwxrwx--x system system 2016-05-31 15:30 firmware
-rw-r----- root root 3464 1969-12-31 13:00 fstab.flo
-rwxr-x--- root root 422740 1969-12-31 13:00 init
-rwxr-x--- root root 8288 1969-12-31 13:00 init.cm.rc
-rwxr-x--- root root 1075 1969-12-31 13:00 init.environ.rc
-rwxr-x--- root root 162 1969-12-31 13:00 init.flo.diag.rc
-rwxr-x--- root root 6831 1969-12-31 13:00 init.flo.power.rc
-rwxr-x--- root root 13544 1969-12-31 13:00 init.flo.rc
-rwxr-x--- root root 7640 1969-12-31 13:00 init.flo.usb.rc
-rwxr-x--- root root 22264 1969-12-31 13:00 init.rc
-rwxr-x--- root root 318 1969-12-31 13:00 init.superuser.rc
-rwxr-x--- root root 1927 1969-12-31 13:00 init.trace.rc
-rwxr-x--- root root 3885 1969-12-31 13:00 init.usb.rc
-rwxr-x--- root root 301 1969-12-31 13:00 init.zygote32.rc
drwxrwxr-x root system 2016-05-31 15:30 mnt
lstat '//persist' failed: Permission denied
dr-xr-xr-x root root 1969-12-31 13:00 proc
-rw-r--r-- root root 3151 1969-12-31 13:00 property_contexts
drwxr-xr-x root root 1969-12-31 13:00 res
drwx------ root root 2016-03-20 19:39 root
drwxr-x--- root root 1969-12-31 13:00 sbin
lrwxrwxrwx root root 2016-05-31 15:30 sdcard -> /storage/emulated/legacy
-rw-r--r-- root root 725 1969-12-31 13:00 seapp_contexts
-rw-r--r-- root root 61 1969-12-31 13:00 selinux_version
-rw-r--r-- root root 140844 1969-12-31 13:00 sepolicy
-rw-r--r-- root root 10574 1969-12-31 13:00 service_contexts
drwxr-x--x root sdcard_r 2016-05-31 15:30 storage
dr-xr-xr-x root root 2016-05-31 15:30 sys
drwxr-xr-x root root 2016-05-24 16:50 system
lrwxrwxrwx root root 2016-05-31 15:30 tombstones -> /data/tombstones
-rw-r--r-- root root 2819 1969-12-31 13:00 ueventd.flo.rc
-rw-r--r-- root root 7514 1969-12-31 13:00 ueventd.rc
lrwxrwxrwx root root 2016-05-31 15:30 vendor -> /system/vendor
ln -s system/etc etc
ln -s system/vendor/ vendor
同时还需要注意的是一些bin文件本身对others没有读权限,因此可以在adb shell中使用find找到,却无法pull上来,这个时候就需要将adb切成root:
adb root
同时因为脚本中配置了
set -e
因为前面二进制文件的路径不正确,编译的时候会有类似下面的错误:
make: *** No rule to make target `vendor/xiaomi/cancro/proprietary/app/qcrilmsgtunnel.apk', needed by `/home/hexiongjun/android/cm13.1/out/target/product/cancro/obj/APPS/qcrilmsgtunnel_intermediates/package.apk'. Stop.
make: *** Waiting for unfinished jobs....
make: Leaving directory `/home/hexiongjun/android/cm13.1'
#### make failed to build some targets (02:11 (mm:ss)) ####