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

Minor cross nixos fixes #44621

Merged
merged 2 commits into from Aug 21, 2018
Merged

Conversation

ElvishJerricco
Copy link
Contributor

Motivation for this change

I'm working on cross compiling nixos to aarch64 a little bit, and there are a few things that aren't quite right in nixpkgs right now for that.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • 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 nox --run "nox-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)
  • Fits CONTRIBUTING.md.

@@ -23,7 +23,7 @@ stdenv.mkDerivation rec {
# Unpack the debian package
unpackCmd = ''
if ! [[ "$curSrc" =~ \.deb$ ]]; then return 1; fi
ar -xf "$curSrc"
$AR -xf "$curSrc"
Copy link
Contributor

Choose a reason for hiding this comment

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

This was fixed another way in master.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea, just rebased and dropped this.

@@ -9,13 +9,13 @@
}:

let
sdClosureInfo = pkgs.closureInfo { rootPaths = storePaths; };
sdClosureInfo = pkgs.buildPackages.closureInfo { rootPaths = storePaths; };
Copy link
Contributor

Choose a reason for hiding this comment

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

This one really needs a proper solution rather sprinkling this buildPackages. in random places and being inconsistent with rest of Nixpkgs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dezgeg Hm what do you suggest? It's only used via string interpolation; it's not depended on in a way that can be put into nativeBuildInputs AFAIK. Also, it's not harmful to be more explicit about buildPackages, is it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah oops, I was supposed to put the comment on the nativeBuildInputs = with pkgs.buildPackages; ... line.

But in general, this buildPackages. thing is bad since it breaks overriding inputs (like in callPackage ./foo { bar = baz; };) so it would need a replacement one day.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dezgeg Ah, so I should take these inputs in the file's argument list and list them under nativeBuildInputs rather than maintaining the with pkgs; that was used before, right? TBH, I'm fairly confident I didn't need to add .buildPackages here....

@@ -71,7 +71,9 @@ stdenv.mkDerivation rec {

nativeBuildInputs = [ pkgconfig perl python gettext ];

propagatedBuildInputs = [ zlib libffi gettext libiconv ];
propagatedNativeBuildInputs = [ gettext ];
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this commit needs to go to staging.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also gettext can be removed from nativeBuildInputs now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea, I'll point this whole PR at staging; it's in no hurry to reach master.

Why can gettext be removed?

Copy link
Contributor

Choose a reason for hiding this comment

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

Because you put it in propagatedNativeBuildInputs it will apply to glib as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, of course. Misread the first comment

@ElvishJerricco
Copy link
Contributor Author

Sorry guys. I messed up the rebase and didn't notice it until I pushed, causing review requests to a bunch of random people :( Branch is fixed now, pointing at staging.

@ElvishJerricco
Copy link
Contributor Author

Note that NixOS still can't be entirely cross compiled. To do so requires a fix smarter than this dumb thing that I've been using: ElvishJerricco@cc093102b4c

@ElvishJerricco
Copy link
Contributor Author

@dezgeg How does it look now?

@@ -97,7 +96,7 @@ in
system.build.sdImage = pkgs.stdenv.mkDerivation {
name = config.sdImage.imageName;

buildInputs = with pkgs; [ dosfstools e2fsprogs mtools libfaketime utillinux ];
nativeBuildInputs = with pkgs.buildPackages; [ dosfstools e2fsprogs mtools libfaketime utillinux ];
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dezgeg Actually, this buildPackages was necessary; not sure why. This isn't a callPackage expression, but I thought that using pkgs.foo in nativeBuildInputs would be the same as pkgs.buildPackages.foo. Yet, with the former you get the cross version.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, exactly, derivations using nativeBuildInputs that aren't inside a callPackage are broken when cross-compiling and need this nativeBuildInputs = with buildPackages; [ ... ]; dance.

I think the solution would be have something like callPackagesInline that instead of a path to a Nix expression takes the Nix expression directly. So this would become something like:

system.build.sdImage = pkgs.callPackageInline ({ stdenv, dosfstools, e2fsprogs, mtools, libfaketime, utillinux }: 
      name = config.sdImage.imageName;

      nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime utillinux ];
      /* and so on */
}):

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dezgeg callPackage can take a function instead of a file. But I'm not sure that's any more elegant than just being explicit...

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, indeed callPackage can take a function. That can be used then without any changes to other places. Well, except the other places that do this buildPackages hack need to be fixed up to use callPackage as well.

But I'm not sure that's any more elegant than just being explicit...

The fact that nativeBuildInputs works correctly in 99% of the cases (i.e. every package included from all-packages.nix) but silently does the wrong thing when not inside callPackage is really, really terrible. If adding a callPackage to those 1% cases makes them work like the 99% cases then that's the correct action. And then mkDerivation should be changed to throw an error when cross-compiling and not inside callPackage instead of silently doing the wrong thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That sounds like fighting a hack with a hack to me. The fact that callPackage is the solution here is a gross hack. There should be minimal relationship between mkDerivation and callPackage. callPackage just happened to be the easiest way to fix this for legacy code. To me it seems like the preference, if we'd started with cross compilation in mind, would have been to somehow be more explicit, not use this insane splicing that's hard to reason about. I don't think we're solving any problem by requiring the use of callPackage, we're just obscuring the code.

Copy link
Contributor

Choose a reason for hiding this comment

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

To me it seems like the preference, if we'd started with cross compilation in mind, would have been to somehow be more explicit, not use this insane splicing that's hard to reason about.

Yes, if someone had >10 years ago from the start decided that cross-compilation would be a thing to support and take it into the account in the design, things would have certainly been designed differently, no question about that. But hindsight is 20/20, and what we have now is what he have, and almost certainly is too late to change. Rewriting/redesigning interfaces for essentially a minority use case (and I really don't see the situation changing with the x86 monopoly for desktops and servers still being strong as ever) and breaking the existing code of the 90% of the userbase who have no need for cross compilation is not the correct tradeoff. (This is a personal opinion, but I don't think I'm the only one).

In other words, of the following choices:

a. Not supporting cross-compilation in Nixpkgs at all,
b. Supporting cross-compilation but with minimal possible changes to existing packages with compat tricks like splicing and separate buildInputs, PATH etc. logic in stdenv between native and cross cases,
c. Redesigning the entirety of nixpkgs around cross-compilation and changing each and single package,

I would pick b. any day, by a long shot (followed by a. then c.).

I don't think we're solving any problem by requiring the use of callPackage, we're just obscuring the code.

Actually, regardless of cross-compilation, using callPackage here would be an improvement because then you could use .override to change say, the version of e2fsprogs used here. Currently when I try it I just get something like error: attribute 'override' in selection path 'config.system.build.sdImage.override' not found which is inconsistent with all the rest of the 99% of the derivations in Nixpkgs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Obviously I wasn't suggesting rewriting all of nixpkgs. I was saying that callPackage isn't holy in any way in this context. Native build input splicing isn't a great reason to use it when it's not necessary. In fact, I originally thought that splicing worked by mkDerivation checking the nativeBuildInputs and splicing those, not by splicing the package itself; that would have made a bit more sense to me, and would have made this fine.

Regardless, I hadn't thought about the desire to override this derivation normally. That's a good point. I've changed it to use callPackage, per your suggestion. Seems to work fine.


propagatedBuildInputs = [ zlib libffi gettext libiconv ];
propagatedNativeBuildInputs = [ gettext ];
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't look right. gettext is definitely a propagated build input. Dependents of glib will use it as a build input, not a native build input, so you won't get the propagated gettext when it's listed native here. I think the old thing was correct. Was there an issue with the previous thing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

gettext is both a lib used at runtime and a binary used to process source code, IIRC. So you need the native one for the binary. Not really sure what the deal with propagation is... Is there a test I can use to confirm how propagation of this dep ought to behave?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, gettext does have a binary but I don't think we want it to propagate through glib. I think it was a propagated build input originally because it depends on some headers in gettext. Unless it's breaking something I would leave it as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@matthewbauer Well, whatever build failure I experienced in past revisions of nixpkgs is now gone without this change, so I guess I'll remove it. @dezgeg Does that mean this PR no longer needs to target staging?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, yeah, if gettext comes with a tool that is used at build-time (I presume it's to parse all the source code of the project to find all the original translations of the strings), then that binary needs to be moved to the dev output. (The cross stdenv stille needs to be fixed to include such tools in PATH, though).

Copy link
Contributor

Choose a reason for hiding this comment

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

At least gettextize definitely belongs to dev. So that's something to fix at some point.

Yes, no longer need for staging if this glib change is dropped.

@ElvishJerricco ElvishJerricco changed the base branch from staging to master August 9, 2018 20:07
@ElvishJerricco
Copy link
Contributor Author

Can this be merged?

Copy link
Member

@bobvanderlinden bobvanderlinden left a comment

Choose a reason for hiding this comment

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

An improvement of what was here before. I'm not sure how to avoid the use of buildPackages.

@@ -94,10 +93,10 @@ in

sdImage.storePaths = [ config.system.build.toplevel ];

system.build.sdImage = pkgs.stdenv.mkDerivation {
system.build.sdImage = pkgs.callPackage ({ stdenv, dosfstools, e2fsprogs, mtools, libfaketime, utillinux }: stdenv.mkDerivation {
Copy link
Member

Choose a reason for hiding this comment

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

Consider moving the package function to a separate let name. I think it would clear up the code a bit due to callPackage ... {}.

@ElvishJerricco
Copy link
Contributor Author

@dezgeg ping

@dezgeg dezgeg merged commit f0957b9 into NixOS:master Aug 21, 2018
@dezgeg
Copy link
Contributor

dezgeg commented Aug 21, 2018

Can you test if this branch which removes the rest of nativeBuildInputs = with buildPackages; [ ... ] stuff: https://github.com/dezgeg/nixpkgs/tree/call-package-in-nixos with cross nixos?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants