Use gcc preprocessor to define filename for #include - c

I would like to specify the name of a C include file at compile time as a C flag.
e.g.
#include MY_INCLUDE_FILE
int main(int argc, const char * argv[]) {...}
Would be expaned by the pre-processor to
#include "some_incfile.h"
int main(int argc, const char * argv[]) {...}
Doing something like this
gcc -DMY_INCLUDE_FILE="some_incfile.h" main.c
I have attempted using the stringizing operator # to expand but have only gotten errors such as error: expected "FILENAME" or <FILENAME>
Is this even possible?
-D define is not entirely necessary, the important part is that the include filename can be set from the gcc command line

You have to escape the ":
gcc -DMY_INCLUDE_FILE=\"some_incfile.h\" main.c

Use the -include option.
gcc -include "somefile.h" main.c

You can do it something like that
# if defined AAA
#define INC "x.h"
#elif defined BBB
#define INC "y.h"
#endif
#include INC
and from command line you do gcc -DAAA.
and of course, you can pass directly gcc -DINC="\"FILE.h\"" if the file is really randomly generated from outside, by makefiles, etc.
Important is INC to be evaluated to a valid file name by the macro expansion procedure (see the Prosser's algorithm).

Related

Dynamic Functionname - Cannot resolve extern symbol

I am trying to generate function names dynamically with preprocessor directives (add a optional prefix).
The generation works and when gcc outputs me the code after the preprocessor (gcc -E), gcc tells me that the function has the right name.
But when i use this function in code, gcc throws an error with unresolved external symbol? (Link2019 / Link1120)
I'm not 100% sure how the linker works but theoretically gcc should run the preprocessor, build all the librarys (more exactly first the prototype and after the main the definition?) so there should be no problem?
Do i have to add a special compiler option? A link?
My main:
#define _CRT_SECURE_NO_WARNINGS
#define STRING_FUNCTION_PREFIX my // Defining a prefix for my string functions
#include <stdlib.h>
#include <stdio.h>
#include <string.h> // Original string functions
#include "string.h" // My string functions
#define ARRAY_SIZE 50
#define HALLO "HALLO"
#define WELT "WELT"
int main()
{
char src1[ARRAY_SIZE], src2[ARRAY_SIZE], dst1[ARRAY_SIZE], dst2[ARRAY_SIZE];
strcpy(src1, HALLO);
strcpy(dst1, WELT);
strcpy(src2, HALLO);
strcpy(dst2, WELT);
strcat(src1, dst1);
mystrcat(src2, dst2);
return 0;
}
My string.h
#pragma once
#include <stdlib.h>
#if defined STRING_FUNCTION_PREFIX
#define FUNCTION_PASTER(ARG1,ARG2) ARG1 ## ARG2
#define FUNCTION_EVALUATER(ARG1,ARG2) FUNCTION_PASTER(ARG1, ARG2)
#define FUNCTION_NAME(FUNCTION) FUNCTION_EVALUATER(STRING_FUNCTION_PREFIX, FUNCTION)
#else
#define FUNCTION_NAME(FUNCTION) FUNCTION
#endif
/*
* \brief: Adds the string from src to the destination string
*/
void FUNCTION_NAME(strcat)(char *dst, char *src);
My string.c
#include "string.h"
void FUNCTION_NAME(strcat)(char *dst, char *src)
{
int counter = 0, offset = 0;
while (dst[offset] != '\0')
{
offset++;
}
dst[offset + counter] = src[counter];
}
Output for string.h when compiling with -E
1> #line 11 "d:\\string.h"
1>
1>
1>
1>
1> void mystrcat(char *dst, char *src);
Thanks for your Help!
The STRING_FUNCTION_PREFIX directive is defined in main.c, but not in string.c. So when string.c is compiled, the substitution does not occur. If you compile string.c with gcc -E, you'll see the effect of this.
You need to put #define STRING_FUNCTION_PREFIX my at the top of string.h instead of in main.c. That way, any .c file that needs it has it defined and it's consistent in all places.
You appear to be attempting to create an emulation of templates in C. If that is the case, you should treat the contents of string.c as a header file that needs to be included by someone that knows what value STRING_FUNCTION_PREFIX should be. If the string.c contents are a header file, rename it to make that clear, for instance, string_template.h.
Then, you can have a file mystring.c implemented as:
#define STRING_FUNCTION_PREFIX my
#include "string_template.h"

Generate #include macro from environment variable

as you say, it works.
But can I build -in some way- the string for the include directive ?
Something like
in .login
setenv REPO "/tmp"
compile
# gcc -D"REPO=${REPO}" source.c
in source.c
#ifdef REPO
#include ${REPO}/my_dir/my_file.h
#endif
thanks
As Joachim writes, in GCC you can use the -D flag to #define things from the command-line:
gcc -DTEST source.c
// in source.c
#include <stdio.h>
int main() {
#ifdef TEST
printf("TEST macro is #defined!\n"); // only runs if -DTEST
#endif
return 0;
}
You can easily plug in environment variables (at compile-time) via this
mechanism:
gcc "-DTEST=$MY_ENV_VAR" source.c
If you need to use the run-time value of the environment variable, then the macro preprocessor (#define, #ifdef, ...) can't help you. Use getenv() instead, and forget about macros.
More to the point:
#include TEST
int main() {
printf("Hello world!\n");
return 0;
}
Will work fine only if compiled with "-DTEST=<stdio.h>" (note the quotes).

C preprocessor Result

Which result does return this construct? I mean the result variable in main-function, and why?
I know, that the example is very strange ;)
header1.h file:
extern const int clf_1;
header2.c file:
#include "header1.h"
const int clf_1 = 2;
test.h file:
#include <header1.h>
#define xyz clf_1
#define NC_CON 2
#if (xyz== NC_CON)
#define test 40
#else
#define test 41
#endif
C file
#include <header1.h>
#include <test.h>
int main(int argc,char *argv[])
{
int result = 0:
if (test == 40)
{
result = 40;
}
}
Read the wikipage on the C preprocessor and the documentation of GNU cpp (the preprocessor inside GCC, i.e run by gcc or g++ etc...). It is a textual thing, and it is run before the definition const int clf_1 = 2; has been processed by the compiler. A #if directive only makes sense if all the names appearing in it are preprocessor symbols (defined with #define or with -D passed on the command line of the GCC or Clang/LLVM compiler)
Use gcc -C -E yoursource.c > yoursource.i (with some other options after gcc, probably -I. is needed ... you should #include "header1.h"
etc...) then look with an editor or a pager into the generated yoursource.i (the preprocessed form)
The world would be very different if the C preprocessor transformed ASTs; for historical reasons, the first C preprocessors were textual filters (run as a different program).

Duplicate header files throughout source files?

// File foo1.c :
#include <stdio.h> // once
void foo1(void);
void foo1(void){
puts("foo1");
}
// File foo2.c :
#include <stdio.h> // again
void foo2(void);
void foo2(void){
puts("foo2");
}
// File foomain.c :
#include <stdio.h> // yet again
void foo1(void); // again
void foo2(void); // again
int main(void){
foo1();
foo2();
puts("foomain");
return 0;
}
// create object files
gcc -fPIC foo1.c -o foo1.o // 1 stdio.h
gcc -fPIC foo2.c -o foo2.o // 1 stdio.h
// create shared library
gcc -fPIC -shared foo1.o foo2.o -o foo.so // foo.so contains stdio.h 2 times ?
// build entire program
gcc foo.so foomain.c -o foomain // foomain contains 1 stdio.h plus the 2 from foo.so ?
Why does the entire program contain 3 stdio.h ? Seems redundant, why not just 1 ? Shouldn't the compiler need only 1 ?
It makes sense for the object files to contain a prototype but why do they have to be specified again in foomain.c ? Shouldn't the compiler know they are already specified in foo.so ?
That's because each file is compiled separately, so each time the compiler should know the signatures of all functions used to perform compile-time checks. So, each file has to contain all declarations used, which are included by the preprocessor before the file is compiled.
If you look at the top of most header files they have an include guard to stop double inclusion.
#ifndef FOO
#define FOO
#endif
See Include Guard for more information.
The #include lines are not actually a part of the compiler, but the C preprocessor.
What the preprocessor does with #include lines is to actually include the file into the source, and creates a new temporary file containing the contents of your file with the #include line replaced by the contents of the file being included.
You don't actually need the include file at all, if all you are doing is calling functions. You might get warnings about the functions not being declared, but those can be adding the prototypes for those functions yourself. For example, in your main source file you only use puts, instead of including <stdio.h> you can add a prototype like this:
int puts(const char *s);
However, <stdio.h> also defines some structures (like the FILE structure) and declares some variables (like stdout) and if you use any of those you need the header file as well.
You can use include guards as #Jeff suggested or just put #pragma once at the top of each header.

Any way to get the c preproccessor to ignore all #include's?

Using pycparser to parse a slew of .c source files, but the parser can't handle many things in the #included libraries, and I really don't need them for my purposes. I don't need to have it compile, just need to generate the AST from the specific .c I'm processing.
The cpp args i'm passing it right now are:
cpp_args=["-D__attribute__=","-D__extension__=","-D__builtin_va_list=void*"]
Any ideas?
Thanks!
Try specifying the -nostdinc option to the preprocessor (and make sure you're not passing any -I options). Given this input in foo.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv) {
return 0;
}
Running:
cpp -nostdinc foo.c
Gives me:
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "foo.c"
int main(int argc, char **argv) {
return 0;
}
And the following errors:
foo.c:1:19: error: no include path in which to search for stdio.h
foo.c:2:20: error: no include path in which to search for stdlib.h
foo.c:3:20: error: no include path in which to search for unistd.h
One solution would be to use the #include guards
If you have the traditional wrapper in each header, eg.
#ifndef THIS_FILE_H
#define THIS_FILE_H
// stuff
#endif
Then you could simply #define all the header guard tags you want to ignore

Resources