`
nfer.zhuang
  • 浏览: 61879 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

深入浅出Android makefile(3)--LOCAL_SRC_FILES

 
阅读更多

讨论完LOCAL_PATH,我们紧接着来看看LOCAL_SRC_FILES。

一、LOCAL_SRC_FILES
LOCAL_SRC_FILES := acp.c
LOCAL_SRC_FILES变量的意思见名知意,很明显是用来记录当前模块的源文件列表的一个变量。

这里是他的赋值,我们下面来看看他的使用的地方。在build/core/binary.mk中有如下的部分:
###########################################################
## C: Compile .c files to .o.
###########################################################

c_arm_sources    := $(patsubst %.c.arm,%.c,$(filter %.c.arm,$(LOCAL_SRC_FILES)))
c_arm_objects    := $(addprefix $(intermediates)/,$(c_arm_sources:.c=.o))

c_normal_sources := $(filter %.c,$(LOCAL_SRC_FILES))
c_normal_objects := $(addprefix $(intermediates)/,$(c_normal_sources:.c=.o))

$(c_arm_objects):    PRIVATE_ARM_MODE := $(arm_objects_mode)
$(c_arm_objects):    PRIVATE_ARM_CFLAGS := $(arm_objects_cflags)
$(c_normal_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
$(c_normal_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)

c_objects        := $(c_arm_objects) $(c_normal_objects)

ifneq ($(strip $(c_objects)),)
$(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c $(yacc_cpps) $(proto_generated_headers) $(LOCAL_ADDITIONAL_DEPENDENCIES)
     $(transform-$(PRIVATE_HOST)c-to-o)
-include $(c_objects:%.o=%.P)
endif

 
分析上面的代码,
1. 我们首先从LOCAL_SRC_FILES中得到所有的C文件
     c_normal_sources value acp.c
2. 定义一个变量,c_normal_objects,用来表示生成的.o文件的路径
     c_normal_objects value out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp.o
其中,$(c_normal_sources:.c=.o)会返回acp.o,那么c_normal_objects的关键就是$(intermediates)变量

二、intermediates
通过查找,我们可以发现在以下地方有intermediates的赋值:
build/core/host_java_library.mk:intermediates := $(call local-intermediates-dir)
build/core/base_rules.mk:intermediates := $(call local-intermediates-dir)
build/core/dynamic_binary.mk:guessed_intermediates := $(call local-intermediates-dir)
build/core/java.mk:intermediates := $(call local-intermediates-dir)
即,他们的都是调用local-intermediates-dir函数获取当前的intermediates的值

在build/core/definitions.mk中有local-intermediates-dir函数的定义:
# Uses LOCAL_MODULE_CLASS, LOCAL_MODULE, and LOCAL_IS_HOST_MODULE
# to determine the intermediates directory.
#
# $(1): if non-empty, force the intermediates to be COMMON
define local-intermediates-dir
$(strip \
    $(if $(strip $(LOCAL_MODULE_CLASS)),, \
        $(error $(LOCAL_PATH): LOCAL_MODULE_CLASS not defined before call to local-intermediates-dir)) \
    $(if $(strip $(LOCAL_MODULE)),, \
        $(error $(LOCAL_PATH): LOCAL_MODULE not defined before call to local-intermediates-dir)) \
    $(call intermediates-dir-for,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(LOCAL_IS_HOST_MODULE),$(1)) \
)
endef
根据注释,我们知道 local-intermediates-dir的定义会依赖于LOCAL_MODULE_CLASS, LOCAL_MODULE, 和 LOCAL_IS_HOST_MODULE这三个变量的值。

我们先通过添加打印的方式,得到如下三个变量的值:
LOCAL_MODULE_CLASS value EXECUTABLES
LOCAL_MODULE value acp
LOCAL_IS_HOST_MODULE value true
其中,LOCAL_MODULE 的值是acp,这个肯定的是没问题的,因为在acp模块的Android.mk文件中有明确的定义:LOCAL_MODULE := acp
那LOCAL_MODULE_CLASS 为什么是EXECUTABLES呢?我们这里先猜一下,估计是和最后一句include $(BUILD_HOST_EXECUTABLE )有关,
同样,LOCAL_IS_HOST_MODULE 为true,估计也是和include $(BUILD_HOST _EXECUTABLE)有关了。

我们还是先回到 local-intermediates-dir函数中,其中前两个判断是判断是否定义LOCAL_MODULE_CLASS和LOCAL_MODULE,如果未空,则直接报错,这里也就说明了在每一个编译模块中(即include $(CLEAR_VARS)和include $(BUILD_XXX)之间)必须定义LOCAL_MODULE的值。

因此,如果LOCAL_MODULE_CLASS和LOCAL_MODULE都不为空时,则执行intermediates-dir-for这个函数,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(LOCAL_IS_HOST_MODULE)还有 local-intermediates-dir函数的第一个参数 $(1)会作为参数传给intermediates-dir-for函数。根据上面intermediates的赋值部分的代码,我们知道调用local-intermediates-dir函数时没有传递任何参数,因此此时的$(1)即为空,传给intermediates-dir-for函数的也就只有上述的3个参数。

三、 intermediates-dir-for
下面我们来看intermediates-dir-for
###########################################################
## The intermediates directory.  Where object files go for
## a given target.  We could technically get away without
## the "_intermediates" suffix on the directory, but it's
## nice to be able to grep for that string to find out if
## anyone's abusing the system.
###########################################################

# $(1): target class, like "APPS"
# $(2): target name, like "NotePad"
# $(3): if non-empty, this is a HOST target.
# $(4): if non-empty, force the intermediates to be COMMON
define intermediates-dir-for
$(strip \
    $(eval _idfClass := $(strip $(1))) \
    $(if $(_idfClass),, \
        $(error $(LOCAL_PATH): Class not defined in call to intermediates-dir-for)) \
    $(eval _idfName := $(strip $(2))) \
    $(if $(_idfName),, \
        $(error $(LOCAL_PATH): Name not defined in call to intermediates-dir-for)) \
    $(eval _idfPrefix := $(if $(strip $(3)),HOST,TARGET)) \
    $(if $(filter $(_idfPrefix)-$(_idfClass),$(COMMON_MODULE_CLASSES))$(4), \
        $(eval _idfIntBase := $($(_idfPrefix)_OUT_COMMON_INTERMEDIATES)) \
      , \
        $(eval _idfIntBase := $($(_idfPrefix)_OUT_INTERMEDIATES)) \
     ) \
    $(_idfIntBase)/$(_idfClass)/$(_idfName)_intermediates \
)
endef
根据注释,我们可以知道$(1),$(2),$(3),$(4)这4个参数的意义。
而以下三行则是使用$(1),$(2),$(3)来定义三个临时变量:_idfClass,_idfName 和_idfPrefix 
$(eval _idfClass := $(strip $(1))) 
$(eval _idfName := $(strip $(2)))
$(eval _idfPrefix := $(if $(strip $(3)),HOST,TARGET))
在本例中这三个临时变量的值则为:EXECUTABLES、acp和HOST

下面关键的一个临时变量是_idfIntBase ,我们发现无论$(if $(filter $(_idfPrefix)-$(_idfClass),$(COMMON_MODULE_CLASSES))$(4)是真还是假,
_idfIntBase 的值不是$(HOST_OUT_COMMON_INTERMEDIATES)就是$(HOST_OUT_INTERMEDIATES),因为上面调用时$(4)为空,在这里估计判断结果 应该为假,即应该执行
$(eval _idfIntBase := $($(_idfPrefix)_OUT_INTERMEDIATES))

下面我就看看这个$(HOST_OUT_INTERMEDIATES )到底是一个什么变量。
在build/core/envsetup.mk中有明确的定义:
HOST_OUT_INTERMEDIATES := $(HOST_OUT)/obj 
HOST_OUT也在本文件中定义:
HOST_OUT := $(HOST_OUT_$(HOST_BUILD_TYPE)) 
HOST_BUILD_TYPE默认值为release:
# the host build defaults to release, and it must be release or debug
ifeq ($(HOST_BUILD_TYPE),)
HOST_BUILD_TYPE := release
endif 
因此,
HOST_OUT := $(HOST_OUT_release)
而HOST_OUT_release的定义如下:
HOST_OUT_release := $(HOST_OUT_ROOT_release)/$(HOST_OS)-$(HOST_ARCH)
HOST_OUT_ROOT_release的定义:
HOST_OUT_ROOT_release := $(OUT_DIR)/host 
在Linux上编译,因此HOST_OS := linux ,而我们的机器采用的是Intel Xeon X3440 CPU,即x86架构,因此HOST_ARCH := x86

经过上述分析,
$(HOST_OUT_INTERMEDIATES ) =out/host/linux-x86/obj
intermediates-dir-for 函数返回out/host/linux-x86/ob/EXECUTABLES/acp_intermediates
local-intermediates-dir 函数返回out/host/linux-x86/ob/EXECUTABLES/acp_intermediates
intermediates 变量的值为out/host/linux-x86/ob/EXECUTABLES/acp_intermediates
c_normal_objects 变量的值为out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp.o

四、c_objects
下面我们回到LOCAL_SRC_FILES的编译部分
 c_objects        := $(c_arm_objects) $(c_normal_objects)

ifneq ($(strip $(c_objects)),)
$(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c $(yacc_cpps) $(proto_generated_headers) $(LOCAL_ADDITIONAL_DEPENDENCIES)
     $(transform-$(PRIVATE_HOST)c-to-o)
-include $(c_objects:%.o=%.P)
endif 
其中c_arm_objects为空,c_normal_objects 的值为out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp.o
所以c_objects 的值也为out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp.o

执行c_objects目标时,依赖$(intermediates)/%.o、 $(TOPDIR)$(LOCAL_PATH)/%.c、$(yacc_cpps) 、$(proto_generated_headers)和$(LOCAL_ADDITIONAL_DEPENDENCIES)
执行如下操作: $(transform-$(PRIVATE_HOST)c-to-o)

$(transform-$(PRIVATE_HOST)c-to-o)函数的具体操作,我们暂时不讲,留待后续分析

分享到:
评论

相关推荐

    openjdk-8-src-b132-03_mar_2014-windows-native.zip

    通过深入研究这个压缩包中的源代码,开发者可以更好地理解OpenJDK在Windows环境下的工作原理,进一步提升Java应用程序的性能和稳定性。无论是为现有项目提供维护,还是为了学习Java和操作系统交互的底层机制,这份源...

    core_analyzer-2.18-src_Only_heap_src-only_analyzer_dump_

    "core_analyzer-2.18-src_Only_heap_src-only_analyzer_dump_" 这个标题表明我们正在讨论一个专门用于分析内存堆(heap)的工具,名为 "core analyzer" 的源代码版本,具体是2.18版。"src only" 指出这个版本仅包含...

    Android Makefile_讲解.doc

    LOCAL_SRC_FILES := $(call all-java-files-under, src) ``` 这里`all-java-files-under`宏将查找指定目录下的所有Java文件并将其添加到源文件列表中。 #### 5. SDK版本指定 - **LOCAL_SDK_VERSION**: 定义了该...

    opal-v2_4_0-src

    3. **构建脚本(Build Scripts)**:用于编译和链接OPAL库的脚本,可能包括Makefile、CMakeLists.txt或其他构建工具的配置文件。 4. **测试用例(Test Cases)**:用于验证OPAL库功能的代码,帮助开发者确保代码的...

    qtcreator4.4.1.zip

    需要替换qt-creator-opensource-src-4.4.1/src/libs/3rdparty/botan/目录下的botan.cpp与botan.h文件。 这里的资源就是需要替换的两个文件。 替换后,删除之前编译qtcreator时make过程中产生的中间文件,重新编译...

    openjdk-7-fcs-src-b147-27_jun_2011.zip

    "openjdk-7-fcs-src-b147-27_jun_2011.zip"这个压缩包包含了OpenJDK 7的最终候选版本(Final Candidate Stage)源代码,发布日期为2011年6月27日,版本号为b147。 OpenJDK 7是Java SE 7的主要开发平台,它引入了...

    blink-led-stm8s103-makefile-master_stm32_labview_blink_

    标题“blink-led-stm8s103-makefile-master_stm32_labview_blink_”涉及了几个关键概念,包括STM8S103微控制器、Makefile、STM32系列芯片以及LabVIEW编程环境。这个项目似乎是一个基于STM8S103的LED闪烁程序,使用了...

    u-boot-1.1.6__Makefile.new

    u-boot-1.1.6__Makefile.new

    blink-led-stm8s103-makefile-master_stm32_labview_blink_源码.zip

    这个压缩包文件“blink-led-stm8s103-makefile-master_stm32_labview_blink_源码.zip”包含了一个项目,该项目涉及到STM8S103微控制器、Makefile构建系统以及与STM32和LabVIEW相关的LED闪烁程序。我们可以从以下几个...

    cmake-3.22.1-linux-x86_64.tar.gz

    3. (可选)创建符号链接以方便使用:`sudo ln -s /usr/local/bin/cmake /usr/bin/cmake` 使用CMake时,开发者会在项目根目录下创建一个名为CMakeLists.txt的文件,写入构建指令。例如: ```txt cmake_minimum_...

    xerces-c-src_2_6_0.tar.gz_xerces

    3. **构建脚本**:如Makefile或CMakeLists.txt,用于编译和构建Xerces-C++库。 4. **测试代码**:用于验证Xerces-C++的功能和性能,这些测试用例对于理解库的正确性和边界条件处理非常有帮助。 5. **文档**:可能...

    WWW-Curl-3_per_www_curl.zip

    《WWW-Curl-3_per_www_curl.zip:探索Curl在Web开发中的应用与源码解析》 Curl是一个强大的命令行工具,用于在各种协议下传输数据,包括HTTP、HTTPS、FTP、FTPS等。它在Web开发中扮演着重要的角色,尤其在自动化...

    shell-and-Makefile.rar_makefile_makefile shell_shell_shell Makef

    通过阅读《跟我一起写Makefile.pdf》和《Linux主要shell命令详解.doc》这两份文档,你可以深入理解并掌握这两个关键工具的使用。这将极大地提高你在Linux开发中的效率和生产力,无论是简单的文件操作还是复杂的项目...

    cmake-3.17.1-Linux-x86_64.tar.gz

    3. **设置环境变量**:添加软链接以将CMake命令添加到PATH环境变量中,如`sudo ln -s /usr/local/cmake-3.17.1/bin/cmake /usr/local/bin/cmake`。 4. **验证安装**:通过运行`cmake --version`来检查CMake是否已...

    cmake-3.9.1-linux-x86_64.tar.gz

    3. **创建链接**:接下来,创建符号链接以将CMake命令添加到系统的PATH环境变量中: ```bash sudo ln -s /usr/local/cmake-3.9.1-Linux-x86_64/bin/cmake /usr/local/bin/cmake ``` 4. **验证安装**:安装完成后...

    mplus-loader3-src_ps2_plus3_

    【标题】"mplus-loader3-src_ps2_plus3_" 指的是一个针对PlayStation 2(PS2)游戏机的加载器项目源代码,它可能是"MPlus Loader 3"的一个增强版本,增加了某些特性或优化,特别是"Plus3"可能意味着这是原版MPlus ...

    proteus-lib-master_proteus_zip_PROTEUSLIB_源码.rar

    3. **配置文件(Configuration Files)**:如Makefile或CMakeLists.txt,用于编译和构建过程的配置,指导编译器如何处理源代码。 4. **元器件模型(Component Models)**:如果涉及Proteus的元器件模拟,可能包含...

    生成android.mk文件

    - **LOCAL_SRC_FILES**: 列出需要编译的源文件,可以是多个源文件。 - **LOCAL_C_INCLUDES**: 指定需要包含的头文件路径。 - **LOCAL_STATIC_LIBRARIES / LOCAL_SHARED_LIBRARIES**: 依赖的静态或共享库。 - **LOCAL...

    makefile-doc.rar_doc_linux makefile_makefile_unix makefile

    本资源包"makefile-doc.rar"专注于讲解`Linux`和`Unix`系统下的`Makefile`编写指南,对于开发者来说是极有价值的参考资料。 `Makefile`的基本结构和语法是它的重要组成部分。在`Linux`和`Unix`环境下,`make`命令...

Global site tag (gtag.js) - Google Analytics