Skip to content

Commit

Permalink
build.hooks.pyprojectHook: Revert to using pypa/installer for cross i…
Browse files Browse the repository at this point in the history
…nstalls

Uv's internal interpreter discovery doesn't work for cross compiled environments and detects the wrong arch glibc.
We can work around this issue by using pypa/installer for cross compiled builds, but still use uv for native.
  • Loading branch information
adisbladis committed Feb 10, 2025
1 parent a3d6336 commit a73f903
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 8 deletions.
24 changes: 24 additions & 0 deletions build/checks/build-systems.nix
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,30 @@ let
};
};

installer =
{
stdenv,
python3Packages,
pyprojectHook,
resolveBuildSystem,
}:
stdenv.mkDerivation {
inherit (python3Packages.installer)
pname
version
src
meta
;

nativeBuildInputs =
[
pyprojectHook
]
++ resolveBuildSystem {
flit-core = [ ];
};
};

setuptools =
{
stdenv,
Expand Down
38 changes: 30 additions & 8 deletions build/hooks/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ let
inherit (pkgs) buildPackages;
pythonSitePackages = python.sitePackages;

isCross = stdenv.buildPlatform != stdenv.hostPlatform;

# When cross compiling create a virtual environment for the build.
#
# Because Nixpkgs builds cross compiled Python in a separate
Expand All @@ -29,7 +31,7 @@ let
'';

pythonInterpreter =
if stdenv.buildPlatform != stdenv.hostPlatform then
if isCross then
"${crossPython}/bin/${baseNameOf pythonOnBuildForHost.interpreter}"
else
pythonOnBuildForHost.interpreter;
Expand All @@ -51,9 +53,7 @@ in
substitutions = {
inherit pythonInterpreter;
pythonPath = lib.concatStringsSep ":" (
lib.optional (
stdenv.buildPlatform != stdenv.hostPlatform
) "${python.pythonOnBuildForHost}/${python.sitePackages}"
lib.optional isCross "${python.pythonOnBuildForHost}/${python.sitePackages}"
++ [
"${python}/${python.sitePackages}"
]
Expand Down Expand Up @@ -194,13 +194,18 @@ in
pyprojectInstallHook
pyprojectOutputSetupHook
]
++ lib.optional (stdenv.buildPlatform != stdenv.hostPlatform) pyprojectCrossShebangHook
++ lib.optional isCross pyprojectCrossShebangHook
++ extraHooks;
} ./meta-hook.sh
)
{
python = pythonOnBuildForHost;
};
(
{
python = pythonOnBuildForHost;
}
// lib.optionalAttrs isCross {
pyprojectInstallHook = hooks.pyprojectPypaInstallHook;
}
);

/*
Hook used to build prebuilt wheels.
Expand Down Expand Up @@ -250,4 +255,21 @@ in
};
} ./pyproject-fixup-editable-hook.sh
) { };

/*
Install hook using pypa/installer.
Used instead of `pyprojectInstallHook` for cross compilation support.
*/
pyprojectPypaInstallHook = callPackage (
{ pythonPkgsBuildHost }:
makeSetupHook {
name = "pyproject-pypa-install-hook";
substitutions = {
inherit (pythonPkgsBuildHost) installer;
inherit pythonInterpreter pythonSitePackages;
wrapper = ./pypa-install-hook/wrapper.py;
};
} ./pypa-install-hook/pyproject-pypa-install-hook.sh
) { };
}
26 changes: 26 additions & 0 deletions build/hooks/pypa-install-hook/pyproject-pypa-install-hook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Setup hook for Pyproject installer.
echo "Sourcing pyproject-pypa-install-hook"

pyprojectPypaInstallPhase() {
echo "Executing pyprojectPypaInstallPhase"
runHook preInstall

pushd dist >/dev/null

for wheel in *.whl; do
env PYTHONPATH=$PYTHONPATH:@installer@/@pythonSitePackages@ @pythonInterpreter@ @wrapper@ --prefix "$out" "$wheel"
echo "Successfully installed $wheel"
done

rm -f "$out/.lock"

popd >/dev/null

runHook postInstall
echo "Finished executing pyprojectPypaInstallPhase"
}

if [ -z "${dontUsePyprojectInstall-}" ] && [ -z "${installPhase-}" ]; then
echo "Using pyprojectPypaInstallPhase"
installPhase=pyprojectPypaInstallPhase
fi
22 changes: 22 additions & 0 deletions build/hooks/pypa-install-hook/wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python3
import os
import sys


def main():
"""
Provides compatibility with uv env vars when using pypa/installer.
Ideally uv should also be used for cross installs, but for now it's not compatible.
"""
compile_bytecode = bool(os.environ.get("UV_COMPILE_BYTECODE", False))

args = sys.argv[1:]
if compile_bytecode:
args.insert(0, "1")
args.insert(0, "--compile-bytecode")

os.execv(sys.executable, [sys.executable, "-m", "installer", *args])


if __name__ == "__main__":
main()

0 comments on commit a73f903

Please sign in to comment.