C/C++ system include dirs when cross-compiling

Hi list,

I'm using clang to cross-compile for a sparc-target.

Except for the compiler I (seem to) rely entirely on gcc-tools (ld,
asm). I doing this by passing the -B
<path-to-gcc-toolchain> - flag to clang.

I'm now facing an issue where I would like to have clang use the
c++-system-includes of my gcc-installation.

When I dump the considered include-dirs with

  echo | sparc-elf-gcc -nostdlib -xc++ -E -Wp,-v - -fsyntax-only

I'm getting a list of all the paths I'm looking for. Doing the same
with clang (even with the -B-flag) having the -target-flag set, the
list is empty.

What is the proper way to let clang now where to find the
system-includes in cross-compilation scenarios?

I'm now using a script which generates -isystem-arguments which based
on a list generated with a call as shown above.

Should the list be derived from the -B-argument?

best regards,

Hi Patrick,

This is a common case when cross compiling, so clang knows how to use a gcc-toolchain installation: you just have to pass it the “–sysroot=…” and “–toolchain=…” arguments, and it will get the header files and linker / assembler for your target — assuming your gcc-toolchain has a standard layout.

Kind regards,
Arnaud

That last caveat is the one that gives me the most trouble on Ubuntu.
They seem to have an odd layout for their ARM-HF toolchain, and using
--sysroot fails to compile/link. Also see "g++-arm-linux-gnueabi
cannot compile a C++ program with --sysroot",
Bug #1375071 “g++-arm-linux-gnueabi cannot compile a C++ progra...” : Bugs : gcc-defaults-armel-cross package : Ubuntu.

Jeff

There must be some misunderstanding there.

The goal is to write:

clang++ -target sparc–netbsd -mcpu=… compile_flags --sysroot=… --toolchain=… -o program.exe program.cpp

And clang will cross-compile program.cpp for this specific sparc cpu using the includes from the sysroot, and link using the linker and libraries from sysroot+toolchain.
I do no think there is any reason to try to use “g+±arm-linux-gnueabi” with sysroot, and the fact that the g++ you refer to does not work with --sysroot is something not relevant to this clang user mailing list — but I may be missing something. For your specific problem, you may want to give a try to the gcc packaged by linaro (http://www.linaro.org/downloads/) which works pretty well in my experience.

Kind regards,
Arnaud

Hi Arnaud,

Hi Patrick,

This is a common case when cross compiling, so clang knows how to use
a gcc-toolchain installation: you just have to pass it the
"--sysroot=..." and "--toolchain=..." arguments, and it will get the
header files and linker / assembler for your target --- assuming your
gcc-toolchain has a standard layout.

It wasn't that straight-forward for me to find information
about this "common case" as you call it :wink: .

I initially had problems finding the -B option of clang (it is
not listed in --help nor in --help-hidden).

The --gcc-toolchain-argument does not work with the clang I built:

../../upstream/build/bin/clang++ --gcc-toolchain
clang-3.8: error: unsupported option '--gcc-toolchain'
clang-3.8: error: no input files

But it is listed in --help.

Is this a bug or is my build faulty?

I tried --sysroot and it made the path appear in the
clang-system-include-paths. But my gcc-toolchain does not have the
c++-headers in there just the C ones.

C++ header files were installed to

  path/to/toolchain/<tuple>/include/c++/<gcc-version>

I generated my gcc-toolchain with crosstool-ng. I haven't found yet the
option (if any) to tell ct-ng to install c++-headers in sysroot as well.

Thank you for your input.

regards,

Stupid me, it is of course --gcc-toolchain=/path/to , I tried
--gcc-toolchain /path/to - which gave me the same error.

It accepts the argument, but it doesn't seem to use anything of it. I
will dig into it.

Hi,

Hi Patrick,

This is a common case when cross compiling, so clang knows how to use
a gcc-toolchain installation: you just have to pass it the
"--sysroot=..." and "--toolchain=..." arguments, and it will get the
header files and linker / assembler for your target --- assuming your
gcc-toolchain has a standard layout.

I'm getting back to you after (some vacations and) having compared
linaro's latest toolchain to the one I built.

Linaro provides a sysroot-package which does not contain
c++-header-files. Instead they are located in the gcc-package, as in
my package, in

  <target>/include/c++/<gcc-version>/

I'm unable to convince clang(++) to include this search-dir using any
combination of the following options with variations on the path name.

  --gcc-toolchain=
  -B
  --sysroot=

sysroot works a little bit, but only for c-include which are located in
<sysroot-dir>/usr/include.

Using gcc-linaro-5.3-2016.02-x86_64_aarch64-elf I would highly
appreciate an example of how to invoke clang++ for cross-compilation
with this gcc and its includes?

My current try is:

TARGET=aarch64-elf \
GCC_ROOT=~/Downloads/gcc-linaro-5.3-2016.02-x86_64_aarch64-elf \
~/devel/upstream/build/bin/clang++ \
    -v \
    --target=$TARGET \
    --gcc-toolchain=$GCC_ROOT/$TARGET \
    --sysroot=$GCC_ROOT/$TARGET/sysroot \
    -nostdlib \
    -o testCCompiler.cpp.obj -c \
    -std=c++11 \
    test.cpp

test.cpp is empty except #include <cstdint> which it doesn't find.

Linaro's gcc has all include paths in its search list.

Thanks in advance for any help,

We found Ubuntu (perhaps Debian) broke the cross-compile using
--sysroot some time ago. Also see "g++-arm-linux-gnueabi cannot
compile a C++ program with --sysroot",
Bug #1375071 “g++-arm-linux-gnueabi cannot compile a C++ progra...” : Bugs : gcc-defaults-armel-cross package : Ubuntu.

We were working around the broken C++ header includes by specifically
calling them out with -I. See the comment "Fix C++ header paths for
Ubuntu" at https://github.com/weidai11/cryptopp/blob/master/setenv-embedded.sh#L96.

ARM's "GCC ARM Embedded Tools" works as expected. Its maintained by
ARM employees. Also see the PPA at
https://launchpad.net/gcc-arm-embedded.

Since the time of the Launchpad bug report, the linker no longer works, either.

Jeff

> TARGET=aarch64-elf \
> GCC_ROOT=~/Downloads/gcc-linaro-5.3-2016.02-x86_64_aarch64-elf \
> ~/devel/upstream/build/bin/clang++ \
> -v \
> --target=$TARGET \
> --gcc-toolchain=$GCC_ROOT/$TARGET \
> --sysroot=$GCC_ROOT/$TARGET/sysroot \
> -nostdlib \
> -o testCCompiler.cpp.obj -c \
> -std=c++11 \
> test.cpp
>
> test.cpp is empty except #include <cstdint> which it doesn't find.
>
> Linaro's gcc has all include paths in its search list.
>
> Thanks in advance for any help,

We found Ubuntu (perhaps Debian) broke the cross-compile using
--sysroot some time ago. Also see "g++-arm-linux-gnueabi cannot
compile a C++ program with --sysroot",
Bug #1375071 “g++-arm-linux-gnueabi cannot compile a C++ progra...” : Bugs : gcc-defaults-armel-cross package : Ubuntu.

I forgot to mention that I'm using llvm/clang 3.8 which I built myself.

We were working around the broken C++ header includes by specifically
calling them out with -I. See the comment "Fix C++ header paths for
Ubuntu" at
https://github.com/weidai11/cryptopp/blob/master/setenv-embedded.sh#L96.

That's what I did as well to work around.

ARM's "GCC ARM Embedded Tools" works as expected. Its maintained by
ARM employees. Also see the PPA at
GNU Arm Embedded Toolchain in Launchpad.

Yeah, but is the problem clang not looking into the right paths or
gcc-toolchains having changed their layouts. Comparing older
gcc-toolchains I had in my attic it seems that clang is not looking hard
enough.

We were working around the broken C++ header includes by specifically
calling them out with -I. See the comment "Fix C++ header paths for
Ubuntu" at
https://github.com/weidai11/cryptopp/blob/master/setenv-embedded.sh#L96.

That's what I did as well to work around.

ARM's "GCC ARM Embedded Tools" works as expected. Its maintained by
ARM employees. Also see the PPA at
GNU Arm Embedded Toolchain in Launchpad.

Yeah, but is the problem clang not looking into the right paths or
gcc-toolchains having changed their layouts. Comparing older
gcc-toolchains I had in my attic it seems that clang is not looking hard
enough.

It sounds like a Clang bug. If you can reduce it to a minimal test
case, consider filing a bug report.

Jeff

After some more investigation I think the non-finding of c++-includes
is related to target-name. From it clang derives the OS and it is
essentially the OS is the tuple which enables the search of the
c++-include-paths.

On my host it is Linux::AddClangCXXStdlibIncludeArgs which is doing the
job.

When cross-compiling I'm with Generic_GCC which doesn't do anything (it
is empty).

I can regenerate a toolchain which will be called -linux, this might
help. Even though it is wrong, I'm on a bare-metal-machine. I just want
the (standard-)includes.

regards,