android.mk中常见local变量解析

本文详细介绍了Android NDK开发中关键的LOCAL变量配置方法,包括LOCAL_PATH、LOCAL_MODULE等,涉及组件路径设置、模块命名、源文件指定等多个方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     local变量是用来向生成系统描述你的组件的。你应该在'include $(CLEAR_VARS)'和'include $(BUILD_XXXXX)'之间定义其中的一些变量。

1.LOCAL_PATH
   这个变量用来设置当前文件的路径。你必须在Android.mk的开始处定义它,比如:
    
    LOCAL_PATH := $(call my-dir)
   
   这个变量不会被$(CLEAR_VARS)消除,所以每个Android.mk仅需一个定义(以防你在
   同一个文件里定义几个组件)。
 
   
2.LOCAL_MODULE
   定义组件的名称。对于所有的组件名,它必须是唯一,且不能包含空格。
   在include $(BUILD_XXX)之前你必须定义它。
 
   这个组件名决定生成的文件(译者注:即库名)。比如,lib<foo>,即这个组件的名称
   为<foo>。但是在你的NDK生成文件(不管是Android.mk还是Application.mk)中
   你只能通过‘正常’的名称(如,<foo>)来引用其它的组件。
 
         
3.LOCAL_SRC_FILES
   用它来定义所有用来生成组件的源文件。仅须列出传给编译器的文件,因为
   生成系统会自动地计算它们的相互依赖关系。
 
   注意,所有文件名都是相对于LOCAL_PATH的,你可以用到路径组件(path component)
   如:
     LOCAL_SRC_FILES := foo.c \ (译者注:‘\’为连接符)
                         toto/bar.c

       
4.LOCAL_CPP_EXTENSION
   这是一个可选的变量,可用它来指明C++源文件的扩展名。默认情况下是'.cpp',
   但你可以改变它。比如:
   
     LOCAL_CPP_EXTENSION := .cxx

     
   
5.LOCAL_C_INCLUDES
   一个相对于相对于NDK*根*目录可选的路径名单,当编译所有的源文件(C,C++和汇编)时,
   它将被添加进include搜索路径。例如:
  
      LOCAL_C_INCLUDES := sources/foo
 
     或者甚至:
    
      LOCAL_C_INCLUDES := $(LOCAL_PATH)/../foo


6.LOCAL_CFLAGS
    一个可选的编译标记集,在生成C与C++源文件时,将解析它。
   
    对指定额外的宏定义或编译选项很有用。
              
    重要:不要试图改变你Android.mk里的optimization/debuggin level,通过
          在你的Android.mk里指定合适的信息,它将被自动处理,并使NDK生成
          调试时可用的有用的数据文件。
         
    注意:在android-ndk-1.5_r1,相应的标记(flags)只适用于C源文件,对C++
        源文件并不适用。为了适用于完整的Android生成系统的特性,已作了修
        正。(现在,你可以使用LOCAL_CPPFLAGS为C++文件指定标记)

for example!

LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
通过设定编译器操作,优化级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
LOCAL_CFLAGS += -W -Wall
LOCAL_CFLAGS += -fPIC -DPIC
LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter
LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE -DSH_HISTORY
LOCAL_CFLAGS += -DUSEOVERLAY2

(现在,你可以使用LOCAL_CFLAGS为C和C++源文件指定标记)

7.LOCAL_STATIC_LIBRARIES
    一份static libraries组件的名单(以BUILD_STATIC_LIBRARY的方式生成),它将被
    连接到欲生成的组件上。这仅在生成shared library组件时有意义。(译者注:将指定
    的一个或多个static library module转化为一个shared library module)

8.LOCAL_SHARED_LIBRARIES
    一份该组件在运行期依赖于它的shared libraries *组件*。在连接时间(link time)里
    与及为该生成的文件嵌入相应的信息都要用到它。

    注意,它并不将这份组件名单添加入生成图表(build graph)。即,在你的Android.mk
    里,你仍应该将它们加入到你的应用程序要求的组件。

9.LOCAL_LDLIBS
    一份能在生成你的组件时用到的额外的连接器标记(linkerflags)的名单。在传递
    有“-l”前缀的特殊系统库的名称时很有用。比如,下面的语句会告诉连接器在装载
    时间(load time)里生成连接到/system/lib/libz.so的组件。

      LOCAL_LDLIBS := -lz

    若想知道在这个NDK版本可以连接哪些暴露的系统库(exposed system libraries),
    请参见docs/STABLE-APIS。

10.LOCAL_ALLOW_UNDEFINED_SYMBOLS
    缺省值情况下,当尝试生成一个shared library遇到没有定义的引用时,会导致“undefined
    symbol”error。这对在你的源代码里捕捉bugs有很大的帮助。
   
    但是,因为一些原因你须要disable这个检查,将这个变量设置为'true’。注意,相应
    的shared library可能在运行期装载失败。

11.LOCAL_ARM_MODE
    缺省值情况下,ARM目标二进制将会以‘thumb’模式生成,这时每个指令都是16-bit宽的。
    如果你想强迫组件的object文件以‘arm’(32位的指令)的模式生成,你可以将这个变量
    定义为'arm'。即:

      LOCAL_ARM_MODE := arm

    注意,你也可以通过将‘.arm’后缀添加到源文件名字的后面指示生成系统将指定的
    源文件以arm模式生成。例如:
  

       LOCAL_SRC_FILES := foo.c bar.c.arm

    告诉生成系统总是以arm模式编译‘bar.c’,但根据LOCAL_ARM_MODE的值生成foo.c

    注意:在你的Application.mk里将APP_OPTIM设置为'debug',这也会强迫生成ARM二进制
    代码。这是因为工具链的调度器有bugs,它对thumb码的处理不是很好。

12.LOCAL_PRELINK_MODULE
Prelink利用事先链接代替运行时链接的方法来加速共享库的加载,它不仅可以加快起动速度,还可以减少部分内存开销,
是各种Linux架构上用于减少程序加载时间、缩短系统启动时间和加快应用程序启动的很受欢迎的一个工具。程序运行时的
动态链接尤其是重定位(relocation)的开销对于大型系统来说是很大的。
动态链接和加载的过程开销很大,并且在大多数的系统上, 函数库并不会常常被更动, 每次程序被执行时所进行的链接
动作都是完全相同的,对于嵌入式系统来说尤其如此。因此,这一过程可以改在运行时之前就可以预先处理好,即花一些时间
利用Prelink工具对动态共享库和可执行文件进行处理,修改这些二进制文件并加入相应的重定位等信息,节约了本来在程序
启动时的比较耗时的查询函数地址等工作,这样可以减少程序启动的时间,同时也减少了内存的耗用。
Prelink的这种做法当然也有代价:每次更新动态共享库时,相关的可执行文件都需要重新执行一遍Prelink才能保
证有效,因为新的共享库中的符号信息、地址等很可能与原来的已经不同了,这就是为什么 android framework代码一改动,
这时候就会导致相关的应用程序重新被编译。
这种代价对于嵌入式系统的开发者来说可能稍微带来一些复杂度,不过好在对用户来说几乎是可以忽略的。
--------------------
变量设置为false那么将不做prelink操作
LOCAL_PRELINK_MODULE := false
默认是需要prlink的,同时需要在 build/core/prelink-linux-arm.map 中加入
libhellod.so 0x96000000
这个map文件好像是制定动态库的地址的,在前面注释上面有一些地址范围的信息,注意库与库之间的间隔数,
如果指定不好的话编译的时候会提示说地址空间冲突的问题。另外,注意排序,这里要把数大的放到前面去,
按照大小降序排序。
解析 LOCAL_PRELINK_MODULE 变量
build/core/dynamic_binary.mk:94:ifeq ($(LOCAL_PRELINK_MODULE),true)
ifeq ($(LOCAL_PRELINK_MODULE),true)
$(prelink_output): $(prelink_input) $(TARGET_PRELINKER_MAP) $(APRIORI)
$(transform-to-prelinked)
transform-to-prelinked定义:
./build/core/definitions.mk:1002:define transform-to-prelinked
define transform-to-prelinked
@mkdir -p $(dir $@)
@echo "target Prelink: $(PRIVATE_MODULE) ($@)"
$(hide) $(APRIORI) \
--prelinkmap $(TARGET_PRELINKER_MAP) \
--locals-only \
--quiet \
$< \
--output $@
endef
./build/core/config.mk:183:APRIORI := $(HOST_OUT_EXECUTABLES)/apriori$(HOST_EXECUTABLE_SUFFIX)
prelink工具不是常用的prelink而是apriori,其源代码位于” <your_android>/build/tools/apriori”
参考文档:
动态库优化——Prelink(预连接)技术
http://www.eefocus.com/article/09-04/71629s.html

 13.LOCAL_JAVA_LIBRARIES 加入jar包

 

<think>我们正在处理Android构建系统的问题,特别是关于Android.mk文件中变量的继承关系。用户希望直观地查看这些继承关系。 在Android构建系统中,变量可以通过多种方式被设置和继承,包括: 1.Android.mk文件中直接定义。 2. 通过`include`指令引入其他.mk文件,从而继承其中定义的变量。 3. 通过模块定义(如`LOCAL_XXX`变量)以及系统预定义的全局变量。 但是,Android构建系统本身并没有提供直接可视化变量继承关系的工具。因此,我们需要通过一些方法来间接查看。 根据引用[1]中的信息,我们知道`build/make/core/config.mk`是核心配置文件,它初始化了许多全局变量,并且会包含其他配置文件(如`product_config.mk`)。同样,在Android.mk中,我们也会包含一些预定义的配置。 为了查看变量继承关系,我们可以考虑以下方法: 方法1:使用make的调试功能 我们可以使用make的`--print-data-base`(或`-p`)选项来打印所有变量和规则,然后通过过滤来查看特定变量的来源和值。但是,这可能会输出大量信息,需要进一步处理。 方法2:在特定位置打印变量Android.mk中,我们可以使用`$(info ...)`来打印变量值,从而跟踪变量的设置点。 方法3:使用图形化工具(需要额外工具) 有一些工具可以解析Makefile并生成依赖图,但可能不直接支持变量继承关系。我们可以尝试使用`makefile2graph`等工具,但需要额外安装。 然而,用户希望“直观查看”,因此我们可能需要一个更友好的方法。这里,我们结合方法1,并借助一些文本处理工具来生成变量继承的树状图。 具体步骤: 1.Android源代码根目录下运行: ```bash make -p > make_db.txt ``` 这将生成一个包含所有变量和规则的文件。 2. 由于变量可能被多次设置,我们需要找出变量被设置的位置。在make的输出中,变量定义会显示其来源(文件位置)。我们可以使用grep等工具来提取特定变量的信息。 3. 但是,变量继承关系通常是通过包含关系形成的,因此我们需要知道每个变量是在哪个文件中被定义的。在make的输出中,每个变量前面都会有注释,标明它是在哪个文件中定义的。 4. 我们可以编写一个脚本(例如用Python)来解析这个输出,并构建变量定义的文件路径树。但请注意,这可能会比较复杂。 5. 另一种思路:使用make的`-n`(或`--just-print`)选项并结合`-rR`(避免使用内置规则)和`-w`(打印进入和离开目录的信息)来跟踪变量的设置。但这样可能仍然不够直观。 6. 实际上,更简单的方法是:在Android.mk中,我们可以通过打印调用栈来查看变量的来源。例如,我们可以定义一个函数: ```makefile define print_var_origin $(info Variable $(1) is set to: $($(1)) (origin: $(origin $(1)), from file: $(lastword $(MAKEFILE_LIST)), value: $($(1)))) endef ``` 然后在需要的地方调用: ```makefile $(call print_var_origin, MY_VARIABLE) ``` 但是,这种方法需要手动添加,并且只能查看特定变量。 考虑到用户希望查看整个Android.mk变量继承关系,我们可能需要一个更全面的方法。这里,我们可以尝试使用一个名为“Makefile Debugger”的工具,或者使用`remake`(一个增强的make版本)来调试。不过,这些工具可能不在标准Android构建环境中。 因此,我建议以下折中方法: 步骤: 1. 使用`make -p`生成数据库。 2. 从数据库中提取我们关心的变量(比如以`LOCAL_`开头的变量)以及它们的定义位置。 3. 根据定义位置(文件名)和包含关系(通过查看`include`指令)来构建一个包含树。 但是,这需要手动处理包含关系。在Android构建系统中,包含关系是动态的,取决于产品配置等。 因此,另一种思路:在构建过程中,让make输出每个包含的文件以及在该文件中定义的变量。我们可以通过修改config.mk等文件来添加调试信息,但这会侵入构建系统。 鉴于以上复杂性,目前Android构建系统没有内置的工具来可视化变量继承关系。 不过,我们可以通过以下命令来查看某个特定变量的来源: ```bash make -n --debug=v <target> 2>&1 | grep <variable_name> ``` 其中`<target>`可以是你的构建目标(比如`droid`),`<variable_name>`是变量名。`--debug=v`会输出详细的变量信息,包括它们被定义的位置。 但是,由于输出非常冗长,我们可以将其重定向到文件,然后搜索变量。 例如: ```bash make -n --debug=v droid 2> make_debug.txt ``` 然后在`make_debug.txt`中搜索变量名。 在输出中,你会看到类似这样的行: ``` file 'build/make/core/config.mk', line 100: MY_VAR := 'value' ``` 这表示在config.mk的第100行定义了MY_VAR。 通过这种方式,我们可以追溯一个变量的定义位置。但若要查看整个继承关系,则需要收集所有变量,并构建一个包含树。 结论: 目前没有直接的工具可以直观地以图形方式展示Android.mk变量继承关系。但是,我们可以通过上述的调试输出,然后手动或通过脚本分析来构建这样的关系。 如果用户需要自动化,可以编写一个脚本,解析`make -p`的输出或`make --debug=v`的输出,然后生成一个树状结构或图形。 这里提供一个简单的脚本思路: 1. 运行`make -p`,获取所有变量及其定义位置。 2. 解析输出,将每个变量与其定义文件关联。 3. 收集所有包含关系(在输出中,包含关系也会被记录,例如:`include build/make/core/main.mk`)。 4. 构建一个文件包含树,并将变量附加到定义它们的文件节点上。 然后,我们可以输出一个文本树状图,或者使用Graphviz生成图形。 由于编写这样的脚本是一个较大的工程,这里不展开。 因此,对于用户当前的问题,我建议使用`make --debug=v`来查看特定变量的定义位置,从而手动追踪继承关系。 另外,在Android.mk中,我们也可以使用`$(info ...)`来输出变量的值,并配合`$(origin)`函数(返回变量的定义来源,如'file', 'environment', 'command line'等)和`$(value)`(获取变量的值)来调试。 示例: ```makefile $(info LOCAL_PATH = $(LOCAL_PATH) (defined in $(origin LOCAL_PATH), file: $(lastword $(MAKEFILE_LIST)))) ``` 这会在构建时打印出LOCAL_PATH的值和定义位置。 综上所述,查看Android.mk变量继承关系的方法主要有: 1. 使用make的`--debug=v`选项。 2.Android.mk中添加调试信息。 3. 编写自定义脚本解析make的输出(高级)。 希望这些方法能帮助用户。</think>在 Android 构建系统中,查看 `Android.mk` 变量的继承关系需要结合构建日志分析和特定调试技术。以下是系统级查看方法: ### 一、核心查看方法 1. **启用 Make 调试模式** 在构建命令中添加 `--debug=v` 参数,输出变量定义位置: ```bash make -j8 --debug=v | grep -E "LOCAL_|正在定义变量" ``` * 输出示例: `file ./build/core/main.mk, line 100: LOCAL_MODULE := MyApp` 显示变量定义文件和行号[^1] 2. **使用 `dumpvar` 函数** 在 `Android.mk` 添加调试代码: ```makefile $(call dump-vars, LOCAL_MODULE LOCAL_SRC_FILES) # 打印指定变量 $(call dump-many-vars) # 打印所有可见变量 ``` 构建时会在日志中输出完整的变量继承链 3. **追踪包含关系** 使用 `$(info Including $(LOCAL_PATH)/sub.mk)` 标记包含过程: ```makefile include $(CLEAR_VARS) $(info >> 包含层级1: $(MAKEFILE_LIST)) include $(LOCAL_PATH)/sub.mk ``` ### 二、继承关系解析 Android.mk 变量继承遵循以下顺序: ```mermaid graph TD A[全局默认值<br>build/core/config.mk] --> B[产品配置<br>device/<vendor>/<product>.mk] B --> C[模块级定义<br>Android.mk] C --> D[条件覆盖<br>ifeq/ifdef] ``` 1. **全局继承** `build/core/config.mk` 初始化 `TARGET_ARCH`、`HOST_OS` 等基础变量[^1] 2. **产品级继承** `device/<vendor>/<product>/product.mk` 覆盖设备相关变量: ```makefile PRODUCT_NAME := my_device PRODUCT_DEVICE := my_chipset ``` 3. **模块级继承** 在 `Android.mk` 中: ```makefile LOCAL_PATH := $(call my-dir) # 继承当前路径 include $(CLEAR_VARS) # 清除前模块变量 LOCAL_MODULE := foo include $(BUILD_SHARED_LIBRARY) ``` ### 三、高级调试技巧 1. **生成变量依赖图** 安装 `makefile2dot` 工具: ```bash make -pnd > make_db.txt cat make_db.txt | makefile2dot | dot -Tpng -o vars.png ``` 2. **交互式调试** 使用 `mm` 命令构建单个模块并输出变量: ```bash mm showcommands LOCAL_MODULE_TAGS ``` 3. **VSCode 扩展** 安装 `Makefile Tools` 扩展,通过 `makefile.launchConfigurations` 配置变量追踪 > **注意事项**: > - 继承关系受 `include $(CLEAR_VARS)` 影响,该指令会重置模块级变量 > - 使用 `$(origin VAR)` 可检查变量来源(file/command line/environment) > - 产品级变量优先于全局变量,模块级变量优先级最高
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值