如何在MacOS10.12.6中为Nexus5编译M固件

前言

  Marshmallow,也就是Android6现在对于我们来说也是古老的东西了,所以在编译就会遇到各种版本问题。于是就想写篇文章,把遇到的坑记录下来。

初始编译环境

环境 版本号
MacOS 10.12.6
JDK 1.8
MacOSX-SDK 12
手机 Nexus5(GSM/LTE)

  其他的make等版本号,基本不用怎么管,就新版的。MacOSX-SDK下面出问题的时候再稍微详细地说一下。

初始工作

  按照官网的教程,搭建编译环境下载源代码,一步一步来。
  这里需要注意的是:因为我们的都是是Nexus5,所以版本最高只能到Android 6.0.1。所以我在配置远程仓库路径的时候用的是

repo init -u https://android.googlesource.com/platform/manifest -b android-6.0.1_r1

  当然这时候需要翻墙,推荐用kcptun加速,它能让搬瓦工最便宜的那种小水管都能达到近2M/s的下载速率。这样能保证repo sync的成功率,要知道这玩意失败后会留下一堆临时文件,还不能断点续传。网上流传的加-f参数只不过是让它不要让失败终止,而是继续下载。下面是我改写的下载脚本。功能就是失败后继续下载,然后统计一下次数,给个交代

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
count=1;
repo sync;
while [ $? == 1 ]; do
echo "$count Sync failed, repeat again:";
find . -iname tmp_pack_* | xargs rm
sleep 3
let count++;
repo sync;
done
echo "finish $count sync";

  因为我已经在git上设置了代理,于是这里就不用proxychains4了。

1
git config --global http.proxy 'socks5://127.0.0.1:1080'

  有些博客会让人加个https.proxy。

1
git config --global https.proxy 'socks5://127.0.0.1:1080'

  可我看文档好像是没有这个东西的

http.proxy
Override the HTTP proxy, normally configured using the http_proxy, https_proxy, and all_proxyenvironment variables (see curl(1)). In addition to the syntax understood by curl, it is possible to specify a proxy string with a user name but no password, in which case git will attempt to acquire one in the same way it does for other credentials. See gitcredentials[7] for more information. The syntax thus is[protocol://][user[:password]@]proxyhost[:port]. This can be overridden on a per-remote basis; see remote..proxy

  按照这个文档来说,http.proxy既管http也管https,所以就没有https.proxy了。不过加上https.proxy也不会报错。当然如果只写了https.proxy肯定不会有效果就是了。

构建

下载驱动

  这个在官网上叫做硬件支持的二进制文件。这时候我们要根据在初始工作中选择的分支看它对应的细分版本号是多少,然后再通过这个版本号找到相应的驱动。所以至少需要了两个表
  第一个表是源代码标记和细分版本。这个表很长,下面就节选我们所需要部分的附近几行

细分版本 分支 版本 支持的设备
MXB48J android-6.0.1_r4 Marshmallow Pixel C
MMB29M android-6.0.1_r3 Marshmallow Nexus 6P、Nexus Player
MMB29K android-6.0.1_r1 Marshmallow Nexus 5、Nexus 5X、Nexus 6、Nexus 7 (flo/deb)、Nexus 9 (volantis/volantisg)
MMB29N android-6.0.0_r41 Marshmallow Nexus 6P
MDB08M android-6.0.0_r26 Marshmallow Nexus 5X、Nexus 6P

  在这个表中找到版本号(MMB29K)后,可以去二进制驱动的下载页面中下载对应的驱动。这个页面很长,还是 cmd+F 方便。下面是我们所需要的部分:

Nexus 5 (GSM/LTE) binaries for Android 6.0.1 (MMB29K)

Hardware Component Company Download SHA-256 Checksum
NFC, Bluetooth, Wi-Fi Broadcom Link 9afb80be898957781aa2e5c05548e0d0ffbfc8fbd976fda4525ea4bda1bdf403
Camera, Sensors, Audio LG Link 5ffaf75530875f8d709bba141e20db4d54417a21246dcceeb6a1194f707995be
Graphics, GSM, Camera, GPS, Sensors, Media, DSP, USB Qualcomm Link 92d92325a3febc6ff39144ef3472fbdc6756bb81d950df67e9c29b5ada80fbf1

  下载完成后解压(tar -zxvf *.tgz)到源码的根目录(默认为/Volumes/android),这样就会看到 extract-公司名-版本代码.sh为名字的脚本。然后执行,就会发现给了一个协议让你最后输入一个 I ACCEPT 。所以可以疯狂按会车,到第八条慢一些,第e小条的下面就让你输 I ACCEPT 了。接受这个协议后,它会自解压一些文件到vendor这个文件夹。

清理

  为了确保新安装的二进制文件在解压后会被适当考虑在内,请使用以下命令删除所有以前编译操作的已有输出:

1
make clobber

  这时候会出现一些错误,参见后面的遇到的问题那一节

设置环境

  使用 envsetup.sh 脚本初始化环境。请注意,将 source 替换成 .(一个点)可以省去一些字符,这种简写形式在文档中更为常用。

1
source build/envsetup.sh

  或

1
build/envsetup.sh

选择目标

  这里呢有二十多种模式,但好在官方给了个参考。在选择编译系统里,我们节选部分表格

设备 代号 编译配置
Nexus 6 shamu aosp_shamu-userdebug
Nexus Player fugu aosp_fugu-userdebug
Nexus 9 volantis (flounder) aosp_flounder-userdebug
Nexus 5 (GSM/LTE) hammerhead aosp_hammerhead-userdebug
Nexus 7 (WLAN) razor (flo) aosp_flo-userdebug

  有上表可见,这时候所需要的编译模式是aosp_hammerhead-userdebug。
  输入下面的命令会给出一个列表让人选择

1
lunch

  列表如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
You're building on Darwin
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-userdebug
15. mini_emulator_x86_64-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]

  这时输入19就行。然后它会返回一个配置列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=6.0.1
TARGET_PRODUCT=aosp_hammerhead
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
TARGET_CPU_VARIANT=krait
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=darwin
HOST_OS_EXTRA=Darwin-16.7.0-x86_64-i386-64bit
HOST_BUILD_TYPE=release
BUILD_ID=MMB29K
OUT_DIR=out
============================================

编译

  这个就简单

1
make -j4

  选择了四个线程同时编译

遇到的问题

  在这个环境里,编译的时候是会报错的。

1
2
3
4
5
build/core/combo/mac_version.mk:39: * Can not find SDK 10.6 at /Developer/SDKs/MacOSX10.6.sdk
build/core/combo/mac_version.mk:40: *****************************************************
build/core/combo/mac_version.mk:41: *** Stop.. Stop.
\e[0;31m#### make failed to build some targets (3 seconds) ####\e[00m

  这个就很明显了,SDK的版本不对。我们去

/Applications/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs

里面找找看,会发现只有10.12的SDK。
  那么现在假设它是向下兼容的,那么我们试试能否强制用10.12的SDK编译。找到build/core/combo/mac_version.mk,在mac_sdk_versions_supported加上10.12

1
mac_sdk_versions_supported := 10.6 10.7 10.8 10.9 10.12

  然后继续编译,这时后又是java版本不对,毕竟我们这个太老了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Checking build tools versions...
************************************************************
You are attempting to build with the incorrect version
of java.
Your version is: java version "1.8.0_112" Java(TM) SE Runtime Environment (build 1.8.0_112-b16) Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode).
The required version is: "1.7.x"
Please follow the machine setup instructions at
https://source.android.com/source/initializing.html
************************************************************
build/core/main.mk:171: *** stop. Stop.
\e[0;31m#### make failed to build some targets (13 seconds) ####\e[00m

  好吧,这个要jdk1.7。可是我其他的项目还是主要要用java8呀,每次改JAVA_HOME也太麻烦了点。这时候就祭出神器jenv了。它可以很方便的切换java版本,而且可以限定作用范围。虽然也能用brew install jenv安装,但是装完后,会出一些奇奇怪怪的问题,还是建议用git clone吧。至于具体操作,可以看它的githubreadme,命令也很简洁方便。

  切换到java7进行编译,然后还是会失败的

1
2
3
4
5
6
7
8
9
10
11
system/core/libcutils/threads.c:38:10: error: 'syscall' is deprecated: first deprecated in OS X 10.12 - syscall(2) is unsupported; please switch to a supported interface. For SYS_kdebug_trace use kdebug_signpost(). [-Werror,-Wdeprecated-declarations]
return syscall(SYS_thread_selfid);
^
../../Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/unistd.h:733:6: note: 'syscall' has been explicitly marked deprecated here
int syscall(int, ...);
^
1 error generated.
make: *** [out/host/darwin-x86/obj/STATIC_LIBRARIES/libcutils_intermediates/threads.o] Error 1
make: *** Waiting for unfinished jobs....
\e[0;31m#### make failed to build some targets (02:26 (mm:ss)) ####\e[00m

  有个函数在MACOSX.SDK里被废除了。那用老版本的?去https://github.com/phracker/MacOSX-SDKs/releases下载MacOSX10.9.sdk.tar.xz,然后解压到

/Applications/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs

  选这个版本的原因是因为我们在前面的原始的build/core/combo/mac_version.mk看到支持的版本号最高是10.9。然后再编译一次试试

1
2
3
4
5
6
7
xcodebuild[42506:10928497] [MT] DVTSDK: Skipped SDK /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk; its version (10.9) is below required minimum (10.11) for the macosx platform.
xcodebuild[42506:10928497] [MT] PluginLoading: Required plug-in compatibility UUID DFFB3951-EB0A-4C09-9DAC-5F2D28CC839C for plug-in at path '~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/ClangFormat.xcplugin' not present in DVTPlugInCompatibilityUUIDs
xcodebuild[42506:10928497] [MT] PluginLoading: Required plug-in compatibility UUID DFFB3951-EB0A-4C09-9DAC-5F2D28CC839C for plug-in at path '~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/Alcatraz.xcplugin' not present in DVTPlugInCompatibilityUUIDs
build/core/combo/mac_version.mk:38: *****************************************************
build/core/combo/mac_version.mk:39: * Can not find SDK 10.6 at /Developer/SDKs/MacOSX10.6.sdk
build/core/combo/mac_version.mk:40: *****************************************************
build/core/combo/mac_version.mk:41: *** Stop.. Stop.

  现在又说版本不能低于10.11。好吧,那重新下10.11,然后修改mac_version.mk,解压编译。

  编译成功后,会输出一个报告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Creating filesystem with parameters:
Size: 1073741824
Block size: 4096
Blocks per group: 32768
Inodes per group: 8192
Inode size: 256
Journal blocks: 4096
Label: system
Blocks: 262144
Block groups: 8
Reserved block group size: 63
Created filesystem with 1701/65536 inodes and 106038/262144 blocks
Install system fs image: out/target/product/hammerhead/system.img
out/target/product/hammerhead/system.img+out/target/product/hammerhead/obj/PACKAGING/recovery_patch_intermediates/recovery_from_boot.p maxsize=1096212480 blocksize=135168 total=419150812 reserve=11083776
\e[0;32m#### make completed successfully (02:51:38 (hh:mm:ss)) ####\e[00m

  所用空间的大小,然后关键的那几个img,于是现在就可以刷机了。

刷机

  Nexus5关机状态下,长按音量下+电源,即可进入recovery模式, 然后在源码根目录下执行下面命令:

1
fastboot -w flashall

  刷机成功后就会自动重启

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
target reported max download size of 1073741824 bytes
Creating filesystem with parameters:
Size: 13725835264
Block size: 4096
Blocks per group: 32768
Inodes per group: 8144
Inode size: 256
Journal blocks: 32768
Label:
Blocks: 3351034
Block groups: 103
Reserved block group size: 823
Created filesystem with 11/838832 inodes and 93654/3351034 blocks
Creating filesystem with parameters:
Size: 734003200
Block size: 4096
Blocks per group: 32768
Inodes per group: 7472
Inode size: 256
Journal blocks: 2800
Label:
Blocks: 179200
Block groups: 6
Reserved block group size: 47
Created filesystem with 11/44832 inodes and 5813/179200 blocks
--------------------------------------------
Bootloader Version...: HHZ20h
Baseband Version.....: M8974A-2.0.50.2.30
Serial Number........: 039da899215fcfec
--------------------------------------------
checking product...
OKAY [ 0.100s]
sending 'boot' (9160 KB)...
OKAY [ 0.500s]
writing 'boot'...
OKAY [ 0.788s]
sending 'recovery' (9898 KB)...
OKAY [ 0.563s]
writing 'recovery'...
OKAY [ 0.834s]
erasing 'system'...
OKAY [ 1.237s]
sending 'system' (408826 KB)...
OKAY [ 13.012s]
writing 'system'...
OKAY [ 29.164s]
erasing 'userdata'...
OKAY [ 10.458s]
sending 'userdata' (137318 KB)...
OKAY [ 4.511s]
writing 'userdata'...
OKAY [ 9.153s]
erasing 'cache'...
OKAY [ 0.670s]
sending 'cache' (13348 KB)...
OKAY [ 0.631s]
writing 'cache'...
OKAY [ 1.062s]
rebooting...
finished. total time: 73.191s

展示一下成果