<div dir="ltr">If --gcc-toolchain is specified, its value overrides the cmake variable GCC_INSTALL_PREFIX.<br>When the value is non-empty: the value is appended to the --prefix list and is used to detect GCC installations.<br>The GCC installation is used to provide include directories/library directories and some startup files (e.g. crtbegin).<br><br>Problem 1.<br><br>--prefix(-B) does more than --gcc-toolchain: clang::driver::Driver::GetProgramPath basically searches for $prefix/$triple-$file and $prefix$file,<br>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><br>The result is that 'ld' and 'as' may come from the system (more precisely, sysroot):<br><br>cd clang/test/Driver<br># Make sure Inputs/opensuse_42.2_aarch64_tree/usr/bin/ld exists.<br>clang -target aarch64-suse-linux --gcc-toolchain=Inputs/opensuse_42.2_aarch64_tree/usr '-###' gcc-toolchain.cpp -v<br><br>   # I have ld in my /usr/local/bin and it takes precedence over /usr/bin/ld<br> "/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"<br><br>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.<br>On many Linux distributions you can normally assume that the system ld and as only support the host architecture.<br>This means --gcc-toolchain can only be used to specify a GCC installation with the same architecture.<br>--prefix can make as and ld paths correct, but: if another --prefix is needed, why do we use --gcc-toolchain?<br><br>I have sent a patch to document the current state: <a href="https://reviews.llvm.org/D97902">https://reviews.llvm.org/D97902</a><br><br><br>Problem 2.<br><br>Non-empty --gcc-toolchain has one nicer property: it suppresses GCC installation detection in the sysroot.<br>Now let me alter the command a bit:<br><br> "/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/../../..<br>/../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"<br><br>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.<br>This behavior looks a bit unfortunate. Should we let the first --prefix win and drop future --prefix and default system installations?<br><br><br><br>[1]:<br><br>The logic is around <a href="https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/ToolChains/Gnu.cpp#L1910">https://github.com/llvm/llvm-project/blob/main/clang/lib/Driver/ToolChains/Gnu.cpp#L1910</a><br><br>   Prefixes = --prefix/-B list (only the directory subset is effective)<br>   StringRef GCCToolchainDir = --gcc-toolchain= or CMake variable GCC_INSTALL_PREFIX<br>   if (GCCToolchainDir != "") {<br>     Prefixes.push_back(std::string(GCCToolchainDir));<br>   } else {<br>     if (!D.SysRoot.empty()) {<br>       Prefixes.push_back(D.SysRoot);<br>       // Add D.SysRoot+"/usr" to Prefixes. Some distributions add more directories.<br>       AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);<br>     }<br><br>     // D.InstalledDir is the directory of the clang executable, e.g. /usr/bin<br>     Prefixes.push_back(D.InstalledDir + "/..");<br><br>     if (D.SysRoot.empty())<br>       AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);<br>   }<br><br>   // Gentoo / ChromeOS specific logic.<br>   // I will move this block in <a href="https://reviews.llvm.org/D97894">https://reviews.llvm.org/D97894</a><br>   if (GCCToolchainDir == "" || GCCToolchainDir == D.SysRoot + "/usr") {<br>     ...<br>   }<br><br>   // Loop over the various components which exist and select the best GCC<br>   // installation available. GCC installs are ranked by version number.<br>   Version = GCCVersion::Parse("0.0.0");<br>   for (const std::string &Prefix : Prefixes) {<br>     auto &VFS = D.getVFS();<br>     if (!VFS.exists(Prefix))<br>       continue;<br><br>     // CandidateLibDirs is a subset of {/lib64, /lib32, /lib}.<br>     for (StringRef Suffix : CandidateLibDirs) {<br>       const std::string LibDir = Prefix + Suffix.str();<br>       if (!VFS.exists(LibDir))<br>         continue;<br>       bool GCCDirExists = VFS.exists(LibDir + "/gcc");<br>       bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");<br><br>       // Precise match. Detect $Prefix/lib/$--target<br>       ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, TargetTriple.str(),<br>                              false, GCCDirExists, GCCCrossDirExists);<br>       // Usually empty.<br>       for (StringRef Candidate : ExtraTripleAliases) // Try these first.<br>         ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, false,<br>                                GCCDirExists, GCCCrossDirExists);<br>       // CandidateTripleAliases is a set with "x86_64-linux-gnu", "x86_64-unknown-linux-gnu", ...<br>       // This loop detects directories like $Prefix/lib/x86_64-linux-gnu.<br>       for (StringRef Candidate : CandidateTripleAliases)<br>         ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, false,<br>                                GCCDirExists, GCCCrossDirExists);<br>     }<br>     for (StringRef Suffix : CandidateBiarchLibDirs) {<br>       const std::string LibDir = Prefix + Suffix.str();<br>       if (!VFS.exists(LibDir))<br>         continue;<br>       bool GCCDirExists = VFS.exists(LibDir + "/gcc");<br>       bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");<br>       for (StringRef Candidate : CandidateBiarchTripleAliases)<br>         ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, true,<br>                                GCCDirExists, GCCCrossDirExists);<br>     }<br>   }<br><div><br></div><div><br></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">宋方睿</div></div></div>