Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can the C preprocessor be used to tell if a file exists?

People also ask

How do you check if a header file is included?

To check if an header file has been included or not in a C or C++ code, we need to check if the macro defined in the header file is being defined in the client code. Standard header files like math. h have their own unique macro (like _MATH_H ) which we need to check. Consider this example of checking if math.

Does preprocessor include header files?

The “#include” preprocessor is responsible for directing the compiler that the header file needs to be processed before compilation and includes all the necessary data type and function definitions. Note: We can't include the same header file twice in any program.

What is __ Has_include?

__has_include ( < h-pp-tokens > ) (5) (since C++17) 1) Searches for a header identified uniquely by h-char-sequence and replaces the directive by the entire contents of the header. 2) Searches for a source file identified by q-char-sequence and replaces the directive by the entire contents of the source file.


Little Update

Some compilers might support __has_include ( header-name ).

The extension was added to the C++17 standard (P0061R1).

Compiler Support

  • Clang
  • GCC from 5.X
  • Visual Studio from VS2015 Update 2 (?)

Example (from clang website):

// Note the two possible file name string formats.
#if __has_include("myinclude.h") && __has_include(<stdint.h>)
# include "myinclude.h"
#endif

Sources

  • SD-6: SG10 Feature Test Recommendations
  • Clang Language Extensions

Create a special folder for missing headers, and make that folder to be searched last
(that is compliler specific - last item in "INCLUDES" environment variable, something like that)

Then if some header1.h can be missing, create in that folder a stub

header1.h:

#define header1_is_missing

Now you can always write

#include <header1.h>
#ifdef header1_is_missing

   // there is no header1.h 

#endif

Generally this is done by using a script that tries running the preprocessor on an attempt at including the file. Depending on if the preprocessor returns an error, the script updates a generated .h file with an appropriate #define (or #undef). In bash, the script might look vaguely like this:

cat > .test.h <<'EOM'
#include <asdf.h>
EOM
if gcc -E .test.h
 then
  echo '#define HAVE_ASDF_H 1' >> config.h
 else 
  echo '#ifdef HAVE_ASDF_H' >> config.h
  echo '# undef HAVE_ASDF_H' >> config.h
  echo '#endif' >> config.h
 fi

A pretty thorough framework for portably working with portability checks like this (as well as thousands others) is autoconf.


The preprocessor itself cannot identify the existence of files but you certainly can use the build environment to do so. I'm mostly familiar with make, which would allow you to do something like this in your makefile:

ifdef $(test -f filename && echo "present")
  DEFINE=-DFILENAME_PRESENT
endif

Of course, you'd have to find an analog to this in other build environments like VisualStudio, but I'm sure they exist.