海王  

Android Build System

 

http://source.android.com/porting/build_system.html#top
    Android 是用一个客制化的编译系统来产生工具,二进制代码,文件系统(documentation)。本文档提供一个Android系统编译的简介以及简单的范例。

 

    android系统编译是基于一个较新版本的GNU Make(也许android使用的某些新特性都有可能没有在GNU Make的官方网站列出)。在编译之前,请通过执行 % make -v 来查看Make的版本号。如果版本号低于3.80,那么就需要更新你的Make版本。

 

Understanding the makefile

makefile 被用来编译指定的应用程序(application),makefile文件一般都会包含如下的几个元素:

1.Name: 编译的应用程序名称(LOCAL_MODULE V := <build_name>)

2.Local Variables: 使用CLEAR_VARS清除本地变量(include $(CLEAR_VARS))

3.Files: 应用程序的源码文件(LOCAL_SRC_FILES := main.c)

4.Tags: 按需给出tags定义(LOCAL_MODULE_TAGS := eng development)

5.Libraries: 定义应用程序将要连接的库(LOCAL_SHARED_LIBRARIES := cutils)

6.Template file:  包含一个make tools 下的模板文件来指定将应用编译成特定的目标(include $(BUILD_EXECUTABLE))

下面小段是一个典型的makefile举例(the following snippet illustrates a typical makefile).

代码
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := <buil_name>
LOCAL_SRC_FILES := main.c
LOCAL_MODULE_TAGS := eng development
LOCAL_SHARED_LIBRARIES := cutils
include $(BUILD_EXECUTABLE)
(HOST_)EXECUTABLE, (HOST_)JAVA_LIBRARY, (HOST_)PREBUILT, (HOST_)SHARED_LIBRARY,
  (HOST_)STATIC_LIBRARY, PACKAGE, JAVADOC, RAW_EXECUTABLE, RAW_STATIC_LIBRARY,
  COPY_HEADERS, KEY_CHAR_MAP

 

The snippet(片段) above includes artificial(人为修改) line breaks to maintain a print-friendly document.

 

 Layers

     编译层级架构(hierarchy)包括下表描述的几个抽象层。

     每个层都对应上面的一个元素(element),它们是一个一对多的关系。例如:一个芯片架构(arch)可以有多余一个板级架构(board)并且每一个板级架构(board)都可以有超于一个的设备架构(device)。你可以给每一个层定义一个元素(element)作为某一个层的特别元素(element),这样就免除了拷贝并简化了维护(eliminating copying and simplifying maintenance)。

 

Layer Example Description
Product myProduct, myProduct_eu, myProduct_eu_fr, j2, sdk The product layer defines a complete specification of a shipping product, defining which modules to build and how to configure them. You might offer a device in several different versions based on locale, for example, or on features such as a camera.(产品层定义了一个完整的特定的销售产品,定义了那些模块会被编译和怎样配置它们。你也许会基于本机的一些情况为设备定义出几种不同版本,如,摄像头特性)
Device myDevice, myDevice_eu, myDevice_eu_lite The device layer represents the physical layer of plastic on the device. For example, North American devices probably include QWERTY keyboards whereas devices sold in France probably include AZERTY keyboards. Peripherals typically connect to the device layer.(设备层描述了在设备上一些可变的物理硬件层。例如:北美设备也许包括QWERTY键盘,然而在法国售卖的设备包括AZERTY键盘。外围设备一般都被认为是与设备层相关)
Board sardine, trout, goldfish The board layer represents the bare schematics of a product. You may still connect peripherals to the board layer.(板级架构描述了一个产品的基本最小核心架构。也许在板子上仍旧还接有外设。)
Arch arm (arm5te) (arm6), x86, 68k The arch layer describes the processor running on your board.(架构层定义了在电路板上运行的处理器)

Building the Android Platform

    本段描述怎样编译默认的android版本。一旦当你能熟悉编译一般的版本,那么你就可以开始修改Anadroid编译成适合你自己目标设备的版本。

 

Device Code

    为编译一个普通版本的android,请使用build/envsetup.sh脚本设置环境变量(source build/envsetup.sh)。这个脚本包含了必要的变量和功能定义,描述如下:

 

% cd $TOP

% . build/envsetup.sh

# pick a configuration using choosecombo
% choosecombo

% make -j4 PRODUCT-generic-user

你也可以用eng 替换 user 编译成一个调试工程(you can also replace user with eng for a debug engineering build):

% make -j4 PRODUCT-generic-eng

这些变种编译(Build Variants)区别在于调试选项和包的安装(these build variants differ in terms of debug options and packages installed)。

 

Cleaning Up

 

    执行 % m clean 可以清除刚刚生成的二进制文件。同样可以执行 % m clobber 删除所有的二进制文件(the binaries of all combos)。% m clobber 相当于删除//out/目录的所有文件,这个目录也是生成文件存储的位置。

 

Speeding Up Rebuilds

    每一种编译组合将作为一个子目录存储在//out/目录下,这样就有可能在不同组合间快速的切换编译而不需要每次都编译整个源码。    

    但是,执行了清除命令,编译系统没有获取到变化的环境变量或者makefiles那么就需要重新编译整个源码。如果这种情况经常发生,那么你就有必要按照如下定义USE_CCACHE环境变量:

% export USE_CCACHE=1

这样就会强制编译系统使用编译器缓存工具(ccache:compiler cache),这个工具可以减少重新编译的代码。ccache二进制执行文件已经在//prebuilt/...目录下(如:prebuilt/linux-x86/ccache)而不需要再在系统中安装。

 

Troubleshooting

下面问题很有可能就是使用了过时的Java版本引起的。

 

代码
device Dex: core  UNEXPECTED TOP-LEVEL ERROR:
java.lang.NoSuchMethodError: method java.util.Arrays.hashCode with
signature ([Ljava.lang.Object;)I was not found.
  at com.google.util.FixedSizeList.hashCode(FixedSizeList.java:66)
  at com.google.rop.code.Rop.hashCode(Rop.java:245)
  at java.util.HashMap.hash(libgcj.so.7)
[...]

    dx 是一个java程序,有用的工具,最先是在Java version 1.5中使用。通过执行% java -version 命令来确认用来编译的Java版本。然后你也许会看到如下信息:

java version "1.5.0_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164)
Java HotSpot(TM) Client VM (build 1.5.0_07-87, mixed mode, sharing)

    如果你的Java 版本不小于1.5但还出现上面错误,那么请确认你已经完好的更新了你的PATH变量。

 

Building the Android Kernel

    本段描述怎样编译Android的默认内核。当你熟悉一般的编译后,那么你就可以开始为你的目标设备更改Android 驱动。为了编译基本的内核,切换到设备目录(/home/joe/android/device)为了建立相关变量请执行如下命令:

 

% . build/envsetup.sh
% partner_setup generic

    然后切换到kernel目录/home/joe/android/kernel

 

Checking Out a Branch

The default branch is always android. To check out a different branch, execute the following:

 

代码
% git checkout --track -b android-mydevice origin/android-mydevice
  
//Branch android-mydevice set up to track remote branch
% refs/remotes/origin/android-mydevice.
  
//Switched to a new branch "android-mydevice"

 

To simplify code management, give your local branch the same name as the remote branch it is tracking (as illustrated in the snippet above). Switch between branches by executing % git checkout <branchname>.

Verifying Location

Find out which branches exist (both locally and remotely) and which one is active (marked with an asterisk[星号]) by executing the following:

 

% git branch -a
  android
* android-mydevice
  origin/HEAD
  origin/android
  origin/android-mydevice
  origin/android-mychipset

 

To only see local branches, omit[忽略] the -a flag.

 

Building the Kernel

 

 

% make -j4

 

Build Variants

    当编译一个特定的产品,在最终编译版本中使用一些少量的可变参数是很有用的(it's often useful to have minor variations on what is ultimately the final release build)。下面都是目前被定义的一些编译变量:

 

 

eng This is the default flavor(原版). A plain(普通) make is the same as make eng.
  • Installs modules tagged with: eng, debug, user, and/or development.
  • Installs non-APK modules that have no tags specified.
  • Installs APKs according to the product definition files, in addition to tagged APKs.
  • ro.secure=0
  • ro.debuggable=1
  • ro.kernel.android.checkjni=1
  • adb is enabled by default.
user make user

This is the flavor intended to be the final release bits.

  • Installs modules tagged with user.
  • Installs non-APK modules that have no tags specified.
  • Installs APKs according to the product definition files; tags are ignored for APK modules.
  • ro.secure=1
  • ro.debuggable=0
  • adb is disabled by default.
userdebug make userdebug

The same as user, except:

  • Also installs modules tagged with debug.
  • ro.debuggable=1
  • adb is enabled by default.
 如果你编译了某种特殊(flavor)的版本,然后要编译其它特殊版本,你必须在两次执行make之间执行 make installclean来担保(guarantee)你不会使用前一个特殊版本安装的文件。make clean 同样可以满足要求(suffice),但是将会消耗更多的时间。

 

 

 

posted on 2011-02-19 11:42  海王  阅读(2036)  评论(0编辑  收藏  举报