This smells similar to - but is different from - Why does OpenBSD's G++ make system headers default to C linkage? This is not BSD, but instead the Arm g++ cross-compiler.
With this trivial pair of source files -
mbed/can.h
template <typename T> void ftest2(T t) { }
src/outer.cpp
template <typename T> void ftest0(T t) { }
#include <can.h>
template <typename T> void ftest1(T t) { }
The following command fails:
/arm-none-eabi-gcc/7.3.1-1.2.2/.content/bin/arm-none-eabi-g++ \
-isystem"mbed" \
-c "src/outer.cpp"
In file included from src/outer.cpp:2:0:
mbed/can.h:1:1: error: template with C linkage
template <typename T> void ftest2(T t) { }
This is deeply strange, since neither of the template definitions in the CPP file fail, and (seemingly) nothing changes from the CPP to the H. I can only assume that gcc is doing some forbidden magic with -isystem
and forcing the header to be interpreted as a C file, but I have no idea why, and I need that to stop. I need -isystem
since, in real life, the mbed code is littered with warnings that I need to suppress for that directory tree.
This mysterious comment seems to be exactly my problem:
Just as a hint for future readers: If you pass an include directory to gcc via -isystem instead of -I, some versions may implicitly apply C linkage. – Jan Schatz Jul 1, 2019 at 15:02
But there is no hint as to how it may be resolved.
It turns out what I actually need is CPLUS_INCLUDE_PATH
; from the manpage:
CPATH
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
OBJC_INCLUDE_PATH
Each variable's value is a list of directories separated by a special character, much like
PATH
, in which to look for header files. The special character, "PATH_SEPARATOR", is target-dependent and determined at GCC build time. For Microsoft Windows-based targets it is a semicolon, and for almost all other targets it is a colon.
CPATH
specifies a list of directories to be searched as if specified with-I
, but after any paths given with-I
options on the command line. This environment variable is used regardless of which language is being preprocessed.The remaining environment variables apply only when preprocessing the particular language indicated. Each specifies a list of directories to be searched as if specified with
-isystem
, but after any paths given with-isystem
options on the command line.