深入浅出 - Android系统移植与平台开发(十)- Android编译系统与定制Android平台系统(瘋耔修改篇二)

第四章、Android编译系统与定制Android平台系统

4.1Android编译系统

Android的源码由几十万个文件构成,这些文件之间有的相互依赖,有的又相互独立,它们按功能或类型又被放到不同目录下,对于这个大的一个工程,Android通过自己的编译系统完成编译过程。

4.1.1 Android编译系统介绍

Android和Linux一样,他们的编译系统都是通过Makefile工具来组织编译源码的。Makefile工具用来解释和执行Makefile文件,在Makefile文件里定义好工程源码的编译规则,通过make命令即可以完成对整个工程的自动编译。因此分析makefile文件是理解编译系统的关键。

在Android中,下面几个主要的makefile文件构成了Android编译系统。

图x-x Android编译系统组成

①   Makefile:编译系统的入口Makefile文件,它只有一行代码,包含build/core/main.mk

②   build/core/main.mk:主要Makefile,定义了Android编译系统的主线

③   build/core/config.mk:根据用户输入的编译选项导出配置变量,影响编译目标

④   build/core/envsetup.mk:定义大量全局变量,用户编译配置

⑤   build/core/product_config.mk:根据用户选择的目标产品,定义编译结果输出目录

⑥   device/*/$(TARGET_DEVICE)/BoardConfig.mk:根据用户选择的目标产品找到对应的设备TARGET_DEVICE,加载设备的板级配置

⑦   build/core/definitions.mk:定义编译过程中用到的大量变量和宏,是编译系统的函数库

⑧   MODULES_DIR/Android.mk :每个模块的规则定义文件,它出现在每个要编译的目录下,如图x-x所示,我们可以自己向Android系统中添加自己的模块,来达到定制系统的目的。

图x-x 模块中的Android.mk文件

⑨   build/core/Makefile:Android编译目标规则定义文件,最终编译结果在该文件中定义,如system.img、ramdisk.img、boot.img、userdata.img等

4.1.2 Android.mk文件

在Android源码中,大量的源码按照功能通过目录来分类,同一功能的代码通常被编译成一个目标文件,目标文件不仅仅包含可执行C/C++应用程序,还包含动态库、静态库、Java类库、Android应用程序等,在Android编译系统中,每个被编译的目标文件被称为一个模块(module),在每个模块的源码目录中必须创建一个Android.mk文件作为编译规则,这些Android.mk文件在编译时被编译系统中的findleaves.py脚本包含进去。

@build/core/main.mk

489 subdir_makefiles := \

490    $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git$(subdirs) Android.mk)

491

492 include $(subdir_makefiles)

注:findleaves.py由Python语言编译的脚本,Python是一种执行效率比较高的面向对象的脚本,上述脚本意思是返回subdirs目录下的Android.mk文件,但是会跳过out、.reop、.git目录。

通常编译一个模块时编译器需要知道以下内容:

Ø 编译什么文件?(指定源码目录和源码文件)

Ø 编译器需要哪些编译参数?

Ø 编译时需要哪些库或头文件?

Ø 如何编译?(编译成动态库、静态库、二进制程序、Android应用还是Java库?)

Ø 编译目标

Android.mk的语法不同于Makefile,Android.mk语法更简洁,用户只需在Android.mk中定义出一些编译变量,Android的编译系统会根据Android.mk文件中变量的值进行编译。

比如Zygote进程app_process模块中的Android.mk如下面代码所示:

@ frameworks/base/cmds/app_process/Android.mk

1LOCAL_PATH:= $(call my-dir)              #指定源码目录

2include $(CLEAR_VARS)                     #包含清除编译变量的mk文件,防止影响本次编译

3

4LOCAL_SRC_FILES:= \                      #指定被编译源码

5     app_main.cpp

6

7LOCAL_SHARED_LIBRARIES := \               #指定编译Zygote时用到的其它动态库

8     libcutils \

9     libutils \

10     libbinder \

11     libandroid_runtime

12

13LOCAL_MODULE:= app_process                #指定被编译模块的名字

14

15include $(BUILD_EXECUTABLE)                  #指定编译方式,编译成可执行程序

再比如Camera应用程序中的Android.mk:

@ packages/apps/Camera/Android.mk

1LOCAL_PATH:= $(call my-dir)                        #指定源码目录

2include $(CLEAR_VARS)                              #包含清除编译变量的mk文件,防止影响本次编译

3

4LOCAL_MODULE_TAGS := optional                      #指定应用程序标签

5

6LOCAL_SRC_FILES := $(call all-java-files-under, src)      #指定被编译源码

7

8LOCAL_PACKAGE_NAME := Camera                   #指定Android应用程序名

9LOCAL_SDK_VERSION := current                        #指定该应用程序依赖的SDK版本

10

11LOCAL_PROGUARD_FLAG_FILES := proguard.flags    #指定混淆编译配置文件

12

13include $(BUILD_PACKAGE)                        #指定模块编译方式,这儿编译成Android应用程序

14

15 # Usethe following include to make our test apk.

16include $(call all-makefiles-under,$(LOCAL_PATH))        # 包含当前目录下子目录中的Android.mk文件,向下编译

通过上面两个例子可以看出来,Android.mk文件结构很简单,每个模块的Android.mk文件必须完成以下操作:

Ø 指定当前模块的目录

通过调用$(call my-dir)命令包(一些Makefile的集合),来获得当前模块目录。

Ø 清除所有的LOCAL_XX变量

通过include命令包含clear_vars.mk文件来清除所有的LOCAL_XX变量,防止影响本次编译结果,clear_vars.mk文件由变量CLEAR_VARS来定义

Ø 指定源码文件

通过LOCAL_SRC_FILES变量指定源码文件,对于C/C++文件,要将它们全部列出来赋值给LOCAL_SRC_FILES(见上面程序代码),对于Java源码,可以通过调用命令包$(callall-java-files-under, src)来实现,它会在src目录下查找所有的Java文件,将其罗列出来。

Ø 指定编译细节

在编译时可能需要修改编译器参数、需要链接其它的库、需要其它路径下的头文件等编译细节。

Ø 指定目标模块名

如果是C/C++库、可执行程序或Java类库,通过LOCAL_MODULE指定最终编译出来的模块名,如果是Android应用程序,通过LOCAL_PACKAGE_NAME变量来指定。

Ø 指定目标模块类型

模块最终都要进行编译,通过include 命令包含一些预定义好的变量来指定模块最终的类型,这些变量分别对应一个makefile文件,包含了模块类型的编译过程。主要的预定义编译变量如下:


编译变量


功能


BUILD_SHARED_LIBRARY


将模块编译成共享库


BUILD_STATIC_LIBRARY


将模块编译成静态库


BUILD_EXECUTABLE


将模块编译成可执行文件


BUILD_JAVA_LIBRARY


将模块编译成Java类库


BUILD_PACKAGE


将模块编译成Android应用程序包

注:上述编译变量的定义在build/core/definitions.mk中。

在Android.mk中,主要编译变量如下表所示:


编译变量


功能


LOCAL_PATH


指定编译路径


LOCAL_MODULE


指定编译模块名


LOCAL_SRC_FILES


指定编译源码列表


LOCAL_SHARED_LIBRARIES


指定使用的C/C++共享库列表


LOCAL_STATIC_LIBRARIES


指定使用的C/C++静态库列表


LOCAL_STATIC_JAVA_LIBRARIES


指定使用的Java库列表


LOCAL_CFLAGS


指定编译器参数


LOCAL_C_INCLUDES


指定C/C++头文件路径


LOCAL_PACKAGE_NAME


指定Android应用程序名


LOCAL_CERTIFICATE


指定签名认证


LOCAL_JAVA_LIBRARIES


指定使用的Java库列表


LOCAL_SDK_VERSION


指定编译Android应用程序时的SDK版本

注:其它的编译变量见附录。

4.1.3实验:编译HelloWorld应用程序

【实验内容】

在Ubuntu系统中使用eclipse开发环境编写简单的HelloWorld应用程序,然后使用Android编译系统进行编译,最终将HelloWorld应用程序作为系统应用集成到Android系统中。

【实验目的】

通过实验,学员掌握在Android源码的编译系统中编译Android应用程序、库、可执行程序,了解Android系统应用程序的定制过程,最终在Android模拟器中,运行自己通过编译系统编译的Android应用程序。

【实验平台】

拥有Android源码的Ubuntu操作系统(可以在Windows系统中虚拟Ubuntu系统)。

【实验步骤】

1.      打开eclipse开发环境,创建一个Android应用程序:HelloWorld:

$ cd ~/android/eclipse

$./eclipse &

2.      将新创建的HelloWorld工程拷贝到源码目录中的packages/apps目录下:

$ cp -rf HelloWorld/~/android/android_source/packages/apps

在HelloWorld工程目录下删除由eclipse开发环境自动生成的文件和目录,仅保留如图x-x所示工程目录结构:

3.      编译HelloWorld工程的Android.mk文件,我们可以仿照Android里自带的应用程序的Android.mk文件,例如Camera工程中的Android.mk文件:

将Camera工程中的Android.mk文件拷贝到HelloWorld工程中:

$ cp  ../Camera/Android.mk./

修改Android.mk文件,删除没必要的编译变量:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := $(call all-java-files-under,src)

LOCAL_PACKAGE_NAME := HelloWorld

LOCAL_SDK_VERSION := current

include $(BUILD_PACKAGE)

4.      编译HelloWorld工程:

Ø 切换到Android源码目录下:

$ cd ~/android/android_source/

Ø 加载编译函数:

$ source build/envsetup.sh

Ø 选择编译目标项:

$ lunch generic-eng

Ø 通过mmm命令编译HelloWorld工程:

$ mmm packages/apps/HelloWorld/

Ø 编译生成模拟器映像system.img:

$ make snod

注:我们也可以直接通过make命令来编译HelloWorld工程并生成system.img映像文件,但是这种方式耗时比较长,所以我们使用上面的编译方式,能节省实验时间,关于Android源码编译的细节,请查看2.3.2编译Android章节。

5.      启动模拟器,查看HelloWorld应用程序运行效果:

$ ./run_emulator.sh

注:run_emulator.sh是快速运行模拟器的脚本,详细说明请查看2.5定制Android模拟器章节。

时间: 2024-08-07 01:41:28

深入浅出 - Android系统移植与平台开发(十)- Android编译系统与定制Android平台系统(瘋耔修改篇二)的相关文章

第一章 Android系统移植与驱动开发概述 心得体会

第一章 Android系统移植与驱动开发概述 心得体会 通过学习Android深度探索(卷1)HAL与驱动开发的第一章Android系统移植与驱动开发,我对android驱动开发与移植概念有了一个整体且系统的把握.在本章中我主要学到了一下的知识 1.Android的系统架构分为Linux内核.C/C++代码库.Android SDK API.应用程序四层. 其中重点讲解第一层 Linux 内核.这一层主要包括Linux的驱动程序以及内存管理.进程管理.电源管理等程序. 2. Android移植可

第一章 Android系统移植与驱动开发概述

本书第一章首先简单概要地介绍了关于Android系统移植和驱动开发的相关内容. 所谓“移植”是指为特定的自己的设备,如手机定制Android的过程.自己开发一些程序(移植)装载在设备上,使得Android系统可以识别设备中的蓝牙,WiFi等,这样就可以使用这些功能了.这些程序大多是支持各种硬件设备的Linux驱动程序. 这一章中介绍了许多在进行Android系统移植和驱动开发前要了解的概念以及要做的准备.接下来主要说的是在Android系统移植过程中的主要工作. Android移植分为两部分:应

Android深度探索(卷1)HAL与驱动开发 第一章 Android系统移植与驱动开发概述 读书笔记

Android深度探索(卷1)HAL与驱动开发 第一章 Android系统移植与驱动开发概述 读书笔记 本章是 Android系统移植与驱动开发概述性的具体讲解.首先,Android被分为了四层架构.在最底层的是Linux内核 .然后分别是C/C++代码库.Android SDK A和应用程序.而Android的移植又分为系统移植和应用移植.系统移植要实现Android操作系统在其他硬件平台上运行起来,其中的关键是Linux的内核.内核必须要完成对平台上运行的各个硬件的识别.所以这就需要Linu

Android系统移植与驱动开发概述读书心得

第一章是Android系统移植与驱动开发概述,包含了Android系统架构.Android系统移植的主要工作.查看Linux内核版本.Linux内核版本号的定义规则.如何学习Linux驱动开发以及Linux设备驱动等六方面内容 Android系统架构分为四层,分别是Linux内核.C/C++代码库.Android SDK API和应用程序.Linux内核这一层主要包括Linux的驱动程序以及内存管理.进程管理.电源管理等程序. Android移植可分为两部分:应用移植和系统移植.应用移植是指将应

《Android深度探索卷一》第一章Android系统移植与驱动开发概述。

<Android深度探索>第一章讲的是Android系统移植与驱动开发概述.这一章节将对Android以及Linux驱动做一个总体的介绍. Android是一个非常优秀的的嵌入式操作系统.经过几年的发展和演进,Android已经形成了非常完善的系统架构.Android的系统架构分为四层,如下图 Android移植可分为两部分:应用移植和系统移植. Android系统移植是指让Android操作系统在某一个特定硬件平台上运行.使一个操作系统在特定硬件平台上运行的一个首要条件就是该操作系统支持硬件

Android系统移植与驱动开发概述 第一章

Android系统移植与驱动开发概述 1. Android的系统架构分为Linux内核.C/C++代码库.Android SDK API.应用程序四层. 2. Android移植可分为应用移植和系统移植.应用移植是指将应用程序移植到特定的硬件平台.系统移植指的是让Android操作系统在某一特定硬件平台上运行(首要条件是该操作系统支持硬件平台的CPU架构).系统移植的主要任务是移植Linux驱动和HAL(Hardware Abstraction Layer:硬件抽象层,位于应用程序与驱动之间).

第一章 Android系统移植与驱动开发概述 心得笔记

1.想要在自己的设备上运行Android,必须为自己的设备开发特定软件,这个为特定设备定制Android的过程被称为“移植”. 2.Android的系统构架分为:最底层Linux内核,和其他Linux系统的差异很小:再上一层是C/C++代码库:再上一层是Android SDK API,这一层是用java编写的Library:最上层是应用程序,这一层所有用户都要接触到,所有的Android应用程序. 3.Android移植分为应用移植和系统移植,主要工作是移植Linux驱动和移植HAL(硬件抽象层

概述 Android系统移植与驱动开发

第一章主要概述绍了Android系统移植与驱动开发和我们之前课上的内容大同小异,Android的系统架构分为四层:Linux内核(Android使用Linux2.系列作为内核).C/C++代码库.Android SDK API(JAVA编写的Library).应用程序. 而Android移植分为系统移植 和 应用移植,在移植中,Android在不同的cpu架构之间 不需要 做过多的改动(有时仍需要一些调整),也是为了可以让Android支持不同的硬件平台,当然我们还需要进行Linux驱动移植.A

学习Android系统移植与驱动开发的心得1

首先,学习Android系统移植与驱动开发,我们需要了解两个概念.什么是“移植”?由于Android原生的代码支持的设备并不多,因此我们想要在自己的设备上完美运行Android,就需要另外开发一些程序,使得Android可以识别相应设备中的各种硬件,这个过程被称为“移植”.在这个移植的过程中,我们必需要了解另外一个知识,就是“驱动开发”(Android是基于Linux内核的).到底什么是“Linux驱动”呢?作为初学者,我们只需要知道任何的Linux驱动都有一个加载函数和一个卸载函数即可,它们分