我有一个小构建,我想在其中只包含一个来自不同目录的头文件(和源文件)。我知道如何使用-I参数,但不希望包含整个目录,只包含单个文件。
我的makefile看起来像这样:
myproj: ui.o data.o string.o
c99 -ggdb -o myproj ui.o data.o string.o
ctags *
ui.o : ui.c data.h
c99 -ggdb -c ui.c
data.o : data.c data.h
c99 -ggdb -c data.c
string.o : ../../shared/src/string.c ../../shared/src/string.h
c99 -ggdb -c ../../shared/src/string.c ../../shared/src/string.h -o ./jcstring.o
当我试图让它抱怨找不到string.h
时:
c99 -ggdb -c ui.c ../../shared/src/string.h
In file included from ui.c:7:0:
data.h:1:22: fatal error: string.h: No such file or directory
#include "string.h"
如何在不包含整个目录的情况下包含此文件?
我知道如何使用-I参数,但不希望包含整个目录,只包含单个文件。
-I
不“包含目录”,它只是将目录放在搜索路径上。目录包含您不想要的其他文件并不重要。编译器将读取的唯一文件是名称在#include
指令中的文件。因此,如果您有../../shared/src/string.h
,那么您可以使用以下编译命令:
c99 -ggdb -I ../../shared/src -c ui.c
对于string.
,标头与源文件位于同一目录中。这是编译器首先看到的地方,所以你根本不需要-I
。
c99 -ggdb -c ../../shared/src/string.c -o ./jcstring.o
添加-I
选项可能会受到影响的唯一情况是,在不同目录中是否存在具有相同名称的头文件。例如,如果存在以下所有四个文件:
one/foo.h
one/bar.h
two/foo.h
two/bar.h
并且你想编译包含的代码
#include "foo.h" /* must refer to one/foo.h */
#include "bar.h" /* must refer to two/bar.h */
那么你不能用-I
指令做到这一点。要么你把-I one
放在第一,#include "bar.h"
将包括one/bar.h
,或者你把-I two
放在首位,#include "foo.h"
将包括two/foo.h
。理智的解决方案是不要遇到这个问题。同一项目中的标题应具有唯一的名称。如果您包含来自不同项目的标题,那么您应该在include指令中包含项目名称。
#include "one/foo.h"
#include "two/bar.h"
原则上,您可以将其中一个头文件复制到一个单独的目录并包含它,但在这种情况下,根据典型的命名约定,您可能会遇到项目之间的名称冲突。
另请注意,string.h
不是标题的好名称,因为它是标准库标题的名称。在你的情况下,编译器不会混淆两者:#include "string.h"
在当前目录中查找头文件(如果有),而#include <string.h>
只查找用-I
指定的目录并回退到标准库。可以发生与系统范围内安装的标头的冲突,并且只要您没有错误输入文件名就可以工作,但是人们使用大多数项目中使用的众所周知的标题名称会让人感到困惑。