When instantiating an environment with the Python interpreter built
with both free threading (aka. without GIL) and `pydebug`, the value
of `passthru.executable` doesn't match any installed file. This was
noticed when building CI pipelines that require the Python interpreter
built with both debug features and free threading.
The cause is that `executable` was built from `libPrefix`, which only
tracks the `t` suffix from `--without-gil` and not the `d` suffix from
`--with-pydebug`. `libPrefix` doubles as the stdlib install directory,
and cpython deliberately shares that directory between debug and
non-debug builds of a given version, so the `d` is intentionally
absent there.
This slipped through because cpython only ever installs a
`python$VERSION -> python$LDVERSION` symlink (e.g. `python3.13 ->
python3.13d`). For debug-only builds the old code happened to ask for
`python3.13`, which is that symlink, so it worked by accident. For
FT+debug, `libPrefix` is `python3.13t`, but cpython installs no such
file; only `python3.13` (symlink) and `python3.13td` (binary).
Fix: append `d` to `executable` (and to the `cp<ver>` wheel ABI tag in
`pythonABITags`) when `enableDebug` is true.
Reproducer for the problem as a bash script:
```bash
set -euo pipefail
nixpkgs="${1:-<nixpkgs>}" # Either custom path if provided, or just <nixpkgs>
read -r -d '' expr <<EOF || true
let
pkgs = import ${nixpkgs} { };
py = pkgs.python313FreeThreading.override {
enableDebug = true;
self = py;
pythonAttr = "python313FreeThreading";
};
in py
EOF
executable=$(nix-instantiate --eval --json --expr "($expr).executable" | tr -d '"')
echo "passthru.executable = ${executable}"
out=$(nix-build --no-out-link --expr "$expr")
echo "store path: ${out}"
if [[ -e "${out}/bin/${executable}" ]]; then
echo "result: OK (binary exists)"
exit 0
fi
echo "result: FAIL (${out}/bin/${executable} not found)"
echo "actually installed:"
ls "${out}/bin/" | grep '^python3\.' | sed 's/^/ /'
exit 1
```
Fixes#476822 and #480467 . By itself this change doesn't trigger many
rebuilds, but it is easier to justify it in conjunction with the
previous commit.
Co-Authored-By: Colin <colin@uninsane.org>
This commit was created by a combination of scripts and tools:
- an ast-grep script to prefix things in meta with `lib.`,
- a modified nixf-diagnose / nixf combination to remove unused `with
lib;`, and
- regular nixfmt.
Co-authored-by: Wolfgang Walther <walther@technowledgy.de>
As documented in https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#abi-tag.
This is useful to check whether a wheel is compatible with a certain interpreter. [Pyproject.nix](https://github.com/pyproject-nix/pyproject.nix) has [functions to perform wheel compatibility checking](https://pyproject-nix.github.io/pyproject.nix/lib/pypa.html#function-library-lib.pypa.isWheelFileCompatible) against a Python interpreter, and has computed interpreter ABI tags itself.
The recent addition of free threading (`python313FreeThreading`) complicates this by not being introspectable:
A GIL Python (non free-threaded) has an ABI tag `cp313` while the free-threaded Python has `cp313t`, but the package doesn't communicate whether `enableGIL` is true or false, leaving no way to compute the tag.
The same goes for if debugging support was added to the derivation: A `d` suffix would need to be added.
Additionally ABI tags has no defined format and can really only be accurately computed by having insight into how the ABI tags are used by a specific interpreter, meaning that the only correct place to compute ABI tags is within the context of a particular Python derivation.
While this has no immediate use within nixpkgs it could be used as a basis to provide compatibility assertions regarding wheel compat at eval time.
The intermediate pythonMinimal build that uses the glibc from bootstrap
files cannot currently be built with PIE, because the Scrt.o startup
script is missing in there.
The 3.13 release dropped support for the crypt module, so this dependency
could have been dropped much earlier.
Drops the `withLibxcrypt` argument, because manging the default has
become quite a bit more complicated.
Removes the build time dependency on pkg-config if python3 is build with the `withMinimal` flag enabled
This change is driven by the motivation to use python3 earlier in stdenv for hooks.