Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

binutils-unwrapped, gcc, gdb: force targetPrefix if cross compiling #119625

Merged
merged 3 commits into from
Apr 16, 2021

Conversation

sternenseemann
Copy link
Member

@sternenseemann sternenseemann commented Apr 16, 2021

The binutils build system checks by itself if it is building a cross
toolchain or not and prepends or omits a targetPrefix accordingly. This
means that we can always pass target via configureTargets.

However the binutils build system and our bintools wrapper disagree over
whether we are building a cross toolchain or not sometimes since cross
compilation can be relatively subtle in nixpkgs. For example every use
of crossOverlays will make nixpkgs build a cross toolchain even though
localSystem == crossSystem. The cross infrastructure is also used to
build native binaries with a different stdenv (musl instead of glibc,
clang instead of gcc). In all of these cases stdenv.hostPlatform.config
== stdenv.targetPlatform.config, causing binutils to not prepend a
target prefix. At the same time stdenv.hostPlatform !=
stdenv.targetPlatform causing the bintools wrapper to expect a target
prefix, thus building an incomplete set of bintools. This is why
currently pkgsCross.gnu64 and pkgsCross.musl64 aren't working.

The solution is quite simple however: If we detect that we are building
a cross toolchain in the binutils-unwrapped expression, we force the
targetPrefix with --programprefix and fulfill the expectations of the
bintools wrapper at the same time.

Tested (on x86_64-linux):

  • pkgsCross.musl64.hello
  • pkgsCross.aarch64-multiplatform.hello
  • pkgs.hello

Still not working is pkgsCross.gnu64.

Motivation for this change
Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

@sternenseemann sternenseemann added the 6.topic: stdenv Standard environment label Apr 16, 2021
@sternenseemann sternenseemann force-pushed the binutils-force-prefix branch from ac3de59 to cccfca6 Compare April 16, 2021 14:59
@github-actions github-actions bot removed the 6.topic: stdenv Standard environment label Apr 16, 2021
@sternenseemann
Copy link
Member Author

For reference, this is the new failure when building pkgsCross.gnu64.hello on x86_64-linux:

*** This configuration is not supported in the following subdirectories:
     gnattools gotools target-libada target-libhsail-rt target-libphobos target-libbacktrace target-libgfortran target-libgo target-libffi target-libobjc target-liboffloadmic
    (Any other directories should still work fine.)
*** --with-headers is only supported when cross compiling
builder for '/nix/store/jn1jnbb6wabgxhiafdbwbk809gag1nv3-x86_64-unknown-linux-gnu-stage-final-gcc-10.2.0.drv' failed with exit code 1
error: build of '/nix/store/jn1jnbb6wabgxhiafdbwbk809gag1nv3-x86_64-unknown-linux-gnu-stage-final-gcc-10.2.0.drv' on 'ssh://edwin' failed: builder for '/nix/store/jn1jnbb6wabgxhiafdbwbk809gag1nv3-x86_64-unknown-linux-gnu-stage-final-gcc-10.2.0.drv' failed with exit code 1
builder for '/nix/store/jn1jnbb6wabgxhiafdbwbk809gag1nv3-x86_64-unknown-linux-gnu-stage-final-gcc-10.2.0.drv' failed with exit code 1
cannot build derivation '/nix/store/ri3gpxdij4pm5x6cljzkxa9qrdawxqdz-x86_64-unknown-linux-gnu-stage-final-gcc-wrapper-10.2.0.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/d2dyi5c0zqbaifz4r81sc9az78nmsk9p-stdenv-linux.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/7c8l5ikhlwkhlysf0j1byrwkj4h1s3w4-hello-2.10-x86_64-unknown-linux-gnu.drv': 1 dependencies couldn't be built
error: build of '/nix/store/7c8l5ikhlwkhlysf0j1byrwkj4h1s3w4-hello-2.10-x86_64-unknown-linux-gnu.drv' failed

The binutils build system checks by itself if it is building a cross
toolchain or not and prepends or omits a targetPrefix accordingly. This
means that we can always pass target via configureTargets.

However the binutils build system and our bintools wrapper disagree over
whether we are building a cross toolchain or not sometimes since cross
compilation can be relatively subtle in nixpkgs. For example every use
of crossOverlays will make nixpkgs build a cross toolchain even though
localSystem == crossSystem. The cross infrastructure is also used to
build native binaries with a different stdenv (musl instead of glibc,
clang instead of gcc). In all of these cases stdenv.hostPlatform.config
== stdenv.targetPlatform.config, causing binutils to not prepend a
target prefix. At the same time stdenv.hostPlatform !=
stdenv.targetPlatform causing the bintools wrapper to expect a target
prefix, thus building an incomplete set of bintools. This is why
currently pkgsCross.gnu64 and pkgsCross.musl64 aren't working.

The solution is quite simple however: If we detect that we are building
a cross toolchain in the binutils-unwrapped expression, we force the
targetPrefix with --programprefix and fulfill the expectations of the
bintools wrapper at the same time.

Tested (on x86_64-linux):

* pkgsCross.musl64.hello
* pkgsCross.aarch64-multiplatform.hello
* pkgs.hello

Still not working is pkgsCross.gnu64, since
x86_64-unknown-linux-gnu-stage-final-gcc gets confused about targets
now, so bootstrapping the stdenv fails. Since this wasn't working
previously anyways, it's proably fine to fix this separately.
Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

@Mindavi Mindavi added the 6.topic: cross-compilation Building packages on a different platform than they will be used on label Apr 16, 2021
@sternenseemann sternenseemann changed the title binutils-unwrapped: force targetPrefix if cross compiling binutils-unwrapped, gcc, gdb: force targetPrefix if cross compiling Apr 16, 2021
Don't rely on gcc detecting from the passed platforms which prefix to
use, but always specify the prefix nixpkgs expects (or doesn't). This
allows us to work around problems where the configure script would add
prefix where nixpkgs doesn't expect one (if `--target` was specified,
but the same as `--host`) or doesn't add one if nixpkgs expects one (if
`--target` and `--host` are the same, but we are actually cross
compiling, but the relevant parts of the platform are not encoded into
the platform config.

See also ca9be05.
@sternenseemann sternenseemann force-pushed the binutils-force-prefix branch from 9a01a6e to 9c396b6 Compare April 16, 2021 20:54
This makes the targetPrefix always conform to nixpkgs' expectations
instead of relying on the autotools build system to figure it out
correctly (which is also inconsistent across versions).

See also ca9be05.
@sternenseemann sternenseemann force-pushed the binutils-force-prefix branch from 9c396b6 to e75c535 Compare April 16, 2021 20:56
@Ericson2314
Copy link
Member

Ericson2314 commented Apr 16, 2021

I built pkgsCross.aarch64-multiplatform.buildPackages.gdb. This stuff looks all the more good to me.

@ofborg ofborg bot requested a review from Ericson2314 April 16, 2021 21:24
@Ericson2314
Copy link
Member

pkgsCross.aarch64-multiplatform.hello too.

@Ericson2314 Ericson2314 merged commit e87d88d into NixOS:staging Apr 16, 2021
@sternenseemann
Copy link
Member Author

Great! I've also checked: All gcc versions in pkgs build, stuff in pkgsCross.musl64 compiles including gdb and also pkgsCross.aarch64-multiplatform.buildPackages.gdb :)

@sternenseemann sternenseemann deleted the binutils-force-prefix branch April 16, 2021 22:03
@sternenseemann sternenseemann restored the binutils-force-prefix branch July 24, 2021 13:34
@sternenseemann sternenseemann deleted the binutils-force-prefix branch December 22, 2021 13:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: cross-compilation Building packages on a different platform than they will be used on 10.rebuild-darwin: 501+ 10.rebuild-darwin: 5001+ 10.rebuild-darwin-stdenv This PR causes stdenv to rebuild 10.rebuild-linux: 501+ 10.rebuild-linux: 5001+ 10.rebuild-linux-stdenv This PR causes stdenv to rebuild
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants