Building world with clang

Dimitry Andric dimitry at andric.com
Tue Aug 17 13:21:45 UTC 2010


On 2010-08-17 13:49, Bob Bishop wrote:
>> However, a disadvantage is that the built-in search paths of the
>> bootstrap compiler are not entirely disabled by using the -isysroot, -B
>> and -L flags,
> 
> This could be viewed as a bug ...

It is probably a bit more complicated than that.  Let me expand a bit
on those compiler flags (and note that clang tries to mimic gcc's
interpretation of them, but is not always perfect).

The -isysroot option
====================
The -isysroot option is supposed to 'reset' the root for include files
to the specified path, according to the gcc documentation.  If I compile
an empty .c file with "gcc -v -S", the default include paths are
printed:

  /usr/include/gcc/4.2
  /usr/include

If you now add "-isysroot ${WORLDTMP}" (the default value of WORLDTMP is
/usr/obj/usr/src/tmp), the resulting include paths become:

  /usr/include/gcc/4.2
  ${WORLDTMP}/usr/include

So unfortunately, gcc seems to only prepend the isysroot path to one of
the directories.

Clang's default include paths are:

  /usr/include/clang/2.8
  /usr/include

With the same -isysroot option added, they become:

  ${WORLDTMP}/usr/include/clang/2.8
  ${WORLDTMP}/usr/include

E.g. clang does the right thing here.

The -B option
=============
The -B option is supposed to "...[specify] where to find the
executables, libraries, include files, and data files of the compiler
itself".  This option is a bit strange, since it is used for finding
both executables (cc1, as, ld), objects (crt*.o) and libraries. 

If you run "gcc -print-search-dirs", it gives its defaults:

  programs: =/usr/bin/:/usr/bin/:/usr/libexec/:/usr/libexec/:/usr/libexec/
  libraries: =/usr/lib/:/usr/lib/

When you add -B${WORLDTMP}/usr/libexec/ (where the cross-tools
built cc1 and cc1plus are), it gives:

  programs: =${WORLDTMP}/usr/libexec/:${WORLDTMP}/usr/libexec/:/usr/bin/:/usr/bin/:/usr/libexec/:/usr/libexec/:/usr/libexec/
  libraries: =${WORLDTMP}/usr/libexec/:${WORLDTMP}/usr/libexec/:/usr/lib/:/usr/lib/

Thus, the -B path is prepended (why it does it twice, I do not know;
probably a bug), but the defaults are *not* removed, so there is still a
risk of picking up an incorrect executable.

Note the path is also prepended to the libraries path, which is rather
useless; there are never any .o or .a files in a libexec directory.  To
fix that path up, you would need to add yet *another* -B option, and you
probably also need yet another -B option to make it find the correct as
and ld.  The final command line would then become:

  gcc -B${WORLDTMP}/usr/bin/ -B${WORLDTMP}/usr/libexec/ -B${WORLDTMP}/usr/lib/

giving the following search dirs:

  programs: =${WORLDTMP}/usr/bin/:${WORLDTMP}/usr/bin/:${WORLDTMP}/usr/libexec/:${WORLDTMP}/usr/libexec/:${WORLDTMP}/usr/lib/:${WORLDTMP}/usr/lib/:/usr/bin/:/usr/bin/:/usr/libexec/:/usr/libexec/:/usr/libexec/
  libraries: =${WORLDTMP}/usr/bin/:${WORLDTMP}/usr/bin/:${WORLDTMP}/usr/libexec/:${WORLDTMP}/usr/libexec/:${WORLDTMP}/usr/lib/:${WORLDTMP}/usr/lib/:/usr/lib/:/usr/lib/

Clang also implements the -B option, but it is not additive yet, so
there is no way to specify both the ${WORLDTMP}/usr/bin directory (for
finding its second stage, as and ld), and ${WORLDTMP}/usr/lib (for
finding startup objects and libraries).

This is also the reason clang-bootstrap-isysroot.diff needs to create
symlinks from ${WORLDTMP}/usr/bin/as and ld to ${WORLDTMP}/usr/lib, as
only the latter directory is specified with -B, and it otherwise would
not be able to find the correct as and ld.

The -L option
=============
The -L option just adds the specified directory to the library search
path.  It puts them before the built-in paths, but it does not disable
those either.  Moreover, the -L paths are *not* used to find the CRT
startup objects:

  $ gcc -L${WORLDTMP}/usr/lib -v test.c
  [...]
   /usr/bin/as -o /tmp/ccZcUXwc.o /tmp/ccYTRRrk.s
   /usr/bin/ld --eh-frame-hdr -V -dynamic-linker /libexec/ld-elf.so.1 -o test /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o -L${WORLDTMP}/usr/lib -L/usr/lib -L/usr/lib /tmp/ccZcUXwc.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/crtend.o /usr/lib/crtn.o

The behaviour of clang is the same for this option, so it does not
improve the situation: it is still possible for libraries outside of
${WORLDTMP} to be found.


>> An advantage of method 2) is that you can be 100% sure all built-in
>> search paths of the bootstrap compiler point to directories under
>> ${WORLDTMP}.  Of course, a disadvantage is that you have to make some
>> modifications to the compiler source itself.
> 
> ... so, which fix to the compiler do you want to make?

My personal preference is method 2), e.g. modify the compiler's
built-in paths, but it is more reasonable to present both methods, and
ask for opinions.  Someone may even know another good method. :)



More information about the freebsd-current mailing list