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
https://launchpad.net/gcc-arm-embedded.

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
https://launchpad.net/gcc-arm-embedded.

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,