Bug 851 - Add option to specify --sysroot value for external toolchain
Summary: Add option to specify --sysroot value for external toolchain
Status: RESOLVED FIXED
Alias: None
Product: buildroot
Classification: Unclassified
Component: Other (show other bugs)
Version: unspecified
Hardware: PC Linux
: P5 enhancement
Target Milestone: 2010.05
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-01-08 19:01 UTC by Grant Edwards
Modified: 2010-04-13 15:33 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:


Attachments
Patch to allow use of relocated external toolchains that require a --sysroot option (2.35 KB, patch)
2010-01-08 19:01 UTC, Grant Edwards
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Grant Edwards 2010-01-08 19:01:01 UTC
Created attachment 887 [details]
Patch to allow use of relocated external toolchains that require a --sysroot option

The current support for external toolchains assumes that the
external toolchain supports but does not require that a sysroot
value be passed when invoking the compiler, linker, etc.

This is inconvenient and overly restrictive for a couple
reasons:

  * You might want to be able to switch back and forth between
    different toolchains.  Building the toolchains with unique
    install paths is painful.

  * Developers want to be able to do development in "isolated"
    non-system directories without having to put the external
    toolchain in a global, hard-wired location -- a location
    that might be in use by a different project for a different
    version/flavor of the toolchain.

The attached patch adds a boolean config option that tells
buildroot that the external toolchain requires a sysroot value.
IOW, the the sysroot value reported by "gcc -v" is not correct.

It also adds a configuration variable that specifies the
correct sysroot value for the external toolchain. This value
defaults to an appropriate value for the already-specified
location of the sysroot toolchain.  In most cases, setting the
boolean BR2_TOOLCHAIN_EXTERNAL_NEEDS_SYSROOT will be
sufficient.
Comment 1 Thomas Petazzoni 2010-02-21 22:33:09 UTC
Move milestone to 2010.05 since enhancements will not be handled before the release of 2010.02.
Comment 2 Thomas Petazzoni 2010-04-04 16:03:56 UTC
While the implementation of the feature looks fine to me, I don't understand which use-case it is trying to solve. Could you elaborate a bit more on this ?
Comment 3 Grant Edwards 2010-04-04 16:22:04 UTC
The use case is when the external toolchain was built in a location
other where it is located at the time buildroot is using it.

Buildroot assumes that it should copy library/include files from the
"sysroot" location printed by gcc -v.  However, that is the location
where the toolchain was _built_.

That may or may not be the where the toolchain is currently located.

The libraries/include files need to be copied from where the toolchain
_is_now_, not from where it was built.

This patch specifies the "sysroot" option appropriate for the current
location of the toolchain.  The patch implements two new option values:


BR2_TOOLCHAIN_EXTERNAL_NEEDS_SYSROOT

  This is a boolean indicating that the location of the external
  toolchain is not the same as the location where that toolchain was
  built, therefore the proper "sysroot" value for the toolchain is
  _not_ the one printed by gcc -v.  [That is the value that buildroot
  uses now.]

BR2_TOOLCHAIN_EXTERNAL_SYSROOT_VALUE

  This is the proper sysroot value for the external toolchain in its
  current location.  This is the value that buildroot should use when
  copying library/include files.  It will default to a value that is
  usually appropriate for the current location of the external
  toolchain.

Without this patch, buildroot cannot use an external toolchain unless
it is located in the place it was built.  Here are three use cases
where you might want to be able to use an external toolchain that is
located in a directory other than the one where it was built:

  * You might want to be able to switch back and forth between
    different toolchains.  Building the toolchains with unique
    install paths is painful.

  * Developers want to be able to do development in "isolated"
    non-system directories without having to put the external
    toolchain in a global, hard-wired location -- a location
    that might be in use by a different project for a different
    version/flavor of the toolchain.

  * A developer may want to use an external toolchain that was built
    by somebody else on a different machine.  It may not be possible
    to place such a "third-party" toolchain in the exact same
    directory where it was built.

Comment 4 Grant Edwards 2010-04-04 16:46:22 UTC
I think perhaps I've been a bit unclear when writing about "where the
external toolchain was built".  What I mean by that is not the actual
build directory where the toolchain was compiled, but the location
from which it was intended to run when it was built -- the location
where it was put by the "make install" step of the toolchain build.
Comment 5 Yann E. MORIN 2010-04-04 18:04:13 UTC
Grant,

This commit: http://git.buildroot.org/buildroot/commit/?id=3b7aee23f2ab732f06b8a090ca002fb102d547ee

should fix the case for sysrooted toolchain that were relocated.

Was that the issue you were facing?
If so, does this commit fix it for you?
Comment 6 Grant Edwards 2010-04-04 19:02:35 UTC
It looks like that commit addresses the same problem except that it's
unconditional.  I made my change configurable because I assumed there
was a reason why it was the way it was and that somebody was depending
on the extant behavior. Though I couldn't figure out exactly how that
behavior would be desirable, it looked like somebody went to extra
effort to extract the "as built" sysroot rather than use the path that
was already known for the current location of the toolchain.

I must admit I'm a bit confused by the effort the committed patch goes
to to figure out the value to use for sysroot.  Isn't it always going
to be "$(BR2_TOOLCHAIN_EXTERNAL_PATH)/.."?  Or does crosstool-ng
structure the toolchain install directory tree differently than does
buildroot?

Trying out that commit will require changes to my build script, so I can't
do it right now.  I'll give it go it when I have some spare time.
Comment 7 Yann E. MORIN 2010-04-04 21:18:38 UTC
Grant,

[wrt sysroot]
> Isn't it always going to be "$(BR2_TOOLCHAIN_EXTERNAL_PATH)/.."?

IIRC, $(BR2_TOOLCHAIN_EXTERNAL_PATH) is the place where to find the executables, eg. target-gcc et al.

So, no, the sysroot should not be in $(BR2_TOOLCHAIN_EXTERNAL_PATH)/.. That would have been the place to find target includes/libraries for the old, non-sysroot case.

There is no way to know where the sysroot is, except by asking gcc where it was previously installed into, subtract that from the configured sysroot prefix, and re-add the current toolchain prefix.

Of course, that rules out a toolchain in which the sysroot was configured out-side the gcc prefix, in which case I have absolutely no clue what could happen if the toolchain gets relocated...
Comment 8 Grant Edwards 2010-04-04 22:03:06 UTC
> [wrt sysroot]
> > Isn't it always going to be "$(BR2_TOOLCHAIN_EXTERNAL_PATH)/.."?
> 
> IIRC, $(BR2_TOOLCHAIN_EXTERNAL_PATH) is the place where to find the
> executables, eg. target-gcc et al.

Almost.  $(BR2_TOOLCHAIN_EXTERNAL_PATH) is where to find the bin
directory that contains the executables.  If the gcc executable is
/foo/bar/usr/bin/arm-linux-gcc, then BR2_TOOLCHAIN_EXTERNAL_PATH is
/foo/bar/usr.

> So, no, the sysroot should not be in $(BR2_TOOLCHAIN_EXTERNAL_PATH)/.. That
> would have been the place to find target includes/libraries for the old,
> non-sysroot case.

For toolchains built by buildroot, the proper sysroot value is always 
$(BR2_TOOLCHAIN_EXTERNAL_PATH)/..

I don't know what you mean by "the old non-sysroot" case.  I've always
built toolchains with sysroot support, and the sysroot value has always
been $(BR2_TOOLCHAIN_EXTERNAL_PATH)/..

> There is no way to know where the sysroot is, except by asking gcc
> where it was previously installed into, subtract that from the
> configured sysroot prefix, and re-add the current toolchain prefix.

OK, we'll use the commited patch's algorithm with my toolchain (which
was built by buildroot).  It is currently located in

/home/nextgen/buildroot/foobar.

BR2_TOOLCHAIN_EXTERNAL_PATH is /home/nextgen/buildroot/foobar/usr

The gcc executble is in /home/nextgen/buildroot/foobar/usr/bin

The proper sysroot value is /home/nextgen/buildroot/foobar

$ /home/nextgen/buildroot/foobar/usr/bin/arm-linux-gcc -v
Using built-in specs.
Target: arm-linux-uclibc
Configured with: /home/nextgen/buildroot-test/buildroot/output/toolchain/gcc-4.4.3/configure --prefix=/usr --build=i386-pc-linux-gnu --host=i386-pc-linux-gnu --target=arm-linux-uclibc --enable-languages=c,c++ --with-sysroot=/home/nextgen/buildroot-test/buildroot/output/staging --with-build-time-tools=/home/nextgen/buildroot-test/buildroot/output/staging/usr/arm-linux-uclibc/bin --disable-__cxa_atexit --enable-target-optspace --with-gnu-ld --disable-libssp --disable-tls --enable-shared --with-gmp=/home/nextgen/buildroot-test/buildroot/output/toolchain/gmp --with-mpfr=/home/nextgen/buildroot-test/buildroot/output/toolchain/mpfr --enable-threads --disable-multilib --disable-decimal-float --with-float=soft --with-abi=apcs-gnu --with-arch=armv5te --with-tune=arm9tdmi --with-pkgversion='Buildroot 2010.02-git' --with-bugurl=http://bugs.buildroot.net/
Thread model: posix
gcc version 4.4.3 (Buildroot 2010.02-git) 

CFG_PREFIX_DIR is "/usr"

CFG_SYSROOT_DIR is "/home/nextgen/buildroot-test/buildroot/output/staging"

REL_SYSROOT_DIR is "/home/nextgen/buildroot-test/buildroot/output/staging"

SYSROOT_DIR is "/home/nextgen/buildroot/foobar/usr/home/nextgen/buildroot-test/buildroot/output/staging"

That's not a valid path, either before or after the toolchain is
copied into staging.

> Of course, that rules out a toolchain in which the sysroot was configured
> out-side the gcc prefix,

That appears to be how buildroot builds toolchains.

> in which case I have absolutely no clue what could happen if the
> toolchain gets relocated...

Has the decision has been made to not support external toolchains
built by buildroot?
Comment 9 Peter Korsgaard 2010-04-07 07:51:52 UTC
Fixed in git (6db57c69360087b)
Comment 10 Grant Edwards 2010-04-12 22:58:16 UTC
The "fix" doesn't work for me.

The fix in ext-tool.mk uses the following line to figure out what
the sysroot directory is:

SYSROOT_DIR=$(shell readlink -f $$(LANG=C $(TARGET_CC) -print-file-name=libc.a |sed -r -e 's:usr/lib/libc\.a::;'))

All that does for me is print "libc.a":

  $ LANG=C /home/nextgen/buildroot/toolchain/usr/bin/arm-linux-gcc -print-file-name=libc.a
  libc.a

The only way I get the desired path for libc.a is to pass gcc the
correct sysroot value:

  $ LANG=C /home/nextgen/buildroot/toolchain/usr/bin/arm-linux-gcc --sysroot=/home/nextgen/buildroot/toolchain -print-file-name=libc.so
  /home/nextgen/buildroot/toolchain/usr/lib/libc.so


But the correct sysroot value is what that line in ext-tool.mk is
supposed to be figuring out.

Can somebody explain to me how that line is supposed to work for a
relocated external toolchain?

BTW, this is with a toolchain built by buildroot:

  $ /home/nextgen/buildroot/toolchain/usr/bin/arm-linux-gcc -v
  Using built-in specs.
  Target: arm-linux-uclibc
  Configured with: /home/nextgen/buildroot-test/buildroot/output/toolchain/gcc-4.4.3/configure --prefix=/usr --build=i386-pc-linux-gnu --host=i386-pc-linux-gnu --target=arm-linux-uclibc --enable-languages=c,c++ --with-sysroot=/home/nextgen/buildroot-test/buildroot/output/staging --with-build-time-tools=/home/nextgen/buildroot-test/buildroot/output/staging/usr/arm-linux-uclibc/bin --disable-__cxa_atexit --enable-target-optspace --with-gnu-ld --disable-libssp --disable-tls --enable-shared --with-gmp=/home/nextgen/buildroot-test/buildroot/output/toolchain/gmp --with-mpfr=/home/nextgen/buildroot-test/buildroot/output/toolchain/mpfr --enable-threads --disable-multilib --disable-decimal-float --with-float=soft --with-abi=apcs-gnu --with-arch=armv5te --with-tune=arm9tdmi --with-pkgversion='Buildroot 2010.02-git' --with-bugurl=http://bugs.buildroot.net/
  Thread model: posix
  gcc version 4.4.3 (Buildroot 2010.02-git) 



Comment 11 Thomas Petazzoni 2010-04-13 05:34:51 UTC
Could you the .config you used to generate the toolchain ? I don't get the same behaviour here.

However, I've tried with a Buildroot generated toolchain, that I moved, and I keep getting the old path.

Buildroot external toolchain, at its original location:

$ ./arm-br/usr/bin/arm-linux-gcc -print-file-name=libc.a
/home/thomas/x-tools/arm-br//usr/lib/libc.a

Buildroot external toolchain, in a different location:

$ ./arm-br.moved/usr/bin/arm-linux-gcc -print-file-name=libc.a
/home/thomas/x-tools/arm-br//usr/lib/libc.a

Crosstool-NG toolchain, original location:

$ ./arm-unknown-linux-uclibcgnueabi/bin/arm-linux-gcc -print-file-name=libc.a
/home/thomas/x-tools/arm-unknown-linux-uclibcgnueabi/arm-unknown-linux-uclibcgnueabi//sys-root/usr/lib/libc.a

Crosstool-NG toolchain, in a different location:

$ ./arm2/bin/arm-linux-gcc -print-file-name=libc.a
/home/thomas/x-tools/arm2/bin/../arm-unknown-linux-uclibcgnueabi//sys-root/usr/lib/libc.a

So, with Buildroot toolchains, the result is not correct: -print-file-name keeps returning paths to the original location. With Crosstool-NG toolchains, it works as expected. Something is definitely wrong in the way Buildroot generates toolchains, IMO.
Comment 12 Grant Edwards 2010-04-13 15:33:35 UTC
I didn't save the .config file for my production toolchain (the one
that just prints "libc.a").  So, I rebuilt it, and now I see the same
behavior that you do: after being relocated it always prints the
original path for the file (e.g. <whaterver>/buildroot/output/staging/usr/lib/libc.a.

In either case, the current fix doesn't work for toolchains built
using buildroot.

I'm going to continue trying to build a toolchain built using
crosstool-ng. So far, it's been rather futile.  The "example"
configuration for arm/linux/uclibc builds fine, but as soon as I try
the current version of anything (gcc, uclibc) the uclibc build fails
due to a bunch of unresolved symbols.

> So, with Buildroot toolchains, the result is not correct:
> -print-file-name keeps returning paths to the original location.

I thought that _was_ the expected behavior and that's why we need to
pass the -sysroot option to the toolchain.

> With Crosstool-NG toolchains, it works as expected. Something is
> definitely wrong in the way Buildroot generates toolchains, IMO.

Now I'm confused again (shocker, eh?): if a gcc toolchain is expected
to be able to find its files after it's been relocated, then it
doesn't need to be passed the -sysroot option. If that's true, why
does buildroot require support for the -sysroot option and try to
figure out what to pass as the sysroot value?

[Is there any way to prevent bugzilla from wrapping comments?
 Presumably that's done in an attempt to render illegible the code
 examples and program output that pastes into comments. It works quite
 well.]