天天看點

Ubuntu16.04編譯Android源碼系列一——7.1.2和4.4及踩坑一、前言二、預置環境三、編譯要求

一、前言

        本文不涉及源碼下載下傳過程,主要記錄自己的編譯源碼過程及其中遇到的問題,并最終運作在真機上。

系列文章:

Ubuntu16.04編譯Android源碼系列二—— android 5.1和android 6.0及踩坑

二、預置環境

        1、ubuntu16.04,8G記憶體,2T硬碟

        2、手機真機nexus 5x, nexus 5

        3、編譯源碼版本為android-7.1.2_r18和android-4.4_r1兩個

        版本選擇參考連結:https://source.android.google.cn/setup/start/build-numbers#source-code-tags-and-builds,根據你的真機型号選擇對應的源碼版本。

三、編譯要求

        由于兩個源碼版本不同,本文依次編譯。

1、編譯android-7.1.2版本

1)要求

參考連結:https://source.android.google.cn/setup/build/requirements

需要jdk、python、gnu make、git

由于本文在下載下傳源碼過程中已經配置了git,是以略過。

a、設定java環境

Ubuntu16.04編譯Android源碼系列一——7.1.2和4.4及踩坑一、前言二、預置環境三、編譯要求

        如圖所示,此時要編譯源碼7.1.2版本,Ubuntu下要求java環境為OpenJDK8

        執行指令安裝:

//正常來說指令行配置jre即可
sudo apt-get install openjdk-8-jre
//但我同時安裝了jdk
sudo apt-get install openjdk-8-jdk
           

        執行指令檢視是否安裝成功:

java -version
javac -version
           

        如果安裝過程沒有出錯,那麼此時應該能夠看到openjdk1.8環境。

b、設定python

        ubuntu中自帶python環境,且版本為2.7,可通過執行python指令檢視。

c、設定gnu make

        ubuntu中自帶gnu make,版本為4.1,但由于我們此時編譯Android版本為7.1,可以在該版本執行,是以也不作改變。可通過執行make指令檢視版本。

2)下載下傳驅動

        因為本文編譯系統最終需要刷到真機上,是以需要下載下傳對應的驅動。google提供了 Nexus 和 Pixel 裝置的驅動檔案,連結:https://developers.google.cn/android/drivers,在連結中,可以根據下載下傳源碼的版本名稱,搜尋到對應的驅動。本文在該7.1.2版本中直接下載下傳編譯好的鏡像檔案,檢視版本選擇時的連結,7.1.2_r18對應的細分版本為N2G47Z,在https://developers.google.cn/android/images中搜尋N2G47Z,找到對應壓縮包下載下傳。

3)安裝需要的庫檔案

sudo apt install g++-multilib
sudo apt install gperf
sudo apt install libxml2-utils
sudo apt install curl
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
sudo apt-get install m4
           

4)開始編譯

進入源碼根目錄

a、初始化編譯環境,執行以下指令,注意.和build之間有空格:

. build/envsetup.sh
           

b、使用lunch選擇編譯目标

lunch
           

執行此指令後,會出現目前可以編譯的版本其對應的數字

Ubuntu16.04編譯Android源碼系列一——7.1.2和4.4及踩坑一、前言二、預置環境三、編譯要求

運作版本檢視連結:https://source.android.google.cn/source/running

在該連結中檢視手機類型,選擇對應的運作版本,這裡我的手機是nexus5x,希望編譯帶有root權限的可調試版本,是以選擇userdebug類型,選擇aosp-bullhead-userdebug對應的數字即可。

c、執行編譯

time make -j8
           

這裡的工作線程數可以設定為實體核心數-邏輯核心數之間的數字,我的電腦實體核心為4,邏輯核心數為8,是以設定-j參數為8.

d、檢視生成的鏡像檔案并刷入

進入源碼目錄下/out/target/product/bullhead,執行以下指令:

//進入手機bootloader
adb reboot bootloader

//開始刷機
fastboot flash boot boot.img

fastboot flash system system.img

fastboot flash cache cache.img

fastboot flash userdata userdata.img

fastboot flash recovery recovery.img
           

        參考連結:https://source.android.google.cn/source/running

        刷入過程中首先需要将手機解鎖,否則無法刷入,同時打開手機調試,這裡可能會遇到一些坑,如果是adb devices 指令udev問題可以參考踩坑7.1的問題e,如果是其他問題可參考官網連結https://source.android.google.cn/source/running或文末部落格連結。

f、刷入vendor.img

        7.1.2版本的源碼編譯過程中,我們沒有下載下傳驅動二進制檔案,是以在/out/target/product/bullhead目錄中也不會有vendor.img,直接解壓前面下載下傳的鏡像包,找到裡面的image***.zip繼續解壓找到vendor.img,刷入vendor.img鏡像。

g、手機重新開機

fastboot reboot
           

此時處于fastboot模式,執行該指令即可重新開機手機。手機重新開機後會報内部錯誤,由于用于自己調試,是以也沒關系,需要解決的同學可以參考文末部落格連結。

5)編譯7.1踩坑

在我修複的過程中,有時候執行make指令會報同樣的錯,這個時候我通常執行make clobber指令清除之前編譯生成的環境和檔案,全部重新執行生效。

a、

[  1% 761/49025] Yacc: aidl <= system/tools/aidl/aidl_language_y.yy

FAILED: /bin/bash -c "prebuilts/misc/linux-x86/bison/bison -d  --defines=out/host/linux-x86/obj/STATIC_LIBRARIES/libaidl-common_intermediates/aidl_language_y.h -o out/host/linux-x86/obj/STATIC_LIBRARIES/libaidl-common_intermediates/aidl_language_y.cpp system/tools/aidl/aidl_language_y.yy"

/bin/bash: prebuilts/misc/linux-x86/bison/bison: No such file or directory

[  1% 761/49025] Lex: aidl <= system/tools/aidl/aidl_language_l.ll

FAILED: /bin/bash -c "prebuilts/misc/linux-x86/flex/flex-2.5.39 -oout/host/linux-x86/obj/STATIC_LIBRARIES/libaidl-common_intermediates/aidl_language_l.cpp system/tools/aidl/aidl_language_l.ll"

flex-2.5.39: loadlocale.c:130: _nl_intern_locale_data: Assertion `cnt < (sizeof (_nl_value_type_LC_TIME) / sizeof (_nl_value_type_LC_TIME[0]))' failed.

Aborted (core dumped)

[  1% 761/49025] target Java: core-all (out/targe...bj/JAVA_LIBRARIES/core-all_intermediates/classes)

Note: Some input files use or override a deprecated API.

Note: Recompile with -Xlint:deprecation for details.

Note: Some input files use unchecked or unsafe operations.

Note: Recompile with -Xlint:unchecked for details.

ninja: build stopped: subcommand failed.

build/core/ninja.mk:148: recipe for target 'ninja_wrapper' failed

make: *** [ninja_wrapper] Error 1

修複:

在build/envsetup.sh腳本中最後添加一句話

export LC_ALL=C
           

這裡需要從build/envsetup.sh重新執行

參考連結:https://stackoverflow.com/questions/49955137/error-when-build-lineageos-make-ninja-wrapper-error-1

b、

ninja: Entering directory `.'

bison/bison: m4 subprocess failed: No such file or directory

[  0% 1/34696] Yacc: aidl <= system/tools/aidl/aidl_language_y.yy

FAILED: /bin/bash -c "prebuilts/misc/linux-x86/bison/bison -d  --defines=out/host/linux-x86/obj/STATIC_LIBRARIES/libaidl-common_intermediates/aidl_language_y.h -o out/host/linux-x86/obj/STATIC_LIBRARIES/libaidl-common_intermediates/aidl_language_y.cpp system/tools/aidl/aidl_language_y.yy"

/bin/bash: prebuilts/misc/linux-x86/bison/bison: No such file or directory

ninja: build stopped: subcommand failed.

build/core/ninja.mk:148: recipe for target 'ninja_wrapper' failed

make: *** [ninja_wrapper] Error 1

修複:

sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386

c、

FAILED: /bin/bash -c "prebuilts/misc/linux-x86/flex/flex-2.5.39 -oout/host/linux-x86/obj/STATIC_LIBRARIES/libaidl-common_intermediates/aidl_language_l.cpp system/tools/aidl/aidl_language_l.ll"

flex-2.5.39: fatal internal error, exec of /usr/bin/m4 failed

[  1% 760/49025] target Java: core-all (out/targe...bj/JAVA_LIBRARIES/core-all_intermediates/classes)

Note: Some input files use or override a deprecated API.

Note: Recompile with -Xlint:deprecation for details.

Note: Some input files use unchecked or unsafe operations.

Note: Recompile with -Xlint:unchecked for details.

ninja: build stopped: subcommand failed.

build/core/ninja.mk:148: recipe for target 'ninja_wrapper' failed

make: *** [ninja_wrapper] Error 1

修複:

sudo apt-get install m4

d、

Communication error with Jack server (52). Try 'jack-diagnose'

修複:

out/host/linux-x86/bin/jack-admin kill-server 
out/host/linux-x86/bin/jack-admin start-server
           

這裡需要注意的是,當執行kill-server時,檢視jack伺服器是否已經成功停止。

啟動時,檢視啟動是否成功。如果啟動成功,可繼續編譯。通常如果機器配置不夠,再次執行會報問題e錯誤。

e、

Out of memory error (version 1.2-rc4 'Carnac' (298900 f95d7bdecfceb327f9d201a1348397ed8a843843 by [email protected])).

GC overhead limit exceeded.

修複:

這也是Jack伺服器編譯過程中會報的錯,修改啟動參數即可。

打開檔案prebuilts/sdk/tools/jack-admin

JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -Xmx4096m -cp $LAUNCHER_JAR $LAUNCHER_NAME"
           

搜尋JACK_SERVER_COMMAND關鍵字元串,在-cp參數前添加-Xmx4096m即可。

此時再按照d問題解決方案,首先kill-server,然後重新啟動start-server,并檢視啟動傳回日志中的參數是否有我們修改後的-Xm4096m。我在修改配置檔案過程中,重新開機後參數未生效,最後執行了make clobber指令然後重新編譯生效。

f、No command 'adb' found, did you mean:

修複:

沒有安裝adb,執行以下指令安裝即可:

sudo apt-get install android-tools-adb
           

如果下載下傳了sdk,也可以直接配置adb環境變量,參考連結:https://blog.csdn.net/u012554768/article/details/48344881

g、adb devices : no permissions(udev)或是fastboot devices:no permissions(udev)

後面跟了一長串udev,還有一個http連結,且使用sudo指令也是同樣的結果

修複:

這個主要是udev檔案的規則配置檔案問題

進入etc/udev/rules.d目錄,使用ls-al指令檢視目錄下檔案

這裡我的機器上是沒有任何檔案,不過這個目錄下的udev配置檔案優先級最高

是以在這裡建立51-android.rules

.将以下字元串複制到建立的.rules檔案中,這是一個比較齊全的規則配置

SUBSYSTEM=="usb", ATTR{idVender}=="0502", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0b05", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="413c", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0489", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="04c5", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="091e", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="18d1", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="109b", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0bb4", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="12d1", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="24e3", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="2116", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0482", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="17ef", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="1004", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="22b8", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0409", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="2080", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0955", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="2257", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="10a9", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="1d4d", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0471", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="04da", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="05c6", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="1f53", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="04e8", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="04dd", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="054c", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0fce", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="2340", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0930", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="19d2", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="1782", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="0a5c", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVender}=="22da", MODE="0666"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0666"
           

再依次執行以下指令。

sudo chmod a+rx /etc/udev/rules.d/51-android.rules
sudo service udev restart
           

最後重新插拔usb生效

h、fastboot < waiting for device >

檢視指令fastboot devices,這裡沒有udev錯誤,若有參考上一問題g解決方案。

若結果顯示no permission,使用which指令檢視fastboot路徑

which fastboot
           

通常這裡的路徑為源碼編譯目錄新生成的檔案。此時有兩種解決方案:

i)使用sudo apt-get install android-tools-fastboot 指令安裝fastboot工具,然後使用sudo 執行fastboot devices即可。

ii)進入which檢視fastboot路徑目錄,執行以下指令:

sudo chown root:root fastboot
sudo chmod +s fastboot
           

此時再運作fastboot device指令成功。

2、編譯android-4.4_r1版本

        在同一台機器上,編譯4.4版本。假設機器已經存在4.4_r1的源碼,且編譯過7.1.2_r18,此時的環境為openjdk8和make 4.1

1)要求

a、javajdk6

Ubuntu16.04編譯Android源碼系列一——7.1.2和4.4及踩坑一、前言二、預置環境三、編譯要求

在編譯7.1.2時查詢了對應版本的jdk要求,4.4要求的環境為javajdk6,而此時我們的電腦中環境為openjdk8,是以需要修改java環境。

點進官網連結:http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase6-419409.html,下載下傳電腦對應的jdk版本,我使用的版本如圖

Ubuntu16.04編譯Android源碼系列一——7.1.2和4.4及踩坑一、前言二、預置環境三、編譯要求

下載下傳完成後,選擇一個目錄建立檔案夾java,進入目錄,将下載下傳好的jdk複制到該目錄中,并執行指令bin檔案,此時會生成對應的java檔案夾,使用pwd檢視目前檔案夾路徑,假如路徑為xxx,java檔案夾目錄為jdk-6u45-linux-x64,執行以下指令設定環境變量:

export JAVA_HOME=/xxx/jdk-6u45-linux-x64;
export PATH=$JAVA_HOME/bin:$PATH;
           

然後使用java -version和javac -version指令檢視目前環境是否已經變為java 1.6

需要注意的是,使用這種方法生成的環境變量隻能在目前控制台生效,一旦關閉則失效。也可以将環境變量設定代碼加入配置檔案中,使其長期有效。我是因為之後編譯8.0源碼時需要使用openjdk1.8是以這麼設定。

b、make 3.82

android4.4版本較低,不支援make 4.1版本,是以需要降低make 版本。這裡我下載下傳的版本是make3.82,具體操作步驟可參考部落格:https://blog.csdn.net/qq_29224775/article/details/46595209

2)下載下傳驅動

7.1源碼編譯過程中,我直接下載下傳的鏡像檔案,是以編譯4.4_r1源碼過程中,選擇下載下傳驅動二進制檔案來直接編譯出vendor.img檔案。

檢視下載下傳源碼版本号連結:https://source.android.google.cn/setup/start/build-numbers

由以上連結可查,4.4_r1對應的細分版本為KRT16M,在驅動鏡像連結中下載下傳KRT16M對應的二進制檔案,二進制連結:https://developers.google.cn/android/drivers

Ubuntu16.04編譯Android源碼系列一——7.1.2和4.4及踩坑一、前言二、預置環境三、編譯要求

如圖所示,下載下傳Broadcom、LG、Qualcomm三個連結,複制到編譯路徑下,分别解壓得到三個.sh檔案,分别執行.sh檔案,每一個.sh檔案需要閱讀一些東西,然後最後會讓你确認是否接受,輸入I ACCEPT即可。執行完三個.sh檔案後,會看到源碼目錄下新增檔案夾vendor,并且vendor下包括了下載下傳檔案的三個同名檔案夾。

3)下載下傳需要的庫檔案

由于在編譯7.1.2的過程中,已經安裝了部分庫檔案,編譯4.4源碼時,隻需要再安裝以下三個庫檔案即可。

sudo apt-get install bison
sudo apt-get install lib32z1
sudo apt-get flex
           

4)編譯執行(具體可參考7.1.2編譯步驟)

a、執行. build/envsetup.sh初始化編譯環境

b、執行lunch指令選擇編譯目标版本(本次運作在nexus 5手機上,是以選擇hammerhead版本)

c、執行time make -j8開始編譯

5)刷機

編譯成功後,進入out/target/product/hammerhead目錄,依次執行以下指令即可。

//進入手機bootloader
adb reboot bootloader
 
//開始刷機
fastboot flash boot boot.img
 
fastboot flash system system.img
 
fastboot flash cache cache.img
 
fastboot flash userdata userdata.img
 
fastboot flash recovery recovery.img
//啟動
fastboot reboot
           

5)編譯4.4踩坑

a、

out/target/product/mx3/obj/GYP/shared_intermediates/content/jni/HashSet_jni.h:10:26: error: extra tokens at end of #ifndef directive [-Werror]

out/target/product/mx3/obj/GYP/shared_intermediates/content/jni/HashSet_jni.h:11:26: error: missing whitespace after the macro name [-Werror]

target thumb C++: content_content_common_gyp <= external/chromium_org/content/common/android/surface_texture_peer.cc

In file included from external/chromium_org/content/common/android/hash_set.cc:5:0:

out/target/product/mx3/obj/GYP/shared_intermediates/content/jni/HashSet_jni.h:24:20: error: expected initializer before '<' token

out/target/product/mx3/obj/GYP/shared_intermediates/content/jni/HashSet_jni.h:26:17: error: expected initializer before '<' token

out/target/product/mx3/obj/GYP/shared_intermediates/content/jni/HashSet_jni.h:29:22: error: expected '{' before '<' token

out/target/product/mx3/obj/GYP/shared_intermediates/content/jni/HashSet_jni.h:29:22: error: expected unqualified-id before '<' token

external/chromium_org/content/common/android/hash_set.cc:30:1: error: expected '}' at end of input

cc1plus: all warnings being treated as errors

make: *** [out/target/product/mx3/obj/STATIC_LIBRARIES/content_content_common_gyp_intermediates/content/common/android/hash_set.o] 錯誤 1

make: *** 正在等待未完成的任務....

修複:

這個錯誤是由于之前使用sudo alternatives --install /usr/bin/javajava /usrjava/jdk1.7.0_25/bin/java 500這種方式設定的java jdk和javac環境,但是沒有設定javap,是以出錯。

保險起見,使用前文所述直接設定環境變量的方式即可。如果出現此錯誤,修改環境變量後,需要執行make clobber并重新build編譯執行。

b、error while loading shared libraries: libz.so.1: cannot open shared object file:No such file or directory

提示缺少庫libz.so.1

修複:

首先安裝apt-file管理器

sudo apt-get install apt-file
           

更新apt-file的緩存

apt-file update
           

搜尋檔案依賴

apt-file search libz.so.1
           

這裡将會得到一個比對libz.so.1字元串的包清單

ib32z1: /usr/lib32/libz.so.1

lib32z1: /usr/lib32/libz.so.1.2.8

libx32z1: /usr/libx32/libz.so.1

libx32z1: /usr/libx32/libz.so.1.2.8

搜尋對應的庫進行安裝即可。

apt-get install lib32z1

c、之後還會遇到一些flex和bison檔案找不到問題,安裝對應的庫檔案即可。

sudo apt-get install bison
sudo apt-get install flex
           

以上就是本次編譯過程中所遇問題及解決方案,如果有什麼問題請指出。

參考連結:https://blog.csdn.net/fuchaosz/article/details/52473660

繼續閱讀