Android编译中m、mm、mmm 详解

简介:

http://blog.csdn.net/yajun0601/article/details/7309010


  Android 完成编译的时候先执行  source build/envsetup.sh。  在这个shell 脚本中定义了 help,  croot, m, mm, mmm 等 function

之后在当前目录下执行help 可以发现它给出的信息和此前见过linux 下面help 的信息不一样了:

[plain]  view plain copy
  1. Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:  
  2. - croot:   Changes directory to the top of the tree.  
  3. - m:       Makes from the top of the tree.  
  4. - mm:      Builds all of the modules in the current directory.  
  5. - mmm:     Builds all of the modules in the supplied directories.  
  6. - cgrep:   Greps on all local C/C++ files.  
  7. - jgrep:   Greps on all local Java files.  
  8. - resgrep: Greps on all local res/*.xml files.  
  9. - godir:   Go to the directory containing a file.  

关于source

source 命令会把对应脚本中的内容读取到当前的bash 解释器中,在当前的执行环境中执行;其中定义的 function 以及通过 export 声明的变量等在 source 执行结束之后依然存在于当前的bash 环境中。比如我们常用的 source .bashrc 或者 source .profile 等目的是为了引用刚刚改动过的环境变量。


m 的解释

m 的定义如下:
[html]  view plain copy
  1. 561 function m()  
  2. 562 {  
  3. 563     T=$(gettop)  
  4. 564     if [ "$T" ]; then  
  5. 565         make -C $T $@  
  6. 566     else  
  7. 567         echo "Couldn't locate the top of the tree.  Try setting TOP."  
  8. 568     fi  
  9. 569 }  
  10. 570   
当你在任何一个目录下打 m 的时候, 它会执行上面的function. 
gettop 返回源码的顶层目录,如果这个目录存在,比如在我的机器上是:
[html]  view plain copy
  1. ~/Android/an403/external/webkit/Source/WebKit/android/jni/test$ gettop  
  2. /home/mypc/Android/an403  

$@ 返回调用这个脚本时传入的参数
比如我们执行  m showcommands -d
经过 function m 的翻译后就执行
[html]  view plain copy
  1. make -C /home/yajun/Android/an403 showcommands -d  
当然如果 当前的目录不在源码树里面,gettop 就返回空,这样 m 的结果就时
[html]  view plain copy
  1. ~$ m  
  2. Couldn't locate the top of the tree.  Try setting TOP.  

下面主要讲解mm 

mm 的定义如下,功能是 Builds all of the modules in the current directory.
[html]  view plain copy
  1. 591 function mm()  
  2. 592 {  
  3. 593     # If we're sitting in the root of the build tree, just do a  
  4. 594     # normal make.  
  5. 595     if [ -f build/core/envsetup.mk -a -f Makefile ]; then  
  6. 596         make $@  
  7. 597     else  
  8. 598         # Find the closest Android.mk file.  
  9. 599         T=$(gettop)  
  10. 600         local M=$(findmakefile)  
  11. 601         # Remove the path to top as the makefilepath needs to be relative  
  12. 602         local M=`echo $M|sed 's:'$T'/::'`  
  13. 603         if [ ! "$T" ]; then  
  14. 604             echo "Couldn't locate the top of the tree.  Try setting TOP."  
  15. 605         elif [ ! "$M" ]; then  
  16. 606             echo "Couldn't locate a makefile from the current directory."  
  17. 607         else  
  18. 608             ONE_SHOT_MAKEFILE=$M make -C $T all_modules $@  
  19. 609         fi  
  20. 610     fi  
  21. 611 }  

从它的注释可以看出,当你在某个目录下执行 mm 的时候,
它首先现判断当前目录是不是 TOP 目录,如果是,就直接开始make 了~
如果不是,就调用findmakefile 寻找 Android.mk , 搜索的路径是 当前目录-> 父目录 -> 父目录 -> ... -> 到根目录
[html]  view plain copy
  1. 571 function findmakefile()  
  2. 572 {  
  3. 573     TOPFILE=build/core/envsetup.mk  
  4. 574     # We redirect cd to /dev/null in case it's aliased to  
  5. 575     # a command that prints something as a side-effect  
  6. 576     # (like pushd)  
  7. 577     local HERE=$PWD  
  8. 578     T=   
  9. 579     while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do  
  10. 580         T=$PWD  
  11. 581         if [ -f "$T/Android.mk" ]; then  
  12. 582             echo $T/Android.mk  
  13. 583             cd $HERE > /dev/null  
  14. 584             return  
  15. 585         fi  
  16. 586         cd .. > /dev/null  
  17. 587     done  
  18. 588     cd $HERE > /dev/null  
  19. 589 }  

当在某个目录下找到Android.mk后,就把它echo 出来。然后 cd $HERE 返回调用 findmakefile 的目录。
以我在 /home/yajun/Android/an403/external/webkit/Source/WebKit/android/benchmark/ 下执行 mm 为例
findmakefile 的返回结果是 /home/yajun/Android/an403/external/webkit/Source/WebKit/android/benchmark/Android.mk
而 gettop 的返回结果是 /home/yajun/Android/an403
所以执行local M=`echo $M|sed 's:'$T'/::'` 之后, M =external/webkit/Source/WebKit/android/benchmark/Android.mk

ONE_SHOT_MAKEFILE=$M make -C $T all_modules $@ 展开后就是 
ONE_SHOT_MAKEFILE=external/webkit/Source/WebKit/android/benchmark/Android.mk make -C /home/yajun/Android/an403 all_modules

到后面怎么make 的?()
上面的执行就可以看作是:
make -C /home/yajun/Android/an403 all_modules ONE_SHOT_MAKEFILE=external/webkit/Source/WebKit/android/benchmark/Android.mk

接下来的执行会进入到  build/core/main.mk 中,在这里会 include external/webkit/Source/WebKit/android/benchmark/Android.mk
[plain]  view plain copy
  1. 439 ifneq ($(ONE_SHOT_MAKEFILE),)                                                    
  2. 440 # We've probably been invoked by the "mm" shell function                         
  3. 441 # with a subdirectory's makefile.                                                
  4. 442 include $(ONE_SHOT_MAKEFILE)                                                     
  5. 443 # Change CUSTOM_MODULES to include only modules that were                        
  6. 444 # defined by this makefile; this will install all of those                       
  7. 445 # modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE           
  8. 446 # so that the modules will be installed in the same place they                   
  9. 447 # would have been with a normal make.                                            
  10. 448 CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS)))          
  11. 449 FULL_BUILD :=                                                                    
  12. 450 # Stub out the notice targets, which probably aren't defined                     
  13. 451 # when using ONE_SHOT_MAKEFILE.                                                  
  14. 452 NOTICE-HOST-%: ;                                                                 
  15. 453 NOTICE-TARGET-%: ;                                                               
  16. 454                                                                                  
  17. 455 else # ONE_SHOT_MAKEFILE   
把其中的变量读取进来:
[plain]  view plain copy
  1. LOCAL_PATH:= $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3.   
  4. LOCAL_SRC_FILES := \  
  5.         main.cpp  
  6.   
  7. # Pull the webkit definitions from the base webkit makefile.  
  8. LOCAL_SHARED_LIBRARIES := libwebcore $(WEBKIT_SHARED_LIBRARIES)  
  9. LOCAL_LDLIBS := $(WEBKIT_LDLIBS)  
  10.   
  11. LOCAL_MODULE := webcore_test  
  12.   
  13. LOCAL_MODULE_TAGS := optional  
  14.   
  15. include $(BUILD_EXECUTABLE)  
这一段开始的地方会 include $(CLEAR_VARS), 我们可用在下面的地方找到
build/core/config.mk:54:CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
它所做的事情是Clear out values of all variables used by rule templates.
[plain]  view plain copy
  1. LOCAL_MODULE:=  
  2. LOCAL_MODULE_PATH:=  
  3. LOCAL_MODULE_STEM:=  
  4. LOCAL_DONT_CHECK_MODULE:=  
  5. LOCAL_CHECKED_MODULE:=  
  6. LOCAL_BUILT_MODULE:=  
  7. 。。。  
  8. 。。。  
在最后一句会 include $(BUILD_EXECUTABLE)  它的定义在:build/core/config.mk:60:BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
[plain]  view plain copy
  1. ifeq ($(strip $(LOCAL_MODULE_CLASS)),)  
  2. LOCAL_MODULE_CLASS := EXECUTABLES  
  3. endif  
  4. ifeq ($(strip $(LOCAL_MODULE_SUFFIX)),)  
  5. LOCAL_MODULE_SUFFIX := $(TARGET_EXECUTABLE_SUFFIX)  
  6. endif  
  7.   
  8. include $(BUILD_SYSTEM)/dynamic_binary.mk  
  9.   
  10. ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)  
  11. $(linked_module): $(TARGET_CRTBEGIN_STATIC_O) $(all_objects) $(all_libraries) $(TARGET_CRTEND_O)  
  12.         $(transform-o-to-static-executable)  
  13. else  
  14. $(linked_module): $(TARGET_CRTBEGIN_DYNAMIC_O) $(all_objects) $(all_libraries) $(TARGET_CRTEND_O)  
  15.         $(transform-o-to-executable)  
  16. endif  
到这里相信写过 Makefile 的朋友顿时觉得熟悉了吧,只是这里的 target, dependencies, executable commands 都被变量代替了:

[plain]  view plain copy
  1. $(linked_module): $(TARGET_CRTBEGIN_DYNAMIC_O) $(all_objects) $(all_libraries) $(TARGET_CRTEND_O)  
  2.         $(transform-o-to-executable)  

如果想进一步了解这里做了什么事情,我们需要知道上面的变量都是什么值,最方便的做法是把他们打印出来。
[plain]  view plain copy
  1. include $(BUILD_SYSTEM)/dynamic_binary.mk  
  2. $(warning "-------------------------------------------")  
  3. $(warning "linked_modle=$(linked_module)")  
  4. $(warning "TARGET_CRTBEGIN_DYNAMIC_O=$(TARGET_CRTBEGIN_DYNAMIC_O)")  
  5. $(warning "all_objects=$(all_objects)")  
  6. $(warning "all_libraries=$(all_libraries)")  
  7. $(warning "TARGET_CRTEND_O=$(TARGET_CRTEND_O)")  
  8. $(warning "transform-o-to-executable=$(transform-o-to-executable)")  
  9. $(warning "--------------------------------------------")  
  10. ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)  
可以然后就可以看出来这里做要 build 出来的是什么东西啦:
[plain]  view plain copy
  1. build/core/executable.mk:16: "-------------------------------------------"  
  2. build/core/executable.mk:17: "linked_modle=out/target/product/generic/obj/EXECUTABLES/webcore_test_intermediates/LINKED/webcore_test"  
  3. build/core/executable.mk:18: "TARGET_CRTBEGIN_DYNAMIC_O=out/target/product/generic/obj/lib/crtbegin_dynamic.o"  
  4. build/core/executable.mk:19: "all_objects=   out/target/product/generic/obj/EXECUTABLES/webcore_test_intermediates/main.o           "  
  5. build/core/executable.mk:20: "all_libraries=out/target/product/generic/obj/lib/libwebcore.so out/target/product/generic/obj/lib/libc.so out/target/product/generic/obj/lib/libstdc++.so out/target/product/generic/obj/lib/libm.so  "  
  6. build/core/executable.mk:21: "TARGET_CRTEND_O=out/target/product/generic/obj/lib/crtend_android.o"  
  7. build/core/executable.mk:22: "transform-o-to-executable=@mkdir -p   
  8. @echo "target Executable:  ()"  
  9.   -nostdlib -Bdynamic -Wl,-T,build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -o  -Lout/target/product/generic/obj/lib -Wl,-rpath-link=out/target/product/generic/obj/lib   out/target/product/generic/obj/lib/crtbegin_dynamic.o       -Wl,-z,noexecstack -Wl,--icf=safe -Wl,--fix-cortex-a8   prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/armv7-a/libgcc.a out/target/product/generic/obj/lib/crtend_android.o"  
  10. build/core/executable.mk:23: "--------------------------------------------"  

我们现看一下上面第八行的 dynamic_binary.mk 做了什么事情:
include $(BUILD_SYSTEM)/dynamic_binary.mk

相关文章
|
5月前
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
364 1
|
3月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
119 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
3月前
|
编译器 Android开发
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
配置环境变量,使CMakeLists.txt可直接使用Android NDK工具链编译项目
|
3月前
|
Ubuntu Shell API
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
|
5月前
|
Android开发 Docker 容器
docker中编译android aosp源码,出现Build sandboxing disabled due to nsjail error
在使用Docker编译Android AOSP源码时,如果遇到"Build sandboxing disabled due to nsjail error"的错误,可以通过在docker run命令中添加`--privileged`参数来解决权限不足的问题。
995 1
|
5月前
|
Java Android开发 芯片
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
本文介绍了如何将基于全志H713芯片的AOSP Android源码导入Android Studio以解决编译和编码问题,通过操作步骤的详细说明,展示了在Android Studio中利用代码提示和补全功能快速定位并修复编译错误的方法。
222 0
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
|
5月前
|
API 开发工具 Android开发
Android Studio:解决AOSP自编译framework.jar引用不到的问题
在Android Studio中解决AOSP自编译framework.jar引用问题的几种方法,包括使用相对路径、绝对路径和通过`${project.rootDir}`动态获取路径的方法,以避免硬编码路径带来的配置问题。
360 0
Android Studio:解决AOSP自编译framework.jar引用不到的问题
|
5月前
|
搜索推荐 Android开发
学习AOSP安卓系统源代码,需要什么样的电脑?不同配置的电脑,其编译时间有多大差距?
本文分享了不同价位电脑配置对于编译AOSP安卓系统源代码的影响,提供了从6000元到更高价位的电脑配置实例,并比较了它们的编译时间,以供学习AOSP源代码时电脑配置选择的参考。
315 0
学习AOSP安卓系统源代码,需要什么样的电脑?不同配置的电脑,其编译时间有多大差距?
|
5月前
|
Java Android开发
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
698 1
|
5月前
|
Ubuntu 开发工具 Android开发
Repo下载、编译AOSP源码:基于Ubuntu 21.04,android-12.1.0_r27
文章记录了作者在Ubuntu 21.04服务器上配置环境、下载并编译基于Android 12.1.0_r27版本的AOSP源码的过程,包括解决编译过程中遇到的问题和错误处理方法。
260 0