【问题标题】:gcc not respecting my include directory ordergcc 不尊重我的包含目录顺序
【发布时间】:2021-11-22 10:06:07
【问题描述】:

我正在尝试使用本地 ../include/records 目录中包含文件的临时版本来构建一些代码。原始文件位于 /home/apps/include/records 中。我将 gcc 命令设置为在 /home/apps/include 之前搜索 ../include,但它仍在从 /home/apps/include 获取原始模块并报告错误。如果我在 /home/apps/include 中重命名原始文件,那么 gcc 会选择我在本地编辑的副本并编译干净。那么,包含顺序是怎么回事……?这种“本地包含优先”逻辑过去一直对我有用,但这可能是我从 AIX 迁移到 Linux 后第一次使用它。

除了 -I 命令行选项的顺序之外,是否有其他东西可以覆盖所请求的包含顺序?

源模块包含语句为:

#include "records/novarec.h"

gcc 命令行如下所示:

$make
gcc -DLINUX64 -c -g  -I. -I../include  -I/home/apps/include -I/home/apps/include/em -I/home/apps/include/odbc -Wno-implicit-function-declaration -Wno-implicit-int -Wno-format-security -Wno-format-truncation -Wno-discarded-qualifiers  novaget.c

编译器抱怨我的本地 novarec.h 副本中有一个未定义的值,但在生产 /home/apps/include/records/novarec.h 中没有:

novaget.c: In function ‘calcComscoreDemoV1’:
novaget.c:2651:15: error: ‘CSCD_W21_49’ undeclared (first use in this function); did you mean ‘CSCD_W25_49’?
   fval = *(dm+CSCD_W21_49);
               ^~~~~~~~~~~

【问题讨论】:

  • 在 Linux 上如何处理包含文件并没有什么独特之处。您向我们提供了原始文件的完整路径名,但没有提供本地副本的路径。我怀疑本地副本是../include/novarec.h,而应该是../include/records/novarec.h。如果是后者,请查看文件和目录权限。如果这些都没有帮助,您可以将-v -E -dD 选项添加到编译行并查看发生了什么。
  • novarec 的路径是正确的 (../include/records/novarec.h)。但是 -v -E -dD 标志出现了一些有趣的东西:它在 /home 中显示了另一个包含文件/apps/include 还拉入“records/novarec.h”,并从 /home/apps/include/records 获取它。那么,是否有可能因为 gcc 从 /home/apps/include 拉入 file1.h,所以当 file1.h 包含它时,它使用该包含路径拉入 file2.h?

标签: gcc include gnu-make


【解决方案1】:

答案似乎是这样的:

我的模块在 2 个包含文件中调用。第一个还包括第二个 - 第一个位于 /home/apps/include 中。这似乎使 gcc 在那里搜索第二个包含文件 - 即使 /home/apps/include 不是我路径中的第一个包含目录。

当我反转 .c 文件中的 2 个包含语句时,novarec.h 遵循正确的路径。即当我编码时:

#include "spottvdemos.h"  (this modules has a #include "records/novarec.h")
#include "records/novarec.h"

novarec.h 是从 /home/apps/include 获取的,但是当我编码时:

#include "records/novarec.h"
#include "spottvdemos.h"

novarec 是从 ../include 中获取的,这正是我想要的。

【讨论】:

  • 相对路径总是相对于被解析的文件进行解析。我建议不要使用-I../include,而是使用-I$(dir $(CURDIR))include(如果你使用GNU make)来获得完全限定的路径。
  • 有趣。即使正在解析的文件与正在编译的文件位于不同的目录中?这似乎是不必要的混乱。尽管在嵌套包含的情况下,调用模型的作者有可能不知道嵌套的一次,并且可能没有在命令行上指定必要的包含路径。但是,在恢复到嵌套文件的相对路径之前先检查 -I 路径列表有什么害处。哦,好吧,至少现在我知道会发生什么。谢谢。
  • 实际上在实践中,../include 和 $HOME/include 是一样的,这可能更加不言自明。
  • 是的,即使在这种情况下。原因正如您所提到的:编写文件的人,无论它是什么文件,都希望它是那样的,如果不是那样,那将是非常糟糕的。您尝试替换全局空间中的标头的情况实际上是不寻常的。通常你会期望全局头文件找到全局包含文件,本地头文件找到本地包含文件。
  • 我个人建议不要使用$HOME/include,因为它不可重定位:如果您决定将项目移动到其他目录,它将中断。
猜你喜欢
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 1970-01-01
  • 2016-10-13
相关资源
最近更新 更多