Ubuntu 18.04 編譯安卓系統源碼 及 adb連接手機遇到的問題詳解

轉載請註明出處: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連接手機進行調試過程中遇到的所有問題,希望能對大家有所幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章