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

wrapCC, wrapBintools: correctly cross-compile if buildPlatform != hostPlatform #304861

Merged

Conversation

sternenseemann
Copy link
Member

@sternenseemann sternenseemann commented Apr 17, 2024

Description of changes

The wrapper scripts have two main dependencies (aside from cc and bintools which are a given):

  • The shell used for executing the scripts, known as shell thus far.
  • expand-response-params, a small C program which requires a wrapped compiler to be built.

Previously, these programs would be essentially taken from/built with the package set used to build the package set that the wrapper itself is a part of (usually buildPackages). This is incorrect, as it only “works” if hostPlatform == buildPlatform (relative to the wrapper) or it will be impossible to execute the dependencies.

This has the consequence that if you e.g. build pkgsCross.aarch64-multiplatform.gcc, it will be impossible to execute the resulting (wrapped) compiler due to exec format errors.

This weird situation stems from the stdenv bootstrapping process where we have the concrete problem that building a shell and C program requires a wrapped C compiler, but we also require these to build the wrapper. The solution is to either do without the dependencies or take them from the previous bootstrapping stage and, ultimately, bootstrapTools. These is sound in this situation since during (initial) stdenv bootstrapping buildPlatform == hostPlatform == targetPlatform. It is, however, incorrect to have this leak into the main package set where cross compilation may happen.

The solution to this problem is to make the wrappers behave correctly in the main package set (taking cross into account) and worry about bootstrapping later. This is exactly what I've done:

  • Instead of shell which defaults to stdenvNoCC.shell (which is usually equivalent to buildPackages.runtimeShell), we use runtimeShell which is an attribute that exposes the default shell we use on the host platform.
  • Instead of ad hoc building expand-response-params inline in the wrapper derivation by trying to pull a stdenv out of buildPackages (so that we are effectively using buildPackages.buildPackages.gcc/clang), we just take it as an ordinary input (which works perfectly in the main package set) and let the caller worry about bootstrapping.

In a second step I've reflected these changes in the darwin and linux stdenvs, making sure that no derivation hash changes by inserting extra bootstrapping instructions where necessary (the single rebuild is caused by the newly added expand-response-params attribute). Some of these may actually be unnecessary (i.e. we may be able to build a proper runtimeShell earlier etc.), but this will have to be investigated separately as that would cause a stdenv rebuild.

This change is best reviewed commit by commit.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 24.05 Release Notes (or backporting 23.05 and 23.11 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

@ofborg ofborg bot added the 6.topic: cross-compilation Building packages on a different platform than they will be used on label Apr 17, 2024
@github-actions github-actions bot added the 6.topic: stdenv Standard environment label Apr 17, 2024
@ofborg ofborg bot added 8.has: package (new) This PR adds a new package 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10 10.rebuild-linux: 1 labels Apr 17, 2024
@sternenseemann sternenseemann force-pushed the cc-bintools-wrappers-correct-cross branch from 0105c54 to 97716b6 Compare April 18, 2024 15:00
@sternenseemann sternenseemann marked this pull request as ready for review April 18, 2024 15:00
@sternenseemann
Copy link
Member Author

cc @AlexandreTunstall

@sternenseemann
Copy link
Member Author

I think the pkgs/by-name CI error can be ignored, since I wouldn't want to move expand-response-params out of build-support for now.

@sternenseemann sternenseemann force-pushed the cc-bintools-wrappers-correct-cross branch from 97716b6 to 3c4b8fd Compare April 18, 2024 15:07
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.

Great work!

We don't need to artificially make sure that we can execute the wrapper
scripts on the build platform by using stdenv's shell (which comes from
buildPackages) since our cross infrastructure will get us the wrapper
from buildPackages. The upside of this change is that cross-compiled
wrappers (e.g. pkgsCross.aarch64-multiplatform.gcc) will actually work
when executed!

For bootstrapping this is also not a problem, since we have a long
build->build platform chain so runtimeShell is just as good as
stdenvNoCC.shell. We do fall back to old ways, though, by explicitly
using the bootstrap-tools shell in stage2, so the adjacent bash is only
used from stage4 onwards. This is unnecessary in principle (I'll try
removing this hack in the future), but ensures this change causes zero
rebuilds.
The cc and bintools wrapper contained ad hoc bootstrapping logic for
expand-response-params (which was callPackage-ed in a let binding). This
lead to the strange situation that the bootstrapping logic related to
expand-response-params is split between the wrapper derivations (where
it is duplicated) and the actual stdenv bootstrapping.

To clean this up, the wrappers simply should take expand-response-params
as an ordinary input: They need an adjacent expand-response-params (i.e.
one that runs on their host platform), but don't care about the how.
Providing this is only problematic during stdenv bootstrapping where we
have to pull it from the previous stage at times.
Since the tool is exposed more prominently now, we should clear up what
it is and note that it is to be considered unstable, i.e. we may change
it if the necessity arises. (In practice it is probably going to be
fairly stable though, as compiler interfaces tend to be quite stable.)

Should we add a version?
@sternenseemann sternenseemann force-pushed the cc-bintools-wrappers-correct-cross branch from 3c4b8fd to b544fd9 Compare April 18, 2024 15:14
@ofborg ofborg bot added 10.rebuild-darwin: 1-10 10.rebuild-darwin: 1 and removed 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin labels Apr 18, 2024
@sternenseemann sternenseemann merged commit 5e8f10f into NixOS:master Apr 18, 2024
24 of 26 checks passed
@sternenseemann sternenseemann deleted the cc-bintools-wrappers-correct-cross branch April 18, 2024 18:49
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 6.topic: stdenv Standard environment 8.has: package (new) This PR adds a new package 10.rebuild-darwin: 1-10 10.rebuild-darwin: 1 10.rebuild-linux: 1-10 10.rebuild-linux: 1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants