限制#include 只搜索当前目录

Restrict #include to only search the current directory

#include 按照惯例使用引号与尖括号来指示预处理器是否应在系统头目录之前搜索当前目录。

假设您只想当前目录搜索,如果找不到该文件则报错并停止。使用路径而不仅仅是文件名是否有效?如

#include "./foo.h"

这将取决于编译器,因为标准称之为 implementation-defined

有趣的是,the GCC docs 也不要以任何一种方式谈论这个,但是,尽管常识表明您的假设是正确的,但对 GCC 4.8.5 的实验表明情况并非如此:

$ mkdir test
$ touch test/inc.h
$ echo '#include "./inc.h"' > test.cpp
$ g++ test.cpp -Itest -c
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)

标准 #include 语法不支持您的要求。

不过,您可以通过两种方式解决此问题:

  1. 如果您只需要包含当前目录中的文件,那么 GCC 标志 -nostdinc 就足够了。它会抑制标准包含路径,让您只看到当前目录。

    $ echo 'int func(void) {return 1;}' > foo.h
    $ echo '#include "foo.h"' | gcc -E -              # success
    $ echo '#include "foo.h"' | gcc -nostdinc -E -    # success
    $ echo '#include "stdio.h"' | gcc -E -            # success
    $ echo '#include "stdio.h"' | gcc -nostdinc -E -  # failure
    
  2. 如果你还希望能够包含其他文件,可以使用命令行定义来指定当前目录的绝对路径,并使用它来包含严格在当前目录中的文件使用其完整路径的目录。这仍然可以让您对其他库使用正常的 include 语法,并且也很容易集成到 Makefile 中。

    要从当前目录 (foo.h) 严格 导入的文件:

    int func(void) {return 1;}
    

    要执行导入的文件 (test.c):

    #define XSTR(x) #x
    #define STR(x) XSTR(x)
    #define ABSOLUTE_PATH(lib) STR(CUR_DIR_PATH/lib)
    
    #include ABSOLUTE_PATH(foo.h)
    

    命令行:

    $ gcc -DCUR_DIR_PATH=$(pwd) -E test.c
    

    #include ABSOLUTE_PATH(stdio.h) 添加到 test.c 将使上述操作按预期失败:

    $ echo '#include ABSOLUTE_PATH(stdio.h)' >> test.c
    $ gcc -DCUR_DIR_PATH=$(pwd) -E test.c
    test.c:7:33: fatal error: /home/marco/stdio.h: No such file or directory
    

    使用 GCC 和 Clang 进行测试,工作正常。