您的位置:首页 > 移动开发 > Android开发

Android编译中m、mm、mmm 详解

2013-08-31 13:19 155 查看
  Android 完成编译的时候先执行  source build/envsetup.sh。  在这个shell 脚本中定义了 help,  croot, m, mm, mmm 等 function

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

[plain] view
plaincopy

Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:  

- croot:   Changes directory to the top of the tree.  

- m:       Makes from the top of the tree.  

- mm:      Builds all of the modules in the current directory.  

- mmm:     Builds all of the modules in the supplied directories.  

- cgrep:   Greps on all local C/C++ files.  

- jgrep:   Greps on all local Java files.  

- resgrep: Greps on all local res/*.xml files.  

- godir:   Go to the directory containing a file.  


关于source

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


m 的解释

m 的定义如下:

[html] view
plaincopy

561 function m()  

562 {  

563     T=$(gettop)  

564     if [ "$T" ]; then  

565         make -C $T $@  

566     else  

567         echo "Couldn't locate the top of the tree.  Try setting TOP."  

568     fi  

569 }  

570   

当你在任何一个目录下打 m 的时候, 它会执行上面的function. 

gettop 返回源码的顶层目录,如果这个目录存在,比如在我的机器上是:

[html] view
plaincopy

~/Android/an403/external/webkit/Source/WebKit/android/jni/test$ gettop  

/home/mypc/Android/an403  

$@ 返回调用这个脚本时传入的参数

比如我们执行  m showcommands -d

经过 function m 的翻译后就执行

[html] view
plaincopy

make -C /home/yajun/Android/an403 showcommands -d  

当然如果 当前的目录不在源码树里面,gettop 就返回空,这样 m 的结果就时

[html] view
plaincopy

~$ m  

Couldn't locate the top of the tree.  Try setting TOP.  


下面主要讲解mm 

mm 的定义如下,功能是 Builds all of the modules in the current directory.

[html] view
plaincopy

591 function mm()  

592 {  

593     # If we're sitting in the root of the build tree, just do a  

594     # normal make.  

595     if [ -f build/core/envsetup.mk -a -f Makefile ]; then  

596         make $@  

597     else  

598         # Find the closest Android.mk file.  

599         T=$(gettop)  

600         local M=$(findmakefile)  

601         # Remove the path to top as the makefilepath needs to be relative  

602         local M=`echo $M|sed 's:'$T'/::'`  

603         if [ ! "$T" ]; then  

604             echo "Couldn't locate the top of the tree.  Try setting TOP."  

605         elif [ ! "$M" ]; then  

606             echo "Couldn't locate a makefile from the current directory."  

607         else  

608             ONE_SHOT_MAKEFILE=$M make -C $T all_modules $@  

609         fi  

610     fi  

611 }  

从它的注释可以看出,当你在某个目录下执行 mm 的时候,

它首先现判断当前目录是不是 TOP 目录,如果是,就直接开始make 了~

如果不是,就调用findmakefile 寻找 Android.mk , 搜索的路径是 当前目录-> 父目录 -> 父目录 -> ... -> 到根目录

[html] view
plaincopy

571 function findmakefile()  

572 {  

573     TOPFILE=build/core/envsetup.mk  

574     # We redirect cd to /dev/null in case it's aliased to  

575     # a command that prints something as a side-effect  

576     # (like pushd)  

577     local HERE=$PWD  

578     T=   

579     while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do  

580         T=$PWD  

581         if [ -f "$T/Android.mk" ]; then  

582             echo $T/Android.mk  

583             cd $HERE > /dev/null  

584             return  

585         fi  

586         cd .. > /dev/null  

587     done  

588     cd $HERE > /dev/null  

589 }  

文章写到一半 CSDN 挂了。。。

当在某个目录下找到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
plaincopy

439 ifneq ($(ONE_SHOT_MAKEFILE),)                                                    

440 # We've probably been invoked by the "mm" shell function                         

441 # with a subdirectory's makefile.                                                

442 include $(ONE_SHOT_MAKEFILE)                                                     

443 # Change CUSTOM_MODULES to include only modules that were                        

444 # defined by this makefile; this will install all of those                       

445 # modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE           

446 # so that the modules will be installed in the same place they                   

447 # would have been with a normal make.                                            

448 CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS)))          

449 FULL_BUILD :=                                                                    

450 # Stub out the notice targets, which probably aren't defined                     

451 # when using ONE_SHOT_MAKEFILE.                                                  

452 NOTICE-HOST-%: ;                                                                 

453 NOTICE-TARGET-%: ;                                                               

454                                                                                  

455 else # ONE_SHOT_MAKEFILE   

把其中的变量读取进来:

[plain] view
plaincopy

LOCAL_PATH:= $(call my-dir)  

include $(CLEAR_VARS)  

  

LOCAL_SRC_FILES := \  

        main.cpp  

  

# Pull the webkit definitions from the base webkit makefile.  

LOCAL_SHARED_LIBRARIES := libwebcore $(WEBKIT_SHARED_LIBRARIES)  

LOCAL_LDLIBS := $(WEBKIT_LDLIBS)  

  

LOCAL_MODULE := webcore_test  

  

LOCAL_MODULE_TAGS := optional  

  

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
plaincopy

LOCAL_MODULE:=  

LOCAL_MODULE_PATH:=  

LOCAL_MODULE_STEM:=  

LOCAL_DONT_CHECK_MODULE:=  

LOCAL_CHECKED_MODULE:=  

LOCAL_BUILT_MODULE:=  

。。。  

。。。  

在最后一句会 include $(BUILD_EXECUTABLE)  它的定义在:build/core/config.mk:60:BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk

[plain] view
plaincopy

ifeq ($(strip $(LOCAL_MODULE_CLASS)),)  

LOCAL_MODULE_CLASS := EXECUTABLES  

endif  

ifeq ($(strip $(LOCAL_MODULE_SUFFIX)),)  

LOCAL_MODULE_SUFFIX := $(TARGET_EXECUTABLE_SUFFIX)  

endif  

  

include $(BUILD_SYSTEM)/dynamic_binary.mk  

  

ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)  

$(linked_module): $(TARGET_CRTBEGIN_STATIC_O) $(all_objects) $(all_libraries) $(TARGET_CRTEND_O)  

        $(transform-o-to-static-executable)  

else  

$(linked_module): $(TARGET_CRTBEGIN_DYNAMIC_O) $(all_objects) $(all_libraries) $(TARGET_CRTEND_O)  

        $(transform-o-to-executable)  

endif  

到这里相信写过 Makefile 的朋友顿时觉得熟悉了吧,只是这里的 target, dependencies, executable commands 都被变量代替了:

[plain] view
plaincopy

$(linked_module): $(TARGET_CRTBEGIN_DYNAMIC_O) $(all_objects) $(all_libraries) $(TARGET_CRTEND_O)  

        $(transform-o-to-executable)  

如果想进一步了解这里做了什么事情,我们需要知道上面的变量都是什么值,最方便的做法是把他们打印出来。

[plain] view
plaincopy

include $(BUILD_SYSTEM)/dynamic_binary.mk  

$(warning "-------------------------------------------")  

$(warning "linked_modle=$(linked_module)")  

$(warning "TARGET_CRTBEGIN_DYNAMIC_O=$(TARGET_CRTBEGIN_DYNAMIC_O)")  

$(warning "all_objects=$(all_objects)")  

$(warning "all_libraries=$(all_libraries)")  

$(warning "TARGET_CRTEND_O=$(TARGET_CRTEND_O)")  

$(warning "transform-o-to-executable=$(transform-o-to-executable)")  

$(warning "--------------------------------------------")  

ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)  

可以然后就可以看出来这里做要 build 出来的是什么东西啦:

[plain] view
plaincopy

build/core/executable.mk:16: "-------------------------------------------"  

build/core/executable.mk:17: "linked_modle=out/target/product/generic/obj/EXECUTABLES/webcore_test_intermediates/LINKED/webcore_test"  

build/core/executable.mk:18: "TARGET_CRTBEGIN_DYNAMIC_O=out/target/product/generic/obj/lib/crtbegin_dynamic.o"  

build/core/executable.mk:19: "all_objects=   out/target/product/generic/obj/EXECUTABLES/webcore_test_intermediates/main.o           "  

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  "  

build/core/executable.mk:21: "TARGET_CRTEND_O=out/target/product/generic/obj/lib/crtend_android.o"  

build/core/executable.mk:22: "transform-o-to-executable=@mkdir -p   

@echo "target Executable:  ()"  

  -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"  

build/core/executable.mk:23: "--------------------------------------------"  

我们现看一下上面第八行的 dynamic_binary.mk 做了什么事情:

include $(BUILD_SYSTEM)/dynamic_binary.mk

详细见 http://blog.csdn.net/yajun0601/article/details/7309010
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 框架