GCC preprocessor [duplicate] - gcc

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Running the GCC preprocessor
Is there a GCC option to make the GCC preprocessor generate C source code but filter out irrelevant source code?
For example, a C file has #define switch to define for many different platforms. I'm only intersted in one platform, so I want the C preprocessor to filter out unrelated code. Does GCC support this?

Use gcc -E to only run the preprocessor part, e.g. give a file in.c
#if 0
0;
#endif
#if 1
1;
#endif
running
$ gcc -E in.c -o in.i
yields a file in.i
# 1 "in.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "in.cpp"
1;
i.e. the parts behind the #if 0 got removed. If you would have #include'd files they would have been pasted too though, so I am not sure how much help this is.

It sounds like you actually want unifdef, not the GCC preprocessor.

Yes - almost certainly your compiler provides certain default definitions in the environment that you can use to turn code on and off for different systems. __GNUC__ is a good one for GCC. For example:
#ifdef __GNUC__
#define SOME_VALUE 12
#else
#define SOME_VALUE 14
#endif
If you compile that block with GCC, SOME_VALUE will be 12, and if you compile with MSVC, for example, SOME_VALUE will be 14. A list of platform specific definitions is available at this question.

You probably can use:
gcc -CC -P -Uswitch -undef -nostdinc -fdirectives-only -dDI -E
With switch the #define you know will be undefined.

Related

How can I differentiate, in my C/C++ code, between GCC and clang as the compiler?

I usually write GCC-targeted code by checking __GNUC__. Now I want to write some code which behaves differently for GCC and for clang - but it seems clang defines __GNUC__ as well. How do I differentiate between them?
While both define __GNUC__, only clang defines __clang__.
So, for GCC-only, you would write:
#if defined(__GNUC__) && !defined(__clang__)
// do GCC-only stuff
#endif
and of course you could adapt this to GCC-only, clang-only and other, by separating the two conditions.
Note: This is the same for C and for C++.

What are __CUDABE__ and __CUDA_LIBDEVICE__ for?

Let's say I'm interested on preprocessing (with gcc) hpp/cpp files which include CUDA kernel declarations. I want the preprocessor to not to scrap the __global__ specifier, otherwise I wouldn't be able to link against the definition in the .cu file.
For instance, a file t1.hpp:
__global__ void foo(int* v, int n);
And preprocess with:
gcc -E t1.hpp -I/usr/local/cuda/include -include cuda_runtime.h
But the result scraps global !:
...
# 1888 "/usr/local/cuda/include/cuda_runtime.h"
#pragma GCC diagnostic pop
# 1 "<command-line>" 2
# 1 "t1.hpp"
void foo();
But if I define __CUDABE__ (on CUDA 8.0) or __CUDA_LIBDEVICE__ in CUDA 9.0+ i amb able to keep that information:
gcc -E t1.hpp -I/usr/local/cuda/include -include cuda_runtime.h -D__CUDABE__
Final result:
...
# 1888 "/usr/local/cuda/include/cuda_runtime.h"
#pragma GCC diagnostic pop
# 1 "<command-line>" 2
# 1 "t1.hpp"
__attribute__((global)) void foo();
So my question is, what is __CUDABE__ and __CUDA_LIBDEVICE__ for and if what could be the side effects.
I've also seen that clang defines those macros in __clang_cuda_runtime_wrapper.h. Is this then this something safe to do?
Since it is not documented anywhere, it's some sort of an internal flag they use (which can, as you've noticed change between the compilers), so you probably shouldn't rely on it. It is defined in crt/host_defines.h, which is not very well documented, so I cannot decipher what it means.
Is there any reason why you cannot preprocess the file with nvcc?
This should do what you want, and it invokes gcc with correct parameters (at least on my system):
nvcc -E --x=cu t1.hpp`
If you cannot use nvcc for whatever reason, you can always call it in verbose mode (nvcc -E -v --x=cu t1.hpp) and see which flags it sets. On my linux system with CUDA 9.1 I get:
gcc -std=c++14 -D__CUDA_ARCH__=300 -E -x c++ \
-DCUDA_DOUBLE_MATH_FUNCTIONS -D__CUDACC__ \
-D__NVCC__ "-I/opt/cuda/bin/..//include" \
-D"__CUDACC_VER_BUILD__=85" -D"__CUDACC_VER_MINOR__=1" \
-D"__CUDACC_VER_MAJOR__=9" -include "cuda_runtime.h" \
-m64 "t1.hpp"
However, you'll probably have to do it for each CUDA version you want to use, as these flags can change.

gcc macro expansion of #error

I have some preprocessor code like this:
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#if GCC_VERSION < 40503
#error Your compiler is outdated.
#error You need at least gcc 4.5.3 for this library.
#error You have: GCC_VERSION
#error You have: STR(GCC_VERSION)
#endif
However both ways I tried to output the current compiler version fail. According to the documentation this is because
Neither ‘#error’ nor ‘#warning’ macro-expands its argument. Internal whitespace sequences are each replaced with a single space. The line must consist of complete tokens. It is wisest to make the argument of these directives be a single string constant; this avoids problems with apostrophes and the like.
How can I output the compiler version with the error message anyway? Is there any preprocessor magic that allows me to achieve this?
The classic "solution" to this problem is to manage to generate an error which includes the desired message. For example:
#define S(x) #x
#define STR(x) S(x)
#if GCC_VERSION < 40503
#error Outdated compiler: you need at least gcc 4.5.3 for this library.
#define above_message_indicates_installed_gcc_version STR(Installed GCC version: GCC_VERSION)
#include above_message_indicates_installed_gcc_version
#endif
While that does provide some information, it is still subject to misinterpretation; personally, I think letting the developer know the minimum version required is sufficient.
Note: The above snippet assumes that GCC_VERSION has already been defined, which I assume must have been done before the snippet in the OP. But beware: since the preprocessor does text substitution, not arithmetic evaluation (except in #if directives), you need to assemble GCC_VERSION in a different form for the error message If you want to try this, you could use the following:
#define GCC_VERSION (__GNUC_PATCHLEVEL__ + 100 * (__GNUC_MINOR__ + 100 * __GNUC__))
#define S_(x) #x
#define STR(x) S_(x)
#if GCC_VERSION < 40503
#undef GCC_VERSION
#define GCC_VERSION __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__
#error Outdated compiler: you need at least gcc 4.5.3 for this library.
#define above_message_indicates_installed_gcc_version STR(Installed GCC version: GCC_VERSION)
#include above_message_indicates_installed_gcc_version
#endif
See it on gcc.godbolt
If #error does not expand its arguments, I would just take a pragmatic approach:
#if GCC_VERSION < 40503
#error Outdated compiler < 4.5.3, run 'gcc --version' to get version.
#endif
The only other possibility I can think of is to preprocess the file with your own preprocessor, to replace all occurences of (for example) xyzzy_GCC_VERSION_plugh with something extracted from gcc --version.
That's going to be a lot of effort and maintenance load to do what probably isn't necessary anyway.
But, if you really want to do it, you could use something like:
actual=$(echo "GCC_VERSION" | gcc -E - | tail -1)
sed "s/xyzzy_GCC_VERSION_plugh/$actual/g" file1.c >file1_morphed.c
gcc -c -o file1.o file1_morphed.c
and your file1.c would contain at the top somewhere:
#if GCC_VERSION < 40503
#error Outdated compiler xyzzy_GCC_VERSION_plugh < 4.5.3
#endif
But, as i said, that's a fair bit of work for not much benefit. My advice is just to tell the person using your library how to get the compiler version themselves. They are developers after all, I'd expect them to be able to handle an instruction like that.
Combining the proposal of paxdiablo and ideas for static compile time assertions I settled for the following solution.
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#define ERROR_MESSAGE(major, minor, patchlevel) compiler_version__GCC_ ## major ## _ ## minor ## _ ## patchlevel ## __ ;
#define OUTDATED_COMPILER_ERROR(major, minor, patchlevel) ERROR_MESSAGE(major, minor, patchlevel)
#if GCC_VERSION < 40503
#error Outdated compiler version < 4.5.3
#error Absolute minimum recommended version is avr-gcc 4.5.3.
#error Use 'avr-gcc --version' from the command line to verify your compiler version.
#error Arduino 1.0.0 - 1.0.6 ship with outdated compilers.
#error Arduino 1.5.8 (avr-gcc 4.8.1) and above are recommended.
OUTDATED_COMPILER_ERROR(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#endif

What are those gcc options doing?

In a makefile I work on, gcc is used with the -D XOPEN_SOURCE=500 and -D_BSD_SOURCE options. gcc --help does not tell me what these are; a quick google search didn't help either. I'm quite a newbie with gcc, could someone give me a hint?
According to the GCC documentation ("3.11 Options Controlling the Preprocessor"), the -D switch defines the macros XOPEN_SOURCE and _BSD_SOURCE with the values 500 and 1 respectively. It's as though you have this code at the beginning of all the source files you pass to GCC:
#define XOPEN_SOURCE 500
#define _BSD_SOURCE 1
Build scripts usually take advantage of the compiler's ability to "insert" macros like these to "communicate" to the source code details about the platform being targeted (e.g. operating system version).
The "opposite" command-line switch for -D is -U, which #undefs a macro.
Most (if not all) modern C/C++ compilers include similar switches. For example, Visual C++ compilers accept the /D compiler switch, which essentially serves the same purpose as GCC's -D switch.
For future reference, the GCC option index is great if you need to look up compiler switches for the GCC compiler.
-D is used to set defines. The source code you are compiling most likely is using those defines to include specific header files.
Think of -D as doing the same thing as:
#define XOPEN_SOURCE 500
#define _BSD_SOURCE 1
at the top of the file it is currently compiling.
These do not nothing for gcc. These are definitions like similar you have in your .c, .cpp or .h files:
#define XOPEN_SOURCE 500
#define _BSD_SOURCE
-D is equlivant of a #define
i.e.
#define XOPEN_SOURCE 500
-D sets a define. It's like adding a header file that contains:
#define XOPEN_SOURCE 500
#define _BSD_SOURCE 1
You can then use #ifdef _BSD_SOURCE to enable conditional compilation of certain part of the code.

What are the gcc predefined macros for the compiler's version number?

I have run into a bug with gcc v3.4.4 and which to put an #ifdef in my code to work around the bug for only that version of the compiler.
What are the GCC compiler preprocessor predefined macros to detect the version number of the compiler?
From the gnu cpp manual...
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
These macros are defined by all GNU compilers that use the C preprocessor: C, C++, Objective-C and Fortran. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. These macros are also defined if you invoke the preprocessor directly.
__GNUC_PATCHLEVEL__ is new to GCC 3.0; it is also present in the widely-used development snapshots leading up to 3.0 (which identify themselves as GCC 2.96 or 2.97, depending on which snapshot you have).
If all you need to know is whether or not your program is being compiled by GCC, or a non-GCC compiler that claims to accept the GNU C dialects, you can simply test __GNUC__. If you need to write code which depends on a specific version, you must be more careful. Each time the minor version is increased, the patch level is reset to zero; each time the major version is increased (which happens rarely), the minor version and patch level are reset. If you wish to use the predefined macros directly in the conditional, you will need to write it like this:
/* Test for GCC > 3.2.0 */
#if __GNUC__ > 3 || \
(__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
(__GNUC_MINOR__ == 2 && \
__GNUC_PATCHLEVEL__ > 0)))
__GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__.
For instance, GCC 4.0.1 will do:
#define __GNUC__ 4
#define __GNUC_MINOR__ 0
#define __GNUC_PATCHLEVEL__ 1
Here is a little command line that is nice to remember when you are wondering which are the predefined preprocessor directives defined by the GNU GCC compiler under your current programming environment:
gcc -E -dM - < /dev/null |less
There's 3 macros for the gcc version you can test on.
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
__GNUC__
e.g. my gcc v 4.3.1 defines them as such:
#define __GNUC_MINOR__ 1
#define __GNUC_PATCHLEVEL__ 3
#define __GNUC__ 4
You can see the "buitin" macros defined by running
gcc -E -dM -x c /dev/null
From the online docs:
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
These macros are defined by all GNU compilers that use the C preprocessor: C, C++, Objective-C and Fortran. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. These macros are also defined if you invoke the preprocessor directly.
and
__VERSION__
This macro expands to a string constant which describes the version of the compiler in use. You should not rely on its contents having any particular form, but it can be counted on to contain at least the release number.

Resources