• Android源码编译makefile文件的调试方法


    1. 前言

            在学习Android源码编译的流程时,需要查看一些定义变量值,阅读makefile的代码时需要通过判断条件走到哪个分支,关键是mk文件没有特定的IDE工具去step-by-step调试,最简单原始的方法就是添加打印log,然后在原工程下make,根据打印信息去梳理代码流程和逻辑。

    2. 调试方法

    2.1 使用info

            格式: $(info   这里写需要打印的log信息 ) ,下面为Android源码中的代码例子:

         1.

       $(info   [1/1] initializing build system ...)

         2. 

    1. ifneq ($(filter user userdebug eng,$(MAKECMDGOALS)),)
    2. $(info ***************************************************************)
    3. $(info ***************************************************************)
    4. $(info Do not pass '$(filter user userdebug eng,$(MAKECMDGOALS))' on \
    5. the make command line.)
    6. $(info Set TARGET_BUILD_VARIANT in buildspec.mk, or use lunch or)
    7. $(info choosecombo.)
    8. $(info ***************************************************************)
    9. $(info ***************************************************************)
    10. $(error stopping)
    11. endif

           当然呢,也可以在括号中加入你想打印的变量,比如:

    1. $(info Invalid variant: $(TARGET_BUILD_VARIANT))
    2. $(info Valid values are: $(INTERNAL_VALID_VARIANTS))

    2.2 使用warning

            格式: $(warning   这里写需要打印的log信息 ),下面为源码中的例子:

    1. ifneq ($(dangling_modules),)
    2. $(warning: Modules '$(dangling_modules)' in PRODUCT_PACKAGES have nothing to install!)
    3. endif

    warning:这里会在终端输出你要打印的变量,只是输出一个警告信息,但是编译仍然可以继续

    如下,这是我在源码中自己加的打印语句:

    2.3 使用error

            格式: $(error  这里写需要打印的log信息), 下面为源码中的例子:

    1. ifeq ($(TARGET_CPU_ABI),)
    2. $(error No TARGET_CPU_ABI defined by board config: $(board_config_mk))
    3. endif

    这段代码表达的意思:如果TARGET_CPU_ABI为空, 则走下面的代码, 会提示:

    No TARGET_CPU_ABI defined by board config: build/make/core/board_config.mk

    就是说 TARGET_CPU_ABI 必须定义在 board_config.mk 文件中

    如果使用error调试的话,终端上会打印你的log信息,然后编译到此处就会停止

    2.4 使用echo增加调试信息

    如果你要用echo打印的话,必须遵循makefile的语法规则,就是必须在target之后,如下:

    • :

    • [Tab]

    1. 第一行冒号前为目标,冒号后为前置条件;

    2. 第二行必须由一个Tab键起首,后接命令;目标是必须的,不可省略;

    3. 前置条件和命令是可选的,但两者必须至少存在一个。

    用图来解释更形象一点:

     如下为源码中的例子:
     

    1. samplecode: $(sample_APKS_COLLECTION)
    2. @echo "Collect sample code apks: $^"
    3. # remove apks that are not intended to be installed.
    4. rm -f $(sample_ADDITIONAL_INSTALLED)

    也就是说,使用@echo增加打印log信息的话,必须在这样子的模板中加入,不能平白无故的想加哪里就加哪里,不然就会报错: commands commence before first target 

            当然了,我们再遵循上述规则的情况下,也可以变通一下,在某个makefile中,我想看下代码中某个变量的值,我就是任性,不想用info/warning/error   我就要用echo打印,怎么搞呢?

            我们可以创建一个伪目标(makefile中的语法: .PHONY),如下:

    1. .PHONY: nothing
    2. nothing:
    3. @echo Successfully read the makefiles.
    4. .PHONY: tidy_only
    5. tidy_only:
    6. @echo Successfully make tidy_only.
    7. .PHONY: modules
    8. modules:
    9. @echo "Available sub-modules:"
    10. @echo "打印此变量值: $(ALL_MODULE_TAGS)"

    代码解释: 首先.PHONY是makefile中的关键字, 定义了伪目标 nothing    tidy_only   modules

    1. nothing:
    2. @echo Successfully read the makefiles.

    nothing 作为目标  冒号(:)后面没有依赖文件,满足第3条语法规则( 前置条件和命令是可选的,但两者必须至少存在一个)。

    然后TAB键    打印自己需要的信息

    最后在终端上输出 :Successfully read the makefiles.

  • 相关阅读:
    在kubernetes里使用AppArmor限制容器对资源的访问
    nginx的location的 优先级和匹配方式
    进程调度的基本过程
    【接口测试系列】- 前端交互测试和后端逻辑测试
    如何提高麻辣烫店利润?
    适用于细胞核、细胞膜、线粒体、细胞骨架的成像的荧光探针推荐
    Rust调用同级目录中的rs文件和调用下级目录中的rs文件
    偏向锁、轻量级锁、重量级锁、synchronized的原理
    大二《web课程设计》网页制作HTML个人主题青春网站(带psd)
    Go常见的语法题目
  • 原文地址:https://blog.csdn.net/u012514113/article/details/126406181