Why would one use #include_next in a project?
GccIncludeC PreprocessorGcc Problem Overview
To quote the iOS Documentation on Wrapper Headers:
> #include_next
does not distinguish between <file> and "file" inclusion, nor does it check that the file you specify has the same
> name as the current file. It simply looks for the file named, starting
> with the directory in the search path after the one where the current
> file was found.
>
> The use of `#include_next' can lead to great confusion. We recommend
> it be used only when there is no other alternative. In particular, it
> should not be used in the headers belonging to a specific program; it
> should be used only to make global corrections along the lines of
> fixincludes.
So, two questions, what is #include_next, and why would you ever need to use it?
Gcc Solutions
Solution 1 - Gcc
It is used if you want to replace a default header with one of your own making, for example, let's say you want to replace "stdlib.h". You would create a file called stdlib.h in your project, and that would be included instead of the default header.
#include_next is used if you want to add some stuff to stdlib.h rather than replace it entirely. You create a new file called stdlib.h containing:
#include_next "stdlib.h"
int mystdlibfunc();
And the compiler will not include your stdlib.h again recursively, as would be the case with plain a #include, but rather continue in other directories for a file named "stdlib.h".
Solution 2 - Gcc
It's handy if you're supporting multiple versions of something. For example, I'm writing code that supports PostgreSQL 9.4 and 9.6. A number of internal API changes exist, mostly new arguments to existing functions.
Compatibility headers and wrapper functions
I could write compatibility headers with static inline
wrapper functions with new names for everything, basically a wrapper API, where I use the wrapper name everywhere in my code. Say something_compat.h
with:
#include "something.h"
static inline something*
get_something_compat(int thingid, bool missing_ok)
{
assert(!missing_ok);
return get_something(thingid);
}
but it's ugly to scatter _compat
or whatever suffixes everywhere.
Wrapper header
Instead, I can insert a compatibility header in the include path when building against the older version, e.g. compat94/something.h
:
#include_next "something.h"
#define get_something(thingid, missing_ok) \
( \
assert(!missing_ok), \
get_something(thingid) \
)
so the rest of the code can just use the 9.6 signature. When building against 9.4 we'll prefix -Icompat94
to the header search path.
Care is required to prevent multiple evaluation, but if you're using #include_next
you clearly don't mind relying on gcc. In that case you can also use statement expressions.
This approach is handy when the new version is the "primary" target, but backward compatibility for an older version is desired for some limited time period. So you're deprecating the older versions progressively and trying to keep your code clean with reference to the current version.
Alternatives
Or be a sensible person, use C++, and use overloaded functions and template inline functions :p
Solution 3 - Gcc
include_next
###For example:###
source file.c contents with the usual file.h from path 1:####
#include <file.h>
int main() {
printf("out value: %d", out_val);
exit 0;
}
file.h header file in path 1 contents with file.h from path 2 included:####
include_next instructs that path 1 sub directory not be used as search path for file.h and instead use path 2 sub directory as search path. This way you can have 2 files of the same name without the fear of invoking a circular reference to itself.
# include_next <file.h>
int out_val = UINT_MAX - INT_MAX;
file.h in path 2 contents
#define INT_MAX 1<<63 - 1
#define UINT_MAX 1<<64 - 1