上文我们讲完LOCAL_STATIC_LIBRARIES,下面我们就一步步来梳理下。BUILD_HOST_EXECUTABLE 一、 初识BUILD_HOST_EXECUTABLE 我们先看BUILD_HOST_EXECUTABLE的定义:
展开即build/core/host_executable.mk 二、 host_executable.mk 我们先看看host_executable.mk文件的注释:
注释中明确的说明了,这是个编译可执行文件的makefile,附加的输入来源于 base_rules.make
明确指出了LOCAL_IS_HOST_MODULE 为真,我们在做LOCAL_PATH分析时,多次使用到该变量,当时我们是估计它肯定是为真,但是没有找到其具体的定义位置,看来就是此处了。
因为模块的初始化部分调用了include $(CLEAR_VARS),所以$(LOCAL_MODULE_CLASS)的值肯定为空,此处为其赋值为EXECUTABLES。此变量也是用在intermediates-dir-for函数中。
同理$(LOCAL_MODULE_CLASS)的值肯定为空,因为这里是要编译成可执行文件,linux上可执行文件是没有后缀的,换句话说,在此处 $(HOST_EXECUTABLE_SUFFIX)应该为空,该变量尚未初始化,所以必定为空。 下面又include了一个文件,include $(BUILD_SYSTEM)/binary.mk 但是打开这个文件,好家伙,600多行,怎么分析,不过看来大部分都是一些公共函数的定义。 我们先不管这个文件,继续下面分析。
紧 接着定义了一个目标$(LOCAL_BUILT_MODULE),这个目标依赖于$(all_objects)和$(all_libraries),执行 两个操作:$(transform-host-o-to-executable)和 $(PRIVATE_POST_PROCESS_COMMAND) 首 先,我们先猜测下$(LOCAL_BUILT_MODULE)目标的值,因为LOCAL_IS_HOST_MODULE = true、LOCAL_MODULE_CLASS := EXECUTABLES它肯定是要放在out/host/linux-x86/obj/EXECUTABLES目录下,而LOCAL_MODULE = acp,故肯定是在刚才的目录下创建acp_intermediates文件夹,而$(LOCAL_BUILT_MODULE)的值估计就是:out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp。下面我们就一步步分析下$(LOCAL_BUILT_MODULE) 三、LOCAL_BUILT_MODULE 根据host_executable.mk文件开始处的注释,我们首先去查看下base_rules.make,我们发现在base_rules.make中有LOCAL_BUILT_MODULE变量的定义:
$(built_module_path)的定义又来源于:
根 据注释,编译EXECUTABLES时OVERRIDE_BUILT_MODULE_PATH 为空,那么 built_module_path := $(intermediates),而$(intermediates)我们之前已经分析过了,它会调用local-intermediates-dir
然后根据LOCAL_MODULE_CLASS 、LOCAL_MODULE 和LOCAL_IS_HOST_MODULE 返回一个字符串,在此处,它返回的是out/host/linux-x86/ob/EXECUTABLES/acp_intermediates 那 么LOCAL_BUILT_MODULE的值就是out/host/linux-x86/ob/EXECUTABLES /acp_intermediates/$(LOCAL_BUILT_MODULE_STEM),下面我们在看看 LOCAL_BUILT_MODULE_STEM的定义 这个变量同样也在base_rules.make中赋值:
同理,此处LOCAL_变量LOCAL_BUILT_MODULE_STEM 肯定为空,那么执行 LOCAL_BUILT_MODULE_STEM := $(LOCAL_INSTALLED_MODULE_STEM)。 LOCAL_INSTALLED_MODULE_STEM在base_rules.make中赋值:
LOCAL_MODULE_STEM在base_rules.make中赋值:
那么LOCAL_MODULE_STEM就为 $(LOCAL_MODULE),即acp $(LOCAL_MODULE_SUFFIX)已经在host_executable.mk中讨讨论空,那么LOCAL_INSTALLED_MODULE_STEM 同样为acp,LOCAL_BUILT_MODULE_STEM也为acp 经过上述分析,LOCAL_BUILT_MODULE目标的值为:out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp ,和我们在上面的猜测是一致的。 四、all_objects 和all_libraries 分析完$(LOCAL_BUILT_MODULE),我们来看看$(all_objects) 和$(all_libraries)依赖。 $(BUILD_SYSTEM)/binary.mk中有对all_objects的定义:
从 all_objects定义看出,它表示了所有的objects文件:asm_objects、cpp_objects、 gen_cpp_objects、gen_asm_objects、c_objects、gen_c_objects、objc_objects等等,但 是在此处我们只是关心$(c_objects)。 c_objects又是由c_arm_objects和c_normal_objects构成:
在此处,$(c_arm_objects)为空, $(c_normal_objects)已经在分析LOCAL_SRC_FILES时得到其值为:out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp.o $(BUILD_SYSTEM)/binary.mk中同样有对all_libraries的定义:
all_libraries 表示了所有的libraries文件:built_shared_libraries、built_static_libraries和 built_whole_libraries,不过此处我们只依赖了静态库$(built_static_libraries)。 我 们在分析LOCAL_STATIC_LIBRARIES时,已经得到$(built_static_libraries)的值:out/host /linux-x86/obj/STATIC_LIBRARIES/libhost_intermediates/libhost.a 因此,在编译$(LOCAL_BUILT_MODULE)目标时,我们依赖于:out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp.o 和out/host/linux-x86/obj/STATIC_LIBRARIES/libhost_intermediates/libhost.a 两个目标。 讨论完目标和依赖后,我们来看一看执行的操作。 五、 $(transform-host-o-to-executable) 在build/core/definitions.mk中有该函数的定义:
该函数只是创建了一下目标文件夹,输出一下目标,然后调用的还是$(transform-host-o-to-executable-inner)函数 但是请注意,在输出目标时,有一个$(PRIVATE_MODULE)变量,通过输出我们知道在此处$(PRIVATE_MODULE)的值为acp。但是PRIVATE_MODULE变量的定义和使用又是在哪里呢? 目标all_objects依赖目标LOCAL_GENERATED_SOURCES
LOCAL_GENERATED_SOURCES目标的依赖就是PRIVATE_MODULE
此处PRIVATE_MODULE 定义为 $(LOCAL_MODULE)即acp 至于为什么还需要创建一个PRIVATE_MODULE 变量来表示当前的LOCAL_MODULE,我个人猜测,LOCAL_MODULE变量一般用于内部使用,而PRIVATE_MODULE 变量可以用于全局 $(transform-host-o-to-executable-inner) 下面我们来看看transform-host-o-to-executable-inner函数的定义
其 中transform-host-o-to-executable-inner函数包含在ifneq ($(HOST_CUSTOM_LD_COMMAND),true)判断中,我们发现只有在darwin平台下,该值才为true。即此处还是会使用公共 的transform-host-o-to-executable-inner函数定义。 在本函数中涉及到一下变量,其中有值的变量如下: PRIVATE_CXX: prebuilt/linux-x86/ccache/ccache g++ HOST_OUT_INTERMEDIATE_LIBRARIES: out/host/linux-x86/obj/lib HOST_GLOBAL_LD_DIRS: -Lout/host/linux-x86/obj/lib PRIVATE_LDFLAGS: -Wl,--no-undefined HOST_GLOBAL_LDFLAGS: -m32 PRIVATE_ALL_OBJECTS: out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp.o PRIVATE_ALL_STATIC_LIBRARIES: out/host/linux-x86/obj/STATIC_LIBRARIES/libhost_intermediates/libhost.a 上面变量中最关键的一个是PRIVATE_CXX,它定义在build/core/binary.mk:
LOCAL_CXX定义如下:
my_prefix的定义如下:
因此在编译acp时,LOCAL_CXX := $(HOST_CXX) 而HOST_CXX的定义并不在HOST_linux-x86.mk文件,而是在select.mk文件中定义:
因此:HOST_CXX 和TARGET_CXX 的值在select.mk中已经有了定义,其值分别为: HOST_CXX: prebuilt/linux-x86/ccache/ccache g++ TARGET_CXX: prebuilt/linux-x86/ccache/ccache prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-g++ 而HOST_CXX和TARGET_CXX的详细定义见下面:
其中ccache的定义是在本文件中根据CCACHE_HOST_TAG变量组合而成。 但是 $(HOST_CXX)的定义却是需要跟踪的。在select.mk中有$(combo_target)CXX := $(CXX)赋值,而makefile中 $(CXX)的默认值为g++。 因此,在编译HOST上的文件时,HOST_CXX即为prebuilt/linux-x86/ccache/ccache g++ ,而在编译TARGET上的文件时,TARGET_CXX则是prebuilt/linux-x86/ccache/ccache prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-g++ , 其中TARGET_CXX的定义是在TARGET_linux-arm.mk中 由$(TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)组成。 而$(TARGET_TOOLS_PREFIX)则是根据CCACHE_HOST_TAG变量组合而成。 五、 $(PRIVATE_POST_PROCESS_COMMAND) 在编译$(LOCAL_INTERMEDIATE_TARGETS)目标时,会依赖到PRIVATE_POST_PROCESS_COMMAND,在这里同时给PRIVATE_POST_PROCESS_COMMAND赋值: build/core/base_rules.mk:
我 们发现在build/core/clear_vars.mk中,有LOCAL_POST_PROCESS_COMMAND:=true语句,即我们在调用 include $(CLEAR_VARS)时,LOCAL_POST_PROCESS_COMMAND被设置为true,即 LOCAL_POST_PROCESS_COMMAND的默认值为true 查看build/core/build-system.html,我们发现如下说明: LOCAL_POST_PROCESS_COMMAND For host executables, you can specify a command to run on the module after it's been linked. You might have to go through some contortions to get variables right because of early or late variable evaluation。 简要理解,就是如果你需要在执行完编译链接后,还需要做一些其他的操作来得到想要的结果,那么就使用LOCAL_POST_PROCESS_COMMAND来完成这个补充工作。 |
|
来自: harryyuan > 《makefile》