Search code examples
c++gccg++

isystem forces header to C linkage


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.


Solution

  • 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.