Android编译过程详解
- 格式:doc
- 大小:157.00 KB
- 文档页数:22
android bp编译流程
Android BP编译流程一般包括以下步骤:
1. 创建项目目录,并在项目根目录下创建一个名为Android.bp的文件。
2. 在Android.bp文件中定义要编译的模块。
这通常包括模块的名称、源代码文件和其他相关属性。
3. 配置模块,指定模块所需的参数和属性。
这可能包括AndroidManifest.xml文件的路径、签名证书的路径、资源目录的路径等。
4. 导入build/make/core/config.mk文件进行环境变量或重要参数的
配置。
5. 导入build/make/core/definitions.mk文件,定义一些其他变量。
6. 定义一系列规则,这些规则的目标是编译要生成的目标文件。
7. 执行编译命令,例如make或gradle编译,将源代码编译成可执行
文件或其他目标文件。
请注意,具体的编译流程可能因项目结构和使用的工具链而有所不同。
因此,以上步骤仅供参考,具体流程可能需要根据实际情况进行调整。
android编译流程Android编译流程是将源代码转化为可执行的Android应用程序的过程。
编译流程包括以下几个主要步骤:1.获取源代码:首先,开发人员需要从Android Open Source Project (AOSP) 或者其他可靠的源代码库中获取Android源代码。
获取源代码可以通过使用版本控制工具如Git来完成。
2.准备构建环境:在编译之前,需要准备好构建环境。
这包括安装正确的开发工具、依赖库和配置。
- 开发工具:Android编译使用Java编程语言,因此需要安装Java Development Kit (JDK)。
同时还需要安装Android软件开发工具包(SDK),用于构建和测试Android应用。
- 依赖库:编译Android需要一些依赖库,包括C/C++编译器、make 工具、libc、libm和其他系统库。
这些库可以通过安装合适的软件包管理工具来获取。
-配置:开发人员需要根据构建计划配置构建环境。
这包括选择编译器版本、构建目标平台以及其他构建选项。
3.设置环境变量:为了让系统能够找到正确的构建工具和依赖库,开发人员需要设置一些环境变量。
这可以通过在命令行终端中设置系统环境变量或者使用脚本文件进行配置来实现。
4.执行初始化构建:在进行实际的编译之前,需要执行一些初始化构建操作。
这包括解压源代码文件、创建构建描述文件、设置编译选项等。
5.编译源代码:编译源代码是整个编译流程的核心步骤。
在此步骤中,构建系统将递归地遍历整个源代码树,并将每个源文件编译成目标文件。
编译过程通常分为以下几个阶段:-预处理:在编译之前,构建系统会首先对源代码进行预处理。
预处理器将处理预处理指令、宏定义等,并将源代码转化为可供编译器识别的形式。
-编译:编译器将源代码编译成汇编语言或者中间代码。
-汇编:汇编器将汇编语言代码转化为机器可执行的二进制指令。
Android ninja编译启动过程分析---make是如何转换到到ninja编译的1.首先你的得对make的工作机制有个大概的了解:运行的命令在要编译的目录下运行make,或者make target_namea.分析处理保存阶段(没有实际编译动作):它首先对当前目录下的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.mk97include$(BUILD_SYSTEM)/help.mk9899#Set up various standard variables based on configuration100#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:=true107endif108endif116ifeq($(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_NINJA122#Remove ninja build mark if it exists.123$(shell rm-f$(OUT_DIR)/ninja_build)124endif......endif////////!relaunch_with_ninja这里是文件底了接着上面的include build/core/ninja.mkbuild/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)139else140COMBINED_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_ninja118ifndef BUILDING_WITH_NINJA119#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。
android img 的编译过程
Android img的编译过程通常包括以下步骤:
在Android源码根目录下执行初始化环境命令:source build/envsetup.sh。
使用lunch命令选择需要编译的版本,如:lunch full-eng。
执行make命令进行编译,如:make bootimage,这个命令会编译生成boot.img。
boot.img的生成过程主要是将kernel、ramdisk、dtb打包到一起。
在这个过程中,需要用到dtb.img,如果dtb.img过大导致编译不过,那么需要分析dtb.img的生成过程。
dtb.img实际上是将kernel下的dts文件重新命名后拷贝到out目录下生成的。
此外,编译Android系统时,make命令实际上是在执行Makefile文件。
Android系统的Makefile文件在源码根目录下,并且这个Makefile文件会包含另一个主要的Makefile文件,即main.mk。
在main.mk中,定义了一个默认目标droid,这个目标依赖于droid_targets。
droid_targets又依赖于droidcode和dist_files两大伪目标。
当执行make命令时,make工具会检查并解析这些依赖关系,然后按照依赖顺序生成目标文件。
Ubuntu12.04下在Android4.0.4源码下载及其编译过程一、下载源码1、下载工具repo:https:///tools/repo/在本地目录建个bin的文件夹,进入bin文件夹;通过git下载:1.git clone https:///tools/repo下载完成后,进入repo文件夹,切换到稳定分支:1.git checkout -b stable origin/stable将repo命令所在的目录,即/home/yourname/bin/repo添加到环境变量中:1.export PATH=$PATH:~/bin/repo在本地目录下新建目录:android4.0.4,并进入该文件夹:[html]view plaincopy1.cd ~;mkdir android4.0.4;cd android4.0.4;在文件夹下执行下面命令来下载Android源码:1.repo init -u https:///platform/manifest你也可以直接切换到你想要下的版本的分支,而不是“master”分支:1.repo init -u https:///platform/manifest -b android-4.0.4_r2关于到底是哪个分支,根据自己的情况而定,详情可参照:https:///platform/manifest/如你想下载最新的Android4.1代码,即可将分支名称更换成:android-4.1.1_r4你也可以参照官网的下载方式来下载:/source/downloading.html实验证明,我总是在下载那个repo工具的时候,无法连接到相应的地址。
下载是个漫长的过程,下载完成后的大小大概有14G,所以要提前准备好这么大的空间。
下载完成后的目录大概有这些:如图二、编译源码如果你的电脑的环境经常做开发,那么很多环境应该已经搭建好了,如果没有,可以参照官网:/source/initializing.html这里要提醒的是:用apt-get或者ubuntu软件中直接安装的jdk,jre的时候,编译Android是总是编译不过,出现JDK版本不一致的情况;解决办法如下:到oracle官网中下载jdk:/technetwork/java/javase/downloads/index-jsp-138363.html建议下载这个:jdk-6u35-linux-i586.bin下载完成后,运行得到一个jdk1.6.0_35文件夹,然后,将相应的JAVA环境加到系统环境中,简单的可以这样:1.vi ~/.bashrc在.bashrc文件最后添加:1.JAVA_HOME=/home/clw712/tools/jdk1.6.0_352.CLASSPATH=$JAVA_HOME/lib/3.ANDROID_PRODUCT_OUT=/home/clw712/bin/android/out/target/product/generic4.ANDROID=/home/clw712/bin/android5.ANDROID_SWT=/home/clw712/bin/android/out/host/linux-x86/framework6.PATH=$ANDROID/out/host/linux-x86/bin:$ANDROID/prebuilt/android-arm/kernel/:$JAVA_HOME/bin:$ANDROID_PRODUCT_OUT:$PATH7.8.export PATH JAVA_HOME CLASSPATH ANDROID_PRODUCT_OUT ANDROID_SWT当然上述路径还有后面编译好了,用到的路径,是用来运行emulator的。
linaro-android-14.10-panda编译过程及问题解决。
一:编译过程参考linaro的官方网站:/14.10/android/panda/,其中building form source 就是详细的从源码的编译过程。
Run the build scriptThe linaro_android_build_cmds.sh script will download the source and create the build.$ chmod +x linaro_android_build_cmds.sh$ ./linaro_android_build_cmds.sh -h #To print the script usageMost commonly used build options:$ ./linaro_android_build_cmds.sh -t #To build from the tip of the branch without overlay$ ./linaro_android_build_cmds.sh -t -o <overlay> #To build from the tip of the branch with provided overlay$ ./linaro_android_build_cmds.sh -m <pinned_manifest> -o <overlay> #To reproduce an exact build from pinned manifest$ ./linaro_android_build_cmds.sh -t -l <login-id> #Providelogin/access ID to clone and build code from linaro-private repositories二:编译过程出现的问题1:无法下载repo在终端执行以下语句之后$ ./linaro_android_build_cmds.sh -t可以发现无法下载repo,打开linaro_android_build_cmds.sh,到176行可以发现下载repo的语句curl"https:///gitweb?p=tools/repo.git;a=blob_plain; f=repo;hb=refs/heads/stable" > repo将这条语句修改为curl "https://android-/gitweb?p=tools/repo.git;a=blob_plain;f=repo;hb=refs/he ads/stable" > repo就可以正常下载repo了问题的原因是网址更换到 了。
Android编译系统(Android.mk⽂件详解)【Android-NDK(Native Development Kit) docs⽂档】NDK提供了⼀系列的⼯具,帮助开发者快速开发C(或C++)的动态库,并能⾃动将so和java应⽤⼀起打包成apk。
Android.mk⽂件是GNU Makefile的⼀⼩部分,它⽤来对Android程序进⾏编译。
因为所有的编译⽂件都在同⼀个 GNU MAKE 执⾏环境中进⾏执⾏,⽽Android.mk中所有的变量都是全局的。
因此,您应尽量少声明变量,不要认为某些变量在解析过程中不会被定义。
⼀个Android.mk⽂件可以编译多个模块,每个模块属下列类型之⼀:1)APK程序⼀般的Android程序,编译打包⽣成apk⽂件2)JAVA库java类库,编译打包⽣成jar⽂件3)C\C++应⽤程序可执⾏的C\C++应⽤程序4)C\C++静态库编译⽣成C\C++静态库,并打包成.a⽂件5)C\C++共享库编译⽣成共享库(动态链接库),并打包成.so⽂,有且只有共享库才能被安装/复制到您的应⽤软件(APK)包中。
可以在每⼀个Android.mk file 中定义⼀个或多个模块,你也可以在⼏个模块中使⽤同⼀个源代码⽂件。
编译系统为你处理许多细节问题。
例如,你不需要在你的 Android.mk 中列出头⽂件和依赖⽂件。
编译系统将会为你⾃动处理这些问题。
这也意味着,在升级 NDK 后,你应该得到新的toolchain/platform⽀持,⽽且不需要改变你的 Android.mk ⽂件。
注意,NDK的Anroid.mk语法同公开发布的Android平台开源代码的Anroid.mk语法很接近,然⽽编译系统实现他们的⽅式却是不同的,这是故意这样设计的,可以让程序开发⼈员重⽤外部库的源代码更容易。
在描述语法细节之前,咱们来看⼀个简单的"hello world"的例⼦,⽐如,下⾯的⽂件:sources/helloworld/helloworld.csources/helloworld/Android.mk'helloworld.c'是⼀个 JNI 共享库,实现返回"hello world"字符串的原⽣⽅法。
ndk 编译NDK是一种能够让开发者使用C/C++等语言编写Android应用程序的工具集。
NDK被广泛应用于需要高性能和底层硬件控制的应用,例如游戏、多媒体应用等。
NDK编译是将C/C++代码转换成Android应用程序的过程。
在NDK编译过程中,我们需要进行一系列配置和设置,方能使C/C++代码能在Android应用中正确运行。
本文将介绍NDK编译的流程、配置和注意事项。
一、NDK编译流程1、准备工作为了进行NDK编译,我们需要先下载NDK工具集以及安装好Android Studio。
然后,在Android Studio中安装好C++插件,以支持C/C++代码的开发。
2、创建项目在Android Studio中新建一个项目,然后选择“native C++”作为项目类型。
这样可以自动生成一些用于编写C/C++代码的文件和目录。
3、编写代码4、配置gradle文件我们需要在项目的gradle文件中指定编译选项和依赖项。
首先,在build.gradle中添加如下代码:此时,我们需要在CMakeLists.txt文件中指定编译选项和依赖项。
例如:```cppcmake_minimum_required(VERSION 3.4.1)target_link_libraries(native-lib# Android NDK librariesandroidlog)```5、进行编译最后,在Android Studio中点击“Sync Project with Gradle Files”按钮,然后再点击“Build”按钮,即可进行NDK编译。
下面是一些NDK编译的配置和注意事项。
1、指定C++标准和编译选项如果我们的C++代码中使用了某些C++11标准的特性,那么需要在gradle文件中指定C++标准。
例如:```cppexternalNativeBuild {cmake {cppFlags "-std=c++11"}}```我们也可以指定一些编译选项,例如“-O3”代表进行优化。
【转】Android编译系统详解(三)——编译流程详解原⽂⽹址:本⽂原创作者: 欢迎转载,请注明出处和1.概述编译Android的第三步是使⽤mka命令进⾏编译,当然我们也可以使⽤make –j4,但是推荐使⽤mka命令。
因为mka将⾃动计算-j选项的数字,让我们不⽤纠结这个数字到底是多少(这个数字其实就是所有cpu的核⼼数)。
在编译时我们可以带上我们需要编译的⽬标,假设你想⽣成recovery,那么使⽤mka recoveryimage,如果想⽣成ota包,那么需要使⽤mka otapackage,后续会介绍所有可以使⽤的⽬标。
另外注意有⼀些⽬标只是起到修饰的作⽤,也就是说需要和其它⽬标⼀起使⽤,共有4个⽤于修饰的伪⽬标:1) showcommands 显⽰编译过程中使⽤的命令2) incrementaljavac⽤于增量编译java代码3) checkbuild⽤于检验那些需要检验的模块4) all如果使⽤all修饰编译⽬标,会编译所有模块研究Android编译系统时最头疼的可能是变量,成百个变量我们⽆法记住其含义,也不知道这些变量会是什么值,为此我专门做了⼀个编译变量的参考⽹站,你可以在该⽹站查找变量,它能告诉你变量的含义,也会给出你该变量的⽰例值,另外也详细解释了编译系统⾥每个Makefile的作⽤,这样你在看编译系统的代码时不⾄于⼀头雾⽔。
编译的核⼼⽂件是和,main.mk主要作⽤是检查编译环境是否符合要求,确定产品配置,决定产品需要使⽤的模块,并定义了许多⽬标供开发者使⽤,⽐如droid,sdk等⽬标,但是⽣成这些⽬标的规则主要在Makefile⾥定义,⽽内核的编译规则放在build/core/task/kernel.mk我们将先整体介绍main.mk的执⾏流程,然后再针对在Linux上编译默认⽬标时使⽤的关键代码进⾏分析。
Makefile主要定义了各个⽬标的⽣成规则,因此不再详细介绍它的执⾏流程,若有兴趣看每个⽬标的⽣成规则,可查看2. main.mk执⾏流程2.1 检验编译环境并建⽴产品配置1) 设置Shell变量为bash,不能使⽤其它shell2) 关闭make的suffix规则,rcs/sccs规则,并设置⼀个规则: 当某个规则失败了,就删除所有⽬标3) 检验make的版本,cygwin可使⽤任意版本make,但是linux或者mac只能使⽤3.81版本或者3.82版本4) 设置PWD,TOP,TOPDIR,BUILD_SYSTEM等变量,定义了默认⽬标变量,但是暂时并未定义默认⽬标的⽣成规则5) 包含,该makefile定义了两个⽬标help和out, help⽤于显⽰帮助,out⽤于检验编译系统是否正确6) 包含,config.mk作了很多配置,包括产品配置,包含该makefile后,会建⽴输出⽬录系列的变量,还会建⽴PRODUCT系列变量,后续介绍产品配置时,对此会有更多详细介绍7) 包含,该makefile会包含所有⼯程的CleanSpec.mk,写了CleanSpec.mk的⼯程会定义每次编译前的特殊清理步骤,cleanbuild.mk会执⾏这些清除步骤8) 检验编译环境,先检测上次编译结果,如果上次检验的版本和此次检验的版本⼀致,则不再检测,然后进⾏检测并将此次编译结果写⼊2.2 包含其它makefile及编译⽬标检测1) 如果⽬标⾥含有incrementaljavac,那么编译⽬标时将⽤incremental javac进⾏增量编译2) 设置EMMA_INSTRUMENT变量的值,emma是⽤于测试代码覆盖率的库3) 包含,该makefile定义了许多辅助函数4) 包含,该makefile定义了⾼通板⼦的⼀些辅助函数及宏5) 包含,该makefile定义了优化dex代码的⼀些宏6) 检测编译⽬标⾥是否有user,userdebug,eng,如果有则告诉⽤户放置在buildspec.mk或者使⽤lunch设置,检测TARGET_BUILD_VARIANT变量,看是否有效7) 包含, PDK主要是能提⾼现有设备升级能⼒,帮助设备制造商能更快的适配新版本的android2.3 根据TARGET_BUILD_VARIANT建⽴配置1) 如果编译⽬标⾥有sdk,win_sdk或者sdk_addon,那么设置is_sdk_build为true2) 如果定义了HAVE_SELINUX,那么编译时为build prop添加属性ro.build.selinux=13) 如果TARGET_BUILD_VARIANT是user或者userdebug,那么tags_to_install += debug 如果⽤户未定义DISABLE_DEXPREOPT为true,并且是user模式,那么将设置WITH_DEXPREOPT := true,该选项将开启apk的预优化,即将apk分成odex代码⽂件和apk资源⽂件4) 判断enable_target_debugging变量,默认是true,当build_variant是user时,则它是false。
android.bp 编译aidl原理一、引言Android应用程序开发中,Android Interface Definition Language(aidl)是用于定义Android中的进程间通信(IPC)的重要工具。
它主要用于实现跨进程的接口调用,为Android应用程序提供了强大的通信机制。
本文将详细介绍android.bp编译aidl的原理。
二、aidl概述aidl是Android平台上的一个重要组件,它允许不同的应用或服务之间进行跨进程通信。
aidl定义了接口和实现,并生成相应的客户端和服务器代码,以实现进程间的通信。
三、编译aidl的过程1. 编写aidl文件:开发者使用文本编辑器或集成开发环境(IDE)编写aidl文件,该文件描述了需要跨进程调用的接口和实现。
aidl文件使用特殊的XML格式编写,包含了接口名、方法名、参数等信息。
2. 编译aidl:开发者使用构建系统(如Gradle)编译aidl文件。
在编译过程中,aidl工具将解析aidl文件,生成相应的Java接口和实现类。
这些生成的代码将被添加到相应的包中,并在构建过程中被包含到最终的APK文件中。
3. AIDL文件的位置:生成的Java代码通常被放置在`gen`目录下,开发者可以通过在代码中添加`import`语句来使用这些生成的代码。
四、原理分析android.bp编译aidl的原理主要基于以下几个步骤:1. 解析aidl文件:aidl工具首先解析aidl文件,生成相应的Java接口和实现类。
这些类包含了跨进程调用的接口和实现方法。
2. 生成Java代码:生成的Java代码包含了跨进程调用的接口和实现方法,以及必要的序列化和反序列化代码。
这些代码将被添加到相应的包中,并在构建过程中被包含到最终的APK文件中。
3. 添加到构建过程中:在构建过程中,生成的Java代码将被添加到相应的包中,并在编译过程中被编译为字节码。
这些字节码将被打包到最终的APK文件中,供应用程序使用。
本文使用Android版本为2.1,采用开发板为华清远见研发的FS_S5PC100 A8开发板。
+--------------------------------------------------------------------------------------------------------------------+1. source build/envsetup.sh这个命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去,我们来分析下它。
envsetup.sh里的主要命令如下:?根据上面的内容,可以推测出,如果要想定义自己的产品编译项,简单的办法是直接在envset up.sh最后,添加上add_lunch_combo myProduct-eng,当然这么做,不太符合上面代码最后的本意,我们还是老实的在vendor目录下创建自己公司名字,然后在公司目录下创建一个新的vendorsetup.sh,在里面添加上自己的产品编译项?这样,当我们在执行source build/envsetup.sh命令的时候,可以在shell上看到下面的信息:?2. 按照android官网的步骤,开始执行lunch full-eng当然如果你按上述命令执行,它编译的还是通用的eng版本系统,不是我们个性系统,我们可以执行lunch命令,它会打印出一个选择菜单,列出可用的编译选项如果你按照第一步中添加了vendorsetup.sh那么,你的选项中会出现:?其中第3项是我们自己添加的编译项。
lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译项,来定义Product和编译过程中用到的全局变量。
我们一直没有说明前面的fs100-eng是什么意思,现在来说明下,fs100是我定义的产品的名字,eng是产品的编译类型,除了eng外,还有user,userdebug,分别表示:eng: 工程机,user:最终用户机userdebug:调试测试机由此可见,除了eng和user外,另外两个一般不能交给最终用户的,记得m8出来的时候,先放出了一部分eng工程机,然后出来了user机之后,可以用工程机换。
好了,我们来分析下lunch命令干了什么??由上面分析可知,lunch命令可以带参数和不带参数,最终导出一些重要的环境变量,从而影响编译系统的编译结果。
导出的变量如下(以实际运行情况为例)?执行完上述两个步骤,就该执行:make命令了,下篇来分析。
通过上篇文章,我们分析了编译android时source build/envsetup.sh和lunch命令,在执行完上述两个命令后,我们就可以进行编译android了。
1. make执行make命令的结果就是去执行当前目录下的Makefile文件,我们来看下它的内容:?呵呵,看到上面的内容,我们都会笑,这是我见过最简单的Makefile了,我们再看下build/ core/main.mk在main.mk里,定义了变量TOPDIR,TOP为当前目录,BUILD_SYSTEM为build/core目录。
在49行,包含了build/core/config.mk文件。
后面的代码是check环境变量,所有的Makefile都通过build/core/main.mk这个文件组织在一起,它定义了一个默认goals:droid,当我们在TOP目录下,敲M ake实际上就等同于我们执行make droid。
当Make include所有的文件,完成对所有make我文件的解析以后就会寻找生成droid的规则,依次生成它的依赖,直到所有满足的模块被编译好,然后使用相应的工具打包成相应的img。
这儿不是我们的重点,不再多说。
2. build/core/config.mk该文件被main.mk包含。
定义了以下环境变量:?上述命令变量其实是对应的mk文件名,所有的Android.mk文件里基本上都包含上述命令变量,如:CLEAR_VARS:用来清除之前定义的环境变量BUILD_SHARED_LIBRARY:用来指定编译动态库过程?112行又包含了另外一个重要的mk文件envsetup.mk,我们来看一下。
3. envsetup.mk25 ifeq ($(TARGET_PRODUCT),) #判断TARGET_PRODUCT是否为空,26 ifeq ($(TARGET_SIMULATOR),true)27 TARGET_PRODUCT := sim28else29 TARGET_PRODUCT := generic30 endif31 endif第25行,判断TARGET_PRODUCT是否为空,根据上一节分析可知,TARGET_PRODUCT=fs1 0034 # the variant -- the set of files that are included for a build35 ifeq ($(strip $(TARGET_BUILD_VARIANT)),)36 TARGET_BUILD_VARIANT := eng37 endif3839 # Read the product specs so we an get TARGET_DEVICE and other40 # variables that we need in order to locate the output files.41 include $(BUILD_SYSTEM)/product_config.mk在41行又包含了product_config.mk文件,等会我们再分析它,先看下面的148 # ---------------------------------------------------------------149 # figure out the output directories150151 ifeq (,$(strip $(OUT_DIR)))152 OUT_DIR := $(TOPDIR)out153 endif154155 DEBUG_OUT_DIR := $(OUT_DIR)/debug156157 # Move the host or target under the debug/ directory158 # if necessary.159 TARGET_OUT_ROOT_release := $(OUT_DIR)/target160 TARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/target161 TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))162...184 PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)187188 HOST_OUT_EXECUTABLES:= $(HOST_OUT)/bin189 HOST_OUT_SHARED_LIBRARIES:= $(HOST_OUT)/lib190 HOST_OUT_JAVA_LIBRARIES:= $(HOST_OUT)/framework191 HOST_OUT_SDK_ADDON := $(HOST_OUT)/sdk_addon...200 TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj201 TARGET_OUT_HEADERS:= $(TARGET_OUT_INTERMEDIATES)/include202 TARGET_OUT_INTERMEDIATE_LIBRARIES := $(TARGET_OUT_INTERMEDIATES)/lib 203 TARGET_OUT_COMMON_INTERMEDIATES := $(TARGET_COMMON_OUT_ROOT)/obj204205 TARGET_OUT := $(PRODUCT_OUT)/system206 TARGET_OUT_EXECUTABLES:= $(TARGET_OUT)/bin207 TARGET_OUT_OPTIONAL_EXECUTABLES:= $(TARGET_OUT)/xbin208 TARGET_OUT_SHARED_LIBRARIES:= $(TARGET_OUT)/lib209 TARGET_OUT_JAVA_LIBRARIES:= $(TARGET_OUT)/framework210 TARGET_OUT_APPS:= $(TARGET_OUT)/app211 TARGET_OUT_KEYLAYOUT := $(TARGET_OUT)/usr/keylayout212 TARGET_OUT_KEYCHARS := $(TARGET_OUT)/usr/keychars213 TARGET_OUT_ETC := $(TARGET_OUT)/etc214 TARGET_OUT_STATIC_LIBRARIES:= $(TARGET_OUT_INTERMEDIATES)/lib215 TARGET_OUT_NOTICE_FILES:=$(TARGET_OUT_INTERMEDIATES)/NOTICE_FILES 216217 TARGET_OUT_DATA := $(PRODUCT_OUT)/data218 TARGET_OUT_DATA_EXECUTABLES:= $(TARGET_OUT_EXECUTABLES)219 TARGET_OUT_DATA_SHARED_LIBRARIES:= $(TARGET_OUT_SHARED_LIBRARIES) 220 TARGET_OUT_DATA_JAVA_LIBRARIES:= $(TARGET_OUT_JAVA_LIBRARIES)221 TARGET_OUT_DATA_APPS:= $(TARGET_OUT_DATA)/app222 TARGET_OUT_DATA_KEYLAYOUT := $(TARGET_OUT_KEYLAYOUT)223 TARGET_OUT_DATA_KEYCHARS := $(TARGET_OUT_KEYCHARS)224 TARGET_OUT_DATA_ETC := $(TARGET_OUT_ETC)225 TARGET_OUT_DATA_STATIC_LIBRARIES:= $(TARGET_OUT_STATIC_LIBRARIES)226227 TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols228 TARGET_OUT_EXECUTABLES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/bin 229 TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system /lib230 TARGET_ROOT_OUT_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)231 TARGET_ROOT_OUT_SBIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/sbin232 TARGET_ROOT_OUT_BIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/bin233234 TARGET_ROOT_OUT := $(PRODUCT_OUT)/root235 TARGET_ROOT_OUT_BIN := $(TARGET_ROOT_OUT)/bin236 TARGET_ROOT_OUT_SBIN := $(TARGET_ROOT_OUT)/sbin237 TARGET_ROOT_OUT_ETC := $(TARGET_ROOT_OUT)/etc238 TARGET_ROOT_OUT_USR := $(TARGET_ROOT_OUT)/usr239240 TARGET_RECOVERY_OUT := $(PRODUCT_OUT)/recovery241 TARGET_RECOVERY_ROOT_OUT := $(TARGET_RECOVERY_OUT)/root242243 TARGET_SYSLOADER_OUT := $(PRODUCT_OUT)/sysloader244 TARGET_SYSLOADER_ROOT_OUT := $(TARGET_SYSLOADER_OUT)/root245 TARGET_SYSLOADER_SYSTEM_OUT := $(TARGET_SYSLOADER_OUT)/root/system246247 TARGET_INSTALLER_OUT := $(PRODUCT_OUT)/installer248 TARGET_INSTALLER_DATA_OUT := $(TARGET_INSTALLER_OUT)/data249 TARGET_INSTALLER_ROOT_OUT := $(TARGET_INSTALLER_OUT)/root250 TARGET_INSTALLER_SYSTEM_OUT := $(TARGET_INSTALLER_OUT)/root/system上面的代码是指定了目标输出代码的位置和主机输出代码的位置,重要的几个如下:PRODUCT_OUT = 这个的结果要根据product_config.mk文件内容来决定,其实是out/target/pr oduct/fs100/TARGET_OUT = $(PRODUCT_OUT)/systemTARGET_OUT_EXECUTABLES = $(PRODUCT_OUT)/system/binTARGET_OUT_SHARED_LIBRARIES = $(PRODUCT_OUT)/system/libTARGET_OUT_JAVA_LIBRARIES = $(PRODUCT_OUT)/system/frameworkTARGET_OUT_APPS = $(PRODUCT_OUT)/system/appTARGET_OUT_ETC = $(PRODUCT_OUT)/system/etcTARGET_OUT_STATIC_LIBRARIES = $(PRODUCT_OUT)/obj/libTARGET_OUT_DATA = $(PRODUCT_OUT)/dataTARGET_OUT_DATA_APPS = $(PRODUCT_OUT)/data/appTARGET_ROOT_OUT = $(PRODUCT_OUT)/rootTARGET_ROOT_OUT_BIN = $(PRODUCT_OUT)/binTARGET_ROOT_OUT_SBIN = $(PRODUCT_OUT)/system/sbinTARGET_ROOT_OUT_ETC = $(PRODUCT_OUT)/system/etcTARGET_ROOT_OUT_USR = $(PRODUCT_OUT)/system/usr总结下:envsetup.mk文件主要包含了product_config.mk文件,然后指定了编译时要输出的所有文件的OUT目录。