How to include makefile variable in include preprocessor directive - c

I want to include header files based on makefile variables.
MakeFile
DISC := left
Pass this variable to the C program like below:
CFLAGS += -DNAME=\"$(DISC)\"
In main.c, need to include header for correct disc based on makefile variable.
Is it possible to do
#include "NAME_header.h"
(where NAME is passed from makefile)
I am getting compilation error
Error: NAME_header.h is not found.
Is this really possible to include header files in this way?

A working solution:
Makefile:
DISC := left
CFLAGS += -DNAME=$(DISC)
C or C++ source:
#define STR(s) STR2(s)
#define STR2(s) #s
#define EXPAND(s) s
#include STR(EXPAND(NAME)_header.h)

Alternative solution; consider using a proxy file. See more details below about mixing macros and #include.
In the Makefile, create v_header.h
echo '#include "${DISC}_header.h"' > v_header.h
Which can be included
#include "v_header.h"
At this time, the cpp grammer does not allow the usage of macros as part of the '#include' statement. It must be '"path.h"' or ''. The "stringifaction" operators (both '#' and '##') are not processed for pre-processor directives (line starting with '#')
// Not working
#include NAME
#include #NAME
#include "#NAME"
#include "##NAME"

Related

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>

How to #include a different file each time based on user input?

I have a program which, depending on the user input, #includes one header headerA.h or another headerB.h I expect the header to be there till the end of the program.
headerA and headerB define structures with the same names but with different fields, and I'm not able to merge both files in one, and neither able to change anything else from the libraries that headerA and headerB are using.
Is there a way to solve this problem?
Preprocessor macros:
#if defined(USE_HEADERA)
# include "headerA.h"
#elif defined(USE_HEADERB)
# include "headerB.h"
#else
# error must define USE_HEADERA or USE_HEADERB
#endif
If you have GCC then you tell the preprocessor which to select using the GCC -D option:
$ gcc -DUSE_HEADERA myfile.c -o myprogram
However, if you want to do it runtime during execution that's impossible. #include is a preprocessor directive, and the preprocessor only runs as part of the compilation.
Although it is possible to conditionally include files, it does not seem to be possible to have this change during runtime. See this answer about it. The if statements only work before runtime.
I don't think it is possible as your #includes are resolved before compilation i.e during preprocessing. So it is not possible to change them during runtime.
But you can try conditional compilation by defining a macro during compiletime.
#ifdef HEADERA
#include <headerA>
#ifdef HEADERB
#include <headerA>
While compilinging gcc
$ gcc prog.c -DHEADERA to include headerA or vice versa

How to pre-compile a C source file without expand the included header file?

I am working on a large project using C language, which has a lot of preprocessor macros: #ifdef/#if. The macros are defined in makefile.
In order to get the clean code, I modified the makefile to use "gcc -E". But the gcc preprocessor would expand the included header file as well, which I do not expect.
Is there any method to get rid of the #ifdef/#if without expand the included header files? I searched GCC options but not find an answer yet.
An example:
#include "a.h"
#ifdef ABC
func()
#else
func(a)
#endif
{
...
}
In makefile, this source is compiled with -DABC, I am looking for a method to change the file to:
#include "a.h"
func()
{
...
}
If you only want to remove preprocessor conditionals from your code you can use unifdef :
unifdef -DFOO header.h

Write a macro for C/C++ #include

I work on AS/400 which is sometimes non-POSIX. We also need to compile our code on UNIX. We have an issue with something as simple as #include.
On AS/400, we need to write: #include "*LIBL/H/MYLIB"
On UNIX, we need to write #include "MYLIB.H"
At the moment we have this (ugly) block at the top of each C/C++ file:
#ifndef IS_AS400
#include "*LIBL/H/MYLIB"
/* others here */
#else
#include "MYLIB.H"
/* others here */
#endif
We would like a unified macro. Is this possible? I don't know how to write it.
Ideally, the resulting syntax would be: SAFE_INCLUDE("MYLIB") that would expand correctly on each platform.
Please advise.
You can simply #include some separate header in every of your source files containing that ugly #ifndef just once. It's a common practice anyway.
You can define prefixes for your platform as macro. Like
#define STRINGY(STR) #STR
#define SAFE_INCLUDE(HDR) STRINGY(HDR)
#ifndef IS_AS400
#define SAFE_INCLUDE(LIB) STRINGY(*LIBL/H/##LIB)
#else
#define SAFE_INCLUDE(LIB) STRINGY(LIB##.H)
#endif
and you can use this as
#include SAFE_INCLUDE(MYLIB)
There are two better solutions:
Use your Makefiles to properly set a path where compiler looks for includes.
For GCC you add to CFLAGS -I <path> (you can do that multiple times).
Wrap the non-compliant libraries with your own header files.

Make the C preprocessor ignore certain #include directives

I use a parser generator here, that unfortunately insists on putting a
#include <some/file.h>
at the top of every generated source file. The header has since long been renamed. While it is no problem forcing the compiler (gcc) to use the new header with -include new/header.h, removing the above directive from every generated file complicates the build-process.
Is there a way to tell gcc to simply ignore some/file.h?
No. You can post-process your generated file - I say: NO!!!
Or you can just add '.' to your system include directories (or whatever your local include path is - make sure it's also a <> system include path).
Then make a 'some' directory and stick your own permanent 'file.h' in there that has 1 line for #include and get rid of your -include.
I'm guess there's some reason that might not work - cause it seems like the more straight forward and understandable thing to do before using -include. Especially since you can comment the pass-through file to explain what's going on.
Replace some/file.h with an empty file.
Why not make a symlink from some/file.h to new/header.h, and remove the -include directive?
Try using preprocessor directives like #if and #ifdef and gcc -DSYMBOL=value command line flag.
In example, if you compile using gcc -DREQUIRE_STDC=1 -o myfile.o myfile.c, and your .c file contains:
#if defined(REQUIRE_STDC) && defined(__STDC__)
#include "some/file.h"
#else
#include "another/file.h"
#endif /* defined(REQUIRE_STDC) && defined(__STDC__) */
It will compile using "some/file.h" if have both STDC and REQUIRE_STDC symbols defined. Also your header may include the proper directive to avoid multiple inclusions of the same file:
#ifndef MY_HEADER_FILE
#define MY_HEADER_FILE 1
/* your C declarations here */
#endif /* MY_HEADER_FILE */
Also, you could the gcc preprocessor manual.
#include <some/file.h>
may start as something like
#ifndef _FILE_H_
#define _FILE_H_
If so, just add #define _FILE_H_ before the #include command and it should ignore it.
I'm not sure whether this is the best solution, though.

Resources