This is an archive of the discontinued LLVM Phabricator instance.

Don't add empty InstalledDir as a candidate GCC location
AbandonedPublic

Authored by jackoalan on Dec 21 2017, 9:18 PM.

Details

Summary

I maintain a couple build tools based on Clang's Tooling framework. The tools are built and used directly out of the CMake binary directory (i.e. not installed in a meaningful way).

This non-installed setup causes issues when finding the GCC Toolchain and using the resulting system include paths. A normally-installed clang -v outputs the following:

clang version 5.0.1 (tags/RELEASE_501/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-pc-linux-gnu/7.2.1
Found candidate GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/7.2.1
Found candidate GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1
Found candidate GCC installation: /usr/lib64/gcc/x86_64-pc-linux-gnu/7.2.1
Selected GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/7.2.1
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64

But my build-tree tool outputs this:

clang version 5.0.1 (tags/RELEASE_501/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: 
Found candidate GCC installation: /../lib/gcc/x86_64-pc-linux-gnu/7.2.1
Found candidate GCC installation: /../lib64/gcc/x86_64-pc-linux-gnu/7.2.1
Found candidate GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1
Found candidate GCC installation: /usr/lib64/gcc/x86_64-pc-linux-gnu/7.2.1
Selected GCC installation: /../lib64/gcc/x86_64-pc-linux-gnu/7.2.1

InstalledDir is empty, which is fine, but the resulting candidate selection is undesirable. The /usr rooted candidate strikes me as a much more stable option. Granted /../lib64/gcc/x86_64-pc-linux-gnu/7.2.1 works, but on a rather hackish technicality where /../ == / and symlink exists at /lib64.

This creates problems with dependency files consumed by Ninja (which is unable to canonicalize paths that feature a mix of .. and multi-level symlinks as explained in D37954). For example: /../lib64/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../include/c++/7.2.1/cstdlib which ninja "canonicalizes" as /../include/c++/7.2.1/cstdlib, but is actually /usr/include/c++/7.2.1/cstdlib when taking symlinks into account.

If clang were to use the /usr/lib64/gcc/x86_64-pc-linux-gnu/7.2.1 candidate instead, the result would be /usr/lib64/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../include/c++/7.2.1/cstdlib which Ninja can correctly canonicalize to /usr/include/c++/7.2.1/cstdlib.

I'm not trying to force clang to produce canonical paths as output; rather avoid the obviously problematic /../ candidate in the first place.

Diff Detail

Repository
rC Clang

Event Timeline

jackoalan created this revision.Dec 21 2017, 9:18 PM
jackoalan abandoned this revision.Jan 15 2018, 2:51 PM

I've found that passing --gcc-toolchain=/usr results in the exact behavior I'm after.

Feel free to reopen if desired.