Android ninja 编译启动过程分析

合集下载

Android编译过程详解(一)

Android编译过程详解(一)

Android编译过程详解(⼀)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() # 检查productfunction check_variant() # 检查变量function setpaths() # 设置⽂件路径function printconfig() # 打印配置function set_stuff_for_environment() # 设置环境变量function set_sequence_number() # 设置序号function settitle() # 设置标题function choosetype() # 设置typefunction chooseproduct() # 设置productfunction choosevariant() # 设置variantfunction tapas() # 功能同choosecombofunction choosecombo() # 设置编译参数function add_lunch_combo() # 添加lunch项⽬function print_lunch_menu() # 打印lunch列表function lunch() # 配置lunchfunction m() # make from topfunction findmakefile() # 查找makefilefunction mm() # make from current directoryfunction mmm() # make the supplied directoriesfunction 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.sh406 # files are included at the end of this file.# 清空LUNCH_MENU_CHOICES变量,⽤来存在编译选项407 unset LUNCH_MENU_CHOICES408 function add_lunch_combo()409 {410 local new_combo=$1 # 获得add_lunch_combo被调⽤时的参数411 local c# 依次遍历LUNCH_MENU_CHOICES⾥的值,其实该函数第⼀次调⽤时,该值为空412 for c in ${LUNCH_MENU_CHOICES[@]} ; do413 if [ "$new_combo" = "$c" ] ; then # 如果参数⾥的值已经存在于LUNCH_MENU_CHOICES变量⾥,则返回414 return415 fi416 done# 如果参数的值不存在,则添加到LUNCH_MENU_CHOICES变量⾥417 LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)418 }# 这是系统⾃动增加了⼀个默认的编译项 generic-eng420 # add the default one here421 add_lunch_combo generic-eng # 调⽤上⾯的add_lunch_combo函数,将generic-eng作为参数传递过去423 # if we're on linux, add the simulator. There is a special case424 # in lunch to deal with the simulator425 if [ "$(uname)" = "Linux" ] ; then426 add_lunch_combo simulator427 fi# 下⾯的代码很重要,它要从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`1039 do1040 echo "including $f"1041 . $f # 执⾏找到的脚本,其实⾥⾯就是⼚商⾃⼰定义的编译选项1042 done1043 unset fenvsetup.sh其主要作⽤如下: 1. 加载了编译时使⽤到的函数命令,如:help,lunch,m,mm,mmm等 2. 添加了两个编译选项:generic-eng和simulator,这两个选项是系统默认选项 3. 查找vendor/<-⼚商⽬录>/和vendor/<⼚商⽬录>/build/⽬录下的vendorsetup.sh,如果存在的话,加载执⾏它,添加⼚商⾃⼰定义产品的编译选项其实,上述第3条是向编译系统添加了⼚商⾃⼰定义产品的编译选项,⾥⾯的代码就是:add_lunch_combo xxx-xxx。

Android启动流程分析

Android启动流程分析

Zygote进程启动System Server
Zygote进程从App_main.cpp中main函数开始,调用runtime.start启动system server,最后就进入 runSelectLoopMode等待并处理来自上层的请求。
int main(int argc, const char* const argv[]){ ...... AppRuntime runtime; ...... int i = runtime.addVmArguments(argc, argv); if(i < argc){ runtime.mParentDir = argv[i++]; }
2. 从以下文件中加载默认属性值。 ① /default.prop ② /system/build.prop ③ /system/default.prop ④ /data/local.prop 属性将会按照如上顺序加载,后加载的属性覆盖原先的。
3. Init进程会启动一个属性服务器Property Service,客户端(Property Setter)只能通过 该属性服务器来进行系统属性的设置。 处理设置属性请求(Write property) 当Property Service通过unix domain socket收到用户请求时,init会调用 handle_property_set_fs函数进行处理。
Kernel创建Init进程
Android Kernel启动后,执行start_kernel函数来初始化Kernel正式运行之前各个功能。 Start_kernel函数最后调用了reset_init函数启动了如下三个进程: ① idle 是操作系统的空闲进程,当 cpu 空闲的时候会去运行它 ② kthreadd 是内核守护进程,其 PID 为 2 ③ kernel_init 函数作为进程被启动,但是之后它将读取根文件系统下的init 程序,这个

ANDROID源码编译流程

ANDROID源码编译流程

ANDROID源码编译流程编译Android源代码是一个相对复杂的过程,但是如果你按照正确的步骤进行,你就可以成功地编译出你自己的Android系统。

下面是一个大致的流程来编译Android源代码:1.环境准备:在开始编译Android源代码之前,你需要确保你的系统满足以下要求:- Linux系统(推荐使用Ubuntu)-64位操作系统-至少8GB的RAM-大规模存储空间(30GB或更多)你还需要安装一些必要的开发包和工具,例如JDK、Git等。

详细的要求可以在Android官方网站上找到。

2.获取源代码:要编译Android系统,你需要先获取源代码。

Android的源代码存储在Git仓库中,你可以使用Repo工具来管理多个Git仓库。

首先,你需要安装Repo工具。

你可以通过下面的命令来安装:```$ sudo apt-get install repo```之后,在一个合适的目录下创建一个新的文件夹来存放源代码:$ mkdir myandroid$ cd myandroid```使用Repo工具来初始化一个仓库:``````之后,同步源代码到你的本地仓库:```$ repo sync```这个过程可能需要花费几个小时甚至更长时间,取决于你的网络速度和计算机配置。

3.构建工具链:Android使用GNU Make和Ninja构建工具来构建系统。

你需要安装这些工具。

首先,安装GNU Make和一些必要的依赖库:```$ sudo apt-get install build-essential然后,安装Ninja:```$ sudo apt-get install ninja-build```4.配置构建环境:在构建Android系统之前,你需要进行一些配置操作。

首先,你需要选择要构建的目标设备和版本。

你可以在Android源代码的根目录中找到`lunch`脚本。

运行`lunch`脚本并选择你的目标:```$ source build/envsetup.sh$ lunch```然后,你需要选择编译时使用的编译器。

Android编译过程总结及android中各种img文件的作用以及系统启动过程

Android编译过程总结及android中各种img文件的作用以及系统启动过程

Android编译过程总结及android中各种img文件的作用以及系统启动过程编译环境:ubuntu 10.04(或者更高)(windows平台目前不被支持)本文以编译android2.3为例,64位操作系统1、编译环境的准备(1)确保安装有ubuntu系统或者虚拟机(2)安装JDK1.6(对于Android2.3以上代码)$ sudo add-apt-repository "deb/ lucid partner"$ sudo add-apt-repository "deb-src/ubuntu lucid partner"$ sudo apt-get update$ sudo apt-get installsun-java6-jdk(3)安装一些需要软件包$ sudo apt-get install git-coregnupg flex bison gperf build-essential \zip curl zlib1g-dev libc6-devlib32ncurses5-dev ia32-libs \x11proto-core-dev libx11-devlib32readline5-dev lib32z-dev \libgl1-mesa-dev g++-multilibmingw32 tofrodos(4)安装repo$ git clonegit:///tools/repo.git$ mkdir ~/bin$ cp repo-script/repo~/bin$ vim ~/.bashrc,将~/bin加入PARH环境变量,如:$ exportPATH=~/bin:$PATH保存后,同步更新:source~/.bashrc(5)设置git执行以下语句$git config "你的名字"$git config --global user.email"你的email地址"(6)同步源代码1)创建工程目录:$ mkdir myandroid$ cd myandroid2)repo初始化以及同步代码$repo init ****************.x.xx:git库名/manifest.git -b 主分支名在此过程中需要输入名字和email地址。

JAVA应用程序和小应用程序编译运行的详细过程

JAVA应用程序和小应用程序编译运行的详细过程

JAVA应用程序和小应用程序编译运行的详细过程Java应用程序和小应用程序的编译和运行过程可以分为以下几个步骤:2. 编译代码:一旦代码编写完成,程序员需要使用Java编译器将源代码转换为字节码。

在命令行中,可以使用javac命令来完成编译过程。

编译器会检查代码的语法和语义错误,并生成一个以.class结尾的字节码文件。

3. 加载类:在运行Java程序之前,Java虚拟机(JVM)需要将编译生成的字节码文件加载到内存中。

当JVM加载类时,它会根据类的名字查找对应的字节码文件,并将字节码文件加载到内存中的方法区。

4.验证:一旦类被加载到内存中,JVM会对它进行验证,以确保它的字节码是有效和安全的。

验证过程包括检查字节码的结构、检查类的继承关系和访问权限,并检查方法的参数和返回值是否正确。

5.准备:在类被实例化之前,JVM会为类的静态成员变量分配内存,并将其初始化为默认值。

这个过程被称为“准备阶段”。

6.解析:在程序执行之前,JVM还需要解析类中的符号引用,例如方法调用和字段访问。

解析阶段将符号引用解析为实际的方法和字段引用。

7.初始化:在准备阶段之后,JVM会执行类的静态初始化。

在静态初始化块中,程序员可以为静态成员变量赋值,并执行其他静态初始化操作。

静态初始化只会执行一次,且在类的第一次使用时才会触发。

8. 执行程序:一旦类被初始化,JVM会按照指定的入口点开始执行程序。

程序会按顺序执行代码,从主方法开始,逐行执行,直到程序结束或遇到return语句。

9.垃圾回收:在程序执行过程中,JVM会通过垃圾回收器自动回收不再使用的对象和内存。

垃圾回收器会周期性地扫描内存,找出无法访问的对象,并释放它们占用的内存空间。

总结:Java应用程序和小应用程序的编译和运行过程可以概括为编写代码、编译代码、加载类、验证、准备、解析、初始化和执行程序。

通过这个过程,程序员可以将Java代码转换为可执行的程序,并在JVM上运行。

如何使用ninja编译系统编译我们的程序?

如何使用ninja编译系统编译我们的程序?

如何使⽤ninja编译系统编译我们的程序?使⽤ninja配置⾃⼰的环境来使⽤ninja构建程序Android使⽤ninjaWindows使⽤调试不使⽤VS技巧问题Ninja的原意是忍者,忍者神龟的忍者。

这⾥被google拿来⽤在他们的编译系统上。

⽬标是替代make之类的构建器,由于他们认为其他的构建器太慢了,为此他们做过对照,对于chrome之类的拥有⼏万个⽂件的超⼤程序来说,⽤ninja的话,差点⼉马上開始编译,⽽make差点⼉要等上个10秒钟才開始编译。

Ninja的另外⼀个特点,事实上不是他娘的特点,就是独⽴于编译系统的输⼊⽂件,我想问下google⼤神。

难道cmake的CMakeList.txt不是吗?Google把别的编译系统⽐作⾼级语⾔,⽽把⾃⼰努⼒设计成更底层的汇编器。

这样才⼲从指令层⾯来优化编译性能。

Ninja的的构建(build)⽂件是给⼈看的。

但不是特别⽅便于⼿写。

这些特点同意她⾼速评估递增构建。

毕竟不是每次都要从头開始。

Ninjia的底层特性使得她更适合嵌⼊功能强⼤的构建系统。

通过gyp(哈哈,拿来的CMakeLists.txt)。

ninja可以构建Chrome和v8, node.js等等项⽬。

通过cmake, ninja可以构建LLVM(虚拟机啊)以及KDE桌⾯等等。

如何获取ninja?github上有:git clone git:///martine/ninja.git或者我们在debian/ubuntu上能够这样:apt-get install ninja-build本⽂属原创。

转载请注明出处,违者必究关注微信公众平台:程序猿互动联盟(coder_online),你能够第⼀时间获取原创技术⽂章,和(java/C/C++/Android/Windows/Linux)技术⼤⽜做朋友。

在线交流编程经验。

获取编程基础知识,解决编程问题。

程序猿互动联盟,开发者⾃⼰的家。

Android源码编译的全过程记录

Android源码编译的全过程记录

Android源码编译的全过程记录写本篇⽂章主要参考了官⽅⽂档和⽹上的⼀些资料,但是对于Android最新的代码来说,⽹上资料有些已经过时。

本⽂中步骤已经作者实验,⼤家可以亲⾃执⾏试试。

由于没有使⽤Eclipse的习惯,所以没有做Eclipse的相关配置。

编译环境:ubuntu9.10,widnows平台⽬前不被⽀持。

1)安装必要的软件环境$ sudo apt-get install git-core gnupg sun-java5-jdk flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev官⽅推荐的就是上⾯这些,如果在编译过程中发现某些命令找不到,就apt-get它。

可能需要的包还有:$ sudo apt-get install make$ sudo apt-get install gcc$ sudo apt-get install g++$ sudo apt-get install libc6-dev$ sudo apt-get install patch$ sudo apt-get install texinfo$ sudo apt-get install zlib1g-dev$ sudo apt-get install valgrind$ sudo apt-get install python2.5(或者更⾼版本)需要注意的是,官⽅⽂档说如果⽤sun-java6-jdk可出问题,得要⽤sun-java5- jdk。

经测试发现,如果仅仅make(make不包括make sdk),⽤sun-java6-jdk是没有问题的。

⽽make sdk,就会有问题,严格来说是在make doc出问题,它需要的javadoc版本为1.5。

因此,我们安装完sun-java6-jdk后最好再安装sun-java5-jdk,或者只安装sun-java5-jdk。

Android编译过程详解(二)

Android编译过程详解(二)

Android编译过程详解(⼆)通过上篇⽂章,我们分析了编译android时source build/envsetup.sh和lunch命令,在执⾏完上述两个命令后, 我们就可以进⾏编译android了。

1. make执⾏make命令的结果就是去执⾏当前⽬录下的Makefile⽂件,我们来看下它的内容:### DO NOT EDIT THIS FILE ###include build/core/main.mk### DO NOT EDIT THIS FILE ###呵呵,看到上⾯ 的内容,我们都会笑,这是我见过最简单的Makefile了,我们再看下build/core/main.mkmain.mk⽂件⾥虽然脚本不多,但是却定义了整个Android的编译关系,它主要引⼊了下列⼏个重要的mk⽂件:49 include $(BUILD_SYSTEM)/config.mk55 include $(BUILD_SYSTEM)/cleanbuild.mk142 include $(BUILD_SYSTEM)/definitions.mk当然每个mk⽂件都有⾃⼰独特的意义,我们⼀并将主线流程相关mk⽂件都列出来,⼤概来介绍下,先有个整体的概念,然后再细化了解。

所有的Makefile都通过build/core/main.mk这个⽂件组织在⼀起,它定义了⼀个默认goals:droid,当我们在TOP⽬录下,敲Make实际上就等同于我们执⾏make droid。

当Make include所有的⽂件,完成对所有make我⽂件的解析以后就会寻找⽣成droid的规则,依次⽣成它的依赖,直到所有满⾜的模块被编译好,然后使⽤相应的⼯具打包成相应的img。

其中,config.mk,envsetup.mk,product_config.mk⽂件是编译⽤户指定平台系统的关键⽂件。

上图中红⾊部分是⽤户指定平台产品的编译主线,我们先来看下config.mk的主要作⽤。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Android ninja编译启动过程分析
---make是如何转换到到ninja编译的
1.首先你的得对make的工作机制有个大概的了解:
运行的命令在要编译的目录下运行make,或者make target_name
a.分析处理保存阶段(没有实际编译动作):它首先对当前目录下的Makefile文件的做一次扫描,语法分析,还有处理,主要是变量的保存,目标依赖列表生成,目标下的action列表的生成,然后记住
b.然后按记住的目标执行action列表动作(有实际编译动作).
编译启动的入口方式还是运行make:
2开始make-jxxx方式进入.....(xxx是本机cpu的数量)
make开始做进行第一次扫描....
目前USE_NINJA还是没有定义,估计以后很久很久才能启用的了!
BUILDING_WITH_NINJA开始也是没定义的
看make扫描入口文件:
Makefile:
include build/core/main.mk
在build/core/main.mk:
在ninia之前都有include help.mk和config.mk
97include$(BUILD_SYSTEM)/help.mk
98
99#Set up various standard variables based on configuration
100#and host information.
101include$(BUILD_SYSTEM)/config.mk
说明make help//显示make帮助make config//当前显示配置
103relaunch_with_ninja:=
104ifneq($(USE_NINJA),false)
105ifndef BUILDING_WITH_NINJA<==第二次扫描不会到这里了
106relaunch_with_ninja:=true
107endif
108endif
116ifeq($(relaunch_with_ninja),true)<===第一次扫描入这里了
117#Mark this is a ninja build.
118$(shell mkdir-p$(OUT_DIR)&&touch$(OUT_DIR)/ninja_build)
119include build/core/ninja.mk//---进入ninja.mk
第一次扫描到此为止就结束掉了,因为在当前ifeq else endif后面没有代码了
120else#///!relaunch_with_ninja<===第二次扫描入这里了
121ifndef BUILDING_WITH_NINJA
122#Remove ninja build mark if it exists.
123$(shell rm-f$(OUT_DIR)/ninja_build)
124endif
......
endif////////!relaunch_with_ninja
这里是文件底了
接着上面的include build/core/ninja.mk
build/core/ninja.mk:
$(sort$(DEFAULT_GOAL)$(ANDROID_GOALS)):ninja_wrapper//使nijia_wrapper成为第一扫描后要做的action 的第一个跳入的标签
ninja_wrapper:$(COMBINED_BUILD_NINJA)$(MAKEPARALLEL)
@echo Starting build with ninja
+$(hide)export NINJA_STATUS="$(NINJA_STATUS)"&&source$(KATI_ENV_SH)&&$(NINJA_MAKEPARALLEL) $(NINJA)$(NINJA_GOALS)-C$(TOP)-f$(COMBINED_BUILD_NINJA)$(NINJA_ARGS)
这里被依赖$(COMBINED_BUILD_NINJA)要先被处理完后才能返回来继续这里的action了
ifeq($(USE_SOONG),true)
135$(COMBINED_BUILD_NINJA):$(KATI_BUILD_NINJA)$(SOONG_ANDROID_MK)
136$(hide)echo"builddir=$(OUT_DIR)">$(COMBINED_BUILD_NINJA)
137$(hide)echo"subninja$(SOONG_BUILD_NINJA)">>$(COMBINED_BUILD_NINJA)
138$(hide)echo"subninja$(KATI_BUILD_NINJA)">>$(COMBINED_BUILD_NINJA)
139else
140COMBINED_BUILD_NINJA:=$(KATI_BUILD_NINJA)
141endif
继续看:$(KATI_BUILD_NINJA)
162$(KATI_BUILD_NINJA):$(KATI)$(MAKEPARALLEL)$(DUMMY_OUT_MKS)$(SOONG_ANDROID_MK)FORCE 163@echo Running kati to generate build$(KATI_NINJA_SUFFIX).ninja...
164+$(hide)$(KATI_MAKEPARALLEL)$(KATI)--ninja--ninja_dir=$(OUT_DIR)
--ninja_suffix=$(KATI_NINJA_SUFFIX)--regen--ignore_dirty=$(OUT_DIR)/%
--no_ignore_dirty=$(SOONG_ANDROID_MK)--ignore_optional_include=$(OUT_DIR)/%.P--detect_android_echo $(KATI_FIND_EMULATOR)-f build/core/main.mk$(KATI_GOALS)--gen_all_targets BUILDING_WITH_NINJA=true SOONG_ANDROID_MK=$(SOONG_ANDROID_MK)
在这个位置触发了的第二次build/core/main.mk(由kati处理的)的扫描,看起来他和make功能一样,这里kati要处理一遍: build/core/main.mk,下面他处理的包括的过程:
文件开始
....117else
#!relaunch_with_ninja
118ifndef BUILDING_WITH_NINJA
119#Remove ninja build mark if it exists.
120$(shell rm-f$(OUT_DIR)/ninja_build)
121endif
.....
#endif
也就是说kati处理了从main.mk文件开始到末尾的全部,不包括include build/core/ninja.mk部分的全部了,包括他include makefiles了
@echo Running kati to generate build$(KATI_NINJA_SUFFIX).ninja...
/////////////在屏幕上可以看到是否kati开始了扫描生成.ninja file的过程
在这个过程中,kati要判断是否生成.ninja是否需要更新了,这个是在kati内部完成的!
./:172:fprintf(stderr,"%s was modified,regenerating...\n",s.c_str());
看来东西不少,然后他回到ninja_wrapper:下继续上一层的action执行
ninja_wrapper:$(COMBINED_BUILD_NINJA)$(MAKEPARALLEL)//重新贴了一遍上面的东西
@echo Starting build with ninja
+$(hide)export NINJA_STATUS="$(NINJA_STATUS)"&&source$(KATI_ENV_SH)&&$(NINJA_MAKEPARALLEL) $(NINJA)$(NINJA_GOALS)-C$(TOP)-f$(COMBINED_BUILD_NINJA)$(NINJA_ARGS)
这个执行就是启动ninja了,看:$(NINJA)$(NINJA_GOALS)
@echo Starting build with ninja
/////////////在屏幕上可以看到是否开是在ninja带领下编译开始了.....
//====到此,第一阶段准备工作部分分析完成了,下面进入具体的ninjia编译阶段了
3.总结
kati代替了make过去做的非常相同一样的工作(连输出打印都很一样,例如遇到$(error xxxx)会退出),parse makefile。

,只是他会输出.ninja file,而不是如过去make解析makefile记在心里,然后给他自己跳入做action,而现在是生成个文件给ninja跳入做action了.
在下载的Android源码下,测试通过make droid-j25最接续编译测试:
####make completed successfully(01:06(mm:ss))####
快的震惊啊!
测试用代码版本:
PLATFORM_VERSION:=7.1.2。

相关文档
最新文档