【问题标题】:Is it possible to specify a #include file path relative to the user's current directory when compiling?编译时是否可以指定相对于用户当前目录的#include 文件路径?
【发布时间】:2015-06-17 18:43:14
【问题描述】:

我知道可以将#include 文件路径指定为相对于文件所在目录的绝对文件路径,或者相对于$PATH 系统变量中的任何目录。有没有办法在编译程序时相对于用户的当前目录指定它?假设我有以下文件结构:

|--dir_a/
|  |--a.c
|  |--a.h
|--dir_b/
|  |--b.c
|  |--b.h
|--makefile

现在假设我想 #include 来自 dir_b/b.h 的文件 dir_a/a.h。使用dir_b/b.h的位置,可以这样写:

#include ../dir_a/a.h

但是,在我看来,这种方法有一个重大缺陷,因为它硬编码了文件相对于彼此的位置,这意味着重新定位文件需要在包含该文件的所有位置更新文件路径。

使用绝对文件路径可以避免这个问题,而是硬编码项目在文件系统中的位置,这似乎是一种不好的做法。

最后,使用<> 标记来指定文件路径也不可行,因为我不能假设该项目将列在$PATH 变量中。

所以我想要做的是能够指定相对于用户编译的路径(或者更好的是,从 makefile 的位置)。在上面的示例中,这将让我使用以下语句从dir_b/b.h#include dir_a/a.h

#include dir_a/a.h

我认为这将是理想的解决方案。这将使#include 语句更加一致且更易于遵循,并避免我上面列出的缺点。是否有可能以任何方式做到这一点,例如。带有编译器标志或其他东西?我使用gcc 作为我的编译器。

【问题讨论】:

  • $PATH 与此无关。使用-I
  • 这看起来很有希望。我将如何使用它来指定项目的根目录?
  • 使用#include "path/to/file.h" 代替#include <file.h>?
  • 谢谢。这帮助我解决了问题。

标签: c gcc path include


【解决方案1】:

如果你一直使用<> 包含,那么makefile 中的-I 选项就足够了。目录布局在父目录中仅显示一个makefile。那可以用

-Idir_a -Idir_b

在编译器选项中,.c 文件就可以了

#include <a.h>
#include <b.h>

引用包含的问题之一是它们与其他编译器的行为可能不同,如What is the difference between #include &lt;filename&gt; and #include “filename”? 中所述(标准不够明确)。使用 gcc 扩展可能不会改善这种情况。

【讨论】:

  • 关于交叉编译器兼容性的要点。我没有考虑到这一点。同时,编译器(本例中为gcc)已经硬编码到makefile中。这种方法也违反了将&lt;&gt; 用于系统库和"" 用于程序本地头文件的标准做法,这在您链接的问题的最佳答案中提到。最后,在每个目录上使用-I 标志可能会导致在不同目录中存在相同名称文件的文件的情况下发生名称冲突。
  • OP的例子没有你建议的问题。我很久以前就停止使用引用的包含了,因为 gcc 与该领域的大多数其他编译器不同。
  • 好的,认为引用的包含是 C 标准的一部分,但我想不是。但是,如何使用此答案解决由不同目录中同名文件引起的命名冲突?
  • 它们是 - 但是引用的包含是否会在包含包含它的文件的目录中获取文件(没有编译器选项)是不是。括号内的包含更可预测。任何情况下的冲突都是通过-I 选项的顺序来解决的。考虑嵌套包含时,最容易看出差异 - gcc 首先在包含文件的目录中查找,而其他编译器可能不会。可能有人写了一个关于它的页面。
  • 供参考 - 请参阅 xterm patch #85 (1998),其中引用的包含已更改为括号内的包含。
【解决方案2】:

我设法解决了我的问题。

解决方案的第一部分涉及在编译时在gcc 中指定-iquote 标志。来自man gcc

-iquotedir
    Add the directory dir to the head of the list of directories to be searched for header files only for the case of #include "file"; they are not searched for #include <file>, otherwise just like -I.

谜题的第二部分是如何在makefile 本身中获取到makefile 的路径。 This answer 为我工作。为方便起见,我在此处粘贴解决方案:

ROOT_DIR = $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

编辑:虽然这种方法有效,但this answer 对交叉编译器更友好,所以我个人将使用它。

【讨论】:

    【解决方案3】:

    是的。任何不直接在项目链接器设置中指定的include 路径中的包含文件都应指定所有子文件夹,例如:

    #include "first/second/third/folder/library.h"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-23
      • 1970-01-01
      • 1970-01-01
      • 2014-04-14
      • 2010-09-19
      • 2021-04-12
      • 2019-03-08
      相关资源
      最近更新 更多