Skip to content

python3.pkgs: fix splice through unsupported hosts #212832

Merged
alyssais merged 2 commits intoNixOS:masterfrom
alyssais:python-splicing
Jan 28, 2023
Merged

python3.pkgs: fix splice through unsupported hosts #212832
alyssais merged 2 commits intoNixOS:masterfrom
alyssais:python-splicing

Conversation

@alyssais
Copy link
Member

Description of changes

Previously, unless unsupported platforms were allowed, the following would fail to evaluate (from an "x86_64-linux" system):

pkgsCross.x86_64-freebsd.__splicedPackages.docutils.__spliced.buildHost

It shouldn't have, because the buildHost package ends up being for Linux. This broke evaluation of e.g. pkgsCross.x86_64-freebsd.libdrm, because it has docutils in nativeBuildInputs. mkDerivation would try to go through __spliced.buildHost on docutils to get to the Linux version, but the check in ensurePythonModules would kick in first, triggering the meta check because of the equality check in the implementation of hasPythonModule, which would fail because Python is not marked as supported on FreeBSD in Nixpkgs at the moment. Thus, even though they're not supposed to be, the meta checks would be triggered even though the only attribute being accessed on the unsupported derivation was __spliced.

We can fix this by using the same mechanism used to implement the meta checks themselves: lib.extendDerivation. Now, attempting to access drvPath or outPath on an attribute that fails the validity check will produce the same error as before, but other accesses will be allowed through, fixing splicing.

I've tested evaluation of packages that pass and fail the validity check, and confirmed that the behaviour is still correct.

While I was here, I also simplified the logic in the validity check.

Things done
  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • 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/)
  • 23.05 Release Notes (or backporting 22.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
    • (Release notes changes) Ran nixos/doc/manual/md-to-db.sh to update generated release notes
  • Fits CONTRIBUTING.md.

@alyssais alyssais requested a review from FRidh as a code owner January 26, 2023 20:28
@github-actions github-actions bot added the 6.topic: python Python is a high-level, general-purpose programming language. label Jan 26, 2023
@alyssais alyssais added the 6.topic: cross-compilation Building packages on a different platform than they will be used on label Jan 26, 2023
@alyssais alyssais changed the title Python splicing python3.pkgs: fix splice through unsupported hosts Jan 26, 2023
@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux. labels Jan 26, 2023
It wasn't clear before, but it turns out that this is just four
separate conditions, and an attribute is valid if any of the
conditions is true, so we don't need a sea of parentheses to express
it.
Previously, unless unsupported platforms were allowed, the following
would fail to evaluate (from an "x86_64-linux" system):

    pkgsCross.x86_64-freebsd.__splicedPackages.docutils.__spliced.buildHost

It shouldn't have, because the buildHost package ends up being for
Linux.  This broke evaluation of e.g. pkgsCross.x86_64-freebsd.libdrm,
because it has docutils in nativeBuildInputs.  mkDerivation would try
to go through __spliced.buildHost on docutils to get to the Linux
version, but the check in ensurePythonModules would kick in first,
triggering the meta check because of the equality check in the
implementation of hasPythonModule, which would fail because Python is
not marked as supported on FreeBSD in Nixpkgs at the moment.  Thus,
even though they're not supposed to be, the meta checks would be
triggered even though the only attribute being accessed on the
unsupported derivation was __spliced.

We can fix this by using the same mechanism used to implement the meta
checks themselves: lib.extendDerivation.  Now, attempting to access
drvPath or outPath on an attribute that fails the validity check will
produce the same error as before, but other accesses will be allowed
through, fixing splicing.

I've tested evaluation of packages that pass and fail the validity
check, and confirmed that the behaviour is still correct.
@ghost
Copy link

ghost commented Jan 28, 2023

but the check in ensurePythonModules would kick in first,

ensurePythonModules = items: let
exceptions = [
stdenv
];
providesSetupHook = lib.attrByPath [ "provides" "setupHook"] false;
valid = value: !((lib.isDerivation value) && !((pythonPackages.hasPythonModule value) || (providesSetupHook value))) || (lib.elem value exceptions);
func = name: value: if (valid value) then value else throw "${name} should use `buildPythonPackage` or `toPythonModule` if it is to be part of the Python packages set.";
in lib.mapAttrs func items;

triggering the meta check because of the equality check in the implementation of hasPythonModule

hasPythonModule = drv: drv?pythonModule && drv.pythonModule == python;

I would love to know why that equality check is there.

Also, testing meta-check-failing derivations for equality against each other shouldn't throw, should it?

the meta checks would be triggered even though the only attribute being accessed on the unsupported derivation was __spliced.

Yeah they should only be triggered upon access to (builtins.derivation drvAttrs).drvPath, since Nix equality among derivations is implemented by comparing .outPath.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

LGTM

See also:

... which will prevent problems like this in the future.

@FRidh
Copy link
Member

FRidh commented Jan 28, 2023

I would love to know why that equality check is there.

To avoid mixing Python packages of different interpreter versions.

Applications don't provide a module and so we stop recursing. We also stop recursing when we encounter a Python module but it is not for the same interpreter. The idea here is that, when we would use this with NIX_PYTHONPATH, we can have different Python versions in the same build not affecting one another.

@FRidh
Copy link
Member

FRidh commented Jan 28, 2023

We can fix this by using the same mechanism used to implement the meta checks themselves: lib.extendDerivation. Now, attempting to access drvPath or outPath on an attribute that fails the validity check will produce the same error as before, but other accesses will be allowed through, fixing splicing.

Interesting trick. Could this also fix overriding a package that has disabled = true in pkgs/development/interpreters/python/mk-python-derivation.nix?

@alyssais
Copy link
Member Author

Interesting trick. Could this also fix overriding a package that has disabled = true in pkgs/development/interpreters/python/mk-python-derivation.nix?

Yes, I think it could!

@alyssais alyssais merged commit b682fef into NixOS:master Jan 28, 2023
@alyssais alyssais deleted the python-splicing branch January 28, 2023 21:09
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: python Python is a high-level, general-purpose programming language. 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants