Files
nixpkgs/pkgs/development/interpreters/python/cpython
Jonas Rembser fa6a2e8f1f python3: include ABI debug suffix d in executable (fixes FT+debug)
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
```
2026-06-03 13:22:42 +02:00
..
2026-02-15 03:17:23 +01:00
2026-03-21 19:12:33 -04:00
2025-10-15 18:01:30 +02:00
2026-06-03 00:44:06 +02:00