Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

#ifdef flag to tell difference between gcc and g++ compilers? [duplicate]

gcc compiles C programs as C, and C++ programs as C++, thus requiring an 'extern "C"' declaration in C++. Whereas, g++ compiles C programs as C++, and C++ programs as C++, thus requiring that the 'extern "C"' declaration must NOT be used in C++.

Checking standard flags without any input, both

 g++ -E -dM - </dev/null 
 gcc -E -dM - </dev/null 

give the same results.

__GNUG__       is equivalent to testing (__GNUC__ && __cplusplus)

which again will not differentiate gcc from g++ inside a C++ source listing.

What is the magic for

#ifndef __MAGIC_G++_INCLUDE_FLAG_BUT_NOT_GCC__ 

to wrap around the extern "C"{ declarations? Thanks.

Edit: I realize this is a rather esoteric case. The test needs to be done on the compiler flavor, not on the source code flavor. In both cases the test is being performed inside a C++ source code listing (which is why I mentioned GNUG is inadequate). To clarify, for test main.cpp:

#include <iostream>
int 
main( int argc, char **argv )
{
#ifdef __cplusplus  <<<< FIX THIS ONE
  std::cout << "I was compiled using g++" << std::endl;
#else
  std::cout << "I was compiled using gcc" << std::endl;
#endif 
}

when compiled with either

 g++ main.cpp

or

gcc main.cpp -lstdc++

in both cases, it seems to incorrectly give as output "I was compiled using g++". So it would seem that cplusplus is not the correct flag to use in this case. Am I wrong? Or what is the correct flag?

Edit 2: Thanks, guys. Here is one example for you. Large legacy system "Alpha" is written mostly in C, with a little C++, and uses large legacy source package "Charlie", written in C++. It uses the g++ system to compile and link, and demands that Charlie's headers have no extern "C" definitions in them, or else it refuses to link. Large legacy system "Bravo" is written mostly in C, with a little C++, and also uses the same legacy source package Charlie, written in C++. It uses the gcc system to compile and link, and demands that Charlie's headers must have extern "C" definitions in them, or else it refuses to link. New systems "Delta", "Echo", and "Foxtrot" would also like to reuse parts of source from Charlie, compiler to be used is uncertain. The correct answer is to hack Charlie's headers, once and for all, with

#ifndef __MAGIC_G++_INCLUDE_FLAG_BUT_NOT_GCC__ 
extern "C" {
#endif
...
declarations of code
...
#ifndef __MAGIC_G++_INCLUDE_FLAG_BUT_NOT_GCC__ 
}
#endif

and then be done with it. Otherwise there will always be linking problems. Yes, of course it could be possible to compile two sets of libraries in this particular case, one under C and one under the C++ convention, and then mandate that thou shalt use this particular library for this particular flavor of linking. Or I could come up with two sets of headers. Either of those is inelegant and will continue to cause problems down the road, in this example; there are other cases. As to the comment that both g++ and gcc are using the same compiler under the hood, and so it can't possibly matter, sadly, it does. The package as a whole refuses to link when the wrong 'extern "C"' dogma is/isn't included. Yes, there are other ways of attacking the general problem, but it's a simple question. Either such a flag exists, or it is known not to exist, or the answer is not known definitively. I don't know, myself.

like image 445
DragonLord Avatar asked Nov 26 '25 03:11

DragonLord


1 Answers

The standard technique is to check if the preprocessor symbol __cplusplus is defined:

#ifdef __cplusplus
extern "C" {
#endif

/* declarations here */

#ifdef __cplusplus
}
#endif
like image 184
nobody Avatar answered Nov 27 '25 17:11

nobody



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!