Android源码编译命令

1.编译过程

1) source build/envsetup.sh

2) lunch,选择编译的平台

3)make -j4

##2. 命令介绍

1)m        编译整个android工程

2)mm    编译当前目录下模块,不包括依赖项

3)mmm path  编译指定目录下的模块

4)mma 编译当前目录下所有模块,包括依赖项

5)mmma path 编译指定目录下所有模块,含依赖项

PS: mm/mmm编译较快,mma/mmma会把所有的依赖项一同编译,比较缓慢,首次编译时用mma,以后用mm编译。

3.Android.mk解析

1. mk文件

  一个android子项目中会存在一个或多个Android.mk文件 

1) 单一的Android.mk文件 

直接参考NDK的sample目录下的hello-jni项目,在这个项目中只有一个Android.mk文件 

2) 多个Android.mk文件 

如果需要编译的模块比较多,我们可能会将对应的模块放置在相应的目录中, 这样,我们可以在每个目录中定义对应的Android.mk文件(类似于上面的写法), 最后,在根目录放置一个Android.mk文件,内容如下:

    include $(call all-subdir-makefiles)

只需要这一行就可以了,它的作用就是包含所有子目录中的Android.mk文件 

2. 变量

注意:‘:=’是赋值的意思;’+=’是追加的意思;‘$’表示引用某变量的值。

1)LOCAL_PATH:  这个变量用于给出当前文件的路径。 

  必须在 Android.mk 的开头定义,可以这样使用:
          LOCAL_PATH := $(call my-dir) 

   如当前目录下有个文件夹名称 src,则可以这样写 $(call src),那么就会得到 src 目录的完整路径 

   这个变量不会被$(CLEAR_VARS)清除,因此每个 Android.mk 只需要定义一次(即使在一个文件中定义了几个模块的情况下)。

2)CLEAR_VARS:  必须在开始一个新模块之前包含这个脚本:include$(CLEAR_VARS),用于重置除LOCAL_PATH变量外的,所有LOCAL_XXX系列变量。

3)LOCAL_MODULE: 这是模块的名字,它必须是唯一的,而且不能包含空格。    

4)LOCAL_SRC_FILES:  这是要编译的源代码文件列表。 

   只要列出要传递给编译器的文件,因为编译系统自动计算依赖。注意源代码文件名称都是相对于 LOCAL_PATH的,你可以使用路径部分,例如: 
    LOCAL_SRC_FILES := foo.c toto/bar.c\ 
    Hello.c 
   文件之间可以用空格或Tab键进行分割,换行请用"\" 
   如果是追加源代码文件的话,请用LOCAL_SRC_FILES += 

5)LOCAL_STATIC_LIBRARIES: 表示该模块需要使用哪些静态库,以便在编译时进行链接时就需要

6)LOCAL_SHARED_LIBRARIES:  表示模块在运行时要依赖的共享库(动态库),在链接时就需要

7)LOCAL_LDLIBS:  编译模块时要使用的附加的链接器选项。这对于使用‘-l’前缀传递指定库的名字是有用的。 
   例如,LOCAL_LDLIBS := -lz表示告诉链接器生成的模块要在加载时刻链接到/system/lib/libz.so 
   可查看 docs/STABLE-APIS.TXT 获取使用 NDK发行版能链接到的开放的系统库列表。

8)LOCAL_MODULE_PATH 和 LOCAL_UNSTRIPPED_PATH 
   在 Android.mk 文件中, 还可以用LOCAL_MODULE_PATH 和LOCAL_UNSTRIPPED_PATH指定最后的目标安装路径. 
   不同的文件系统路径用以下的宏进行选择: 
   TARGET_ROOT_OUT:表示根文件系统。 
   TARGET_OUT:表示 system文件系统。 
   TARGET_OUT_DATA:表示 data文件系统。 
   用法如:LOCAL_MODULE_PATH :=$(TARGET_ROOT_OUT) 
9)BUILD_STATIC_LIBRARY:编译为静态库。 
    BUILD_SHARED_LIBRARY :编译为动态库 
    BUILD_EXECUTABLE:编译为Native C可执行程序

4. 编译后的文件

 经过make编译后的产物,都位于/out目录,该目录下主要关注下面几个目录:

1). /out/host:Android开发工具的产物,包含SDK各种工具,比如adb,dex2oat,aapt等。

2) /out/target/common:通用的一些编译产物,包含Java应用代码和Java库;

3) /out/target/product/[product_name]:针对特定设备的编译产物以及平台相关C/C++代码和二进制文件;

其中,有几个重量级的镜像文件:

system.img:挂载为根分区,主要包含Android OS的系统文件;

ramdisk.img:主要包含init.rc文件和配置文件等;

userdata.img:被挂载在/data,主要包含用户以及应用程序相关的数据;

当然还有boot.img,reocovery.img等镜像文件,这里就不介绍了。

##5. 编译遇到的问题

###1. GC overhead limit exceeded
解决:

1
2
3
4
5
export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4g"

./prebuilts/sdk/tools/jack-admin kill-server

./prebuilts/sdk/tools/jack-admin start-server

2. lunch一定要在根目录

lunch一定要在根目录进行,否则会删除之前编译好的文件。

例如:我先全部编译一遍,此时在out目录下生成镜像文件。如果再新建一个Terminal,cd 到其它目录里,source一下,然后lunch,此时我原先编译好的文件都丢失了。

3. 编译完成后刷入镜像

make snod命令