- 浏览: 61877 次
- 性别:
- 来自: 深圳
最新评论
上文我们讲完LOCAL_STATIC_LIBRARIES,下面我们就一步步来梳理下。BUILD_HOST_EXECUTABLE
一、 初识BUILD_HOST_EXECUTABLE
我们先看BUILD_HOST_EXECUTABLE的定义:
build/core/config.mk:BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
展开即build/core/host_executable.mk
二、 host_executable.mk
我们先看看host_executable.mk文件的注释:
########################################################### ## Standard rules for building an executable file. ## ## Additional inputs from base_rules.make: ## None. ###########################################################
注释中明确的说明了,这是个编译可执行文件的makefile,附加的输入来源于 base_rules.make
LOCAL_IS_HOST_MODULE := true
明确指出了LOCAL_IS_HOST_MODULE 为真,我们在做LOCAL_PATH分析时,多次使用到该变量,当时我们是估计它肯定是为真,但是没有找到其具体的定义位置,看来就是此处了。
ifeq ($(strip $(LOCAL_MODULE_CLASS)),) LOCAL_MODULE_CLASS := EXECUTABLES endif
因为模块的初始化部分调用了include $(CLEAR_VARS),所以$(LOCAL_MODULE_CLASS)的值肯定为空,此处为其赋值为EXECUTABLES。此变量也是用在intermediates-dir-for函数中。
ifeq ($(strip $(LOCAL_MODULE_SUFFIX)),) LOCAL_MODULE_SUFFIX := $(HOST_EXECUTABLE_SUFFIX) endif
同理$(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),这个目标依赖于$(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变量的定义:
LOCAL_BUILT_MODULE := $(built_module_path)/$(LOCAL_BUILT_MODULE_STEM)
$(built_module_path)的定义又来源于:
# OVERRIDE_BUILT_MODULE_PATH is only allowed to be used by the # internal SHARED_LIBRARIES build files. OVERRIDE_BUILT_MODULE_PATH := $(strip $(OVERRIDE_BUILT_MODULE_PATH)) ifdef OVERRIDE_BUILT_MODULE_PATH ifneq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES) $(error $(LOCAL_PATH): Illegal use of OVERRIDE_BUILT_MODULE_PATH) endif built_module_path := $(OVERRIDE_BUILT_MODULE_PATH) else built_module_path := $(intermediates) endif
根
据注释,编译EXECUTABLES时OVERRIDE_BUILT_MODULE_PATH 为空,那么 built_module_path :=
$(intermediates),而$(intermediates)我们之前已经分析过了,它会调用local-intermediates-dir
intermediates := $(call 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_BUILT_MODULE_STEM := $(strip $(LOCAL_BUILT_MODULE_STEM)) ifeq ($(LOCAL_BUILT_MODULE_STEM),) LOCAL_BUILT_MODULE_STEM := $(LOCAL_INSTALLED_MODULE_STEM) endif
同理,此处LOCAL_变量LOCAL_BUILT_MODULE_STEM 肯定为空,那么执行 LOCAL_BUILT_MODULE_STEM := $(LOCAL_INSTALLED_MODULE_STEM)。
LOCAL_INSTALLED_MODULE_STEM在base_rules.make中赋值:
LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE_STEM)$(LOCAL_MODULE_SUFFIX)
LOCAL_MODULE_STEM在base_rules.make中赋值:
LOCAL_MODULE_STEM := $(strip $(LOCAL_MODULE_STEM)) ifeq ($(LOCAL_MODULE_STEM),) LOCAL_MODULE_STEM := $(LOCAL_MODULE) endif
那么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 := \ $(asm_objects) \ $(cpp_objects) \ $(gen_cpp_objects) \ $(gen_asm_objects) \ $(c_objects) \ $(gen_c_objects) \ $(objc_objects) \ $(yacc_objects) \ $(lex_objects) \ $(proto_generated_objects) \ $(addprefix $(TOPDIR)$(LOCAL_PATH)/,$(LOCAL_PREBUILT_OBJ_FILES))
从
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_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 := \ $(built_shared_libraries) \ $(built_static_libraries) \ $(built_whole_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中有该函数的定义:
define transform-host-o-to-executable @mkdir -p $(dir $@) @echo "host Executable: $(PRIVATE_MODULE) ($@)" $(transform-host-o-to-executable-inner) endef
该函数只是创建了一下目标文件夹,输出一下目标,然后调用的还是$(transform-host-o-to-executable-inner)函数
但是请注意,在输出目标时,有一个$(PRIVATE_MODULE)变量,通过输出我们知道在此处$(PRIVATE_MODULE)的值为acp。但是PRIVATE_MODULE变量的定义和使用又是在哪里呢?
目标all_objects依赖目标LOCAL_GENERATED_SOURCES
$(all_objects) : | $(LOCAL_GENERATED_SOURCES)
LOCAL_GENERATED_SOURCES目标的依赖就是PRIVATE_MODULE
$(LOCAL_GENERATED_SOURCES): PRIVATE_MODULE := $(LOCAL_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函数的定义
########################################################### ## Commands for running gcc to link a host executable ########################################################### ifneq ($(HOST_CUSTOM_LD_COMMAND),true) define transform-host-o-to-executable-inner $(hide) $(PRIVATE_CXX) \ -Wl,-rpath-link=$(HOST_OUT_INTERMEDIATE_LIBRARIES) \ -Wl,-rpath,\$$ORIGIN/../lib \ $(HOST_GLOBAL_LD_DIRS) \ $(PRIVATE_LDFLAGS) \ $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \ $(HOST_GLOBAL_LDFLAGS) \ ) \ $(PRIVATE_ALL_OBJECTS) \ -Wl,--whole-archive \ $(call normalize-host-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \ -Wl,--no-whole-archive \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \ $(call normalize-host-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(call normalize-host-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_LDLIBS) endef endif
其
中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
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_INTERMEDIATE_TARGETS): PRIVATE_CXX := $(LOCAL_CXX)
LOCAL_CXX定义如下:
ifeq ($(strip $(LOCAL_CXX)),) LOCAL_CXX := $($(my_prefix)CXX) endif
my_prefix的定义如下:
ifdef LOCAL_IS_HOST_MODULE my_prefix:=HOST_ else my_prefix:=TARGET_ endif
因此在编译acp时,LOCAL_CXX := $(HOST_CXX)
而HOST_CXX的定义并不在HOST_linux-x86.mk文件,而是在select.mk文件中定义:
$(combo_target)CXX := $(ccache) $($(combo_target)CXX)
因此: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++
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的详细定义见下面:
ifneq ($(USE_CCACHE),) //是否采用ccache CCACHE_HOST_TAG := $(HOST_PREBUILT_TAG) # If we are cross-compiling Windows binaries on Linux # then use the linux ccache binary instead. ifeq ($(HOST_OS)-$(BUILD_OS),windows-linux) CCACHE_HOST_TAG := linux-$(BUILD_ARCH) //windows下仍然使用linux的ccache endif ccache := prebuilt/$(CCACHE_HOST_TAG)/ccache/ccache //指定ccache文件 # Check that the executable is here. ccache := $(strip $(wildcard $(ccache))) ifdef ccache //判断ccache文件是否存在, # prepend ccache if necessary ifneq ($(ccache),$(firstword $($(combo_target)CC))) $(combo_target)CC := $(ccache) $($(combo_target)CC) //如果支持ccache,而$($(combo_target)CC)中没有$(ccache),则给$($(combo_target)CC)添加上$(ccache) 前缀,注意$(ccache)和$($(combo_target)CXX)之间有空格 endif ifneq ($(ccache),$(firstword $($(combo_target)CXX))) $(combo_target)CXX := $(ccache) $($(combo_target)CXX) //同理,和$($(combo_target)CC)处理一致 endif ccache = endif endif
其中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:
$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_POST_PROCESS_COMMAND:= $(LOCAL_POST_PROCESS_COMMAND)
我
们发现在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。
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来完成这个补充工作。
发表评论
-
深入浅出Android makefile(4)--LOCAL_STATIC_LIBRARIES
2013-01-01 16:14 21894上文我们讲完LOCAL_SRC_FILES,下面我们 ... -
深入浅出Android makefile(3)--LOCAL_SRC_FILES
2012-12-22 16:49 12966讨论完LOCAL_PATH,我们紧接着来看 ... -
深入浅出Android makefile(2)--LOCAL_PATH
2012-12-22 16:24 9549一、说明 上文我们对acp的Android.m ... -
深入浅出Android makefile(1)--初探
2012-12-22 16:09 7650一、说明 android build system是一个非常 ...
相关推荐
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_...
而对于主机编译,则可以使用`BUILD_HOST_EXECUTABLE`、`BUILD_HOST_SHARED_LIBRARY`和`BUILD_HOST_STATIC_LIBRARY`等宏。 - **安装路径**:为了正确地安装编译后的程序或库,还需要配置相应的安装路径。通过设置`...
### Android移植iperf详解 #### 一、iperf简介与移植意义 iperf是一款广泛使用的网络性能测试工具,主要用于测量TCP和UDP带宽质量。它支持多线程测试及多种平台,包括Linux、Windows等。在Android平台上移植iperf...
- 主机的模板:`include $(BUILD_HOST_EXECUTABLE)`、`include $(BUILD_HOST_SHARED_LIBRARY)`、`include $(BUILD_HOST_STATIC_LIBRARY)` #### 四、安装路径的问题 在Android.mk文件中,可以通过指定`LOCAL_...
本文将深入探讨Android.mk的结构、关键变量和常用指令,帮助开发者更好地理解和利用这一构建工具。 首先,每个Android.mk文件都需要定义`LOCAL_PATH`变量。`LOCAL_PATH`是指包含Android.mk文件的目录路径,通常通过...
pcf8563_i2c1_r8_ruoge_ov2640通过给RTC驱动增加... if (argc < 5) { printf("Usage:\n%s /dev/i2c-x start_addr reg_addr rw[0|1] [write_val]\n", argv[0]); return 0; } fd = open(argv[1], O_RDWR); ...
GEN /home/wwt/linux_r16/lichee/out/sun8iw5p1/linux/common/buildroot/Makefile KCONFIG_AUTOCONFIG=/home/wwt/linux_r16/lichee/out/sun8iw5p1/linux/common/buildroot/build/buildroot-config/auto.conf ...
3. 在$(YOUR_ANDROID)/development/hello/目录编写 Android.mk 文件,这是 Android Makefile 的标准命名,不要更改 Android.mk 文件的格式和内容可以参考其他已有的 Android.mk 文件的写法,针对 helloworld 程序的...
export PATH=$PATH:$ANDROID_HOME/out/host/linux-x86/bin export ANDROID_PRODUCT_OUT=$ANDROID_HOME/out/target/product/generic ``` 完成环境设置后,可以开始创建Android项目。使用`android create project`...
This version includes a resident DPMI host program, DPMIRES.EXE, that allows you to preload the server before invoking TC, TCC, or any other DPMI-hosted executables. If you want to run such hosted ...
This version includes a resident DPMI host program, DPMIRES.EXE, that allows you to preload the server before invoking TC, TCC, or any other DPMI-hosted executables. If you want to run such hosted ...