【问题标题】:Understanding Makefile rule了解 Makefile 规则
【发布时间】:2021-11-12 15:26:04
【问题描述】:

我一直在调试特定目标(android)的链接错误,对于所有其他目标,构建成功。

错误类似于

Test.cpp:29:57: fatal error: linux/ethtool.h: No such file or directory compilation terminated.
make: *** [../../../makefiles/rules.makefile:1012: android-arm-r/Test.o] Error 1

构建命令是:

make DEBUG=no TARGET=android

我检查了这个 rules.makefile 的 1012 行:

$(OBJDIR)/%.$(OBJ_SUFFIX): %.cpp $(OBJDIR)/%.d 
     @$(cpp_PRECOMPILE) 
     $(cpp_COMMAND) $< 
     @$(cpp_POSTCOMPILE)

现在,作为典型的 make 规则模式,我可以理解 那个,

  • 目标是$(OBJDIR)/%.$(OBJ_SUFFIX)

  • 先决条件是%.cpp $(OBJDIR)/%.d (源文件,主要是Test.cpp,是该目录中唯一的cpp文件)

  • 食谱是

      @$(cpp_PRECOMPILE) 
      $(cpp_COMMAND) $< 
      @$(cpp_POSTCOMPILE)
    

这里,查看其他文件,我可以看到,

cpp_PRECOMPILE is :
cpp_COMMAND is gcc -x c++
cpp_PRECOMPILE is :

所以配方有点像:

     @: 
     /opt/android-arm-r9/bin/arm-linux-androideabi- gcc -x c++ $< 
     @:

现在,我无法理解:

  1. @$ 是干什么用的?

  2. $&lt; 是自动变量保存先决条件名称。但总的来说,这个配方试图做什么?

  3. 当没有给出TARGET 时(默认是linux)

    make CPU=x86_64 DEBUG=no 
    

    完美运行。

    但是当TARGET=android时,它失败了。

    make CPU=x86_64 DEBUG=no TARGET=android
    

【问题讨论】:

  • $(cpp_COMMAND) 的扩展不是$(gcc -x c++)。只是gcc -x c++$(cpp_PRECOMPILE) 的扩展不是$(:) 它只是:$(...) 是变量引用的一部分,在扩展过程中与变量名一起被替换。
  • 如果cpp_COMMAND 变量的值真的只是gcc -x c++,那么对于这个目标来说,这真的是错误的。它应该有更多的内容。但是您没有向我们展示它是如何设置或修改的,所以我们无话可说,除非它是错误的。
  • @MadScientist 你是对的!!实际命令是“$(TOOLSPATH) gcc -x C++”,其中 TOOLSPATH = /opt/android-arm-r9/bin/arm-linux-androideabi-
  • @MadScientist 我已经用 MadScientist 提供的更多信息和一些澄清更新了这个问题。
  • 我很确定您在$(TOOLSPATH)gcc 之间添加的额外空间实际上并不存在于您的makefile 中。不过,这不是我的意思。这里应该有很多额外的标志,而不仅仅是-x。应该有至少一个-c 选项,以及几乎可以肯定的各种-I 和其他选项。您为什么不直接查看 make 实际调用的命令行,它会在您在上面显示的错误之前为您打印出来,并告诉我们它说了什么?

标签: c++ makefile


【解决方案1】:
  1. @$ 有什么用?

@$ 不是一个单位。 @ 是一个前缀,它禁止将命令的输出转发到 make 的输出。 $ 是变量引用 ($(cpp_PRECOMPILE)) 的开头,它扩展为要运行的命令。

  1. $

更具体地说,$&lt; 扩展为 first 先决条件的名称。这对您的情况很重要,因为该规则指定了多个先决条件。

配方中出现的变量名称清楚地表明了配方应该做什么:

  1. $(cpp_PRECOMPILE) -- 某种准备编译的步骤。那可能是什么,也可能什么都不是;它可能取决于其他变量的值,也可能取决于其他因素。

  2. $(cpp_COMMAND) $&lt; -- 编译第一个先决条件命名的源文件。大概是用 C++ 编译器。

  3. $(cpp_POSTCOMPILE) -- 编译后要执行的某种后处理、清理或后续步骤。与预编译步骤一样,这可以是任何东西,也可以什么都不是,细节取决于 makefile 的其他部分。

  1. 当没有给出 TARGET 时(默认是 linux)

    make CPU=x86_64 DEBUG=no
    

    完美运行。

    但是当target=android时,它会失败。

    make CPU=x86_64 DEBUG=no TARGET=android
    

TARGET(和DEBUGCPU)是特定于您的特定makefile 的详细信息,而不是make 通常的功能。我们无法谈论其影响的细节。但是,这些错误消息...

Test.cpp:29:57: fatal error: linux/ethtool.h: No such file or directory compilation terminated.
make: *** [../../../makefiles/rules.makefile:1012: android-arm-r/Test.o] Error 1

... 给出了当前问题的相当清晰的图片:文件Test.cpp,在编译时,尝试#include C 头文件linux/ethtool.h,该文件在交叉中找不到支持您的交叉构建的环境。当您执行不同类型的构建时不会出现错误并不是特别相关。

您应该查看项目的构建要求文档。它可能会指定特定的所需包,对于您尝试执行的交叉构建,可能需要在交叉环境中安装这些包。可能是内核头文件。您可能还想寻求项目维护人员的帮助。

【讨论】:

    【解决方案2】:

    "@" 只是将当前行静音。

    “-x”选项确定语言,因此$(gcc -x c++) $&lt; 将文件(先决条件)编译为 C++ 文件。

    【讨论】:

    • 我不明白为什么当没有给出 TARGET 参数时(默认是 LINUX),它工作得很好。但是如果给定让我们说 TARGET=android,它就会失败。这意味着规则的先决条件具有针对不同目标的灵活配方。
    • TARGET 在这里不是一个选项,它是一个简单的变量,不会出现在您提供的行中。寻找评估的地方并发布它,然后我们可以讨论它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多