轉載請註明出處:https://blog.csdn.net/turtlejj/article/details/89328174,謝謝~
最近在自己的電腦上重裝了系統,把Ubuntu 16.04升級成了Ubuntu 18.04,不得不說,性能真的提升了好多(至少心理上感覺提升了╮(╯▽╰)╭)。
但在升級之後,編譯安卓系統源碼的過程中卻遇到了各種各樣16.04上沒有遇到過的問題。因此在這裏把解決的過程記錄一下,既算是給自己做一個筆記,同時希望能讓其他遇到這些問題的朋友少走一些彎路。
關於Ubuntu如何下載Android源碼,網上有很多文章在寫,大家可以自行百度,我這裏就不多說了。我們只關注編譯安卓源碼及adb連接手機兩方面的問題解決方案。
如果有同學希望瞭解如何使用Android Studio導入安卓系統源碼,並進行單步調試的話,也可以參考我的另外兩篇文章。
《使用Android Studio導入Android系統源碼》
《使用Android Studio對Android系統源碼進行單步調試》
好,廢話不多說,下面我們就開始吧~
一、編譯前的準備工作
1. 運行以下命令安裝編譯所需的工具
sudo apt-get install git-core ccache automake lzop bison gperf build-essential zip curl zlib1g-dev zlib1g-dev:i386 g++-multilib python-networkx libxml2-utils bzip2 libbz2-dev \
libbz2-1.0 libghc-bzlib-dev squashfs-tools pngcrush schedtool dpkg-dev liblz4-tool make optipng maven
2. 安裝openjdk8
順序執行以下兩條命令安裝openjdk8
sudo apt-get update
sudo apt-get install openjdk-8-jdk
我的Ubuntu 18.04自帶的java版本是openjdk11,因此,在安裝完openjdk8以後,需要手動做以下切換:
sudo update-alternatives --config java
有 2 個候選項可用於替換 java (提供 /usr/bin/java)。
選擇 路徑 優先級 狀態
------------------------------------------------------------
* 0 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1101 自動模式
1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1101 手動模式
2 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 手動模式
要維持當前值[*]請按<回車鍵>,或者鍵入選擇的編號:2 (回車)
javac的版本可能也需要做一下切換(我的電腦上不需要):
sudo update-alternatives --config javac
鏈接組 javac (提供 /usr/bin/javac)中只有一個候選項:/usr/lib/jvm/java-8-openjdk-amd64/bin/javac
無需配置。
二、開始編譯
關於編譯的方法,我們此處以Android 8.0爲例。
在編譯的過程中,需要執行以下三條命令:
1. "source build/envsetup.sh" (source可以用 . 代替,即". build/envsetup.sh")
2. "lunch",並選擇要編譯的項目(或在lunch命令後鍵入空格,並直接連接編號,即"lunch 編號")
3. 全編 "make -j4" (這裏的 -j4 表示用4線程來編譯,可以不加)
或模塊編譯 "make framework -j4"(其中framework爲模塊名,後面我們詳細講解如何查找要編譯的模塊名)
下面進行分佈講解:
1. 進入系統源碼的根目錄(即可以看到frameworks、kernel等等文件夾的那一級目錄),執行". build/envsetup.sh"命令:
xxxxxx@xxxxxx-Ubuntu:~/code/android$ . build/envsetup.sh
including device/generic/mini-emulator-arm64/vendorsetup.sh
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/qcom/common/vendorsetup.sh
including vendor/qcom/proprietary/common/vendorsetup.sh
including sdk/bash_completion/adb.bash
2. 而後,繼續執行"lunch"命令,並選擇你想要編譯的那個項目,這裏我選了2,即編譯 aosp_arm64-eng:
xxxxxx@xxxxxx-Ubuntu:~/code/android$ lunch
You're building on Linux
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
Which would you like? [aosp_arm-eng] 2
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=8.1.0
TARGET_PRODUCT=aosp
TARGET_BUILD_VARIANT=arm64-eng
TARGET_BUILD_TYPE=release
TARGET_PLATFORM_VERSION=OPM1
TARGET_BUILD_APPS=
TARGET_ARCH=arm64
TARGET_ARCH_VARIANT=armv8-a
TARGET_CPU_VARIANT=kryo300
TARGET_2ND_ARCH=arm
TARGET_2ND_ARCH_VARIANT=armv7-a-neon
TARGET_2ND_CPU_VARIANT=cortex-a9
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-4.15.0-38-generic-x86_64-with-Ubuntu-18.04-bionic
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=OPM1.171019.026
OUT_DIR=out
AUX_OS_VARIANT_LIST=
============================================
3. 前面兩步是對編譯環境進行配置,接下來執行"make -j4",並等待,這個過程可能會很漫長,取決於電腦的性能,幾十分鐘至幾小時不等,該過程中屏幕會輸出很多log,這裏只貼出了最後一句:
xxxxxx@xxxxxx-Ubuntu:~/code/android$ make -j4
......
#### build completed successfully (32:57 (mm:ss)) ####
4. 那麼對於模塊編譯,我們可以用以下方法找到模塊名
(1) 編譯產物作爲依賴的模塊(一般編譯產物爲.jar或.so文件)
比如,我修改了“frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaCall.java”這個文件,那麼我們就可以從本級目錄,一級一級向上找,看在哪級目錄中可以找到Android.mk文件。
最終,我們發現,在"frameworks/opt/telephony/"目錄下,找到了Android.mk文件。打開該文件,我們可以搜索“LOCAL_MODULE”這個變量的定義,其後面的“telephony-common”,即爲該模塊的名字。
因此,想編譯該模塊,要使用的命令即爲"make telephony-common -j4"。
(2) 編譯產物是應用程序的模塊(編譯產物爲.apk文件)
比如,我修改了“packages/apps/Dialer/java/com/android/dialer/calling/ui/NewCallLogFragment.java”這個文件,同理,我們從本級目錄向上找,可以發現,在"packages/apps/Dialer/"目錄下,存在Android.mk文件。打開該文件,我們可以搜索“LOCAL_PACKAGE_NAME”這個變量的定義,其後面的“Dialer”,即爲該模塊的名字。
因此,想編譯該模塊,要使用的命令即爲"make Dialer -j4"。
三、編譯錯誤的解決
順利的話,在執行 "make -j4" 或 "make moduleName -j4" 後就可以等待編譯完成了。但Ubuntu 18.04在編譯的過程中會遇到各種各樣的編譯錯誤。下面我就將我所遇到的問題及解決方法共享給大家,以便大家在遇到以下問題時,能夠更方便的解決問題,而不用像我當時一樣再去搜索並嘗試網上的各種方案及解決辦法。
1. "loadlocale.c"文件報錯
flex-2.5.39: loadlocale.c:130: _nl_intern_locale_data: Assertioncnt < (sizeof (_nl_value_type_LC_TIME) / sizeof (_nl_value_type_LC_TIME[0]))' failed.
解決方法如下:
1. 打開.bashrc文件
xxxxxx@xxxxxx-Ubuntu:~/code/android$ gedit ~/.bashrc &
2. 在文件最下面添加以下內容並保存
export LC_ALL=C
3. 執行以下命令使修改生效
xxxxxx@xxxxxx-Ubuntu:~/code/android$ source ~/.bashrc
2. 如果編譯了"bootable/bootloader/edk2"目錄下的代碼,可能會遇到以下問題
......
g++ -I Pccts/h -I .. -I ../Include/Common -I ../Include/ -I ../Include/IndustryStandard -I ../Common/ -I .. -I . -I ../Include/X64/ -c -o VfrUtilityLib.o VfrUtilityLib.cpp
VfrUtilityLib.cpp: In member function ‘CHAR8* CVfrStringDB::GetVarStoreNameFormStringId(EFI_STRING_ID)’:
VfrUtilityLib.cpp:3288:26: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
if (mStringFileName == '\0' ) {
^~~~
<內置>: recipe for target 'VfrUtilityLib.o' failed
make[3]: *** [VfrUtilityLib.o] Error 1
......
解決方法如下:
在"bootable/bootloader/edk2/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp"文件中
搜索"mStringFileName == '\0'",將其修改爲"mStringFileName == NULL",如下:
@@@ -3284,7 -3284,7 +3284,7 @@@ CVfrStringDB::GetVarStoreNameFormString
UINT8 BlockType;
EFI_HII_STRING_PACKAGE_HDR *PkgHeader;
-- if (mStringFileName == '\0' ) {
++ if (mStringFileName == NULL ) {
return NULL;
}
3. 在編譯secimage時,可能會報以下錯誤
......
FAILED: gensecimage_target
......
install_base_dir=out/target/product/FJDEV061 > out/target/product/FJDEV061/secimage.log 2>&1 ) && (echo Completed secimage signed appsbl \\(logs in out/target/product/arm64-eng/secimage.log\\) )"
......
ninja: build stopped: subcommand failed.
11:38:32 ninja failed with: exit status 1
該問題是由於Ubuntu 18.04自帶的openssl版本過高所導致的,解決方法如下:
這裏建議不要刪除Ubuntu18.04自帶的openssl,而是更換低版本的openssl
我參考了這篇帖子中替換openssl版本的步驟,只不過他裝的是1.1.0e,而我安裝的1.0.1f (Ubuntu 16.04自帶的是1.0.1f版本的openssl,可以確保其可以另編譯通過)。
PS: (1) 關於openssl的1.0.1f版本,可以從這裏下載到
(2) 在上面提到的帖子中,如果在運行其中的命令時,發生權限不足的問題,可以在命令前加上"sudo"
(3) 在執行上面提到的帖子中"sudo make install"的過程中,會報如下錯誤:
POD document had syntax errors at /usr/bin/pod2man line 71.
可以參考這篇帖子裏的解決方法。
4. 如果源代碼在"repo sync"後移動了位置,或是源代碼是從別的地方拷貝而來的,可能會報以下錯誤
makefile:68: recipe for target 'ABL_FV_IMG' failed
make: *** [ABL_FV_IMG] Error 127
make: Leaving directory '/home/xxxxxx/code/android/bootable/bootloader/edk2'
問題分析:
(1) 進入目錄 bootable/bootloader/edk2
(2) 執行 "./edksetup.sh BashTools" 命令
觀察打印可以看到如下信息:
WORKSPACE:
/home/xxxxxx/code/android/bootable/bootloader/edk2
EDK_TOOLS_PATH:
/home/xxxxxx/code/myDisk/android/bootable/bootloader/edk2/BaseTools
CONF_PATH:
/home/xxxxxx/code/android/bootable/bootloader/edk2/Conf
代碼在被移動後,EDK_TOOLS_PATH所保存的目錄依舊是代碼下載時的路徑,與WORKSPACE和CONF_PATH不一致 (其中EDK_TOOLS_PATH中多了一級myDisk目錄)。
此時執行"which build“ 命令,無任何打印。
解決方法如下:
1) 進入 "bootable/bootloader/edk2/" 目錄下
2) 刪除 "Conf/BuildEnv.sh" 文件
3) 執行 "unset EDK_TOOLS_PATH" 命令
4) 執行 ". ./edksetup.sh BaseTools" 命令 (兩個點之間有空格)
5) 最後使用 which build 命令查看,目錄正確
/home/xxxxxx/code/android/bootable/bootloader/edk2/BaseTools/BinWrappers/PosixLike/build
三、adb連接手機問題
Ubuntu 18.04在連接手機時可能會遇到以下問題:
xxxxxx@xxxxxx-Ubuntu:~$ adb devices
List of devices attached
1234abcd device
xxxxxx@xxxxxx-Ubuntu:~$ adb shell
error: insufficient permissions for device
解決方法如下:
(1) 在/etc/udev/rules.d/目錄下新建一個叫做"51-android.rules"的文件
(2) 執行 "sudo vim 51-android.rules" 並在文件中添加以下內容
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0666"
保存
PS: 這裏就默認大家會使用vim了,如果不會,也可以執行"sudo gedit 51-android.rules",並添加上述內容,用圖形化界面來解決問題
(3) 重啓系統即可
以上就是我在安裝了Ubuntu 18.04後,在編譯安卓源碼及adb連接手機進行調試過程中遇到的所有問題,希望能對大家有所幫助。