CMake : different configure_file() for each target - c

I'm not very familiar with cmake but as the title says what i'd like to do is the following:
I've an header file of configuration (eg config.h.in), in which I'd like to specify all my parameters depending on which target I'm currently calling. So my header file is something like:
#cmakedefine TEST #TEST#
#cmakedefine PINK #PINK#
#ifndef TEST
#define MY_A 10
#endif
#ifdef PINK
#define MY_A 20
#endif
Now, in my CMakeLists.txt I would like to have multiple targets, so for example (actually the config.hfile is just included from other .c files)
add_executable(FirstTarget
something.c
somethingelse.c
config.h
)
add_executable(SecondTarget
something.c
somethingother.c
config.h
)
And what i would really like to do is that FirstTarget And SecondTarget have different configuration file, so what I'm asking is if it possible to run something like
set(TEST Test)
configure_file(config.h.in config.h)
just for target FirstTarget, and then someway running for SecondTarget
set(PINK Test2)
configure_file(config.h.in config.h)
so that if i call make FirstTarget and make SecondTarget they've different configuration parameters each.
Thanks!

The command configure_file creates a "real" file: it has the same content for each target.
However, the created file may contain #ifdef (or other conditional statements), so its interpretation may differ for different target.
Following example uses target_compile_definitions command for "assign" compile definitions for a specific target.
config.h:
#ifndef TEST
#define MY_A 10
#endif
#ifdef PINK
#define MY_A 20
#endif
CMakeLists.txt:
add_executable(FirstTarget ...)
# When "config.h" will be included into this target, it will use "PINK" branch.
target_compile_definitions(FirstTarget PRIVATE PINK)
add_executable(SecondTarget ...)
# When "config.h" will be included into this target, it will use "TEST" branch.
target_compile_definitions(FirstTarget PRIVATE TEST)

Related

Multiple application header files included error in C

I am doing a porting project implemented from INTEGRITY OS to UBUNTU. Facing compiler error as explained below. Even though not compiled in INTEGRITY OS, i think there is no errors there.
I got the root cause. I am expecting solution how i can achieve this.
main.c
#include "file1.h"
#include "file2.h"
#include "file3.h"
.
.
.
Inside all the files from
file1.h to file3.h below is there at the beginning of each file.
#ifdef INC_HEADER_FILE
#error Multiple header files included.
#endif
#define INC_HEADER_FILE
.
.
.
Above throws error while compiling
In file included from ../main.c:
../file1.h: error: #error Multiple application header files included.
# error Multiple application header files included.
^~~~~
Same error is thrown for all the files for file1.h to file3.h
If all three (or however many there are) of those header files use the same symbol INC_HEADER_FILE, then you will only be allowed to include one of them.
That's because including (for example) file1.h will set that symbol, meaning that including the next header will complain because it's already defined.
The include guard symbol is usually specific to the header file itself, such as INC_HEADER_1_FILE but it's my no means necessary - I've seen this sort of thing done when you only want one variation of a header file.
An example of that is a system I worked on for LED display devices where each header had different dimensions. These were constructed from 8x8 units but different quantities across and down. Having the LED addressing map in a header file allowed for efficiencies that weren't available with dynamic configuration and the include guard made sure we didn't try to use more than one map.
regarding the include guard for header1.h suggest:
#ifndef HEADER1_H
#define HEADER1_H
...
#endif
regarding the include guard for header2.h suggest:
#ifndef HEADER2_H
#define HEADER2_H
....
#endif
and similar for each header file.
The result is in any one compilation unit (source file.c) any specific header file can only be included once.

Include header file if it exists to redefine macros in C

I have two header files, one that is a library with a number of default macros defined
i.e:
libraryheader.h:
#define ANAME 1
#define BNAME 2
.
.
.
and I want to be able to have another optional header that the user can supply to redefine these macros in the project
optional.h:
#define ANAME 5
#define BNAME 15
.
.
.
The header optional.h doesn't always exist and I only want to include it if it does exist. Is there a way in the makefile or library header to check if this header exists and redefine the macros.
I'm thinking to check if the file exists in the makefile and set a flag by putting the following in the makefile
ifdef $(test -f optional.h && echo "present")
and then somehow check the flag macro in the library header.
But I haven't had any success yet. Thank you
As #Matt mentioned in comment "wildcard" can be used.
However, when I tested it using a small program I had to do the following things.
If I include the "optional.h" in my .c file always, then it will give build error when the .h file is not present. Similarly, if I dont include, even if the file is present I will not be able to update the macros. So I did the following in my makefile.
CFLAGS += $(if $(wildcard ./optional.h),-include ./optional.h -DINCLUDE_OPTIONAL_H)
In my .c file I used INCLUDE_OPTIONAL_H for including the optional.h as below.
#ifdef INCLUDE_OPTIONAL_H
#include "optional.h"
#endif
In optional.h, I checked if a macro is already defined and undefined it and then updated it.
#ifdef ANAME
#undef ANAME
#endif
#define ANAME <new_value>

Multiple #ifndef statements - which one gets applied

Say I have five files: main.c, sample1.c, sample1.h, sample2.c and sample2.h, where in each of these files DEBUG_PRINTS is defined as follows:
#ifndef DEBUG_PRINTS
#define DEBUG_PRINTS 0
#endif
and the code is compiled using gcc:
gcc -Wall main.c sample1.c sample2.c -o main
Now I change the value of DEBUG_PRINTS in one file to 1. Without printing to the terminal how can you determine, which value will be applied?
Additionally, how can I define DEBUG_PRINTS locally per file - the same as using the static keyword for variables?
Each file is compiled separately. Macros from one file are not visible in any other file. Once the files are independently compiled, the resulting objects are linked together to create an executable.
#ifndef means if the macro isn't defined at all in that file before or in an header you included. In your case, it defaults to 0.
If you change DEBUG_PRINTS in that one file to 1, it will override that #define in #ifndef found in the header file. You are basically locally defining or overriding the default DEBUG_PRINTS in the imported header file to 1.
Otherwise, macros are visible only to this file or header.

Trouble with #ifdef across multiple files

util.h contains the following code:
#ifdef DEBUG
#define LOGGER() MACRO_WRAP(printf("Entering %s\n", __func__))
#else
#define LOGGER() MACRO_WRAP()
#endif
foo.c contains this code:
void foo_start(foo *m)
{
LOGGER();
do_action(m, START);
}
and then foo_unit_tests.c contains calls to foo_start(). I'd like to be able to #define DEBUG at the top of the relevant files -- i.e. I want it to be turned on for unit tests, but not for the main code.
I can't get it to work. Putting #define DEBUG at the top of foo_unit_tests.c doesn't produce the desired behavior. The only way I can get it to work is by putting #define DEBUG either at the top of util.h or foo.c, both of which are much messier than I would like.
What am I missing here? I thought that the macro defined in the .c file would be visible inside of all of the .h files that it included.
You have to have the #define at the beginning of all your files that need that macro defined, or through including a .h file that has it in it.
If you want a cleaner way of doing that, then it is probably better to use the compiler flags to set environmental variables.
For example
icpc -DDEBUG=whatever source.c ...
Or even better, you can enable this compiler flag though an environmental variable in your makefile.
foo_unit_tests.c most likely does not include foo.c, so the #define there is never seen when compiling foo_unit_tests.c
define your normal logger somewhere.. the in the unit test..
#undef LOGGER()
#define LOGGER(x) fprintf(stdout, x)
or alternately you could do something like:
#ifdef UNITTEST
#define LOGGER ...
#else
#define LOGGER ...
#endif
and you pass in the UNITTEST macro from the build env when you build test

Include a header file for parsing of all other files with Doxygen preprocessor

I want to include the #defines from a h file for parsing of all other files with Doxygen.
Project background:
My C project includes a header file config.h on it's the build command.
It also defines a target MODEL_A on the same build command.
config.h creates defines depending on the target being built (not the same lists of defines for MODEL_A as for MODEL_B):
#if defined(MODEL_A)
#define HAS_FUNCTIONALITY_1
#define HAS_FUNCTIONALITY_2
#elif defined(MODEL_B)
#define HAS_FUNCTIONALITY_3
#define HAS_FUNCTIONALITY_4
#endif
My issue with Doxygen:
I try to generate documentation with Doxygen. I have in the Doxyfile:
# including of config.h to INPUT seems necessary.
INPUT = ./source/config.h \
./source
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
INCLUDE_PATH = ./source
INCLUDE_FILE_PATTERNS = ./source/config.h
PREDEFINED = MODEL_A
The code that is dependent on the defines HAS_FUNCTIONALITY_x is not included in the documentation, as if the preprocessor did not get the defines in config.h.
My findings so far:
I inspected the preprocessor output with help of doxygen -d Preprocessor, and could see that:
./source/config.h was parsed first, and correctly according to MODEL_A (I can see the correct #defines in the preprocessor output). #define HAS_FUNCTIONALITY_1 figures in the preprocessor output.
the preprocessing of C files which depend on HAS_FUNCTIONALITY_1 act as if it was not defined.
Defining HAS_FUNCTIONALITY_1 in the field PREDEFINED of the Doxyfile works as expected. This is not a practical solution, but still interesting.
How do I make sure that the #define rows that are preprocessed first from config.h stay defined when the preprocessor works on all subsequent C files?
It would probably be beneficial for you to show the C code itself. In general, Doxygen runs a standard preprocessor - i.e. the rendered code should be the same as if the compiler preprocessed it. In order to achieve the equivalent of #define HAS_FUNCTIONALITY_1 in the code - it has to be defined.
I understand from your reluctance to add it to the doxygen configuration that it is defined somewhere else in the project (or perhaps the Makefile) and that that is the reason that the actual code acts as though it was defined.
If this is the case, I don't see a plausible workaround other than more preprocessor trickery or simply adding it in the doxygen config file.
I ran into a very similar issue.
My headers were in a different directory from my source, e.g.:
doxy_input_dir/
|
+ src/
|
+ inc/
I had RECURSIVE input file option set to YES. I assumed the preprocessor would correctly find my headers. However, when I viewed the preprocessor output by running doxygen -d Predefined <doxyfile> I saw a lot of #include foo.h: not found! skipping....
The solution was to specify all of the header directories explicitly using the INCLUDE_PATH tag.

Resources