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连接手机进行调试过程中遇到的所有问题,希望能对大家有所帮助。

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