I'm trying to figure out how to build a variable string for the #include statement using GCC.
The idea is that for each source module I have written, I want to include as a header, a dynamically generated C source, that was created earlier in the build process.
Generating this file is not an issue. Including it, unfortunately, is.
What I have so far is (identities.h):
// identities.h
# define PASTER2(str) #str
# define PASTER(str) PASTER2(str ## .iden)
# define EVALUATOR(x) PASTER(x)
# define IDENTITIES_FILE EVALUATOR(__FILE__)
# include IDENTITIES_FILE
Ideally, this would be used like so (main.c):
//main.c
# include "identities.h"
int main() {return 0;}
Which would be expanded in a single pass by the preprocessor before compilation to yield:
//main.c (preprocessed)
# include "main.c.iden"
int main() {return 0;}
The two levels of indirection I'm using (PASTER and EVALUATOR) are a result of this post.
Unfortunately, this is not working and I am left with the error:
obj/win32/dbg/main.o
In file included from main.c:1:0:
identities.h:42:1: error: #include expects "FILENAME" or <FILENAME>
I think the problem is that the include statement is missing quotes.. Any ideas?
This is actually done in the Linux source tree; See line 100 of compiler-gcc.h.
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(__GNUC__)
I'm trying to figure out how to build a variable string for the #include statement using GCC.
This token pastes the value of __GNUC__
to a string; "linux/compiler-gcc" __GNUC__
".h" and then stringifies the result. This maybe a gcc pre-processor extension.
Here is an example,
#define FOO 10
#define FOO 20
#ifndef VERSION
#define VERSION 1
#endif
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(t##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(VERSION)
#include <stdio.h>
int main(void)
{
printf("FOO is %d\n", FOO);
return 0;
}
Here are two compiles,
g++ -o a a.cc
g++ -DVERSION=2 -o a a.cc
The output of either compile gives expected result.
As with the Linux source, you can key off of gcc pre-defined values. echo | g++ -dM -E -
will give a list.
For your case, you can use the makefile to pass a define to the compile to allow dynamic inclusion of the generated header without altering the source. But then a simple alternative is just to run sed
, etc on a template source file and replace it with the known include name.
Either technique is good for generating test fixtures, etc. However, for compiler feature discovery, this is a better method. For programmers who use IDEs, this might be their only choice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With