Skip to content

Fix the errmap.h wall: port MSYS2 0007 (-I$(srcdir)/PC on mingw) + close the smoke gate gap - #16

Merged
ronaldtse merged 1 commit into
mainfrom
fix/msys-errmap
Sep 12, 2026
Merged

ronaldtse merged 1 commit into
mainfrom
fix/msys-errmap

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

Root cause

The v0.3.0 windows-msys series (patches/3.14/) defines MS_WINDOWS under __MINGW32__ (pyport_ms_windows_msys) but never ported the include-path half of the MSYS2 port. That define wakes Objects/exceptions.c:1976's #include "errmap.h", and the POSIX build has no way to resolve it:

  • errmap.h is not generated on this line. Upstream retired the PC/generrmap.c generator at bpo-37705 (GH-15623, 3.8 era); 3.14.7 ships PC/errmap.h as checked-in source (verified against the v3.14.7 tag: PC/errmap.h present, no generrmap.c anywhere in the tree). The "generation rule missing from the Makefile patch" hypothesis in the task brief is stale — there is nothing to generate and no Makefile rule involved.
  • What is missing is the include path. Upstream Makefile.pre.in's PY_CPPFLAGS is -I. -I$(srcdir)/Include (plus Include/internal*); PC/ is PCbuild-only territory (MSVC's pythoncore.vcxproj adds ..\PC to the include dirs). Under the ported MS_WINDOWS define the quoted include finds nothing and the TU dies — tebako-runtime-python PR Fix the errmap.h wall: port MSYS2 0007 (-I$(srcdir)/PC on mingw) + close the smoke gate gap #16, run 34692047817 job 103631971290.

Build-shape investigation (the brief's question): both sides build the same shape — the runtime factory configures in-tree (python_build.rb: ./configure with chdir: src_dir) and the smoke also configures in-tree (tools/compile_smoke: Open3.capture3(configure, ..., chdir: src)). It was never VPATH-vs-in-tree. The delta was the smoke's bounded target set: the factory's full make compiles Objects/exceptions.o; the smoke's wall set (pylifecycle/pytime/Programs/python) never did.

The fix

patches/3.14/configure_pc_include_msys.patch — a verbatim port of MSYS2 MINGW-packages 0007-build-Add-PC-to-CPPFLAGS-and-to-SRCDIRS-on-Mingw.patch:

  • configure.ac: under *-*-mingw*, prepend -I$(srcdir)/PC to CPPFLAGS and append PC to SRCDIRS (ported verbatim, dnl comments included).
  • configure: the hand-synced equivalents (this factory ships configure-ready tarballs; no autoreconf downstream — same convention as the series' other configure patches).
  • Registered in patch-3.14.yaml after configure_machdep_msys (MSYS2 numbering order 0002 → 0004 → 0007 → 0052).

Placement is shape-independent: -I$(srcdir)/PC resolves the header in-tree and VPATH, and lands after -I. on the compile line so the generated pyconfig.h still wins over PC/pyconfig.h (the MSYS2 comment's constraint). The linux-gnu asset is untouched (the _msys suffix keeps the POSIX tree byte-identical with upstream).

The gate-gap fix

tools/compile_smoke: Objects/exceptions.o joins WALL_OBJECTS, and the header now states the coverage contract — the smoke IS the factory's shape (in-tree configure, native make, same scenario tree), narrowed only in the target set; the wall set is a regression list and every TU that hard-stops the factory's windows build joins it in the PR that fixes it. This is the v0.2.8 rule ("patches must compile before they release") repeated: v0.3.0 shipped green while the factory wall sat outside the smoke's target set.

Verification (local, macOS — the ucrt64 compile is this PR's CI oracle)

  • tools/lint 3.14.7: OK — all five patches apply clean against the pristine 3.14.7 tree (sha256-verified).
  • Configure probe on the staged windows-msys tree (host triple overridden to x86_64-w64-mingw32): CONFIGURE_CPPFLAGS = -I$(srcdir)/PC …, SRCDIRS = … PC, and make -n Objects/exceptions.o shows -I./PC on the compile line with PC/errmap.h present to be found; bash -n configure clean.
  • bundle exec rspec: 101 examples, 0 failures. tools/validate_manifests: OK. (No rubocop in this repo — Gemfile carries rspec + json_schemer only.)
  • tools/compile_smoke 3.14.7 --platform linux-gnu: green with the extended 4-TU wall set (POSIX regression check).
  • CI: this PR's windows-2022 compile-smoke leg now compiles Objects/exceptions.o under ucrt64 — the exact TU and toolchain that died in trp#16.

Downstream

After merge the owner cuts v0.3.1 (tfs-python-3.14.7-src-windows-msys.tar.gz repacked via the diff-aware release); tebako-runtime-python PR #16 then re-runs against the new source release. No release is tagged from this PR.

…ose the smoke gate gap

The 3.14 windows-msys series defined MS_WINDOWS (pyport_ms_windows_msys)
without porting MSYS2's 0007, so Objects/exceptions.c:1976's
MS_WINDOWS-gated #include "errmap.h" had no resolution path: upstream
ships errmap.h as checked-in PC/errmap.h (the PC/generrmap.c generator
was retired at bpo-37705) and the POSIX compile line
(PY_CPPFLAGS = -I. -I$(srcdir)/Include ...) never covers PC/ — upstream
that dir is PCbuild-only. tebako-runtime-python PR #16's windows leg
died there (run 34692047817, job 103631971290).

configure_pc_include_msys.patch ports MSYS2 0007 verbatim for
configure.ac (CPPFLAGS += -I$(srcdir)/PC and SRCDIRS += PC under
*-*-mingw*) with the generated-configure hunks hand-synced, per the
factory's no-autoreconf rule. The -I lands after -I. on the compile
line, so the generated pyconfig.h still wins over PC/pyconfig.h; the
$(srcdir)-rooted path resolves identically in-tree and VPATH.

Gate gap: the v0.3.0 compile smoke went green because its wall-TU set
(pylifecycle/pytime/Programs/python) never compiled exceptions.o — the
smoke matches the factory's in-tree/native shape and differs only in
the bounded target set. Objects/exceptions.o joins WALL_OBJECTS, and
the smoke header now states the coverage contract: the wall set is the
regression list, every factory windows wall TU joins it in the fixing
PR.

Verified locally (macOS — the ucrt64 compile itself is CI's oracle):
the five-patch series applies clean (tools/lint), the patched configure
under a mingw host triple emits -I$(srcdir)/PC into CONFIGURE_CPPFLAGS
and PC into SRCDIRS, and make -n Objects/exceptions.o shows -I./PC on
the compile line with PC/errmap.h present; rspec 101/0;
validate_manifests OK; the linux-gnu compile smoke re-green with the
extended wall set.
@ronaldtse
ronaldtse merged commit 8099143 into main Sep 12, 2026
10 checks passed
ronaldtse pushed a commit to tamatebako/tebako-runtime-python that referenced this pull request Sep 12, 2026
v0.3.1 is the v0.3.0 catalog plus the MSYS2-MINGW-packages 0007 port
(tamatebako/python#16): PC/errmap.h is checked-in source and upstream's
Makefile grants -I$(srcdir)/PC to MSVC only; the windows-msys scenario
tarball now compiles Objects/exceptions.o through. The version catalog
is unchanged.
ronaldtse pushed a commit that referenced this pull request Sep 13, 2026
…hape

Two observed walls from tebako-runtime-python PR #16 (run 34725669811):

- Python/sysmodule.c:3924 VPATH undeclared — the use is MS_WINDOWS-gated
  and MSVC gets VPATH from PC/pyconfig.h; the autotools sysmodule.o rule
  passes only -DABIFLAGS/$(MULTIARCH_CPPFLAGS). Ported MSYS2 0054
  (-DVPATH='"$(VPATH)"' on the sysmodule.o rule).
- Python/thread_pthread.h:413 native_id / :440 pause — the pthread
  ladder has no __MINGW32__ rung (upstream's pthread path is POSIX-only;
  the Windows thread support upstream tests is thread_nt.h behind the
  MSVC build). Ported MSYS2's proven answer, 0001: --with-nt-threads
  defaults yes on *-*-mingw*, AC_DEFINEs NT_THREADS, skips the pthread
  probe set; pythread.h/pycore_pythread.h/pycore_condvar.h undef
  _POSIX_THREADS (winpthreads leaks it via <windows.h>), so thread.c
  compiles thread_nt.h and thread_pthread.h never enters the build.

Then the full sweep of the MSYS2 MINGW-packages mingw-w64-python series
(103 patches) for our build shape (static-ish, --disable-shared, ucrt64,
MS_WINDOWS via pyport_ms_windows_msys). Ported, in MSYS2 numbering:
0001 (above), 0005 (mingw configure defaults — Misc/config_mingw loads
for EVERY mingw host, native included; despite the MSYS2 title it is
not cross-only: it pins ac_cv_func_alarm/ftruncate/truncate and
ac_cv_file__dev_ptmx/ptc off — run 34730588522's native ucrt64 walls:
signalmodule.c:398 implicit alarm() (the link probe finds alarm in the
import libs; ucrt64's unistd.h declares it only under
__USE_MINGW_ALARM) and posixmodule.c:9000 ioctl/I_PUSH (the msys shell
emulates /dev/ptmx, so HAVE_DEV_PTMX came out set and os_openpty_impl
reached the STREAMS ioctls mingw-w64 lacks) — and forces getpeername
on), 0008 (nt module naming — PyInit_nt vs posix registration,
os.py needs nt at MACHDEP=win32), 0016 (frozenmain.o references
PC/frozen_dllmain.c symbols — exe link wall), 0017 + 0041 (socketmodule
mingw support + the inet_pton probes — without them _socket never
builds), 0036 (_signal signalmodule.c -lws2_32 — signalmodule.c:773's
MS_WINDOWS WSAGetLastError walls the bootstrap links, which never see
the factory's TEBAKO_LIBS), 0045 (ucrt _timezone spellings), 0054
(above), 0056 (_bootstrap_python defines wmain — needs -municode),
0059 (static openssl needs -lws2_32 -lcrypt32 + the cert-store
widening), 0060 (winsock.h for the netdb probes — without it every
netdb probe fails on mingw, HAVE_GETHOSTNAME/HAVE_SHUTDOWN stay
undefined while PC/pyconfig.h defines them, and socket.gethostname /
shutdown vanish from the 0017-enabled _socket; proven by this PR's
cross probe), 0063 (deterministic .exe), 0075 (the POSIX-only module
set is n/a on mingw; subsumes 0058), 0078 (GCC 14 escalated
-Wincompatible-pointer-types to an error; the MSVC-oriented MS_WINDOWS
branches (PathCchSkipRoot, _wexecv/_wspawnv families) pass wchar_t**
where the CRT wants const wchar_t* const* — MSYS2 demotes to warning
on mingw rather than diverging from upstream at every call site;
gate-critical on any current toolchain — CI ships gcc 16), 0097
(mmap's __try/__except is a GCC error once the gate passes on mingw),
0100 (_PYTHREAD_NAME_MAXLEN is used UNGUARDED in _threadmodule.c's
Windows branch). With 0002, 0004, 0007, 0052, 0096 already in the tree
from the earlier rounds, the series is 23 patches. One tebako deviation with no MSYS2 counterpart:
configure_syslibs_msys — the factory's modlib_rewrites rewrite
MODULE__SSL_LDFLAGS/MODULE__HASHLIB_LDFLAGS to absolute .a paths,
dropping 0059's -lws2_32 -lcrypt32 tail, so a host-conditional
WINDOWS_SYSLIBS (-lws2_32 -lcrypt32 -ladvapi32 -lbcrypt on
*-*-mingw*) rides SYSLIBS, which sits after MODLIBS on every link line
and is never rewritten downstream. (MSYS2 builds shared and never
needs this.) All generated-configure hunks are machine-exact regens
with the upstream-pinned autoconf 2.72 (byte-identical regen against
pristine proven), not hand-syncs. The deliberate skips (shared-build/
DLL naming, feature parity like 0018's _winapi, cross-only, tests/CI,
warning-grade) are grouped in the PR body.

Two tooling changes the sweep forced:

- Tfs::SourcePrep#audit now applies the series CUMULATIVELY in manifest
  order instead of git apply --check per patch on pristine: a quilt
  series cannot satisfy per-patch-pristine (0036's context line is
  @MODULE_POSIXMODULE_NAME@, which only exists after 0008). On a
  mid-series failure the remaining patches report a not-checked
  failure. Specs pin the dependent-context and not-checked-tail
  behavior; the lint/README/onboarder comments follow.
- tools/compile_smoke WALL_OBJECTS gains the round-2 walls and the
  patched module TUs (sysmodule, thread, posixmodule, signalmodule,
  timemodule, socketmodule, _threadmodule, _bootstrap_python — the
  regression-list contract). Patch-named .c auto-adds now probe the
  generated Makefile for a literal rule first: an n/a module (e.g.
  _ssl without an openssl dev package in the smoke env) emits NO rule,
  and make's implicit %.o:%.c fallback would otherwise compile it with
  the wrong flags and fail. Skips are reported in the OK line.
  WALL_OBJECTS never probe — a missing rule there is the regression.

Verified locally (macOS + homebrew mingw-w64 gcc 14 — the ucrt64
compile itself is CI's oracle): the 23-patch series applies clean to
pristine 3.14.7 (tools/lint) and reproduces the independently staged
manifest-order MSYS2 reference tree byte-for-byte; the shipped
configure and pyconfig.h.in equal the pinned autoconf 2.72 regen of the
shipped configure.ac exactly (regen-fidelity checked on the assembled
tree); rspec 103/0; validate_manifests OK; the POSIX smoke leg compiles
all 12 wall TUs on the pristine tree; a cross configure
(--host=x86_64-w64-mingw32, --disable-shared, no manual ac_cv presets —
config_mingw loads itself) confirms NT_THREADS defined with
_POSIX_THREADS undef'd, nt posixmodule.c and _signal signalmodule.c
-lws2_32 in Setup.bootstrap, EXE/BUILDEXE=.exe, MODULE__SOCKET_STATE=
yes with the ws2_32 tail, HAVE_GETHOSTNAME/HAVE_SHUTDOWN defined (MSVC
parity), HAVE_ALARM/HAVE_DEV_PTMX/HAVE_TRUNCATE pinned off,
HAVE_GETPEERNAME forced on, _posixshmem/grp/resource n/a,
_PYTHREAD_NAME_MAXLEN=32766, the SYSLIBS tail, -Wno-error=
incompatible-pointer-types in CFLAGS_NODIST, and -DVPATH on the
make -n Python/sysmodule.o compile line with -I./PC present. And the
compile sweep: all 12 wall TUs cross-compile clean, and the FULL core
(libpython3.14.a — 191 objects) cross-compiles with zero errors.
ronaldtse pushed a commit that referenced this pull request Sep 13, 2026
… shape

Two observed walls from tebako-runtime-python PR #16 (run 34725669811):

- Python/sysmodule.c:3924 VPATH undeclared — the use is MS_WINDOWS-gated
  and MSVC gets VPATH from PC/pyconfig.h; the autotools sysmodule.o rule
  passes only -DABIFLAGS/$(MULTIARCH_CPPFLAGS). Ported MSYS2 0054
  (-DVPATH='"$(VPATH)"' on the sysmodule.o rule).
- Python/thread_pthread.h:413 native_id / :440 pause — the pthread
  ladder has no __MINGW32__ rung (upstream's pthread path is POSIX-only;
  the Windows thread support upstream tests is thread_nt.h behind the
  MSVC build). Ported MSYS2's proven answer, 0001: --with-nt-threads
  defaults yes on *-*-mingw*, AC_DEFINEs NT_THREADS, skips the pthread
  probe set; pythread.h/pycore_pythread.h/pycore_condvar.h undef
  _POSIX_THREADS (winpthreads leaks it via <windows.h>), so thread.c
  compiles thread_nt.h and thread_pthread.h never enters the build.

Then the full sweep of the MSYS2 MINGW-packages mingw-w64-python series
(103 patches) for our build shape (static-ish, --disable-shared, ucrt64,
MS_WINDOWS via pyport_ms_windows_msys). Ported, in MSYS2 numbering:
0001 (above), 0005 (mingw configure defaults — Misc/config_mingw loads
for EVERY mingw host, native included; despite the MSYS2 title it is
not cross-only: it pins ac_cv_func_alarm/ftruncate/truncate and
ac_cv_file__dev_ptmx/ptc off — run 34730588522's native ucrt64 walls:
signalmodule.c:398 implicit alarm() (the link probe finds alarm in the
import libs; ucrt64's unistd.h declares it only under
__USE_MINGW_ALARM) and posixmodule.c:9000 ioctl/I_PUSH (the msys shell
emulates /dev/ptmx, so HAVE_DEV_PTMX came out set and os_openpty_impl
reached the STREAMS ioctls mingw-w64 lacks) — and forces getpeername
on), 0008 (nt module naming — PyInit_nt vs posix registration,
os.py needs nt at MACHDEP=win32), 0016 (frozenmain.o references
PC/frozen_dllmain.c symbols — exe link wall), 0017 + 0041 (socketmodule
mingw support + the inet_pton probes — without them _socket never
builds), 0036 (_signal signalmodule.c -lws2_32 — signalmodule.c:773's
MS_WINDOWS WSAGetLastError walls the bootstrap links, which never see
the factory's TEBAKO_LIBS), 0037 (winconsoleio + _testconsole —
run 34732802820's _freeze_module LINK wall: upstream's autotools build
never compiles Modules/_io/winconsoleio.c (the MSVC vcxproj carries
it), so once 0002's HAVE_WINDOWS_CONSOLE_IO arm makes the console code
paths live on mingw the link dies on _get_console_type
(Parser/myreadline.c:273/:276), _PyIO_get_console_type and
winconsoleio_spec (Modules/_io/_iomodule.c); the TU is
HAVE_WINDOWS_CONSOLE_IO-guarded, an empty object on POSIX), 0045 (ucrt
_timezone spellings), 0054 (above), 0056 (_bootstrap_python defines
wmain — needs -municode), 0059 (static openssl needs -lws2_32 -lcrypt32
+ the cert-store widening), 0060 (winsock.h for the netdb probes —
without it every netdb probe fails on mingw,
HAVE_GETHOSTNAME/HAVE_SHUTDOWN stay undefined while PC/pyconfig.h
defines them, and socket.gethostname / shutdown vanish from the
0017-enabled _socket; proven by this PR's cross probe), 0063
(deterministic .exe), 0075 (the POSIX-only module set is n/a on mingw;
subsumes 0058), 0078 (GCC 14 escalated -Wincompatible-pointer-types to
an error; the MSVC-oriented MS_WINDOWS branches (PathCchSkipRoot,
_wexecv/_wspawnv families) pass wchar_t** where the CRT wants const
wchar_t* const* — MSYS2 demotes to warning on mingw rather than
diverging from upstream at every call site; gate-critical on any
current toolchain — CI ships gcc 16), 0097 (mmap's __try/__except is a
GCC error once the gate passes on mingw), 0100 (_PYTHREAD_NAME_MAXLEN
is used UNGUARDED in _threadmodule.c's Windows branch). With 0002,
0004, 0007, 0052, 0096 already in the tree from the earlier rounds, the
series is 24 patches. One tebako deviation: configure_syslibs_msys —
the factory's modlib_rewrites rewrite MODULE__SSL_LDFLAGS/
MODULE__HASHLIB_LDFLAGS to absolute .a paths, dropping 0059's -lws2_32
-lcrypt32 tail, so a host-conditional WINDOWS_SYSLIBS rides SYSLIBS,
which sits after MODLIBS on every link line and is never rewritten
downstream. The lib set is MSYS2's: the original four plus the
-lversion -lshlwapi -lpathcch tail of 0010's mingw LIBS hunk (0010
itself stays skipped as shared-build machinery; MSVC gets the same
libs via #pragma comment(lib, ...) in the sources, which GCC ignores —
run 34732802820's undefined GetFileVersionInfoSizeW/GetFileVersionInfoW/
VerQueryValueW (-> -lversion) and __imp_PathCchSkipRoot/
__imp_PathCchCombineEx (-> -lpathcch) are exactly those pragmas going
silent). All generated-configure hunks are machine-exact regens with
the upstream-pinned autoconf 2.72 (byte-identical regen against
pristine proven), not hand-syncs. The deliberate skips (shared-build/
DLL naming, feature parity like 0018's _winapi, cross-only, tests/CI,
warning-grade) are grouped in the PR body.

Two tooling changes the sweep forced:

- Tfs::SourcePrep#audit now applies the series CUMULATIVELY in manifest
  order instead of git apply --check per patch on pristine: a quilt
  series cannot satisfy per-patch-pristine (0036's context line is
  @MODULE_POSIXMODULE_NAME@, which only exists after 0008). On a
  mid-series failure the remaining patches report a not-checked
  failure. Specs pin the dependent-context and not-checked-tail
  behavior; the lint/README/onboarder comments follow.
- tools/compile_smoke WALL_OBJECTS gains the round-2 walls and the
  patched module TUs (sysmodule, thread, posixmodule, signalmodule,
  timemodule, socketmodule, _threadmodule, _bootstrap_python — the
  regression-list contract), plus a platform-conditional
  WALL_OBJECTS_MSYS for Modules/_io/winconsoleio.o: the TU exists only
  in the patched tree (0037 adds it to the _io bootstrap line), so the
  pristine POSIX leg has no rule for it and must not fail on its
  absence, while on windows-msys a missing rule IS the regression.
  Patch-named .c auto-adds now probe the generated Makefile for a
  literal rule first: an n/a module (e.g. _ssl without an openssl dev
  package in the smoke env) emits NO rule, and make's implicit %.o:%.c
  fallback would otherwise compile it with the wrong flags and fail.
  Skips are reported in the OK line.

Verified locally (macOS + homebrew mingw-w64 gcc 14 — the ucrt64
compile itself is CI's oracle): the 24-patch series applies clean to
pristine 3.14.7 (tools/lint) and reproduces the independently staged
manifest-order MSYS2 reference tree byte-for-byte; the shipped
configure and pyconfig.h.in equal the pinned autoconf 2.72 regen of the
shipped configure.ac exactly (regen-fidelity checked on the assembled
tree); rspec 103/0; validate_manifests OK; the POSIX smoke leg compiles
all 12 wall TUs on the pristine tree; a cross configure
(--host=x86_64-w64-mingw32, --disable-shared, no manual ac_cv presets —
config_mingw loads itself) confirms NT_THREADS defined with
_POSIX_THREADS undef'd, nt posixmodule.c and _signal signalmodule.c
-lws2_32 in Setup.bootstrap, EXE/BUILDEXE=.exe, MODULE__SOCKET_STATE=
yes with the ws2_32 tail, HAVE_GETHOSTNAME/HAVE_SHUTDOWN defined (MSVC
parity), HAVE_ALARM/HAVE_DEV_PTMX/HAVE_TRUNCATE pinned off,
HAVE_GETPEERNAME forced on, _posixshmem/grp/resource n/a,
_PTHREAD_NAME_MAXLEN=32766, the extended SYSLIBS tail
(-lws2_32 -lcrypt32 -ladvapi32 -lbcrypt -lversion -lshlwapi -lpathcch),
-Wno-error=incompatible-pointer-types in CFLAGS_NODIST, and -DVPATH on
the make -n Python/sysmodule.o compile line with -I./PC present. And
the compile+link sweep: all 13 wall TUs cross-compile clean, the FULL
core (libpython3.14.a — 191 objects) cross-compiles with zero errors,
and Programs/_freeze_module — the run 34732802820 casualty — now
cross-LINKS clean (winconsoleio.o in the _io objects, the extended
SYSLIBS resolving version/pathcch).
ronaldtse added a commit that referenced this pull request Sep 13, 2026
… shape (#17)

Two observed walls from tebako-runtime-python PR #16 (run 34725669811):

- Python/sysmodule.c:3924 VPATH undeclared — the use is MS_WINDOWS-gated
  and MSVC gets VPATH from PC/pyconfig.h; the autotools sysmodule.o rule
  passes only -DABIFLAGS/$(MULTIARCH_CPPFLAGS). Ported MSYS2 0054
  (-DVPATH='"$(VPATH)"' on the sysmodule.o rule).
- Python/thread_pthread.h:413 native_id / :440 pause — the pthread
  ladder has no __MINGW32__ rung (upstream's pthread path is POSIX-only;
  the Windows thread support upstream tests is thread_nt.h behind the
  MSVC build). Ported MSYS2's proven answer, 0001: --with-nt-threads
  defaults yes on *-*-mingw*, AC_DEFINEs NT_THREADS, skips the pthread
  probe set; pythread.h/pycore_pythread.h/pycore_condvar.h undef
  _POSIX_THREADS (winpthreads leaks it via <windows.h>), so thread.c
  compiles thread_nt.h and thread_pthread.h never enters the build.

Then the full sweep of the MSYS2 MINGW-packages mingw-w64-python series
(103 patches) for our build shape (static-ish, --disable-shared, ucrt64,
MS_WINDOWS via pyport_ms_windows_msys). Ported, in MSYS2 numbering:
0001 (above), 0005 (mingw configure defaults — Misc/config_mingw loads
for EVERY mingw host, native included; despite the MSYS2 title it is
not cross-only: it pins ac_cv_func_alarm/ftruncate/truncate and
ac_cv_file__dev_ptmx/ptc off — run 34730588522's native ucrt64 walls:
signalmodule.c:398 implicit alarm() (the link probe finds alarm in the
import libs; ucrt64's unistd.h declares it only under
__USE_MINGW_ALARM) and posixmodule.c:9000 ioctl/I_PUSH (the msys shell
emulates /dev/ptmx, so HAVE_DEV_PTMX came out set and os_openpty_impl
reached the STREAMS ioctls mingw-w64 lacks) — and forces getpeername
on), 0008 (nt module naming — PyInit_nt vs posix registration,
os.py needs nt at MACHDEP=win32), 0016 (frozenmain.o references
PC/frozen_dllmain.c symbols — exe link wall), 0017 + 0041 (socketmodule
mingw support + the inet_pton probes — without them _socket never
builds), 0036 (_signal signalmodule.c -lws2_32 — signalmodule.c:773's
MS_WINDOWS WSAGetLastError walls the bootstrap links, which never see
the factory's TEBAKO_LIBS), 0037 (winconsoleio + _testconsole —
run 34732802820's _freeze_module LINK wall: upstream's autotools build
never compiles Modules/_io/winconsoleio.c (the MSVC vcxproj carries
it), so once 0002's HAVE_WINDOWS_CONSOLE_IO arm makes the console code
paths live on mingw the link dies on _get_console_type
(Parser/myreadline.c:273/:276), _PyIO_get_console_type and
winconsoleio_spec (Modules/_io/_iomodule.c); the TU is
HAVE_WINDOWS_CONSOLE_IO-guarded, an empty object on POSIX), 0045 (ucrt
_timezone spellings), 0054 (above), 0056 (_bootstrap_python defines
wmain — needs -municode), 0059 (static openssl needs -lws2_32 -lcrypt32
+ the cert-store widening), 0060 (winsock.h for the netdb probes —
without it every netdb probe fails on mingw,
HAVE_GETHOSTNAME/HAVE_SHUTDOWN stay undefined while PC/pyconfig.h
defines them, and socket.gethostname / shutdown vanish from the
0017-enabled _socket; proven by this PR's cross probe), 0063
(deterministic .exe), 0075 (the POSIX-only module set is n/a on mingw;
subsumes 0058), 0078 (GCC 14 escalated -Wincompatible-pointer-types to
an error; the MSVC-oriented MS_WINDOWS branches (PathCchSkipRoot,
_wexecv/_wspawnv families) pass wchar_t** where the CRT wants const
wchar_t* const* — MSYS2 demotes to warning on mingw rather than
diverging from upstream at every call site; gate-critical on any
current toolchain — CI ships gcc 16), 0097 (mmap's __try/__except is a
GCC error once the gate passes on mingw), 0100 (_PYTHREAD_NAME_MAXLEN
is used UNGUARDED in _threadmodule.c's Windows branch). With 0002,
0004, 0007, 0052, 0096 already in the tree from the earlier rounds, the
series is 24 patches. One tebako deviation: configure_syslibs_msys —
the factory's modlib_rewrites rewrite MODULE__SSL_LDFLAGS/
MODULE__HASHLIB_LDFLAGS to absolute .a paths, dropping 0059's -lws2_32
-lcrypt32 tail, so a host-conditional WINDOWS_SYSLIBS rides SYSLIBS,
which sits after MODLIBS on every link line and is never rewritten
downstream. The lib set is MSYS2's: the original four plus the
-lversion -lshlwapi -lpathcch tail of 0010's mingw LIBS hunk (0010
itself stays skipped as shared-build machinery; MSVC gets the same
libs via #pragma comment(lib, ...) in the sources, which GCC ignores —
run 34732802820's undefined GetFileVersionInfoSizeW/GetFileVersionInfoW/
VerQueryValueW (-> -lversion) and __imp_PathCchSkipRoot/
__imp_PathCchCombineEx (-> -lpathcch) are exactly those pragmas going
silent). All generated-configure hunks are machine-exact regens with
the upstream-pinned autoconf 2.72 (byte-identical regen against
pristine proven), not hand-syncs. The deliberate skips (shared-build/
DLL naming, feature parity like 0018's _winapi, cross-only, tests/CI,
warning-grade) are grouped in the PR body.

Two tooling changes the sweep forced:

- Tfs::SourcePrep#audit now applies the series CUMULATIVELY in manifest
  order instead of git apply --check per patch on pristine: a quilt
  series cannot satisfy per-patch-pristine (0036's context line is
  @MODULE_POSIXMODULE_NAME@, which only exists after 0008). On a
  mid-series failure the remaining patches report a not-checked
  failure. Specs pin the dependent-context and not-checked-tail
  behavior; the lint/README/onboarder comments follow.
- tools/compile_smoke WALL_OBJECTS gains the round-2 walls and the
  patched module TUs (sysmodule, thread, posixmodule, signalmodule,
  timemodule, socketmodule, _threadmodule, _bootstrap_python — the
  regression-list contract), plus a platform-conditional
  WALL_OBJECTS_MSYS for Modules/_io/winconsoleio.o: the TU exists only
  in the patched tree (0037 adds it to the _io bootstrap line), so the
  pristine POSIX leg has no rule for it and must not fail on its
  absence, while on windows-msys a missing rule IS the regression.
  Patch-named .c auto-adds now probe the generated Makefile for a
  literal rule first: an n/a module (e.g. _ssl without an openssl dev
  package in the smoke env) emits NO rule, and make's implicit %.o:%.c
  fallback would otherwise compile it with the wrong flags and fail.
  Skips are reported in the OK line.

Verified locally (macOS + homebrew mingw-w64 gcc 14 — the ucrt64
compile itself is CI's oracle): the 24-patch series applies clean to
pristine 3.14.7 (tools/lint) and reproduces the independently staged
manifest-order MSYS2 reference tree byte-for-byte; the shipped
configure and pyconfig.h.in equal the pinned autoconf 2.72 regen of the
shipped configure.ac exactly (regen-fidelity checked on the assembled
tree); rspec 103/0; validate_manifests OK; the POSIX smoke leg compiles
all 12 wall TUs on the pristine tree; a cross configure
(--host=x86_64-w64-mingw32, --disable-shared, no manual ac_cv presets —
config_mingw loads itself) confirms NT_THREADS defined with
_POSIX_THREADS undef'd, nt posixmodule.c and _signal signalmodule.c
-lws2_32 in Setup.bootstrap, EXE/BUILDEXE=.exe, MODULE__SOCKET_STATE=
yes with the ws2_32 tail, HAVE_GETHOSTNAME/HAVE_SHUTDOWN defined (MSVC
parity), HAVE_ALARM/HAVE_DEV_PTMX/HAVE_TRUNCATE pinned off,
HAVE_GETPEERNAME forced on, _posixshmem/grp/resource n/a,
_PTHREAD_NAME_MAXLEN=32766, the extended SYSLIBS tail
(-lws2_32 -lcrypt32 -ladvapi32 -lbcrypt -lversion -lshlwapi -lpathcch),
-Wno-error=incompatible-pointer-types in CFLAGS_NODIST, and -DVPATH on
the make -n Python/sysmodule.o compile line with -I./PC present. And
the compile+link sweep: all 13 wall TUs cross-compile clean, the FULL
core (libpython3.14.a — 191 objects) cross-compiles with zero errors,
and Programs/_freeze_module — the run 34732802820 casualty — now
cross-LINKS clean (winconsoleio.o in the _io objects, the extended
SYSLIBS resolving version/pathcch).

Co-authored-by: tebako-ci <tebako@ribose.com>
ronaldtse pushed a commit that referenced this pull request Sep 13, 2026
…win cluster (0011-0015) + 0018 + 0066 + 0039; the smoke leg goes --enable-shared

The wall (tebako-runtime-python PR #16, run 34735362057, leg
windows/3.14.7): the full factory build reaches the extension modules
and dies linking Modules/array.cpython-314.so — undefined references
to PyExc_EOFError/_Py_Dealloc/PyUnicode_* and the rest of the core
API. On PE/Windows a loadable module cannot carry undefined symbols at
link time, and statically embedding the core per-extension breaks
interpreter-state identity — the --disable-shared + .so extensions
shape is impossible by construction on Windows. The intended shape is
--enable-shared (the factory's PythonVersion#msys_dll_name and
upload_release dll-facet path were written for it; the ruby factory
ships that way).

Eight MSYS2 MINGW-packages ports close it, inserted in series order:

- 0009 -> exports_declspec_msys (verbatim): HAVE_DECLSPEC_DLL on
  __MINGW32__ + the cygwin arms (auto-import functions, dllimport
  data, exported PyMODINIT_FUNC). Without it the core exports nothing
  in the MSVC style and the import library binds no API surface.
  Inert for the static build: the special-linkage block still gates on
  defined(Py_ENABLE_SHARED) || defined(__CYGWIN__).
- 0010 -> configure_shared_mingw_msys, with ONE hunk elided (the
  closing LIBS hunk — one carrier for -lversion/-lshlwapi/-lpathcch/
  -lbcrypt, the syslibs deviation's post-MODLIBS SYSLIBS position; a
  pre-MODLIBS LIBS copy of -lbcrypt would not resolve libcrypto's
  static refs). The ported hunks: the enable_shared MINGW arms
  (LDLIBRARY=libpython$(LDVERSION).dll.a, DLLLIBRARY=
  libpython$(LDVERSION).dll — the factory's msys_dll_name —,
  BLDLIBRARY=-L. -lpython$(LDVERSION)), the static LDLIBRARY=.a arm,
  LDSHARED/LDCXXSHARED=$(CC) -shared -Wl,--enable-auto-image-base, and
  LIBPYTHON/MODULE_DEPS_SHARED for win32 — what puts $(BLDLIBRARY) on
  every stdlib extension link and $(LDLIBRARY) on its dependency list.

The 0009+0010 cross proof then exposed the wall cascade; each further
port is forced by named evidence (local cross build,
x86_64-w64-mingw32-gcc 14 on macOS, configure --host=
x86_64-w64-mingw32 --enable-shared):

1. The libpython3.14.dll link died: Modules/getpath.o references
   PyWin_DLLhModule (Modules/getpath.c:811-816, compiled only under
   Py_ENABLE_SHARED && MS_WINDOWS — the static tree never misses it),
   and upstream defines the symbol only in PC/dl_nt.c, which the
   autoconf build never compiles. 0012 (dynload_win_msys, verbatim)
   cures it: DYNLOADFILE=dynload_win.o plus PC/dl_nt.o in
   extra_machdep_objs. The loader switch is itself forced — base mingw
   has no dlopen (configure falls to dynload_stub.o = a shared build
   that cannot load anything; the v0.3.2 skip note's "ucrt64 has
   dlfcn" was wrong).
2. 0012 drags its coherence cluster, previously deferred as interop
   naming: the dynload_win.o compile rule passes
   -DPYD_PLATFORM_TAG='"$(PYD_PLATFORM_TAG)"' (0011), and
   dynload_win's import filetab is .pyd-based
   (Include/internal/pycore_importdl.h, upstream), so the build-time
   suffix must agree — 0013 (SHLIB_SUFFIX=.pyd + the import-lib
   install rule) and 0014 (mingw SOABI=cp<ver><thread>-
   <PYD_PLATFORM_TAG>, EXT_SUFFIX=.<SOABI>.pyd). Observable rename:
   windows-msys extension modules change spelling from
   .cpython-314.so to .cp314-mingw_x86_64_ucrt_gnu.pyd. And dl_nt.c's
   PyWin_DLLVersionString = MS_DLL_ID needs 0015's definition
   (MS_DLL_ID via CFLAGS_NODIST; upstream defines it only in the MSVC
   pyconfig).
3. dynload_win.c then failed to COMPILE: its static _Py_CheckPython3
   collides with pylifecycle.h's external declaration under
   MS_WINDOWS. 0066 (verbatim) drops the declaration; no other caller
   exists.
4. python.exe then failed to link: Programs/python.c provides wmain
   under MS_WINDOWS, and linking wmain needs -municode — without it
   the mingw CRT pulls the WinMain startup (crtexewin) and dies
   (crtexewin.c:62: undefined reference to `WinMain'). 0039 (one
   anchor elided — its closing configure.ac hunk rides on 0010's
   elided LIBS case; the FIELD3/RCFLAGS additions apply verbatim in a
   fresh mingw case at the same spot) rewrites the interpreter link
   with -municode + the python_exe.o version/icon resource, adds
   pythonw.exe (-municode -mwindows, the GUI variant every windows
   install ships), the DLL's python_nt.o version resource, the
   windres/RCFLAGS configure machinery, and the altbininstall
   python3w.exe lines.

This PR's own CI then exposed the next wall (run 34741183330, leg
smoke 3.14.7 (windows-msys)): with the link shape fixed, every make
target died at frozen-module regen — ModuleNotFoundError: No module
named 'winreg' / Fatal Python error: _PyImport_InitExternal: external
importer setup failed (Makefile:1957/1960, frozen_modules/abc.h,
codecs.h). Root cause: Lib/importlib/_bootstrap_external.py:36 imports
winreg at module top level whenever sys.platform == 'win32', and the
autoconf build never builds winreg (upstream compiles it MSVC-only via
PCbuild) — so EVERY mingw interpreter boot dies in import setup,
_bootstrap_python included. 0018 (winreg_modules_msys, verbatim +
regen) cures it: winreg/msvcrt/_winapi become bootstrap-static modules
(Setup.bootstrap.in + PY_STDLIB_MOD), winsound gains -lwinmm and
_overlapped -lws2_32 (Setup.stdlib.in), crtdbg.h is debug-gated in
_winapi.c/msvcrtmodule.c, and dynamic_annotations.c's _MSC_VER guard
becomes MS_WINDOWS.

Deliberately skipped from the cluster's neighborhood (recorded in the
PR body): 0067 (PYTHONLEGACYWINDOWSDLLLOADING — uninstalled-tree test
convenience; its mingw_smoketests.py hunk targets an MSYS2-CI-local
file), 0068 (GetPythonImport libpython-name port — without it the
wrong-python-version guard is inert, not broken: the .pyd imports
libpython3.14.dll, which never matches the MSVC "python" prefix),
0069 (backslash normalization — its precondition is MSYS2-fork
forward-slash path handling this series does not carry), 0070
(suppress the python3.dll preload under mingw — with PY3_DLLNAME=
libpython3.14.dll the preload resolves to the already-loaded core DLL,
a harmless no-op; its hunk context also rides on the skipped 0067).

tools/compile_smoke follows the factory's new linkage shape (the
coverage contract — the smoke IS the factory's shape): the windows-msys
leg configures --enable-shared and gains the one LINK regression
target — Modules/array$(EXT_SUFFIX), the exact run-34735362057
casualty, never probed, EXT_SUFFIX read off the generated Makefile (it
now resolves to the .pyd spelling). The POSIX leg is untouched
(pristine tree, upstream's static default, 12 wall TUs).

Verified locally (macOS + homebrew mingw-w64 gcc 14; the native ucrt64
build is CI's oracle): the 34-patch series applies clean to pristine
3.14.7 (tools/lint) and reproduces the reference tree byte-for-byte;
shipped configure/pyconfig.h.in equal the pinned autoconf 2.72 regen
exactly; rspec 103/0; validate_manifests OK; the POSIX smoke leg
compiles all 12 wall TUs on the pristine tree. Cross proof: configure
yields the MSYS2 spellings (LDLIBRARY=libpython3.14.dll.a,
DLLLIBRARY=libpython3.14.dll, DYNLOADFILE=dynload_win.o,
MACHDEP_OBJS=PC/dl_nt.o, SHLIB_SUFFIX=.pyd,
EXT_SUFFIX=.cp314-mingw_x86_64_ucrt_gnu.pyd, PY_ENABLE_SHARED=1); the
build links libpython3.14.dll (38 MB), python.exe, pythonw.exe, and
Modules/array.cp314-mingw_x86_64_ucrt_gnu.pyd — the
run-34735362057 casualty under its new name; the DLL export table
carries PyExc_EOFError/_Py_Dealloc/PyUnicode_FromString (the wall's
undefined symbols) among 3678 exports; the .pyd imports
libpython3.14.dll; the DLL's own imports add libgcc_s_seh-1.dll and
libwinpthread-1.dll — the two mingw runtime DLLs the factory's windows
layout must stage beside the exe. The 0018 shape is proven as far as a
cross build can take it: winreg/msvcrt/_winapi compile clean into the
core archive (PC/winreg.o, PC/msvcrtmodule.o, Modules/_winapi.o), the
generated Modules/config.c registers all three in _PyImport_Inittab,
and PyInit_winreg exports from the DLL — the interpreter boot itself
is provable only natively, so the smoke leg is the oracle.
ronaldtse pushed a commit that referenced this pull request Sep 13, 2026
…win cluster (0011-0015) + 0018 + 0034 + 0066 + 0039; the smoke leg goes --enable-shared

The wall (tebako-runtime-python PR #16, run 34735362057, leg
windows/3.14.7): the full factory build reaches the extension modules
and dies linking Modules/array.cpython-314.so — undefined references
to PyExc_EOFError/_Py_Dealloc/PyUnicode_* and the rest of the core
API. On PE/Windows a loadable module cannot carry undefined symbols at
link time, and statically embedding the core per-extension breaks
interpreter-state identity — the --disable-shared + .so extensions
shape is impossible by construction on Windows. The intended shape is
--enable-shared (the factory's PythonVersion#msys_dll_name and
upload_release dll-facet path were written for it; the ruby factory
ships that way).

Eight MSYS2 MINGW-packages ports close it, inserted in series order:

- 0009 -> exports_declspec_msys (verbatim): HAVE_DECLSPEC_DLL on
  __MINGW32__ + the cygwin arms (auto-import functions, dllimport
  data, exported PyMODINIT_FUNC). Without it the core exports nothing
  in the MSVC style and the import library binds no API surface.
  Inert for the static build: the special-linkage block still gates on
  defined(Py_ENABLE_SHARED) || defined(__CYGWIN__).
- 0010 -> configure_shared_mingw_msys, with ONE hunk elided (the
  closing LIBS hunk — one carrier for -lversion/-lshlwapi/-lpathcch/
  -lbcrypt, the syslibs deviation's post-MODLIBS SYSLIBS position; a
  pre-MODLIBS LIBS copy of -lbcrypt would not resolve libcrypto's
  static refs). The ported hunks: the enable_shared MINGW arms
  (LDLIBRARY=libpython$(LDVERSION).dll.a, DLLLIBRARY=
  libpython$(LDVERSION).dll — the factory's msys_dll_name —,
  BLDLIBRARY=-L. -lpython$(LDVERSION)), the static LDLIBRARY=.a arm,
  LDSHARED/LDCXXSHARED=$(CC) -shared -Wl,--enable-auto-image-base, and
  LIBPYTHON/MODULE_DEPS_SHARED for win32 — what puts $(BLDLIBRARY) on
  every stdlib extension link and $(LDLIBRARY) on its dependency list.

The 0009+0010 cross proof then exposed the wall cascade; each further
port is forced by named evidence (local cross build,
x86_64-w64-mingw32-gcc 14 on macOS, configure --host=
x86_64-w64-mingw32 --enable-shared):

1. The libpython3.14.dll link died: Modules/getpath.o references
   PyWin_DLLhModule (Modules/getpath.c:811-816, compiled only under
   Py_ENABLE_SHARED && MS_WINDOWS — the static tree never misses it),
   and upstream defines the symbol only in PC/dl_nt.c, which the
   autoconf build never compiles. 0012 (dynload_win_msys, verbatim)
   cures it: DYNLOADFILE=dynload_win.o plus PC/dl_nt.o in
   extra_machdep_objs. The loader switch is itself forced — base mingw
   has no dlopen (configure falls to dynload_stub.o = a shared build
   that cannot load anything; the v0.3.2 skip note's "ucrt64 has
   dlfcn" was wrong).
2. 0012 drags its coherence cluster, previously deferred as interop
   naming: the dynload_win.o compile rule passes
   -DPYD_PLATFORM_TAG='"$(PYD_PLATFORM_TAG)"' (0011), and
   dynload_win's import filetab is .pyd-based
   (Include/internal/pycore_importdl.h, upstream), so the build-time
   suffix must agree — 0013 (SHLIB_SUFFIX=.pyd + the import-lib
   install rule) and 0014 (mingw SOABI=cp<ver><thread>-
   <PYD_PLATFORM_TAG>, EXT_SUFFIX=.<SOABI>.pyd). Observable rename:
   windows-msys extension modules change spelling from
   .cpython-314.so to .cp314-mingw_x86_64_ucrt_gnu.pyd. And dl_nt.c's
   PyWin_DLLVersionString = MS_DLL_ID needs 0015's definition
   (MS_DLL_ID via CFLAGS_NODIST; upstream defines it only in the MSVC
   pyconfig).
3. dynload_win.c then failed to COMPILE: its static _Py_CheckPython3
   collides with pylifecycle.h's external declaration under
   MS_WINDOWS. 0066 (verbatim) drops the declaration; no other caller
   exists.
4. python.exe then failed to link: Programs/python.c provides wmain
   under MS_WINDOWS, and linking wmain needs -municode — without it
   the mingw CRT pulls the WinMain startup (crtexewin) and dies
   (crtexewin.c:62: undefined reference to `WinMain'). 0039 (one
   anchor elided — its closing configure.ac hunk rides on 0010's
   elided LIBS case; the FIELD3/RCFLAGS additions apply verbatim in a
   fresh mingw case at the same spot) rewrites the interpreter link
   with -municode + the python_exe.o version/icon resource, adds
   pythonw.exe (-municode -mwindows, the GUI variant every windows
   install ships), the DLL's python_nt.o version resource, the
   windres/RCFLAGS configure machinery, and the altbininstall
   python3w.exe lines.

This PR's own CI then exposed the next wall (run 34741183330, leg
smoke 3.14.7 (windows-msys)): with the link shape fixed, every make
target died at frozen-module regen — ModuleNotFoundError: No module
named 'winreg' / Fatal Python error: _PyImport_InitExternal: external
importer setup failed (Makefile:1957/1960, frozen_modules/abc.h,
codecs.h). Root cause: Lib/importlib/_bootstrap_external.py:36 imports
winreg at module top level whenever sys.platform == 'win32', and the
autoconf build never builds winreg (upstream compiles it MSVC-only via
PCbuild) — so EVERY mingw interpreter boot dies in import setup,
_bootstrap_python included. 0018 (winreg_modules_msys, verbatim +
regen) cures it: winreg/msvcrt/_winapi become bootstrap-static modules
(Setup.bootstrap.in + PY_STDLIB_MOD), winsound gains -lwinmm and
_overlapped -lws2_32 (Setup.stdlib.in), crtdbg.h is debug-gated in
_winapi.c/msvcrtmodule.c, and dynamic_annotations.c's _MSC_VER guard
becomes MS_WINDOWS.

The second CI leg then moved one step deeper (run 34742370411, job
103684133612): with winreg in place the interpreter boots past
_PyImport_InitExternal and dies at Lib/site.py:330 — _get_path's win32
branch (sys.platform == 'win32' via configure_machdep_msys) reads
sys.winver -> AttributeError: module 'sys' has no attribute 'winver'
(Makefile:1964/1967, the same frozen-headers regen). Upstream
sysmodule.c installs winver/dllhandle only under MS_COREDLL, an
MSVC-project-only macro (PC/pyconfig.h) the autotools build never
defines — while the definitions it guards DO exist in this link (0012
compiles PC/dl_nt.o, 0015 defines MS_DLL_ID). 0034
(sysmodule_coredll_msys — the transformation verbatim, the hunks
re-authored against 3.14.7: the upstream hunk-3 context rides MSYS2's
own 0003 sys._is_mingw_ucrt patch, which this series does not carry)
makes the guard defined(MS_WINDOWS) && defined(Py_ENABLE_SHARED); in
the static shape the guard stays false (static behavior unchanged),
POSIX untouched, no configure.ac change so no regen.

Deliberately skipped from the cluster's neighborhood (recorded in the
PR body): 0067 (PYTHONLEGACYWINDOWSDLLLOADING — uninstalled-tree test
convenience; its mingw_smoketests.py hunk targets an MSYS2-CI-local
file), 0068 (GetPythonImport libpython-name port — without it the
wrong-python-version guard is inert, not broken: the .pyd imports
libpython3.14.dll, which never matches the MSVC "python" prefix),
0069 (backslash normalization — its precondition is MSYS2-fork
forward-slash path handling this series does not carry), 0070
(suppress the python3.dll preload under mingw — with PY3_DLLNAME=
libpython3.14.dll the preload resolves to the already-loaded core DLL,
a harmless no-op; its hunk context also rides on the skipped 0067).

tools/compile_smoke follows the factory's new linkage shape (the
coverage contract — the smoke IS the factory's shape): the windows-msys
leg configures --enable-shared and gains the one LINK regression
target — Modules/array$(EXT_SUFFIX), the exact run-34735362057
casualty, never probed, EXT_SUFFIX read off the generated Makefile (it
now resolves to the .pyd spelling). The POSIX leg is untouched
(pristine tree, upstream's static default, 12 wall TUs).

Verified locally (macOS + homebrew mingw-w64 gcc 14; the native ucrt64
build is CI's oracle): the 35-patch series applies clean to pristine
3.14.7 (tools/lint) — the 34-patch prefix reproduces the reference
tree byte-for-byte, and 0034's only target (Python/sysmodule.c) is
touched by no other entry; shipped configure/pyconfig.h.in equal the
pinned autoconf 2.72 regen exactly; rspec 103/0; validate_manifests
OK; the POSIX smoke leg compiles all 12 wall TUs on the pristine tree.
Cross proof: configure yields the MSYS2 spellings (LDLIBRARY=
libpython3.14.dll.a, DLLLIBRARY=libpython3.14.dll, DYNLOADFILE=
dynload_win.o, MACHDEP_OBJS=PC/dl_nt.o, SHLIB_SUFFIX=.pyd,
EXT_SUFFIX=.cp314-mingw_x86_64_ucrt_gnu.pyd, PY_ENABLE_SHARED=1); the
build links libpython3.14.dll (38 MB), python.exe, pythonw.exe, and
Modules/array.cp314-mingw_x86_64_ucrt_gnu.pyd — the
run-34735362057 casualty under its new name; the DLL export table
carries PyExc_EOFError/_Py_Dealloc/PyUnicode_FromString (the wall's
undefined symbols) among 3678 exports; the .pyd imports
libpython3.14.dll; the DLL's own imports add libgcc_s_seh-1.dll and
libwinpthread-1.dll — the two mingw runtime DLLs the factory's windows
layout must stage beside the exe. The 0018 shape: winreg/msvcrt/
_winapi compile into the core archive (PC/winreg.o,
PC/msvcrtmodule.o, Modules/_winapi.o), the generated Modules/config.c
registers all three in _PyImport_Inittab, and PyInit_winreg exports
from the DLL. The 0034 shape: Python/sysmodule.o compiles for the
target and the python.exe link still closes. Both boot-time fixes are
provable only at run time — the CI smoke leg is the oracle.
ronaldtse added a commit that referenced this pull request Sep 13, 2026
…cluster + 0018 + 0034 + 0066 + 0039); the smoke leg goes --enable-shared (#18)

The wall (tebako-runtime-python PR #16, run 34735362057, leg
windows/3.14.7): the full factory build reaches the extension modules
and dies linking Modules/array.cpython-314.so — undefined references
to PyExc_EOFError/_Py_Dealloc/PyUnicode_* and the rest of the core
API. On PE/Windows a loadable module cannot carry undefined symbols at
link time, and statically embedding the core per-extension breaks
interpreter-state identity — the --disable-shared + .so extensions
shape is impossible by construction on Windows. The intended shape is
--enable-shared (the factory's PythonVersion#msys_dll_name and
upload_release dll-facet path were written for it; the ruby factory
ships that way).

Eight MSYS2 MINGW-packages ports close it, inserted in series order:

- 0009 -> exports_declspec_msys (verbatim): HAVE_DECLSPEC_DLL on
  __MINGW32__ + the cygwin arms (auto-import functions, dllimport
  data, exported PyMODINIT_FUNC). Without it the core exports nothing
  in the MSVC style and the import library binds no API surface.
  Inert for the static build: the special-linkage block still gates on
  defined(Py_ENABLE_SHARED) || defined(__CYGWIN__).
- 0010 -> configure_shared_mingw_msys, with ONE hunk elided (the
  closing LIBS hunk — one carrier for -lversion/-lshlwapi/-lpathcch/
  -lbcrypt, the syslibs deviation's post-MODLIBS SYSLIBS position; a
  pre-MODLIBS LIBS copy of -lbcrypt would not resolve libcrypto's
  static refs). The ported hunks: the enable_shared MINGW arms
  (LDLIBRARY=libpython$(LDVERSION).dll.a, DLLLIBRARY=
  libpython$(LDVERSION).dll — the factory's msys_dll_name —,
  BLDLIBRARY=-L. -lpython$(LDVERSION)), the static LDLIBRARY=.a arm,
  LDSHARED/LDCXXSHARED=$(CC) -shared -Wl,--enable-auto-image-base, and
  LIBPYTHON/MODULE_DEPS_SHARED for win32 — what puts $(BLDLIBRARY) on
  every stdlib extension link and $(LDLIBRARY) on its dependency list.

The 0009+0010 cross proof then exposed the wall cascade; each further
port is forced by named evidence (local cross build,
x86_64-w64-mingw32-gcc 14 on macOS, configure --host=
x86_64-w64-mingw32 --enable-shared):

1. The libpython3.14.dll link died: Modules/getpath.o references
   PyWin_DLLhModule (Modules/getpath.c:811-816, compiled only under
   Py_ENABLE_SHARED && MS_WINDOWS — the static tree never misses it),
   and upstream defines the symbol only in PC/dl_nt.c, which the
   autoconf build never compiles. 0012 (dynload_win_msys, verbatim)
   cures it: DYNLOADFILE=dynload_win.o plus PC/dl_nt.o in
   extra_machdep_objs. The loader switch is itself forced — base mingw
   has no dlopen (configure falls to dynload_stub.o = a shared build
   that cannot load anything; the v0.3.2 skip note's "ucrt64 has
   dlfcn" was wrong).
2. 0012 drags its coherence cluster, previously deferred as interop
   naming: the dynload_win.o compile rule passes
   -DPYD_PLATFORM_TAG='"$(PYD_PLATFORM_TAG)"' (0011), and
   dynload_win's import filetab is .pyd-based
   (Include/internal/pycore_importdl.h, upstream), so the build-time
   suffix must agree — 0013 (SHLIB_SUFFIX=.pyd + the import-lib
   install rule) and 0014 (mingw SOABI=cp<ver><thread>-
   <PYD_PLATFORM_TAG>, EXT_SUFFIX=.<SOABI>.pyd). Observable rename:
   windows-msys extension modules change spelling from
   .cpython-314.so to .cp314-mingw_x86_64_ucrt_gnu.pyd. And dl_nt.c's
   PyWin_DLLVersionString = MS_DLL_ID needs 0015's definition
   (MS_DLL_ID via CFLAGS_NODIST; upstream defines it only in the MSVC
   pyconfig).
3. dynload_win.c then failed to COMPILE: its static _Py_CheckPython3
   collides with pylifecycle.h's external declaration under
   MS_WINDOWS. 0066 (verbatim) drops the declaration; no other caller
   exists.
4. python.exe then failed to link: Programs/python.c provides wmain
   under MS_WINDOWS, and linking wmain needs -municode — without it
   the mingw CRT pulls the WinMain startup (crtexewin) and dies
   (crtexewin.c:62: undefined reference to `WinMain'). 0039 (one
   anchor elided — its closing configure.ac hunk rides on 0010's
   elided LIBS case; the FIELD3/RCFLAGS additions apply verbatim in a
   fresh mingw case at the same spot) rewrites the interpreter link
   with -municode + the python_exe.o version/icon resource, adds
   pythonw.exe (-municode -mwindows, the GUI variant every windows
   install ships), the DLL's python_nt.o version resource, the
   windres/RCFLAGS configure machinery, and the altbininstall
   python3w.exe lines.

This PR's own CI then exposed the next wall (run 34741183330, leg
smoke 3.14.7 (windows-msys)): with the link shape fixed, every make
target died at frozen-module regen — ModuleNotFoundError: No module
named 'winreg' / Fatal Python error: _PyImport_InitExternal: external
importer setup failed (Makefile:1957/1960, frozen_modules/abc.h,
codecs.h). Root cause: Lib/importlib/_bootstrap_external.py:36 imports
winreg at module top level whenever sys.platform == 'win32', and the
autoconf build never builds winreg (upstream compiles it MSVC-only via
PCbuild) — so EVERY mingw interpreter boot dies in import setup,
_bootstrap_python included. 0018 (winreg_modules_msys, verbatim +
regen) cures it: winreg/msvcrt/_winapi become bootstrap-static modules
(Setup.bootstrap.in + PY_STDLIB_MOD), winsound gains -lwinmm and
_overlapped -lws2_32 (Setup.stdlib.in), crtdbg.h is debug-gated in
_winapi.c/msvcrtmodule.c, and dynamic_annotations.c's _MSC_VER guard
becomes MS_WINDOWS.

The second CI leg then moved one step deeper (run 34742370411, job
103684133612): with winreg in place the interpreter boots past
_PyImport_InitExternal and dies at Lib/site.py:330 — _get_path's win32
branch (sys.platform == 'win32' via configure_machdep_msys) reads
sys.winver -> AttributeError: module 'sys' has no attribute 'winver'
(Makefile:1964/1967, the same frozen-headers regen). Upstream
sysmodule.c installs winver/dllhandle only under MS_COREDLL, an
MSVC-project-only macro (PC/pyconfig.h) the autotools build never
defines — while the definitions it guards DO exist in this link (0012
compiles PC/dl_nt.o, 0015 defines MS_DLL_ID). 0034
(sysmodule_coredll_msys — the transformation verbatim, the hunks
re-authored against 3.14.7: the upstream hunk-3 context rides MSYS2's
own 0003 sys._is_mingw_ucrt patch, which this series does not carry)
makes the guard defined(MS_WINDOWS) && defined(Py_ENABLE_SHARED); in
the static shape the guard stays false (static behavior unchanged),
POSIX untouched, no configure.ac change so no regen.

Deliberately skipped from the cluster's neighborhood (recorded in the
PR body): 0067 (PYTHONLEGACYWINDOWSDLLLOADING — uninstalled-tree test
convenience; its mingw_smoketests.py hunk targets an MSYS2-CI-local
file), 0068 (GetPythonImport libpython-name port — without it the
wrong-python-version guard is inert, not broken: the .pyd imports
libpython3.14.dll, which never matches the MSVC "python" prefix),
0069 (backslash normalization — its precondition is MSYS2-fork
forward-slash path handling this series does not carry), 0070
(suppress the python3.dll preload under mingw — with PY3_DLLNAME=
libpython3.14.dll the preload resolves to the already-loaded core DLL,
a harmless no-op; its hunk context also rides on the skipped 0067).

tools/compile_smoke follows the factory's new linkage shape (the
coverage contract — the smoke IS the factory's shape): the windows-msys
leg configures --enable-shared and gains the one LINK regression
target — Modules/array$(EXT_SUFFIX), the exact run-34735362057
casualty, never probed, EXT_SUFFIX read off the generated Makefile (it
now resolves to the .pyd spelling). The POSIX leg is untouched
(pristine tree, upstream's static default, 12 wall TUs).

Verified locally (macOS + homebrew mingw-w64 gcc 14; the native ucrt64
build is CI's oracle): the 35-patch series applies clean to pristine
3.14.7 (tools/lint) — the 34-patch prefix reproduces the reference
tree byte-for-byte, and 0034's only target (Python/sysmodule.c) is
touched by no other entry; shipped configure/pyconfig.h.in equal the
pinned autoconf 2.72 regen exactly; rspec 103/0; validate_manifests
OK; the POSIX smoke leg compiles all 12 wall TUs on the pristine tree.
Cross proof: configure yields the MSYS2 spellings (LDLIBRARY=
libpython3.14.dll.a, DLLLIBRARY=libpython3.14.dll, DYNLOADFILE=
dynload_win.o, MACHDEP_OBJS=PC/dl_nt.o, SHLIB_SUFFIX=.pyd,
EXT_SUFFIX=.cp314-mingw_x86_64_ucrt_gnu.pyd, PY_ENABLE_SHARED=1); the
build links libpython3.14.dll (38 MB), python.exe, pythonw.exe, and
Modules/array.cp314-mingw_x86_64_ucrt_gnu.pyd — the
run-34735362057 casualty under its new name; the DLL export table
carries PyExc_EOFError/_Py_Dealloc/PyUnicode_FromString (the wall's
undefined symbols) among 3678 exports; the .pyd imports
libpython3.14.dll; the DLL's own imports add libgcc_s_seh-1.dll and
libwinpthread-1.dll — the two mingw runtime DLLs the factory's windows
layout must stage beside the exe. The 0018 shape: winreg/msvcrt/
_winapi compile into the core archive (PC/winreg.o,
PC/msvcrtmodule.o, Modules/_winapi.o), the generated Modules/config.c
registers all three in _PyImport_Inittab, and PyInit_winreg exports
from the DLL. The 0034 shape: Python/sysmodule.o compiles for the
target and the python.exe link still closes. Both boot-time fixes are
provable only at run time — the CI smoke leg is the oracle.
ronaldtse added a commit to tamatebako/tebako-runtime-python that referenced this pull request Sep 13, 2026
* Return the windows-2022 leg on the source factory's scenario axis (TODO.python/05 item 2)

The windows row comes back to the matrix (63e8336's descope), now
buildable: tamatebako/python's platform-scenario axis ships the
msys2/ucrt64 patch series as tfs-python-<base>-src-windows-msys.tar.gz
assets (tamatebako/python#14).

- .github/matrix.json: re-add the windows-2022 row, exactly as
  descoped. The windows-gated legs in _build-platform.yml (msys2
  provisioning, build, symbol provenance, boot smoke) and publish.yml's
  windows job need no edits — they light up on the row's legs.
- SourceFetcher: scenario-aware assets (the ruby factory's
  scenario_asset_names convention, minus ruby's msys two-pass split —
  CPython needs one tree per scenario). fetch/tarball_sha256 take an
  optional platform; a mingw host names the -windows-msys asset, POSIX
  keeps the unsuffixed back-compat asset. Builder threads @platform.
- compute_matrix.rb: jit lines skip windows (upstream's JIT target
  whitelist admits MSVC windows only — the musl skip's sibling), and a
  windows leg exists only when the pinned source_release's SHA256SUMS
  carries the line's windows-msys asset — missing asset = loud skip,
  not a red leg. The SHA256SUMS read is lazy and scoped to a windows
  env row surviving the filters (POSIX triggers stay fetch-free), and
  an unreadable pin surfaces as a named exit-64 error, never a stack
  trace.
- contract.yml: source_release v0.2.0 -> v0.3.0 (the release carrying
  the scenario axis). EXPECTED RED until tamatebako/python#14 merges
  and v0.3.0 is cut: the pinned SHA256SUMS 404s, and lint.yml's
  unfiltered compute_matrix fails named. Once v0.3.0 exists this PR
  goes green with no further edits (the #2 expected-red precedent).

Verified locally: rspec 14/0 (new source_fetcher_spec covers the
scenario grammar over a file:// mirror); check_contract green; POSIX
matrices byte-identical to main; PLATFORM_FILTER=windows against a
staged SHA256SUMS yields exactly the 3.14.7 leg with loud skips for
the other five catalog lines, and the all-missing case yields an empty
matrix with six loud skips; ruby -c sweep clean.

* contract: consume source release v0.3.1 (the errmap.h msys include fix)

v0.3.1 is the v0.3.0 catalog plus the MSYS2-MINGW-packages 0007 port
(tamatebako/python#16): PC/errmap.h is checked-in source and upstream's
Makefile grants -I$(srcdir)/PC to MSVC only; the windows-msys scenario
tarball now compiles Objects/exceptions.o through. The version catalog
is unchanged.

* contract: consume source release v0.3.2 (the msys compile-wall sweep)

v0.3.2 is the v0.3.1 catalog plus the MSYS2-MINGW-packages sweep for
the static ucrt64 shape (tamatebako/python#17): 18 more patches ported
— the observed round-2 walls (0054 -DVPATH on the sysmodule.o rule,
0001 --with-nt-threads default + the _POSIX_THREADS undefs) plus the
series audit's compile/link/module-reach set (0005 mingw configure
defaults — the alarm/dev-ptmx probe pins that walled the native ucrt64
smoke leg, 0008 nt module naming, 0016 frozenmain exe-link, 0017+0041
socketmodule + inet_pton probes, 0036 _signal -lws2_32, 0037
winconsoleio in the _io bootstrap line, 0045 ucrt _timezone spellings,
0056 -municode for _bootstrap_python, 0059 ssl/hashlib -l tails, 0060
winsock netdb probes, 0063 deterministic EXEEXT, 0075 POSIX-only
modules n/a, 0078 -Wno-error=incompatible-pointer-types for gcc>=14,
0097 mmapmodule SEH, 0100 _PTHREAD_NAME_MAXLEN) and the syslibs
deviation extended with 0010's -lversion -lshlwapi -lpathcch tail.
The version catalog is unchanged.

* contract: consume source release v0.3.3 (the mingw shared-build machinery)

v0.3.3 is the v0.3.2 catalog plus the MSYS2-MINGW-packages
shared-build port (tamatebako/python#18): 0009/0010 (declspec exports
+ the enable_shared mingw configure arms — LDLIBRARY=
libpython3.14.dll.a / DLLLIBRARY=libpython3.14.dll), the dynload_win
coherence cluster (0011 PYD_PLATFORM_TAG, 0012 dynload_win + PC/dl_nt.o,
0013 SHLIB_SUFFIX=.pyd, 0014 mingw SOABI/EXT_SUFFIX, 0015 MS_DLL_ID),
the two interpreter boot walls the PR's own smoke leg forced (0018:
winreg/msvcrt/_winapi as bootstrap-static modules — _bootstrap_external
imports winreg at top level on win32; 0034: sysmodule's winver/dllhandle
guard MS_COREDLL -> defined(MS_WINDOWS) && defined(Py_ENABLE_SHARED)),
0066 (the _Py_CheckPython3 declaration conflict), and 0039 (-municode
exe link + the win resources + pythonw.exe). Observable rename on
windows-msys: extension modules are .cp314-mingw_x86_64_ucrt_gnu.pyd.
The version catalog is unchanged.

* windows-msys: build --enable-shared + ship the runtime DLL (issue 40's answer)

The v0.3.3 source release carries the MSYS2-series machinery (0009/0010
shared build, 0011-0015, 0018, 0034, 0039, 0066); the first trp leg
against it (run 34745803168) failed exactly as predicted on the static
shape: the stdlib extensions link as loadable PE modules
(array.cp314-mingw_x86_64_ucrt_gnu.pyd, Makefile:3624) and PE modules
cannot carry undefined symbols — the link died on _Py_Dealloc & co
because --disable-shared gives them no libpython to resolve against.
On PE the answer is structural, not a patch: build --enable-shared and
ship the DLL.

- configure: --enable-shared on windows-msys (POSIX keeps
  --disable-shared, the shipped single-exe shape).
- substitute_makefiles: the exe link recipe substitution is now
  platform-shaped. The 0039 patch (win_resources_pythonw_msys) rewrites
  the rule to `...$(LINKFORSHARED) -municode -o $@ Programs/python.o ...
  $(SYSLIBS) python_exe.o` — the old POSIX regex never matched that
  line, so the prereq side rewrote python.o -> tebako_python.o while the
  recipe kept linking Programs/python.o: the driver link was SILENTLY
  lost (the fs TU compiled but never linked). The msys substitution
  strips -municode (the fs TU defines plain main; the mingw CRT demands
  wmain otherwise) and keeps python_exe.o (the version/icon resource).
  verify_substitutions now also requires the rewritten recipe line
  (-o $@ Programs/tebako_python.o) — the silent-loss class fails closed.
- abi: EXT_SUFFIX regex accepts the mingw spelling
  (cp314-mingw_x86_64_ucrt_gnu.pyd) alongside the POSIX cpython-* one.
- make: on msys pre-build the DLL target SERIALLY before the -j make.
  Upstream's `$(DLLLIBRARY) libpython$(LDVERSION).dll.a` two-target rule
  (-Wl,--out-implib=$@) is parallel-unsafe: observed locally, the
  interleaved import-library write replaced the 39 MB libpython3.14.dll
  with the 1.2 MB import stub. The serial pre-build materializes both
  files with the correct expansion; the parallel make then finds the
  rule up-to-date and never re-runs it.
- finalize stages libpython<X.Y>.dll beside the runtime package as
  <package>.dll (unique per leg — two same-ABI legs share the PE name
  and would collide in the merged release workspace); a missing DLL is
  a named error (exit 130), never a silent static regression. The image
  layout card declares runtime_dll (additive, schema_minor 3,
  spec 22 §2.1); PythonVersion#msys_dll_name stays the name's single
  owner. tools/boot_smoke materializes the PE-named copy next to the
  in-leg exe before any scenario boots it (the OS loader resolves it
  before any driver code runs).
- upload_release: expected_facets requires <package>.dll on windows —
  a leg that failed to stage it is an incomplete release, not an
  optional facet. (The dll manifest facet, install_as included, was
  already modeled; the comments claiming "nothing ships it today" are
  corrected.)
- The mingw support set never reaches the user: LIBS="-static-libgcc
  -l:libwinpthread.a" static-links libgcc/libwinpthread INTO the
  runtime's PE modules (ruby factory's proven Mlibs::MSYS_DLL_LIBRARIES
  recipe; LIBS lands in the link tail, after the objects, so the
  archives resolve). Verified against a local cross build of the v0.3.3
  tree: libpython3.14.dll (39,320,791 bytes) imports system DLLs only
  (KERNEL32/ADVAPI32/VERSION/WS2_32/bcrypt/api-ms-win-*) —
  libgcc_s_seh-1.dll and libwinpthread-1.dll are gone; the exe imports
  system + libpython3.14.dll only. A bare windows machine installs
  nothing (audience rule 1).
- README's windows-boundary section describes the shared shape.

Gates: rspec 14/0; check_contract.rb green; ruby -c sweep green. The
recipe substitutions were cross-checked by driving the real
exe_recipe_substitution against the real v0.3.3 Makefile.pre shapes
(msys probe tree + POSIX smoke trees): each pair matches its own shape
exactly once; the msys result line verified char-exact. trp#16 stays
draft — no merge without the owner's go-ahead.

* contract: consume source release v0.3.4 (the sysconfig posix-mode pair)

v0.3.4 (tamatebako/python#19) ports MSYS2 0003 (sys._is_mingw flags) +
0020 (mingw builds take the posix sysconfig path) — the answer to the
first --enable-shared leg's pybuilddir.txt wall (run 34748169561:
KeyError 'LIBPL'; upstream's nt path never merges the Makefile-parsed
build_time_vars). 0034's hunk 3 returns to MSYS2-verbatim context.
Windows-msys asset verified on the release (sha256
d5628491ee94b21dce0c92ba6913342cd68c3f99e7a569428ab16a4278803052).

* contract: consume source release v0.3.5 (the module-libs cluster)

v0.3.5 (tamatebako/python#20) ports MSYS2 0061 + 0073
(_multiprocessing: the win32 enable condition, then -lws2_32), 0074
(select: _MSC_VER → MS_WIN32 guards + -lws2_32), and 0076 (_ctypes:
-lole32 -loleaut32 -luuid) — the answer to the shared-extension link
wall the v0.3.4 leg hit (run 34750005177: undefined __WSAFDIsSet /
__imp_select / __imp_WSAGetLastError at the select.pyd and
_multiprocessing.pyd links; PE resolves every symbol at link time and
upstream's PY_STDLIB_MOD stanzas carry no per-module libs — MSVC gets
them via PCbuild). Windows-msys asset verified on the release (sha256
18f20a10922e55da3ce2213769cccf2db4a732b8898e2c128173051ed7b1f8b3;
the POSIX assets are byte-identical with v0.3.4's).

* contract: consume source release v0.3.6 (the mmap + legacy-DLL trio)

v0.3.6 (tamatebako/python#21) ports MSYS2 0062 (mmap builds on win32 —
its absence killed ensurepip in `make install` on the v0.3.5 leg, run
34753278108: pip's vendored cachecontrol imports mmap), 0067
(PYTHONLEGACYWINDOWSDLLLOADING — the bpo-36085 DEFAULT_DIRS search
never consults PATH, so the build-tree check removed
_decimal/_zstd/_testinternalcapi whose dep DLLs live in
<ucrt64>/bin), and 0064 (have_dynamic_loading for the dlopen-gated
test modules); 0076 returns to MSYS2-verbatim context. Windows-msys
asset verified on the release (sha256
20ec675d03bb3612e4c69026fa723d97cdd323a2faf38a22bee32105236f1c23;
the POSIX assets are byte-identical with v0.3.5's).

* windows-msys: install with prefix=/A/t + stage pip explicitly (round-6)

CPython's install rules spell every destination $(DESTDIR)$(dir) with no
separator; with the baked drive-qualified prefix (A:/t) that concatenates
into one junk component (stage + "A:/t/..." — the failing recipes are
mostly `-`-prefixed, so make exited green over the wreckage and
staged_prefix_tree's "no A/t tree" was the first truth, exit 105 on run
34756006093). The msys install now overrides prefix to the POSIX spelling
/A/t — every install dir var derives unexpanded from $(prefix) (autoconf
convention), so the override flows to every rule — and skips ensurepip:
pip's --root rebase drive-strips the built python's BUILD-TREE prefix,
never the staged one, so its pip landed under <stage>/<build-tree path>.

place_pip stages pip explicitly instead: the bundled wheel's own
installer run into the staged lib/pythonX.Y/site-packages (the series'
0026 site.py branch puts the runtime's site-packages there — verified
against the applied tree), mirroring ensurepip's -c invocation but with
--target deciding placement. The paths ride argv so the msys runtime
translates them for the native exe (a path embedded in the -c payload
crosses verbatim), and --no-compile mirrors ensurepip: .pyc records
written here would spell the stage paths — dead links in the mounted
image.

POSIX legs keep the old recipe exactly (ensurepip still rides the
install). Recorded follow-up: whether ensurepip's --root placement ever
landed pip in the POSIX staged trees either (the build-tree prefix
rebase exists there too) — checked separately, not in this commit.

* ci: spell the provenance exe with .exe on the windows leg (round-7)

msys stat() transparency lets foo.exe satisfy `[ -s foo ]`, so the
step's extensionless-or-.exe dance always kept the extensionless
spelling; the native nm/objdump receive the argument verbatim, get
ENOENT, and the script's discarded stderr read back as a stripped exe
(five failed provenance checks on run 34758424181 — the exe itself was
fine: the same build's place_pip had just run it). The name carries
.exe on this leg by construction (Platform#exe_suffix) — spell it out,
the ruby factory's ruby.exe spelling. The script now also prints nm's
own diagnostic when the symbol-table capture comes back empty, so a
silent nm failure never reads as "stripped" again.

* ci: capture-then-test the disassembly greps (the SIGPIPE false negative)

grep -q exits on its first match; under pipefail the still-writing
printf then dies of SIGPIPE and the pipeline reads 141 — a false
"not found". POSIX legs never noticed: their objdump honors
--disassemble=main tightly (a screenful, under the pipe buffer). A
binutils PE objdump's span runs from the symbol to the next data
island — 4,700 lines on the windows leg — so grep matched early,
printf was killed, and run 34759975017 failed the forwarding check
while its own evidence printout showed main calling
tebako_driver_boot at 140da1789. Same discipline as the nm side
already documented in this script: capture first, then test.

* windows-msys: bare boot pins driver + getpath warnings, not exit status (round-9)

Run 34760958198's windows leg failed the bare scenario on its POSIX
assertions: the child printed 'unreached' and exited 0, with only the
driver warning and getpath's "Could not find platform independent
libraries <prefix>" on stderr.

Mechanism, established against the 3.14.7 sources: the encodings import
at startup is unconditional (pylifecycle.c _PyUnicode_InitEncodings ->
unicodeobject.c _PyCodec_InitRegistry, fatal on failure), so a child
that ran user code necessarily FOUND a stdlib. The channel is upstream:
Modules/getpath.py's winreg section (os_name == 'nt' and
use_environment and winreg) appends the HKCU/HKLM
SOFTWARE\Python\PythonCore\<ver>\PythonPath registry values to sys.path
— and the GHA runner has a registered host python. Bare boot on windows
is therefore environment-dependent by upstream design: exit status and
the encodings fatal are not assertable there.

The msys bare scenario now pins the deterministic surface instead: the
driver's bare-boot warning (ours, every platform) plus getpath's
platstdlib warning (the prefix fell back to the baked-in mount root,
which never exists on the runner). POSIX keeps the strict trio
(non-zero exit + driver warning + encodings fatal) — no registry
fallback exists there.

---------

Co-authored-by: tebako-ci <tebako@ribose.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants