pypy: Stop the prebuilt interpreters depending on Tcl/Tk 8.5

`prebuilt.nix` (3.10, 3.11) asked for Tcl/Tk 8.5 on Linux, but the
`_tkinter` extension in those tarballs is linked against `libtcl8.6.so`
and `libtk8.6.so`. It resolved anyway, because the tarball vendors its own
copy of both under `lib/`. So the declared dependency was doing nothing,
and `tkinter` -- which is stdlib, not an optional extra -- was quietly
running against a bundled Tcl that we do not update.

Point it at our 8.6 instead, and delete the vendored libraries so it has
to. The vendored *script* libraries have to go too: `init.tcl` checks the
exact patchlevel, so our 8.6.16 rejects the bundled 8.6.14 copy as "not
usable" and `Tcl_Init` fails. Note that the existing `installCheckPhase`
does not catch that, as `import tkinter` never creates an interpreter;
`tkinter.Tcl()` does.

`prebuilt_2_7.nix` genuinely needs 8.5 -- its `tklib_cffi` asks for
`libtcl8.5.so` and its `installPhase` does not keep the bundled `lib/` --
but it exists only to bootstrap the source build of PyPy2, where nothing
imports `tkinter`. Let the module go unresolved and drop it from the
import check rather than keep an end-of-life Tcl alive for it.

Assisted-by: Claude Code (Claude Opus 5)
This commit is contained in:
John Ericson
2026-08-22 14:46:23 -04:00
parent 671231f7ac
commit c8e1365d31
2 changed files with 31 additions and 20 deletions

View File

@@ -11,8 +11,6 @@
gdbm,
ncurses6,
sqlite,
tcl-8_5,
tk-8_5,
tcl-8_6,
tk-8_6,
zlib,
@@ -83,12 +81,6 @@ stdenv.mkDerivation {
sqlite
zlib
stdenv.cc.cc.libgcc or null
]
++ lib.optionals stdenv.hostPlatform.isLinux [
tcl-8_5
tk-8_5
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
tcl-8_6
tk-8_6
];
@@ -102,10 +94,24 @@ stdenv.mkDerivation {
echo "Moving files to $out"
mv -t $out bin include lib
mv $out/bin/libpypy*-c${stdenv.hostPlatform.extensions.sharedLibrary} $out/lib/
${lib.optionalString stdenv.hostPlatform.isLinux ''
rm $out/bin/*.debug
''}
''
+ lib.optionalString stdenv.hostPlatform.isLinux ''
rm $out/bin/*.debug
''
# The tarball vendors Tcl/Tk. Drop it so `tkinter` -- which is stdlib, not an
# optional extra -- resolves against ours instead: the same 8.6 the extension
# module asks for by soname, but one that gets updated.
#
# The script libraries have to go with the shared ones. `init.tcl` checks the
# exact patchlevel, so our 8.6.16 rejects the bundled 8.6.14 copy as "not
# usable" and `Tcl_Init` fails -- which `import tkinter` alone does not
# catch, since that never creates an interpreter.
+ lib.optionalString stdenv.hostPlatform.isLinux ''
rm $out/lib/libtcl8.6${stdenv.hostPlatform.extensions.sharedLibrary}
rm $out/lib/libtk8.6${stdenv.hostPlatform.extensions.sharedLibrary}
rm -r $out/lib/tcl8.6 $out/lib/tk8.6
''
+ ''
echo "Removing bytecode"
find . -name "__pycache__" -type d -depth -delete

View File

@@ -11,8 +11,6 @@
gdbm,
ncurses6,
sqlite,
tcl-8_5,
tk-8_5,
tcl-8_6,
tk-8_6,
zlib,
@@ -84,10 +82,6 @@ stdenv.mkDerivation {
zlib
stdenv.cc.cc.libgcc or null
]
++ lib.optionals stdenv.hostPlatform.isLinux [
tcl-8_5
tk-8_5
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
tcl-8_6
tk-8_6
@@ -95,6 +89,15 @@ stdenv.mkDerivation {
nativeBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [ autoPatchelfHook ];
# Only a bootstrap interpreter, so its `tkinter` is never imported. The
# tarball bundles the Tcl/Tk it wants but `installPhase` does not keep
# `lib/`, so rather than depend on a Tcl this old just to satisfy a module
# nobody loads, let the module stay unresolved.
autoPatchelfIgnoreMissingDeps = lib.optionals stdenv.hostPlatform.isLinux [
"libtcl8.5.so"
"libtk8.5.so"
];
installPhase = ''
runHook preInstall
@@ -150,10 +153,12 @@ stdenv.mkDerivation {
"sys"
"curses"
]
++ lib.optionals (!isPy3k) [
# Only Linux gives up on `tkinter`; Darwin still links it against a Tcl
# of ours in `preFixup`.
++ lib.optionals (!isPy3k && !stdenv.hostPlatform.isLinux) [
"Tkinter"
]
++ lib.optionals isPy3k [
++ lib.optionals (isPy3k && !stdenv.hostPlatform.isLinux) [
"tkinter"
];
imports = lib.concatMapStringsSep "; " (x: "import ${x}") modules;