Android编译系统如何添加厂商自己软件定义网络 pdf产品

Android 编译系统(一):Android.mk的学习
++++++++++++++++++++++++++++++++++++++++++
本文系本站原创,欢迎转载! 转载请注明出处:
++++++++++++++++++++++++++++++++++++++++++
Android的优势就在于其开源,手机和平板生产商可以根据自己的硬件进行个性定制自己的手机产品,如小米,LePhone,M9等,因此,在我们在对Android的源码进行定制的时候,很有必要了解下,Android的编译过程。
如果你从来没有做过Android代码的编译,那么最官方的编译过程就是查看Android的官方网站:
但是,这儿只是告诉你了如何去编译一个通用的系统,并没有详细告诉你细节,我们跟着编译过程来了解下。
+--------------------------------------------------------------------------------------------------------------------+
本文使用Android版本为2.1,采用开发板为华清远见研发的FS_S5PC100 A8开发板。
+--------------------------------------------------------------------------------------------------------------------+
按照google给出的编译步骤如下:
1& source build/envsetup.sh:加载命令
2& lunch:选择平台编译选项
3& make:执行编译
我们按照编译步骤来分析编译过程的细节,最终添加自己的平台产品的编译选项。
1. source build/envsetup.sh
这个命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去,我们来分析下它。
envsetup.sh里的主要命令如下:
function help()                  # 显示帮助信息
function get_abs_build_var()           # 获取绝对变量
function get_build_var()             # 获取绝对变量
function check_product()             # 检查product
function check_variant()             # 检查变量
function setpaths()                # 设置文件路径
function printconfig()              # 打印配置
function set_stuff_for_environment()      
# 设置环境变量
function set_sequence_number()        
# 设置序号
function settitle()                # 设置标题
function choosetype()               # 设置type
function chooseproduct()            
# 设置product
function choosevariant()            
# 设置variant
function tapas()                
# 功能同choosecombo
function choosecombo()             
# 设置编译参数
function add_lunch_combo()           
# 添加lunch项目
function print_lunch_menu()            # 打印lunch列表
function lunch()                 # 配置lunch
function m()                   # make from top
function findmakefile()              # 查找makefile
function mm()                   # make from current directory
function mmm()                 
# make the supplied directories
function croot()                 # 回到根目录
function cproj()
function pid()
function systemstack()
function gdbclient()
function jgrep()                 # 查找java文件
function cgrep()                
# 查找c/cpp文件
function resgrep()
function tracedmdump()
function runhat()
function getbugreports()
function startviewserver()
function stopviewserver()
function isviewserverstarted()
function smoketest()
function runtest()
function godir ()                 # 跳到指定目录 405
# add_lunch_combo函数被多次调用,就是它来添加Android编译选项
# Clear this variable.
It will be built up again when the vendorsetup.sh
406 # files are included at the end of this file. # 清空LUNCH_MENU_CHOICES变量,用来保存编译选项
407 unset LUNCH_MENU_CHOICES
408 function add_lunch_combo()
local new_combo=$1
# 获得add_lunch_combo被调用时的参数
# 依次遍历LUNCH_MENU_CHOICES里的值,其实该函数第一次调用时,该值为空
for c in ${LUNCH_MENU_CHOICES[@]} ; do
if [ "$new_combo" = "$c" ] ; then
# 如果参数里的值已经存在于LUNCH_MENU_CHOICES变量里,则返回 414
# 如果参数的值不存在,则添加到LUNCH_MENU_CHOICES变量里
LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
# 这是系统自动增加了一个默认的编译项 generic-eng
420 # add the default one here
421 add_lunch_combo generic-eng
# 调用上面的add_lunch_combo函数,将generic-eng作为参数传递过去
423 # if we're on linux, add the simulator.
There is a special case
424 # in lunch to deal with the simulator
425 if [ "$(uname)" = "Linux" ] ; then
add_lunch_combo simulator
# 下面的代码很重要,它要从vendor目录下查找vendorsetup.sh文件,如果查到了,就加载它
1037 # Execute the contents of any vendorsetup.sh files we can find.
1038 for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh 2& /dev/null`
echo "including $f"
# 执行找到的脚本,其实里面就是厂商自己定义的编译选项
1043 unset f
envsetup.sh其主要作用如下:
加载了编译时使用到的函数命令,如:help,lunch,m,mm,mmm等添加了两个编译选项:generic-eng和simulator,这两个选项是系统默认选项查找vendor/&-厂商目录&/和vendor/&厂商目录&/build/目录下的vendorsetup.sh,如果存在的话,加载执行它,添加厂商自己定义产品的编译选项 其实,上述第3条是向编译系统添加了厂商自己定义产品的编译选项,里面的代码就是:add_lunch_combo xxx-xxx。
根据上面的内容,可以推测出,如果要想定义自己的平台产品编译项,简单的办法是直接在envsetup.sh最后添加上add_lunch_combo myProduct-eng,当然这么做,不太符合上面代码最后的本意,我们还是老实的在vendor目录下创建自己公司名字,然后在公司目录下创建一个新的vendorsetup.sh,在里面添加上自己的产品编译项
#mkdir vendor/farsight/
#touch vendor/farsight/vendorsetup.sh
#echo "add_lunch_combo fs100-eng" & vendor/farsight/vendorsetup.sh
这样,当我们在执行source build/envsetup.sh命令的时候,可以在shell上看到下面的信息:
including vendor/farsight/vendorsetup.sh
2. 按照android官网的步骤,开始执行lunch full-eng
当然如果你按上述命令执行,它编译的还是通用的eng版本系统,不是我们个性定制系统,我们可以执行lunch命令,它会打印出一个选择菜单,列出可用的编译选项
如果你按照第一步中添加了vendorsetup.sh那么,你的选项中会出现:
You're building on Linux
generic-eng simulator fs100-eng
Lunch menu... pick a combo:
1. generic-eng
2. simulator
3. fs100-eng
其中第3项是我们自己添加的编译项。
lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译项,来定义Product和编译过程中用到的全局变量。
我们一直没有说明前面的fs100-eng是什么意思,现在来说明下,fs100是我定义的产品的名字,eng是产品的编译类型,除了eng外,还有user, userdebug,分别表示:
eng: 工程机,
user:最终用户机
userdebug:调试测试机
tests:测试机
由此可见,除了eng和user外,另外两个一般不能交给最终用户的,记得m8出来的时候,先放出了一部分eng工程机,然后出来了user机之后,可以用工程机换。
那么这四个类型是干什么用的呢?其实,在main.mk里有说明,在Android的源码里,每一个目标(也可以看成工程)目录都有一个Android.mk的makefile,每个目标的Android.mk中有一个类型声明:LOCAL_MODULE_TAGS,这个TAGS就是用来指定,当前的目标编译完了属于哪个分类里。
PS:Android.mk和Linux里的makefile不太一样,它是Android编译系统自己定义的一个makefile来方便编译成:c,c++的动态、静态库或可执行程序,或java库或android的程序,
好了,我们来分析下lunch命令干了什么?
function lunch()
local answer
# lunch后面直接带参数的情况,则编译项为指定的参数: $1
if [ "$1" ] ; then
# lunch后面不带参数的情况,则调用print_lunch_menu函数,打印所有的target product和variant菜单提供用户选择
print_lunch_menu
echo -n "Which would you like? [generic-eng] "
read answer
# 读取用户选择的结果,注意,这儿可以是数字,也可以是字符串的选项内容
local selection=
# 如果用户在菜单中没有输入任何内容(直接回车),则为系统缺省的generic-eng编译项
if [ -z "$answer" ]
selection=generic-eng
elif [ "$answer" = "simulator" ]
# 如果是用户输入的是模拟器:simulator
selection=simulator
# 如果answer是菜单中的数字,则获取该数字
elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
# 如果用户输入的菜单数字不合法(超过全部选项数组的元素个数)
# ${#LUNCH_MENU_CHOICES[@]}是指,取得LUNCH_MENU_CHOICES这个数组的元素个数,LUNCH_MENU_CHOICES[@]指引用数组里的全部元素,以列表返回
selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}
#这儿通过$answer - $_arrayoffset来引用用户输入的数字对应的数组LUNCH_MENU_CHOICES中的编译项,其中_arrayoffset这个变量表示,是否是数组下标从0开始,这儿其值为:1
# 如果 answer字符串匹配 *-*模式(开头结尾不能为-)
elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
selection=$answer
#如果selection为空,出错退出
if [ -z "$selection" ]
echo "Invalid lunch combo: $answer"
# special case the simulator
if [ "$selection" = "simulator" ]
#如果用户选项为使用模拟器
# 导出4个环境变量,这4个环境变量将指定编译系统编译为模拟器
export TARGET_PRODUCT=sim
export TARGET_BUILD_VARIANT=eng
#版本型号变量
export TARGET_SIMULATOR=true
#编译在模拟器中
export TARGET_BUILD_TYPE=debug
# 将 product-variant模式中的product分离出来,sed命令是将-后面的字符串替换为空串,也就是只保留-前面的内容
local product=$(echo -n $selection | sed -e "s/-.*$//")
# 检查之,调用关系 check_product()-&get_build_var()-&build/core/config.mk比较罗嗦,不展开了
check_product $product
if [ $? -ne 0 ]
echo "** Don't have a product spec for: '$product'"
echo "** Do you have the right repo manifest?"
# 将 product-variant模式中的variant分离出来,sed命令将-前面的内容替换为空串
local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
# 检查之,看看是否在 (user userdebug eng) 范围内
check_variant $variant
if [ $? -ne 0 ]
echo "** Invalid variant: '$variant'"
echo "** Must be one of ${VARIANT_CHOICES[@]}"
if [ -z "$product" -o -z "$variant" ]
#再次检查两个变量是否为空
导出4个环境变量(和上面模拟器的对比着看),这里很重要,因为后面的编译系统都是依赖于这里定义的几个变量的
export TARGET_PRODUCT=$product
export TARGET_BUILD_VARIANT=$variant
export TARGET_SIMULATOR=false
export TARGET_BUILD_TYPE=release
fi # !simulator
# 设置到环境变量,比较多,不再一一列出,最简单的方法 set &env.txt 可获得
set_stuff_for_environment
# 打印一些主要的变量, 调用关系 printconfig()-&get_build_var()-&build/core/config.mk-&build/core/envsetup.mk 比较罗嗦,不展开了
printconfig
由上面分析可知,lunch命令可以带参数和不带参数,最终导出一些重要的环境变量,从而影响编译系统的编译结果。导出的变量如下(以实际运行情况为例)
TARGET_PRODUCT=fs100
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
执行完上述两个步骤,就该执行:make命令了,当然如果你按照上述两个步骤做完,执行make之后肯定会出问题,我们还要做一些其它的操作,下篇来分析。
没有更多推荐了,自定义Android产品
添加新设备您可以参考本页中的信息为自己的设备和产品创建 Makefile。请注意,与本部分中的其他页面不同,本页中的内容仅适合在创建全新的设备类型时参考,而且仅适合公司编译和产品团队参考。了解编译层编译层次结构包括与设备的物理结构对应的抽象层。下表中介绍了这些层。每个层都与上一层存在一对多的关系。例如,一个架构可以有多个板,一个板可以有多个产品。您可以将指定层中的某个元素定义为同一层中某个元素的特化元素,从而免去复制操作并简化维护工作。层示例说明产品myProduct、myProduct_eu、myProduct_eu_fr、j2、sdk产品层用于定义所开发产品的功能规范,例如要编译的模块、支持的语言区域,以及针对各语言区域的配置。也就是说,这是总体产品的名称。产品特定变量在产品定义 Makefile 中进行定义。一个产品可以沿用其他产品的定义,这有助于简化维护工作。一种常用的方法是:先创建一个基础产品,其中包含会应用到所有产品的功能,然后再基于这个基础产品创建产品变体。例如,如果有两个产品只是使用的无线技术不同(分别使用 CDMA 和 GSM),那么您可以让这两个产品沿用未定义无线技术的同一个基础产品的定义。板/设备sardine、trout、goldfish设备/主板层代表设备上由可塑材料组成的物理层(即设备的工业设计)。例如,在北美销售的设备可能包括 QWERTY 键盘,而在法国销售的设备则可能包括 AZERTY 键盘。该层还用于展现产品的基本架构图。这些架构图包括板上的外围设备及其配置。所使用的名称只不过是代表不同主板/设备配置的代码。架构arm、x86、mips、arm64、x86_64、mips64架构层用于描述主板上运行的处理器配置和 ABI(应用二进制接口)。使用编译类型在针对特定产品进行编译时,如果能在最终发布版本的基础上进行细微修改,通常会非常有用。在模块定义中,模块可以通过 LOCAL_MODULE_TAGS 指定标记,这些标记可以是以下一个或多个值:optional(默认)、debug、eng。如果某个模块没有通过 LOCAL_MODULE_TAGS 指定标记,则其标记默认为 optional。仅当 PRODUCT_PACKAGES 的产品配置需要可选模块时,系统才会安装可选模块。以下是当前已定义的编译类型:eng这是默认的编译类型。user这是旨在用作最终版本配置步骤的编译类型。userdebug除了以下几点之外,其余均与 user 相同:利用资源叠加层定制版本Android 编译系统会在编译时利用资源叠加层定制产品。资源叠加层用于指定在默认文件之上应用的资源文件。要使用资源叠加层,请修改项目编译文件,将 PRODUCT_PACKAGE_OVERLAYS 设为相对于顶级目录的路径。当编译系统搜索资源时,该路径将成为影子根目录,系统除了在当前根目录中进行搜索外,还会一并在该路径中搜索。 文件中包含用户最常自定义的设置。要在此文件上设置资源叠加层,请将叠加层目录添加到项目编译文件中,如下所示:PRODUCT_PACKAGE_OVERLAYS := device/DEVICE_IMPLEMENTER/DEVICE_NAME/overlay
或PRODUCT_PACKAGE_OVERLAYS := vendor/VENDOR_NAME/overlay
然后,将一个叠加层文件添加到该目录下,例如:vendor/foobar/overlay/frameworks/base/core/res/res/config.xml
在叠加层 config.xml 文件中找到的所有字符串或字符串数组都将会替换在原始文件中找到的对应字符串或字符串数组。编译产品您可以通过多种方式组织设备的源文件。我们将以 Nexus 6 为例,简要介绍是如何组织其实施文件的,不过您可以按照自己认为合适的方式组织源文件并进行编译。为 Nexus 6 实施了一个名为 shamu 的主设备配置。根据此设备配置创建了一个产品以及一个产品定义 Makefile,该 Makefile 用于声明关于设备的产品特定信息,例如名称和型号。您可以查看 device/moto/shamu 目录,了解所有相关配置的具体设置方式。编写 Makefile以下步骤介绍了如何采用与设置 Nexus 6 产品线类似的方式设置产品 Makefile:设置产品定义变量产品特定变量在产品的 Makefile 中定义。在产品定义文件中维护的变量包括:参数说明示例PRODUCT_AAPT_CONFIG创建程序包时使用的 aapt 配置 PRODUCT_BRAND对软件进行自定义所针对的品牌(如果有),例如运营商 PRODUCT_CHARACTERISTICSaapt 特性,用于允许向程序包添加变体特定资源。tablet、nosdcardPRODUCT_COPY_FILES字词列表,例如 source_path:destination_path。在编译相应产品时,应将源路径下的文件复制到目标路径。config/Makefile 中定义了针对复制步骤的规则 PRODUCT_DEVICE工业设计的名称。这也是板名称,编译系统会使用该名称查找 BoardConfig.mk.tunaPRODUCT_LOCALES以空格分隔的列表,用于列出由双字母语言代码和双字母国家/地区代码组成的代码对,以便说明针对用户的一些设置,例如界面语言和时间、日期以及货币格式。PRODUCT_LOCALES 中列出的第一个语言区域会被用作产品的默认语言区域。en_GB de_DE es_ES fr_CAPRODUCT_MANUFACTURER制造商的名称acmePRODUCT_MODEL最终产品的最终用户可见名称 PRODUCT_NAME总体产品的最终用户可见名称,将显示在“设置”&“关于”屏幕中。 PRODUCT_OTA_PUBLIC_KEYS产品的无线下载 (OTA) 公钥列表 PRODUCT_PACKAGES列出要安装的 APK 和模块。Calendar ContactsPRODUCT_PACKAGE_OVERLAYS指明是使用默认资源还是添加任何产品特定叠加层vendor/acme/overlayPRODUCT_PROPERTY_OVERRIDES系统属性分配(采用“key=value”格式)列表 设置 ANDROID_VENDOR_KEYS 以通过 USB 进行连接借助 ANDROID_VENDOR_KEYS 环境变量,设备制造商可以通过 adb 访问正式版。为每个版本生成每台设备都可以接受的密钥并将其存储在内部(如存储在 vendor/oem-name/security/adb/),然后通过 ANDROID_VENDOR_KEYS 让 adb 使用这些规范密钥,而不是随机密钥。使用 ANDROID_VENDOR_KEYS 环境变量指向生成的加密用 adb 公钥和私钥所在的目录。私钥存储在文件中。公钥存储在 file.pub 中。ANDROID_VENDOR_KEYS 环境变量指向存储生成的密钥对的文件或目录。该变量被设为一个文件或目录,其中包含使用 adb keygen 文件命令生成的 2048 位 RSA 身份验证密钥对。 这些密钥对是对 ADB 服务器生成的 RSA 密钥对的补充。首次使用 adb 通过 USB 进行连接时,需要使用 RSA 密钥对。您必须接受主机的 RSA 密钥,才能显式授予 adb 对设备的访问权限。默认情况下,ADB 服务器生成的密钥对以 adbkey(私钥)和 adbkey.pub(公钥)的形式存储在以下密钥存储库目录中:在 MacOS 上,文件位置可能为:$HOME/.android。在 Windows 和 Linux 上,文件位置为:%USERPOFILE%\.android。在 Windows 上,RSA 身份验证密钥在某些情况下也可能存储在 C:\Windows\System32\config\systemprofile\.android 中。当 ADB 服务器需要密钥时,它会先搜索 ADB 服务器密钥存储库目录。如果找不到任何密钥,它会接着检查 ANDROID_VENDOR_KEYS 环境变量。如果还是找不到任何密钥,本地 ADB 服务器会生成一个新密钥对,并将其保存在 ADB 服务器密钥存储库目录中。注意:您可以通过设置 ANDROID_SDK_HOME 环境变量来替换 ADB 服务器存储 RSA 密钥的默认目录。在设备上,密钥存储在 /data/misc/adb/adb_keys/ 文件中,新的经过授权的密钥会在您接受它们后附加到同一个文件中。
没有更多推荐了,专注移动互联网,连续创业中,著有《深入浅出嵌入式底层软件开发》北航出版社...
深入浅出 - Android系统移植与平台开发(五)- 编译Android源码
2.3编译Android源码
Android源码体积非常庞大,由Dalvik虚拟机、Linux内核、编译系统、框架代码、Android定制C库、测试套件、系统应用程序等部分组成,在编译Android源码之前,必须要先掌握Android源码的组成。
2.3.1Android源码目录结构
在Android源码中,按照不同功能代码被放在不同的目录下:
针对Android系统定制的仿生标准C库、链接器等所在目录,Android系统并没有使用Linux的glibc库,bioinc C库针对嵌入式系统做了优化,添加了一些Android特定的函数API同时大大减少库的体积,也避免了LGPL版权的问题。
Android系统引导启动代码,用来引导系统、更新系统、恢复系统。
Android的编译系统目录,里面包含大量的Makefile,用来编译目标系统、Host主机开发环境等。
兼容性测试工具目录。
Dalvik虚拟机,Android系统得以运行的虚拟执行环境。
development
程序开发所需要的模板和工具。
Android系统使用的其它开源代码目录,如jpeg图片解码开源库、opencore开源代码等。
frameworks
框架层代码,frameworks/base目录下存放目标系统的框架库,frameworks/policies/base下存放应用程序框架代码。
HAL(Hardware Abstraction Layer)硬件抽象层代码。
Linux内核目录,默认下载的Android源码里没有,需单独下载。
Android系统级应用程序源码目录,如摄像应用、电话应用等。
主机编译工具目录,如arm-linux-gcc交叉系统工具链等。
SDK及模拟器。
init进程、蓝牙、无线WIFI工具、uevent进程目录。
厂商设备配置目录,针对不同设备,由不同的子目录来分别管理,用来裁剪实现不同设备上Android目标系统。
在external目录下存放着大量的外部开源代码:
外部开源项目
外部开源项目
apache-http
网页服务器
netbeans-visual
蓝牙相关、协议栈
simple Unix utility which reads and writes dataacross network connections
网络性能测量工具
clearsilver
看代码和JNI相关
低延时、低开销、高可用性的IPC机制
多媒体框架
SSL加密相关
SSH2的server
OProfile是Linux内核支持的一种性能分析机制
pppd拨号命令,好像还没有chat
复制ELF的工具
a flexible, efficient, automated mechanism for serializing structured data
Embedded Unit Project
functions for performing safe integer operations
java代码覆盖率统计工具
Enlightened Sound Daemon,将多种音频流混合在一个设备上播放
skia图形引擎
Expat is a stream-oriented XML parser
sole MIDI solution for Google Android Mobile Phone Platform
FDLIBM (Freely Distributable LIBM)
Nuance 公司提供的开源连续非特定人语音识别
google的无线数据相关
swing-worker
googleclient
google用户库
TagSoup是一个Java开发符合SAX的HTML解析器
ICU(International Component for Unicode)在C/C++下的版本
抓TCP包的软件
TinyXml is a simple, small, C++ XML parser
generate a report describing the difference between two public Java APIs
jfreechart
I stream and file decoder provides an embeddable,integer-only library
浏览器核心
wpa_supplicant
无线网卡管理
libffi is a foreign function interface library.
yaffs文件系统
网络数据包捕获函数
a general purpose data compression library
在packages/app目录下存放着大量系统级应用程序,我们可以拿到这些应用程序代码分析、理解,编写出效率更高,性能更好的应用:
系统应用程序
AlarmClock
Calculator
GoogleSearch
Google搜索
HTML Viewer
浏览器附属界面,被浏览器应用调用,同时提供存储记录功能
即时通讯,为手机提供信号发送、接收、通信的服务
Android的桌面
音乐播放器
PackageInstaller
应用程序安装、卸载器
SoundRecorder
短信接收和发送
VoiceDialer
语音识别通话
在package/providers目录下存放的是系统级内容提供器(Content Provider):
系统内容提供器
CalendarProvider
日历提供器
ContactsProvider
联系人提供器
DownloadProvider
下载管理提供器
DrmProvider
DRM受保护数据存储服务,创建和更新数据库时调用
GoogleContactsProvider
谷歌联系人提供器
GoogleSubscribedFeedsProvider
Google同步功能
ImProvider
即时通讯提供器
MediaProvider
媒体提供器、提供存储数据
SettingsProvider
系统设置提供器
SubscribedFeedsProvider
TelephonyProvider
彩信提供器
按照Android官方网站给出的步骤,编译Android源码过程如下:
? 初始化编译环境
在编译Android之前,编译系统需要加载一些编译脚本命令到环境变量中,通过下面的指令来初始化编译环境:
$ sourcebuild/envsetup.sh
在执行完上述命令后,可以通过执行help命令来查看所有加载的命令。
Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
Changes directory to the top of the tree.
Makes from the top of the tree.
Builds all of the modules in the current directory.
Builds all of the modules in the supplied directories.
Greps on all local C/C++ files.
Greps on all local Java files.
- resgrep: Greps on all local res/*.xml files.
Go to the directory containing a file.
Look at the source to view more functions. The complete list is:
add_lunch_combo cgrep check_product check_variant choosecombo chooseproduct choosetype choosevariant cproj croot findmakefile gdbclient get_abs_build_var getbugreports get_build_var getprebuilt gettop godir help isviewserverstarted jgrep lunch m mm mmm pid printconfig print_lunch_menu resgrep runhat runtest setpaths set_sequence_number set_stuff_for_environment settitle smoketest startviewserver stopviewserver systemstack tapas tracedmdump
常用脚本命令:
帮助信息,打印所有命令
add_lunch_combo
添加新目标编译项
print_lunch_menu
打印所有目标编译项
选择目标编译项
从源码树顶级目录向下编译源码,相当于执行make
从当前目录向下编译源码
从指定目录向下编译源码,通常用来编译某个模块
从所有的C,C++文件里查找指定字符串
从所有的Java文件里查找指定字符串
? 选择编译选项
由于Android源码是一个开源的系统,然要匹配很多设备产品,也就是说一个版本的Android源码,可以编译出针对不同产品的系统。通过选择一个目标编译项,来决定编译出针对哪个产品的系统,我们可以通过执行下面的命令来选择要编译的目标系统:
You're building on Linux
generic-eng simulator
Lunch menu... pick a combo:
1. generic-eng
2. simulator
Which would you like? [generic-eng]
通过lunch命令可知,让用户输入目标编译项,我们可以选择编译项前的数字,也可以直接输入编译项的名字。
…接前面终端输出信息
Which would you like? [generic-eng]1 [回车]
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.1-update1
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=ERE27
============================================
由上面结果可知,当用户输入:1或generic-eng时,会打印出上面的信息,这些信息是Android的编译系统必须依赖的环境变量,只有设置了这些变量,才能决定Android系统如何编译,编译成什么平台,编译成什么版本。
目标编译项格式:产品名-版本变量名,目标编译项可以由用户添加(见xxx章节),产品名是目标设备的产品名,由厂商自己定义,generic产品是通用产品,它是Android默认设备的产品名,它包含了常用的手机的所有功能,自己定义的产品可以继承generic,并重写它的功能,达到定制产品的目的(见xxx章节)。
版本变量名由以下几个组成:
eng:工程版本,user:最终用户版本userdebug:调试版本 tests:测试版本
其中,eng版本产品其实就是手机行业的工程机,它不是最终销售的产品,而是产品在定型下线之前放出的一些测试用机器,用于检测和标准的认证,这些工程机上安装的系统为eng版本,user是最终用户机发行版本,userdebug是调试版本,它比用户机添加了一些调试功能,如adb调试默认打开等,tests测试版本,该版本会安装一些测试程序,用于测试系统。
上述四种版本的分类作用,其一:用于区分目标系统里的所有的应用程序、库、测试程序等,将它们打上对应的Tags,当选择一个版本编译时,拥有对应Tags及低级别的Tags的程序会被编译安装到目标设备上,应用程序Tags的包含关系如下图:。其二:根据不同的版本,系统会有不同的设置,如adbd在用户版本里是关闭的,在其它版本中是默认打开的,ro.secure属性用户版本值为1,其它版本为0。
? 编译源码
执行完前面的命令后,我们可以输入make指令开始编译目标系统:
编译的时长与机器的硬件配置有关系,当第一次编译时一般需要数小时以上。后续编译,相对快多了,编译完的效果如下图所示:
通过上面的输出信息可知,Android系统编译完后,在out/target/product/generic/目录下产出了三个文件:system.img、ramdisk.img、userdata.img。
system.img:android系统的文件系统,里面包含了android系统的应用程序(apk),系统用到的各种库(jar, so)和资源,配置文件(etc目录下),系统命令(bin,usr/bin, xbin),该映像文件是由out/target/product/generic/system目录打包生成的,我们可以对这个目录里的东西进行定制化,比如,你要想让android系统默认安装一个应用程序,那么可以将要安装的apk文件拷贝到out/target/product/generic/system/app目录下。 userdata.img:用户数据映像,里面包含有程序安装信息等,好比如是windows的C:/Program Files/目录。ramdisk.img:内存磁盘映像。linux内核启动起来,要挂载一个文件系统作为自己的根文件系统,里面含有Linux内核启动过程中依赖的一些程序和配置文件。ramdisk.img就是一个最小化的根文件系统,它被加载到内存中作为Android的根文件系统。该映像是由out/target/product/generic/root目录打包生成的。前面所述的userdata.img和system.img映像,在linux系统启动起来后挂载到ramdisk.img中的data,system目录下。
其实,Android手机的ROM包(通常为update.zip文件),就是主要由上述三个映像文件构成的:
android-info.txt
ROM版本及刷写配置信息
Linux内核zImage、ramdisk.img
system.img
Android系统映像
userdata.img
用户数据映像
只要我们拿到手机的源码,就可以自己编译出自己的ROM,不过,一般手机厂商不会开源自己产品源码,都是第三方爱好者自己下载,修改编译的,如:业界著名的CM团队:。
由于完全编译Android系统耗时很长,并且Android源码由很多模块组成,我们可以通过下面一些编译命令来减少编译时间:
打包生成system.img,不检查依赖关系
make bootimage
打包生成ramdisk.img
指定编译某个目录下的模块
上述三个命令经常在我们源码开发时使用,希望大家记住。
2.3.3编译内核
Android使用Linux内核,在源码级开发过程中,有时要修改内核代码,通常内核代码是和目标设备相关的,我们使用的是模拟器的内核,即使没有硬件设备也可以完成实验。
编译Android的内核,需要用到交叉编译器,我们可以直接使用Android源码里自带的arm-eabi-gcc编译器,为了编译出针对模拟器的内核(模拟器的CPU为Goldfish),还要配置内核(如果不知道如何配置内核,请读者阅读内核裁剪相关资料),为了方便我们编译Goldfish内核,我们编写了如下脚本,方便编译。
$ cd /home/linux/android/android_source/kernel/goldfish/
$ vi build_kernel.sh
添加如下内容:
@ /home/linux/android/android_source/kernel/goldfish/build_kernel.sh
#!/bin/bash
export PATH=/home/linux/android/android_source/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin:$PATH
export ARCH=arm
export SUBARCH=arm
export CROSS_COMPILE=arm-eabi-
if [ ! –f .config ] ; then
make goldfish_armv7_defconfig
注:当Andorid源码目录发生改变时,要修改PATH的路径,让它指向对应的交叉编译器。
给脚本加上可执行权限,然后执行该脚本:
$ chmod a+x build_kernel.sh
$ ./build_kernel.sh
内核编译完成如图x-x所示:
图x-x 内核编译结果
没有更多推荐了,
作者,早期从事Android移动开发、嵌入式系统开发,连续两次创业,全栈带队开发全球知名校友在线咨询平台。

我要回帖

更多关于 厂商租赁定义 的文章

 

随机推荐