[cfe-dev] --gcc-toolchain (GCC_INSTALL_PREFIX) and --prefix(-B)
Fāng-ruì Sòng via cfe-dev
cfe-dev at lists.llvm.org
Thu Mar 4 00:19:10 PST 2021
If --gcc-toolchain is specified, its value overrides the cmake variable
GCC_INSTALL_PREFIX.
When the value is non-empty: the value is appended to the --prefix list and
is used to detect GCC installations.
The GCC installation is used to provide include directories/library
directories and some startup files (e.g. crtbegin).
Problem 1.
--prefix(-B) does more than --gcc-toolchain:
clang::driver::Driver::GetProgramPath basically searches for
$prefix/$triple-$file and $prefix$file,
where $prefix is taken from the list of --prefix(-B). --gcc-toolchain does
not participate in the search. <have attached a summary of the algorithm at
the bottom>
The result is that 'ld' and 'as' may come from the system (more precisely,
sysroot):
cd clang/test/Driver
# Make sure Inputs/opensuse_42.2_aarch64_tree/usr/bin/ld exists.
clang -target aarch64-suse-linux
--gcc-toolchain=Inputs/opensuse_42.2_aarch64_tree/usr '-###'
gcc-toolchain.cpp -v
# I have ld in my /usr/local/bin and it takes precedence over /usr/bin/ld
"/usr/local/bin/ld" "-EL" "--eh-frame-hdr" "-m" "aarch64linux"
"-dynamic-linker" "/lib/ld-linux-aarch64.so.1" "-o" "a.out"
"Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64/crt1.o"
"Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64/crti.o"
"Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtbegin.o"
"-LInputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8"
"-LInputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64"
"-L/lib/aarch64-linux-gnu" "-L/lib/../lib64" "-L/usr/lib/aarch64-linux-gnu"
"-L/usr/lib/../lib64"
"-LInputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/../../.."
"-L/tmp/RelA/bin/../lib" "-L/lib" "-L/usr/lib"
"/tmp/gcc-toolchain-f87f08.o" "-lgcc" "--as-needed" "-lgcc_s"
"--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
"Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtend.o"
"Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64/crtn.o"
The -L and crt* files are indeed from
Inputs/opensuse_42.2_aarch64_tree/usr, but ld (and as if
-fno-integrated-as) is from the system.
On many Linux distributions you can normally assume that the system ld and
as only support the host architecture.
This means --gcc-toolchain can only be used to specify a GCC installation
with the same architecture.
--prefix can make as and ld paths correct, but: if another --prefix is
needed, why do we use --gcc-toolchain?
I have sent a patch to document the current state:
https://reviews.llvm.org/D97902
Problem 2.
Non-empty --gcc-toolchain has one nicer property: it suppresses GCC
installation detection in the sysroot.
Now let me alter the command a bit:
"/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld"
"-EL" "--eh-frame-hdr" "-m" "aarch64linux" "-dynamic-linker"
"/lib/ld-linux-aarch64.so.1" "-o" "a.out"
"/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../..
/../aarch64-linux-gnu/lib/crt1.o"
"/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/lib/crti.o"
"/usr/lib/gcc-cross/aarch64-linux-gnu/10/crtbegin.o"
"-L/usr/lib/gcc-cross/aarch64-linux-gnu/10"
"-L/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../aarch64-linux-gnu"
"-L/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../lib64"
"-L/lib/aarch64-linux-gnu" "-L/lib/../lib64" "-L/usr/lib/aarch64-linux-gnu"
"-L/usr/lib/../lib64" "-L/usr/lib/aarch64-linux-gnu/../../lib64"
"-L/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/lib"
"-L/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../.."
"-L/tmp/RelA/bin/../lib" "-L/lib" "-L/usr/lib"
"/tmp/gcc-toolchain-b491cd.o" "-lgcc" "--as-needed" "-lgcc_s"
"--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
"/usr/lib/gcc-cross/aarch64-linux-gnu/10/crtend.o"
"/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/lib/crtn.o"
I have installed an aarch64 cross gcc. Because its version is larger than
the version of the GCC installation under --prefix, the system
gcc-cross/aarch64-linux-gnu takes precedence.
This behavior looks a bit unfortunate. Should we let the first --prefix win
and drop future --prefix and default system installations?
[1]:
The logic is around
https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/ToolChains/Gnu.cpp#L1910
Prefixes = --prefix/-B list (only the directory subset is effective)
StringRef GCCToolchainDir = --gcc-toolchain= or CMake variable
GCC_INSTALL_PREFIX
if (GCCToolchainDir != "") {
Prefixes.push_back(std::string(GCCToolchainDir));
} else {
if (!D.SysRoot.empty()) {
Prefixes.push_back(D.SysRoot);
// Add D.SysRoot+"/usr" to Prefixes. Some distributions add more
directories.
AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
}
// D.InstalledDir is the directory of the clang executable, e.g.
/usr/bin
Prefixes.push_back(D.InstalledDir + "/..");
if (D.SysRoot.empty())
AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
}
// Gentoo / ChromeOS specific logic.
// I will move this block in https://reviews.llvm.org/D97894
if (GCCToolchainDir == "" || GCCToolchainDir == D.SysRoot + "/usr") {
...
}
// Loop over the various components which exist and select the best GCC
// installation available. GCC installs are ranked by version number.
Version = GCCVersion::Parse("0.0.0");
for (const std::string &Prefix : Prefixes) {
auto &VFS = D.getVFS();
if (!VFS.exists(Prefix))
continue;
// CandidateLibDirs is a subset of {/lib64, /lib32, /lib}.
for (StringRef Suffix : CandidateLibDirs) {
const std::string LibDir = Prefix + Suffix.str();
if (!VFS.exists(LibDir))
continue;
bool GCCDirExists = VFS.exists(LibDir + "/gcc");
bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");
// Precise match. Detect $Prefix/lib/$--target
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir,
TargetTriple.str(),
false, GCCDirExists, GCCCrossDirExists);
// Usually empty.
for (StringRef Candidate : ExtraTripleAliases) // Try these first.
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate,
false,
GCCDirExists, GCCCrossDirExists);
// CandidateTripleAliases is a set with "x86_64-linux-gnu",
"x86_64-unknown-linux-gnu", ...
// This loop detects directories like $Prefix/lib/x86_64-linux-gnu.
for (StringRef Candidate : CandidateTripleAliases)
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate,
false,
GCCDirExists, GCCCrossDirExists);
}
for (StringRef Suffix : CandidateBiarchLibDirs) {
const std::string LibDir = Prefix + Suffix.str();
if (!VFS.exists(LibDir))
continue;
bool GCCDirExists = VFS.exists(LibDir + "/gcc");
bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");
for (StringRef Candidate : CandidateBiarchTripleAliases)
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, true,
GCCDirExists, GCCCrossDirExists);
}
}
--
宋方睿
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20210304/b02b6ba7/attachment.html>
More information about the cfe-dev
mailing list