zoukankan      html  css  js  c++  java
  • [转组第10天] | Android6.0.0_r1源码编译和POC程序的编译

    2018-05-23

    Android6.0.0_r1源码编译

    简要说明:android源码编译的四个流程:1.源码下载;2.构建编译环境;3.编译源码;4运行.下文也将按照该流程讲述。

    主机环境

    Ubuntu 16.04 LTS

    Android 6.0.0_r1

    Open JDK 7

    源码下载

    由于某墙的原因,这里我们采用国内的镜像源进行下载.
    目前,可用的镜像源一般是科大和清华的,具体使用差不多,这里我选择清华大学镜像进行说明.(参考:科大源,清华源)

    Google采用Repo管理Android源码,所以要先下载Repo工具.

    通过执行以下命令实现repo工具的下载和安装:

    1 mkdir ~/bin
    2 PATH=~/bin:$PATH
    3 curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
    4 chmod a+x ~/bin/repo

    建立源码文件夹 

    熟悉Git的同学都应该知道,我们需要为项目在本地创建对应的仓库.同样,这里为了方便对代码进行管理,我们为其创建一个文件夹.这里我在当前用户目录下创建了source文件夹,后面所有的下载的源码和编译出的产物也都放在这里,命令如下:

    1 mkdir source
    2 cd source


    初始化仓库
     

    我们将上面的source文件夹作为仓库,现在需要来初始化这个仓库了.通过执行初始化仓库命令可以获取AOSP项目master上最新的代码并初始化该仓库,命令如下:

    1 repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.0_r1

    (AOSP项目当前所有的分支列表参看:分支列表)-b参数表示指定获取某个特定的Android版本,这里我们指定android-6.0.0_r1.

     

    同步源码到本地

    初始化仓库之后,就可以开始正式同步代码到本地了,命令如下:

    1 repo sync

    将该文件保存在源码目录下,也就是我们的source目录,然后执行该脚本即可,安心的等待源码下载完成,预计花费3小时左右就可下载完成。由于网络原因,在使用repo sync同步代码的过程中会多次出错,这里我们采用一个shell脚本使其同步失败时自动重试:

    1 #!/bin/bash  
    2 echo "======start repo sync======"  
    3         repo sync  # 第一次下载android源代码
    4         while [ $? != 0 ]; do
    5         echo "======sync failed, re-sync again======"  
    6         sleep 2
    7         repo sync  #  如果出错,隔2秒后回继续调用repo sync下载android源代码
    8         done

    注意:由于 .repo 目录是隐藏目录,因此在下载完成之前你是不看到啥东西的。

     

    构建编译环境

    硬件要求:

    64位的操作系统只能编译2.3.x以上的版本,如果你想要编译2.3.x以下的,那么需要32位的操作系统.

    软件要求:

    操作系统,在AOSP开源中,主分支使用Ubuntu长期版本开发和测试的,因此也建议你使用Ubuntu进行编译,下面我们列出不同版本的的Ubuntu能够编译那些android版本:

    Android版本

    编译要求的Ubuntu最低版本

    Android 6.0至AOSP master

    Ubuntu 14.04

    Android 2.3.x至Android 5.x

    Ubuntu 12.04

    Android 1.5至Android 2.2.x

    Ubuntu 10.04

    JDK版本,

    Android版本

    编译要求的JDK版本

    AOSP的Android主线

    OpenJDK 8

    Android 5.x至android 6.0

    OpenJDK 7

    Android 2.3.x至Android 4.4.x

    Oracle JDK 6

    Android 1.5至Android 2.2.x

    Oracle JDK 5

    更具体的可以参看:Google源码编译要求

     

    安装JDK

    由于我们安装的是android6.0,我们需要采用OpenJDK7,而但是在Ubuntu 15.04及之后的版本的在线安装库中只支持openjdk8和openjdk9的安装,因此在Ubuntu16.04上安装OpenJDK7需要执行下面命令:

    1 sudo add-apt-repository ppa:openjdk-r/ppa
    2 sudo apt-get update
    3 sudo apt-get install openjdk-7-jdk

    配置OpenJDK,打开/etc/profile文件:

    1 sudo gedit /etc/profile

    在末尾追加下面代码:

    1 # jdk path config
    2 export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
    3 export JRE_HOME=${JAVA_HOME}/jre
    4 export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
    5 export PATH=${JAVA_HOME}/bin:$PATH

    修改/etc/profile文件重启生效:

    1 source /etc/profile

    检查OpenJDK配置是否正确:

    1 java -version

     配置成功如下图:

     

    安装环境依赖:(16.04环境依赖)

     1 sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib
     2 sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386
     3 sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386
     4 sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev
     5 sudo apt-get install git-core gnupg flex bison gperf build-essential
     6 sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib
     7 sudo apt-get install libc6-dev-i386
     8 sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev
     9 sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
    10 sudo apt-get install lib32z-dev ccache

     注意:不同Ubuntu所需要的依赖不同,一定要安装正确。

    修改源码:

    修改source/art/build/Android.common_build.mk文件,定位到75行,将下面代码:

    1 ifneq ($(WITHOUT_HOST_CLANG),true)

    改为:

    1 ifeq ($(WITHOUT_HOST_CLANG),false)

    修改的目的是把CLANG编译选项关闭。

    上面的工作完成后,基本的预准备工作就已经完成。下面是正式的编译步骤。

     

    初始化编译环境:

    (当前目录在包含Android源码的source目录下)

    确保上述过程完成后,接下来我们需要初始化编译环境

    1)在.bashrc文件末尾添加:export USER_CCACHE = 1

    1 echo export USER_CCACHE=1 >> ~/.bashrc

    2)为了提高编译效率,设置编译器高速缓存:

    1 prebuilts/misc/linux-x86/ccache/ccache -M 50G

    3)接着导入编译Android源码所欲要得环境变量和其他参数:

    1 source build/envsetup.h

     执行命令结果如下:

    不难发现该命令只是引入了其他执行脚本,至于这些脚本做什么,目前不在本文中细说.
    该命令执行成功后,我们会得到了一些有用的命令,比如最下面要用到的lunch命令.

     

    编译源码

    执行lunch命令

    1 lunch

     控制台会列出所有的编译目标,如下:

    这里选择aosp_arm-eng,表示生成arm架构的工程师版本,拥有最大权限(root),此外还附带了许多debug工具。

    这里输入1之后,会输出一些环境变量信息:

    开始编译

    通过make指令进行代码编译,该指令通过-j参数来设置参与编译的线程数量,以提高编译速度.比如这里我们设置8个线程同时编译:

    1 make -j8

    如果一切顺利的话,在几个小时之后,便可以编译完成.看到### make completed successfully (01:18:45(hh:mm:ss)) ###表示你编译成功了.需要注意的是,参与编译的线程并不是越多越好,通常是根据你机器cup的核心来确定:core*2,即当前cpu的核心的2倍.比如,我现在的笔记本是双核四线程的,因此根据公式,最快速的编译可以make -j8.
    (通过cat /proc/cpuinfo查看相关cpu信息)

     

    运行模拟器

    编译完成之后,就可以通过下面命令运行Android虚拟机了,命令如下:

    1 source build/envsetup.sh
    2 lunch(选择刚才你设置的目标版本,比如这里了我选择的是1)
    3 emulator

    不出意外,稍作等待,会看到运行界面:像lunch,emulator这些命令是属于envsetup.sh的,如果你没有离开刚编译完源码的终端,直接输入emulator也是可以的。

     

    Android源码的编译到此就完成了,我在编译过程中遇到了一些问题,多半是依赖没有装全,上网查16.04装Android6的文章,对着重新过一遍依赖就可以了。

    POC源码编译

    这里针对的是对Android源码有所依赖的程序的编译,因为要编译的POC程序大多要模拟客户端的底层与系统服务通信,需要调用一些客户端底层的函数,如下:

     

    如果在Android.mk里面配置头文件和库文件路径的话,会很麻烦,而且头文件还有嵌套,不太好配置,我也没找到配置库文件路径的参数,最终选择了源码编译环境中的mmm指令进行编译。

    下面是编译步骤:

    1)创建一个目录里面存放poc.cpp和Android.mk.

    Android.mk中的内容是:

    1 LOCAL_PATH  :=  $(call  my-dir)
    2 include  $(CLEAR_VARS)
    3 LOCAL_MODULE  :=  poc
    4 LOCAL_MODULE_TAGS  :=  optional
    5 LOCAL_SRC_FILES  :=  poc.cpp
    6 LOCAL_CFLAGS  +=  -march=armv4
    7 LOCAL_SHARED_LIBRARIES  :=  libbinder  libutils  libmedia  libstagefright_foundation
    8 include  $(BUILD_EXECUTABLE)

    这些大部分参数在官方NDK入门指南都有介绍,说两个:

    LOCAL_MODULE_TAGS :=optional,表示在任何版本(usr,debug,eng)下都编译。

    include  $(BUILD_EXECUTABLE),表示生成可执行文件。

    LOCAL_CFLAGS += -march=armv4,相当于在编译时指定了-march参数,gcc将不会再用兼容的指令去编译,而是根据指定的CPU结构,采用其特定的指令集去生成二进制代码。因此,当你确定所编译的程序只会在特定的环境中运行时,可以使用-march参数来指定CPU架构,这样编译器就可以根据你的CPU架构进行指令上的优化,而这个指定带来的后果就是,如果你将程序放在其他机器上运行,有可能得到Illegal instruction的运行错误。

    2)进入Android源码目录,初始化源码编译环境

    1 cd source(android源码目录)
    2 source build/envsetup.sh
    3 lunch 1

    mmm属于envsetup.sh的指令,作用是编译指定目录下的所有模块。

    3)利用mmm进行编译

    1 mmm AndroidWP/jni(poc.cpp目录)

     使用mmm的好处是,它会自动寻找头文件和库文件路径,把要编译的模块作为android的一个内部模块进行编译,输出到out里。所以只需要在Android.mk中指定共享库的名字就可以了。

    注意:在使用mmm编译的前几次,它会默认执行make clean操作,会把你之前编译安装的android源码的输出全部remove,目前我就是只能再重新编译一遍android源码,不过这就很快了,更多的是copy和install的操作,不要惊慌。

    具体的mmm指令细节没有深究,有兴趣可以上网看源码分析。

    编译完之后,利用adb把程序push到android机上,运行即可。

     参考:

    https://blog.csdn.net/dd864140130/article/details/51718187

    https://blog.csdn.net/fuchaosz/article/details/51487585

  • 相关阅读:
    envoy部分二: envoy的配置组件
    envoy部分一:enovy基础
    envoy部分四:envoy的静态配置
    envoy部分七:envoy的http流量管理基础
    envoy部分六:envoy的集群管理
    十七、Kubernetes的网络管理模型
    SQL 日期时间函数
    JSON 和 JavaScript eval
    Ajax 读取.ashx 返回404
    Repeat 数据为空时的处理
  • 原文地址:https://www.cnblogs.com/nww-570/p/9080136.html
Copyright © 2011-2022 走看看