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?
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".
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
include_next is used as a preprocessor directive to tell the compiler to exclude the search paths up to and including filename file.h from resolving to this header file. The typical need is when two header files of the same name need to be used. Use such features sparingly and only when absolutely necessary.
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
Related
When trying to run my makefile (https://pastebin.com/CYqsYtj9), I run into an error:
C:/STM32_Projects/blink_project/test/cpputest/build/MakefileWorker.mk:485: *** multiple target patterns. Stop.
I'm going to link the MakefileWorker.mk as well (https://pastebin.com/5JSy3HsB), even tho I'm pretty sure it's written properly since it's from https://github.com/cpputest/
So, question: why am I getting this error?
EDIT:
When I'm trying to make the makefile from Cygwin CLI, the error I get is the following:
C://STM32_Projects/blink_project//test/cpputest/build/MakefileWorker.mk:485: *** target pattern contains no '%'. Stop.
EDIT 2(Minimal, verifiable example):
// test/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main (int ac, char ** av){
return CommandLineTestRunner::RunAllTests(ac,av);
}
so this is a simple main.cpp that my makefile should compile, other than that, you need a full repo from https://github.com/cpputest/cpputest compiled as shown in README in that repo.
Well, as mentioned I'm no expert when it comes to Windows and I know even less about cygwin.
But, my suspicion is that the environment you're trying to use is not well-supported or well-tested on Windows. Here's what I see:
You set:
PROJECT_DIR=C:/STM32_Projects/blink_project
TEST_DIR=$(PROJECT_DIR)/test
TEST_SRC_DIRS=$(TEST_DIR)
which means TEST_SRC_DIRS is set to C:/STM32_Projects/blink_project/test.
Next in MakefileWorker.mk you get an error because TEST_DEPS is set to objs/C:/STM32_Projects/blink_project/test/main.o ... which, I hope we can all easily see, is a totally bogus path.
So how did we get this path? Let's look backwards and see:
At line 484 we see how TEST_DEPS is set:
TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) ...
So, it's likely the bogus path is in TEST_OBJS. That is set at line 380:
TEST_OBJS = $(call src_to_o,$(TEST_SRC))
First, what's TEST_SRC? It's set on line 379 as the result of the user-defined macro get_src_from_dir_list with TEST_SRC_DIRS (which you set above). That macro will locate all the source files, so files that match *.cpp, *.cc, and *.c in each directory in TEST_SRC_DIRS. So based on the info output we can infer that this returns:
C:/STM32_Projects/blink_project/test/main.cpp
which is to be expected. Then we pass that to src_to_o which is a user-defined macro on line 363, which uses another user-defined macro src_to defined on line 362:
src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2))
Oho!! Well, CPPUTEST_OBJS_DIR is set to obj at line 226, so this is very likely the start of our problem.
In a POSIX filesystem where there is no such abomination as a "drive letter", paths are fully constructable: if you have a fully-qualified path you can create another path by adding a new path as a prefix. That can't work on Windows, where the drive letter must always come first.
But let's keep going. So we see where the obj/ prefix comes from, now where does the rest of the path come from? That's the expansion of a user-defined macro __src_to defined at line 361 that starts with our source path above. What does this do? It wants to replace the .cpp extension with .o. But note this bit here:
$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2)
If CPPUTEST_USE_VPATH is true then we return notdir of the path; this would strip out all the drive and directory info and return just main.cpp which would turn into main.o and then the result would be obj/main.o, which would work fine.
But if CPPUTEST_USE_VPATH is false (which it is by default), we don't strip off the path and obj is added to the full path with the drivespec and you get a syntax error.
So. Basically, the cpputest makefiles have issues on Windows. It looks like you have one of these choices:
Either set the CPPUTEST_USE_VPATH option to Y to enable it (and read about what that option means and how to use it in the cpputest docs),
Or, remove the drive specs from your paths in your makefile and just use:
PROJECT_DIR = /STM32_Projects/blink_project
which means you need to be careful that your current drive is C: before you invoke this else it won't be able to find things.
HTH!
How do I create a custom library in GNU? What I mean is:
When we use #include < stdio.h> and printf
we can compile it with gcc main.c
Now I create my custom headers and .a/.so library files, I know I can set the environment variable C_INCLUDE_PATH and include my header files with #include<> instead of #include"". However, I still have to compile it with
gcc main.c -o program -L/whatever/ -lwahtever
(with set environment variable if using .so)
Is it possible to make it behave like #include< stdio.h> where I don't need to include the paths with corresponding command line arguments?
You actually don't need -L/whatever/, just -lwhatever. The first option supplies the path to your library, but you have already taken care of that with the #include and modifying C_INCLUDE_PATH. The second option tells the linker which library to link your executable with. An example of this is when using functions from the C math library, you #include <math.h>, but to compile, you still need the linker option -lmath. So to answer your question, no. You can remove the first option, but you must leave the second.
When a file contains an include line like this:
#include "name.h"
gcc (and other C compilers) search for the file "name.h" in the directory containing the file being compiled. This does not by default happen if the line looks like this:
#include <name.h>
Is there an option to gcc to make it behave this way in the latter case too? As noted in the gcc documentation, "-I. searches the compiler's current working directory for header files. That may or may not be the same as the directory containing the current file." In the case I am working on (importing external code that used a build environment that automatically added the containing directory to the search path into a system that doesn't have such a build facility), the current directory is unfortunately not the same. What can I do? I'd rather not have to specifically modify the files...
I'm writing library routines of which some characteristics can be tailored through #include'ing a configuration file. However, I'd like this configuration file to be optional, some default parameters being provided in the source. Here is a typical source beginning:
#include "userconf.h"
#ifndef BUFSIZE
#define BUFSIZE 100
#endif
...
where file userconf.h, if it exists, contains:
#define BUFSIZE 255
Standard compilers (gcc or others) consider a missing #include file an error (and they're right!). In this case, and only for this line, I'd like the compiler to continue without objection since default values are provided for parameters expected from the missing configuration file.
Is there a way to do this?
Note: I don't mind checking for this existence of the file from the make system (I'm using CMake) and passing a -Doption if that's easier to do (but, please, provide CMake directives for it, I'm not familiar with it and open documentation gives a hard time to grab the whole picture).
I found the answer "by accident" when including the wrong file.
You make profit of the multiple include directory search feature of the compiler (aka. -I option). You arrange your -I option list in such a way that there is a directory, preferentially at the end of the chain, containing a skeletal version of the configuration file.
For example, directory default/ contains the following userconf.h:
#define BUFSIZE 255
and the developement directory develop/ contains the live userconf.h:
#define BUFSIZE 100
Then, the source file of the original question may be compiled with
gcc source.c -Idevelop -Idefault ...
and -Idevelop may be omitted if it is part of the default searched directories.
I have a rather long list of preprocessor definitions that I want to make available to several C programs that are compiled with gcc.
Basically I could create a huge list of -DDEF1=1 -DDEF2=2 ... options to pass to gcc, but that would create a huge mess, is hard to use in a versioning-system and may at some time in the future break the command line length limit.
I would like to define my defines in a file.
Basically the -imacros would do what I want except that it only passes it to the first source file: (below from the gcc documentation):
-include file Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched
for file is the preprocessor's working directory instead of the
directory containing the main source file. If not found there, it is
searched for in the remainder of the #include "..." search chain as
normal. If multiple -include options are given, the files are included
in the order they appear on the command line.
-imacros file Exactly like -include, except that any output produced by scanning file is thrown away. Macros it defines remain defined.
This allows you to acquire all the macros from a header without also
processing its declarations. All files specified by -imacros are
processed before all files specified by -include.
I need to have the definitions available in all source files, not just the first one.
Look at the bottom of this reference.
What you might want is the #file option. This option tells GCC to use file for command-line options. This file can of course contain preprocessor defines.
Honestly - it sounds like you need to do a bit more in your build environment.
For example, one suggestion is that it sounds like you should create a header file that is included by all your source files and #define all your definitions.
You could also use -include, but specify an explicit path - which should be determined in your Makefile/build environment.
The -imacros would work, if your Makefile were building each source file independently, into its own object file (which is typical). Its sounds like you're just throwing all the sources into building a single object.