Skip to content

Commit a73f903

Browse files
committed
build.hooks.pyprojectHook: Revert to using pypa/installer for cross installs
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.
1 parent a3d6336 commit a73f903

File tree

4 files changed

+102
-8
lines changed

4 files changed

+102
-8
lines changed

build/checks/build-systems.nix

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,30 @@ let
402402
};
403403
};
404404

405+
installer =
406+
{
407+
stdenv,
408+
python3Packages,
409+
pyprojectHook,
410+
resolveBuildSystem,
411+
}:
412+
stdenv.mkDerivation {
413+
inherit (python3Packages.installer)
414+
pname
415+
version
416+
src
417+
meta
418+
;
419+
420+
nativeBuildInputs =
421+
[
422+
pyprojectHook
423+
]
424+
++ resolveBuildSystem {
425+
flit-core = [ ];
426+
};
427+
};
428+
405429
setuptools =
406430
{
407431
stdenv,

build/hooks/default.nix

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ let
1313
inherit (pkgs) buildPackages;
1414
pythonSitePackages = python.sitePackages;
1515

16+
isCross = stdenv.buildPlatform != stdenv.hostPlatform;
17+
1618
# When cross compiling create a virtual environment for the build.
1719
#
1820
# Because Nixpkgs builds cross compiled Python in a separate
@@ -29,7 +31,7 @@ let
2931
'';
3032

3133
pythonInterpreter =
32-
if stdenv.buildPlatform != stdenv.hostPlatform then
34+
if isCross then
3335
"${crossPython}/bin/${baseNameOf pythonOnBuildForHost.interpreter}"
3436
else
3537
pythonOnBuildForHost.interpreter;
@@ -51,9 +53,7 @@ in
5153
substitutions = {
5254
inherit pythonInterpreter;
5355
pythonPath = lib.concatStringsSep ":" (
54-
lib.optional (
55-
stdenv.buildPlatform != stdenv.hostPlatform
56-
) "${python.pythonOnBuildForHost}/${python.sitePackages}"
56+
lib.optional isCross "${python.pythonOnBuildForHost}/${python.sitePackages}"
5757
++ [
5858
"${python}/${python.sitePackages}"
5959
]
@@ -194,13 +194,18 @@ in
194194
pyprojectInstallHook
195195
pyprojectOutputSetupHook
196196
]
197-
++ lib.optional (stdenv.buildPlatform != stdenv.hostPlatform) pyprojectCrossShebangHook
197+
++ lib.optional isCross pyprojectCrossShebangHook
198198
++ extraHooks;
199199
} ./meta-hook.sh
200200
)
201-
{
202-
python = pythonOnBuildForHost;
203-
};
201+
(
202+
{
203+
python = pythonOnBuildForHost;
204+
}
205+
// lib.optionalAttrs isCross {
206+
pyprojectInstallHook = hooks.pyprojectPypaInstallHook;
207+
}
208+
);
204209

205210
/*
206211
Hook used to build prebuilt wheels.
@@ -250,4 +255,21 @@ in
250255
};
251256
} ./pyproject-fixup-editable-hook.sh
252257
) { };
258+
259+
/*
260+
Install hook using pypa/installer.
261+
262+
Used instead of `pyprojectInstallHook` for cross compilation support.
263+
*/
264+
pyprojectPypaInstallHook = callPackage (
265+
{ pythonPkgsBuildHost }:
266+
makeSetupHook {
267+
name = "pyproject-pypa-install-hook";
268+
substitutions = {
269+
inherit (pythonPkgsBuildHost) installer;
270+
inherit pythonInterpreter pythonSitePackages;
271+
wrapper = ./pypa-install-hook/wrapper.py;
272+
};
273+
} ./pypa-install-hook/pyproject-pypa-install-hook.sh
274+
) { };
253275
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Setup hook for Pyproject installer.
2+
echo "Sourcing pyproject-pypa-install-hook"
3+
4+
pyprojectPypaInstallPhase() {
5+
echo "Executing pyprojectPypaInstallPhase"
6+
runHook preInstall
7+
8+
pushd dist >/dev/null
9+
10+
for wheel in *.whl; do
11+
env PYTHONPATH=$PYTHONPATH:@installer@/@pythonSitePackages@ @pythonInterpreter@ @wrapper@ --prefix "$out" "$wheel"
12+
echo "Successfully installed $wheel"
13+
done
14+
15+
rm -f "$out/.lock"
16+
17+
popd >/dev/null
18+
19+
runHook postInstall
20+
echo "Finished executing pyprojectPypaInstallPhase"
21+
}
22+
23+
if [ -z "${dontUsePyprojectInstall-}" ] && [ -z "${installPhase-}" ]; then
24+
echo "Using pyprojectPypaInstallPhase"
25+
installPhase=pyprojectPypaInstallPhase
26+
fi
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env python3
2+
import os
3+
import sys
4+
5+
6+
def main():
7+
"""
8+
Provides compatibility with uv env vars when using pypa/installer.
9+
Ideally uv should also be used for cross installs, but for now it's not compatible.
10+
"""
11+
compile_bytecode = bool(os.environ.get("UV_COMPILE_BYTECODE", False))
12+
13+
args = sys.argv[1:]
14+
if compile_bytecode:
15+
args.insert(0, "1")
16+
args.insert(0, "--compile-bytecode")
17+
18+
os.execv(sys.executable, [sys.executable, "-m", "installer", *args])
19+
20+
21+
if __name__ == "__main__":
22+
main()

0 commit comments

Comments
 (0)