Restrict #include to only search the current directory

Viewed 166

#include by convention uses quotes versus angle brackets to indicate whether the preprocessor should search the current directory before the system header directories.

Suppose you want to search only the current directory, and stop with an error if the file is not found there. Is it valid to do that with a path rather than just a file name? Such as

#include "./foo.h"
2 Answers

Standard #include syntax does not support what you're asking for.

You can however work around the issue in two ways:

  1. If you only need to include files in the current directory, then the GCC flag -nostdinc will suffice. It suppresses standard include paths and leaves you with only the current directory.

    $ 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. If you also want to be able to include other files, you can use a command line define to specify the absolute path of the current directory and use it to include files that are strictly in the current directory by using their full path. This will still let you use the normal include syntax for other libraries and is also pretty easy to integrate in a Makefile.

    File to import strictly from current directory (foo.h):

    int func(void) {return 1;}
    

    File where you want to perform the import (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)
    

    Command line:

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

    Adding #include ABSOLUTE_PATH(stdio.h) to test.c will make the above fail as intended:

    $ 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
    

    Tested with GCC and Clang and it works fine.

This is going to depend on the compiler, since the standard calls it implementation-defined.

Interestingly, the GCC docs also don't talk about this either way but, despite common sense suggesting that your hypothesis is valid, experimentation with GCC 4.8.5 suggests otherwise:

$ 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)
Related