编译时是否可以指定相对于用户当前目录的#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 扩展可能不会改善这种情况。
我知道可以指定 #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 扩展可能不会改善这种情况。