I'm experiencing an extremely weird problem in a fresh OSX 10.4.11 + Xcode 2.5 installation. I've reduced it to a minimal test case. Here's test.cpp:
#include "macros.h"
int main (void)
{
return 1;
}
And here's macros.h:
#ifndef __JUST_TESTING__
#define __JUST_TESTING__
template<typename T> void swap (T& pT1, T& pT2)
{
T pTmp = pT1;
pT1 = pT2;
pT2 = pTmp;
}
#endif //__JUST_TESTING__
This compiles and works just fine if both files are in the same directory. HOWEVER, if I put macros.h in /usr/include/gfc2 (it's part of a custom library I use) and change the #include in test.cpp, compilation fails with this error :
/usr/include/gfc2/macros.h:4: error: template with C linkage
I researched that error and most of the comments point to a "dangling extern C", which doesn't seem to be the case at all.
I'm at a complete loss here. Is g++ for some reason assuming everything in /usr/include/gfc2
is C even though it's included from a .cpp file that doesn't say extern "C" anywhere?
Any ideas?
EDIT : It does compile if I use the full path in the #include
, ie #include "/usr/include/gfc2/macros.h"
EDIT2 : It's not including the wrong header. I've verified this using cpp
, g++ -E
, and renaming macros.h
to foobarmacros.h
G++ may well indeed be assuming that everything in /usr/include is C. Try compiling your code with -E and studying the line markers in the preprocessor output:
g++ -E test.cpp | grep '^#'
You'll likely see things like
# 1 "/usr/include/gfc2/macros.h" 1 3 4
The 4
is the preprocessor hinting to G++ that it should wrap everything in extern "C"
, on the supposition that your platform's ancient header files in /usr/include predate C++. See Preprocessor Output in the CPP manual.
These days G++ mostly ignores this hint, because most platforms' C headers are no longer ancient. See the NO_IMPLICIT_EXTERN_C
target macro in the GCC Internals manual. But it may be that this old version of Xcode has GCC configured without NO_IMPLICIT_EXTERN_C
and thus is listening to the preprocessor's hint. (This is set when GCC itself is built -- I don't think there's a command-line switch to override it.)
You may be able to work around this by wrapping the contents of your header file in extern "C++"
.
This is a shot in the dark, but is there another file named macros.h
somewhere under /usr/include
or in your GCC installation? GCC has a facility for wrapping headers, called #include_next
, which might be the cause of your problem.
One thing you can do to disambiguate your macros.h
from any other macros.h
in the include path is to include it as gfc2/macros.h
. This way, the compiler will search every directory in the include path for a subdirectory named gfc2
containing a file named macros.h
, reducing the chance of a collision. It also prevents you from having to add /usr/include/gfc2
to the include path.
BTW, #include "file.h"
searches the current directory first. To skip that and go straight to the include path, use #include <file.h>
:
#include <stdio.h>
#include <gfc2/macros.h>
Another approach is to choose a filename that is more likely to be unique, like gfc2macros.h
.
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