Clang++ --gcc-toolchain and gcc 4.9.3 linking issues

8.6k views Asked by At

(Ubuntu 16.04.1)

By default on 16.04.1 clang is picking the gcc tool chain for 5.4. Unfortunately I have a library that requires pre-5.0 ABI and I do NOT have access to the source, nor has the implementer released a new version. I've been trying to use the --gcc-toolchain option, but I can NOT get it to work. (ctrbegin.o and crtend.o don't get the proper prefix at link.)

$ clang++-3.8 -v -print-search-dirs

clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/5.4.0
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/6.0.0
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9.3
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/6.0.0
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/5.4.0
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/6.0.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.3
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/5.4.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/6.0.0
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0
Candidate multilib: .;@m64
Selected multilib: .;@m64
programs: =/usr/bin:/usr/lib/llvm-3.8/bin:/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../x86_64-linux-gnu/bin

libraries: =/usr/lib/llvm-3.8/bin/../lib/clang/3.8.0:
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0:
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu:
/lib/x86_64-linux-gnu:
/lib/../lib64:
/usr/lib/x86_64-linux-gnu:
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../..:
/usr/lib/llvm-3.8/bin/../lib:
/lib:
/usr/lib

When I attempt to specify the --gcc-toolchain, clang seems to accept, then completely ignore the value. (Same thing happens with clang++-3.5 on 16.04.1.)

Is this the proper syntax? Notice that the library directories are missing from the output.

$ clang++-3.8 -v --gcc-toolchain=/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9.3 -print-search-dirs

clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
programs: =/usr/bin:/usr/lib/llvm-3.8/bin:/..//bin

libraries: =/usr/lib/llvm-3.8/bin/../lib/clang/3.8.0:/lib/x86_64-linux-gnu:/lib/../lib64:/usr/lib/x86_64-linux-gnu:/usr/lib/llvm-3.8/bin/../lib:/lib:/usr/lib

I have tried MANY variations on the above theme. (4.9, removing the relative path, etc.) I've tried the -isystem option and the -cxx-isystem option. (Both suggested as solutions to similar issues.)

What am i missing? (I hope it is simple and a head smack is in order!)

4

There are 4 answers

1
Nikolai On

It seems that you're passing a wrong path to --gcc-toolchain option. It expects a path to GCC install prefix which is /usr in case of GCC installed with a package manager. However, I don't think it's possible to choose what toolchain to use if you have several versions of GCC installed in your system and they all have the same prefix. Seems that clang just takes the latest version in $PREFIX/lib/gcc/x86_64-linux-gnu directory. So, I'd recommend you to build the toolchain you need yourself and pass the installation prefix to --gcc-toolchain option.

0
Gaetano On

Unfortunately I have a library that requires pre-5.0 ABI and I do NOT have access to the source

you don't need to switch gcc-toolchain to change ABI as the newer gcc versions have dual-abi support.

To switch the ABI overriding the preprocessor macro:

clang++ -D_GLIBCXX_USE_CXX11_ABI=0 

So, I'd recommend you to build the toolchain you need yourself and pass the installation prefix to --gcc-toolchain option.

If it is alredy available, you might want to trick clang to use your selected toolchain by mimicking your /usr folder via symlinks while excluding the gcc versions you dont need.

0
proski On

As Gaetano wrote in the linked ticket, you need to build a separate directory that can be passed to clang as --gcc-toolchain. Here's my slightly refined code. No bin and include links are needed.

# The libstdc++ version you want to use
libstdcxx_version="4.9"
# Avoid calling arch twice
arch="$(arch)"
# The new toolchain root in the current directory
toolchain_root="$(pwd)/toolchain"
# The gcc library directory to be created
toolchain_gcc="$toolchain_root/lib/gcc/$arch-linux-gnu"
# Create that directory
mkdir -p "$toolchain_gcc"
# Find the longest matching libstdc++ version.
# Needed for clang-3.8 and older - they need 4.9.x rather than 4.9.
libstdcxx_dir=$(ls -d /usr/lib/gcc/$arch-linux-gnu/${libstdcxx_version}* \
  | tail -1)
# Link the libstdc++ library directory to the new location
ln -sfn "$libstdcxx_dir" "$toolchain_gcc/"
# Now you can add "--gcc-toolchain=$toolchain_root" to the clang flags
0
Sebastian Redl On

As of Clang-16, you can use --gcc-install-dir to simply pass the full path of the GCC installation you want to use.