<div dir="ltr"><div>In the case of Chrome OS, we currently are using all 3 options:</div><div>"-B", "--prefix" and "--gcc-toolchain". "--gcc-toolchain" is only used when the clang binary is not inside /usr/bin e.g. installed as /opt/llvm/bin/clang.</div><div dir="ltr"><br>I think the reason is the layout of gcc and binutils for cross compilation. Example for aarch64:<br><br>binutils installation: /usr/libexec/gcc/aarch64-cros-linux-gnu  -> This is path for "--prefix" (--prefix='<span style="color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">/usr/libexec/gcc/aarch64-cros-linux-gnu/aarch64-cros-linux-gnu-') </span>and "-B" (-B'<span style="color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">/usr/libexec/gcc/aarch64-cros-linux-gnu/')</span></div><div dir="ltr">gcc binaries: /usr/x86_64-pc-linux-gnu/aarch64-cros-linux-gnu/gcc-bin/10.2.0/<br>gcc libraries: /usr/lib/gcc/aarch64-cros-linux-gnu/10.2.0/<br>libc headers + libs: /usr/aarch64-cros-linux-gnu/usr/{include,lib64}, /usr/aarch64-cros-linux-gnu/lib64<br>sysroot: /build/device : Also has libc headers + libraries when building for the device, substitutes libc files from /usr/aarch64-cros-linux-gnu (--sysroot=/build/device).</div><div dir="ltr"><br></div><div dir="ltr">The final command line looks like:</div><div dir="ltr">/opt/llvm/bin/clang --prefix='<span style="font-size:13px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif">/usr/libexec/gcc/aarch64-cros-linux-gnu/aarch64-cros-linux-gnu-' </span>-B'<span style="font-size:13px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif">/usr/libexec/gcc/aarch64-cros-linux-gnu --gcc-toolchain='/usr' --sysroot=/build/device .</span></div><div dir="ltr"><br>My understanding is without passing "--gcc-toolchain=/usr", clang (when not installed in /usr/bin) is not able to find libgcc from /usr/lib/gcc/aarch64-cros-linux-gnu/10.2.0/. i.e. -B/--prefix options were insufficient for finding gcc library paths.<br></div><div dir="ltr"><br></div><div>Thanks,</div><div>Manoj</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Mar 4, 2021 at 3:14 PM Fāng-ruì Sòng via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Thu, Mar 4, 2021 at 2:31 PM Hubert Tong<br>
<<a href="mailto:hubert.reinterpretcast@gmail.com" target="_blank">hubert.reinterpretcast@gmail.com</a>> wrote:<br>
><br>
> On Thu, Mar 4, 2021 at 1:54 PM Fāng-ruì Sòng <<a href="mailto:maskray@google.com" target="_blank">maskray@google.com</a>> wrote:<br>
>><br>
>> On 2021-03-04, Hubert Tong wrote:<br>
>> >On Thu, Mar 4, 2021 at 3:19 AM Fāng-ruì Sòng via cfe-dev <<br>
>> ><a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<br>
>> ><br>
>> >> If --gcc-toolchain is specified, its value overrides the cmake variable<br>
>> >> GCC_INSTALL_PREFIX.<br>
>> >> When the value is non-empty: the value is appended to the --prefix list<br>
>> >> and is used to detect GCC installations.<br>
>> >> The GCC installation is used to provide include directories/library<br>
>> >> directories and some startup files (e.g. crtbegin).<br>
>> >><br>
>> >> Problem 1.<br>
>> >><br>
>> >> --prefix(-B) does more than --gcc-toolchain:<br>
>> >> clang::driver::Driver::GetProgramPath basically searches for<br>
>> >> $prefix/$triple-$file and $prefix$file,<br>
>> >> where $prefix is taken from the list of --prefix(-B). --gcc-toolchain does<br>
>> >> not participate in the search. <have attached a summary of the algorithm at<br>
>> >> the bottom><br>
>> >> The result is that 'ld' and 'as' may come from the system (more precisely,<br>
>> >> 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<br>
>> >> --gcc-toolchain=Inputs/opensuse_42.2_aarch64_tree/usr '-###'<br>
>> >> gcc-toolchain.cpp -v<br>
>> >><br>
>> >>    # I have ld in my /usr/local/bin and it takes precedence over<br>
>> >> /usr/bin/ld<br>
>> >>  "/usr/local/bin/ld" "-EL" "--eh-frame-hdr" "-m" "aarch64linux"<br>
>> >> "-dynamic-linker" "/lib/ld-linux-aarch64.so.1" "-o" "a.out"<br>
>> >> "Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64/crt1.o"<br>
>> >> "Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64/crti.o"<br>
>> >> "Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtbegin.o"<br>
>> >> "-LInputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8"<br>
>> >> "-LInputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/../../../../lib64"<br>
>> >> "-L/lib/aarch64-linux-gnu" "-L/lib/../lib64" "-L/usr/lib/aarch64-linux-gnu"<br>
>> >> "-L/usr/lib/../lib64"<br>
>> >> "-LInputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/../../.."<br>
>> >> "-L/tmp/RelA/bin/../lib" "-L/lib" "-L/usr/lib"<br>
>> >> "/tmp/gcc-toolchain-f87f08.o" "-lgcc" "--as-needed" "-lgcc_s"<br>
>> >> "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"<br>
>> >> "Inputs/opensuse_42.2_aarch64_tree/usr/lib64/gcc/aarch64-suse-linux/4.8/crtend.o"<br>
>> >> "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<br>
>> >> Inputs/opensuse_42.2_aarch64_tree/usr, but ld (and as if<br>
>> >> -fno-integrated-as) is from the system.<br>
>> >> On many Linux distributions you can normally assume that the system ld and<br>
>> >> as only support the host architecture.<br>
>> >> This means --gcc-toolchain can only be used to specify a GCC installation<br>
>> >> with the same architecture.<br>
>> >><br>
>> >... and specifying a GCC installation with the same architecture (e.g., to<br>
>> >use a newer libstdc++) is something that people do:<br>
>> >$ clang++ -fuse-ld=ld --gcc-toolchain=/opt/rh/devtoolset-7/root -xc -<br>
>> >-fno-integrated-as <<<'#include <stdio.h>'$'\n''int main(void) {<br>
>> >printf("Hello, world!\n"); }' && echo OKAY<br>
>> >OKAY<br>
>> >... but it does seem ld is coming from --gcc-toolchain for me anyway:<br>
>> >$ ./build/bootstrap/stage1/build/bin/clang++ -fuse-ld=ld<br>
>> >--gcc-toolchain=/opt/rh/devtoolset-7/root -xc - -fno-integrated-as<br>
>> ><<<'#include <stdio.h>'$'\n''int main(void) { printf("Hello, world!\n"); }'<br>
>> >-### 2>&1 | grep /ld<br>
>> > "/opt/rh/devtoolset-7/root/lib/gcc/ppc64le-redhat-linux/7/../../../../bin/ld"<br>
>> >"--hash-style=gnu" "--eh-frame-hdr" "-m" "elf64lppc" "-dynamic-linker"<br>
>> >"/lib64/ld64.so.2" "-o" "a.out" "/lib/../lib64/crt1.o"<br>
>> >"/lib/../lib64/crti.o"<br>
>> >"/opt/rh/devtoolset-7/root/lib/gcc/ppc64le-redhat-linux/7/crtbegin.o"<br>
>> >"-L/opt/rh/devtoolset-7/root/lib/gcc/ppc64le-redhat-linux/7"<br>
>> >"-L/opt/rh/devtoolset-7/root/lib/gcc/ppc64le-redhat-linux/7/../../../../lib64"<br>
>> >"-L/lib/powerpc64le-linux-gnu" "-L/lib/../lib64"<br>
>> >"-L/usr/lib/powerpc64le-linux-gnu" "-L/usr/lib/../lib64"<br>
>> >"-L/opt/rh/devtoolset-7/root/lib/gcc/ppc64le-redhat-linux/7/../../.."<br>
>> >"-L/data1/hstong.local/wybuild/build/bootstrap/stage1/build/bin/../lib"<br>
>> >"-L/lib" "-L/usr/lib" "/tmp/--8f8c6a.o" "-lstdc++" "-lm" "-lgcc_s" "-lgcc"<br>
>> >"-lc" "-lgcc_s" "-lgcc"<br>
>> >"/opt/rh/devtoolset-7/root/lib/gcc/ppc64le-redhat-linux/7/crtend.o"<br>
>> >"/lib/../lib64/crtn.o"<br>
>><br>
>> 'ld' path is computed by clang/lib/Driver/Driver.cpp Driver::GetProgramPath.<br>
>> Did you set PATH to the devtoolset-7 bin directory?<br>
><br>
> No, I did not.<br>
<br>
Do you mind debugging clang '-###' a bit: set a breakpoint on<br>
clang/lib/Driver/Driver.cpp `GetProgramPath` and report how the 'ld'<br>
under --gcc-toolchain is selected?<br>
<br>
>><br>
>><br>
>> If --gcc-toolchain and multiple -B are specified, the search order is:<br>
>><br>
>> -B -B -B --gcc-toolchain<br>
>><br>
>> Currently the GCC installation with the largest version wins.<br>
>> Do you think we should stop search after one -B provides a GCC installation?<br>
><br>
> Well, the ordering where --gcc-toolchain follows all of the -B seems okay in the context of looking for ld or as. For changing "largest version wins", it might make some sense to order --gcc-toolchain first for the resolution of the GCC installation (which allows "largest version wins" to continue with -B). I suppose it means people using builds preconfigured with a GCC install prefix will be somewhat inconvenienced when they don't want to use the preconfigured path; however, I think this retains most functionality (there is a way to limit the search for GCC installations but also a way to compose search paths for the latest GCC version).<br>
<br>
If cmake GCC_INSTALL_PREFIX was specified configuring llvm-project, I<br>
think it makes sense that explicit options (-B, --gcc-toolchain) take<br>
precedence over GCC_INSTALL_PREFIX.<br>
When --gcc-toolchain is specified: yes, probably it should take<br>
precedence over --prefix. I wonder whether it should suppress --prefix<br>
for GCC installation.<br>
<br>
I played with gcc -B a bit: looks like it picks the first --prefix<br>
where files can be found. So I am going to send a patch making the<br>
"largest version wins" local to one -B (i.e. if multiple versions are<br>
detected, pick the largest).<br>
<br>
<br>
>><br>
>><br>
>> >> --prefix can make as and ld paths correct, but: if another --prefix is<br>
>> >> needed, why do we use --gcc-toolchain?<br>
>> >><br>
>> >Well, I'm not sure that another --prefix is needed. Also, --prefix doesn't<br>
>> >help to pick up the GCC header and library paths and --sysroot overrides<br>
>> >too much:<br>
>> >$ clang++ -fuse-ld=ld --sysroot=/opt/rh/devtoolset-7/root -xc -<br>
>> >-fno-integrated-as <<<'#include <stdio.h>'$'\n''int main(void) {<br>
>> >printf("Hello, world!\n"); }'<br>
>> ><stdin>:1:10: fatal error: 'stdio.h' file not found<br>
>> >#include <stdio.h><br>
>> >         ^~~~~~~~~<br>
>> >1 error generated.<br>
>><br>
>> (The example used --sysroot instead of --prefix)<br>
><br>
> Yes.<br>
><br>
>><br>
>><br>
>> OK, your other reply clarified that --prefix does pick up include/library directories.<br>
><br>
> Yes.<br>
<br>
<br>
<br>
-- <br>
宋方睿<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div></div>