编译时是否可以指定相对于用户当前目录的#include 文件路径?

Is it possible to specify a #include file path relative to the user's current directory when compiling?

我知道可以指定 #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 作为我的编译器。

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

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

我设法解决了我的问题。

解决方案的第一部分涉及在编译时在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))))

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

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

-Idir_a -Idir_b

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

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

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