| Summary: | Add option to specify --sysroot value for external toolchain | ||
|---|---|---|---|
| Product: | buildroot | Reporter: | Grant Edwards <grant.b.edwards> |
| Component: | Other | Assignee: | unassigned |
| Status: | RESOLVED FIXED | ||
| Severity: | enhancement | CC: | buildroot, yann.morin.1998 |
| Priority: | P5 | ||
| Version: | unspecified | ||
| Target Milestone: | 2010.05 | ||
| Hardware: | PC | ||
| OS: | Linux | ||
| Host: | Target: | ||
| Build: | |||
| Attachments: | Patch to allow use of relocated external toolchains that require a --sysroot option | ||
Move milestone to 2010.05 since enhancements will not be handled before the release of 2010.02. 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 ?
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.
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. 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? 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. 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...
> [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? Fixed in git (6db57c69360087b) 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) 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. 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.] |
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.