From 70b8dc8e8925dd528ade388fc0ebc4544ba74bd4 Mon Sep 17 00:00:00 2001 From: dwoz <1527763+dwoz@users.noreply.github.com> Date: Tue, 6 Oct 2026 02:28:33 +0000 Subject: [PATCH 1/2] Release 0.22.29 --- CHANGELOG.md | 6 ++++++ relenv/common.py | 2 +- relenv/python-versions.json | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 837b027f..9a2ce082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +0.22.29 +======= + +* Update expat to 2.9.0 + + 0.22.28 ======= diff --git a/relenv/common.py b/relenv/common.py index f1b0381e..5ca9d8b7 100644 --- a/relenv/common.py +++ b/relenv/common.py @@ -27,7 +27,7 @@ from collections.abc import Callable, Iterable, Mapping # relenv package version -__version__ = "0.22.28" +__version__ = "0.22.29" log = logging.getLogger(__name__) diff --git a/relenv/python-versions.json b/relenv/python-versions.json index 774da6af..35ff9fe2 100644 --- a/relenv/python-versions.json +++ b/relenv/python-versions.json @@ -675,6 +675,15 @@ "darwin", "win32" ] + }, + "2.9.0": { + "url": "https://github.com/libexpat/libexpat/releases/download/R_2_9_0/expat-{version}.tar.xz", + "sha256": "1e6371862cc31999b368c3b89b49994f0677e1bab5f1b2b85ae3741f5d803051", + "platforms": [ + "linux", + "darwin", + "win32" + ] } } } From ee60b8c37a5608916d8cf1a4b6a4e4cd227c0be3 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Wed, 7 Oct 2026 14:50:46 -0700 Subject: [PATCH 2/2] Fix pyexpat link failure with expat 2.9.0 expat 2.9.0 extracted xcslen/xcscmp/xcsncmp into a new translation unit (lib/xcs.c), but Python's build system only compiles the three fixed sources xmlparse.c/xmlrole.c/xmltok.c. When relenv's update_expat() drops the raw 2.9.0 tarball sources into Modules/expat/, xcs.c is never compiled and pyexpat.so fails to link with undefined references to the xcs* symbols on every platform. CPython's own refresh.sh handles this upstream by renaming xcs.c to xcsinc.c and including it from xmlparse.c. Mirror that approach: when the dropped-in tarball ships xcs.c, append #include "xcs.c" to xmlparse.c so the symbols land in the TU Python's build already compiles. The existing entropy-source append is left in place, and the new include is gated on xcs.c's presence so expat < 2.9.0 drop-ins continue to work unchanged. --- relenv/build/darwin.py | 6 ++++++ relenv/build/linux.py | 6 ++++++ relenv/build/windows.py | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/relenv/build/darwin.py b/relenv/build/darwin.py index c35fb80f..228ac22f 100644 --- a/relenv/build/darwin.py +++ b/relenv/build/darwin.py @@ -119,6 +119,12 @@ def update_expat(dirs: Dirs, env: MutableMapping[str, str]) -> None: f.write('#if defined(HAVE_ARC4RANDOM_BUF)\n#include "random_arc4random_buf.c"\n#endif\n') f.write('#if defined(HAVE_ARC4RANDOM)\n#include "random_arc4random.c"\n#endif\n') f.write('#if !defined(_WIN32) && defined(XML_DEV_URANDOM)\n#include "random_dev_urandom.c"\n#endif\n') + # expat >= 2.9.0 moved xcslen/xcscmp/xcsncmp into a separate TU + # (xcs.c). Python's build system only compiles xmlparse.c, + # xmlrole.c, and xmltok.c, so pull xcs.c into xmlparse.c's TU to + # avoid undefined-reference failures when linking pyexpat. + if (expat_dir / "xcs.c").exists(): + f.write('#include "xcs.c"\n') # Update SBOM with correct checksums for updated expat files files_to_update = {} diff --git a/relenv/build/linux.py b/relenv/build/linux.py index 62b10c9d..775b8326 100644 --- a/relenv/build/linux.py +++ b/relenv/build/linux.py @@ -476,6 +476,12 @@ def update_expat(dirs: Dirs, env: EnvMapping) -> None: f.write('#if defined(HAVE_ARC4RANDOM_BUF)\n#include "random_arc4random_buf.c"\n#endif\n') f.write('#if defined(HAVE_ARC4RANDOM)\n#include "random_arc4random.c"\n#endif\n') f.write('#if !defined(_WIN32) && defined(XML_DEV_URANDOM)\n#include "random_dev_urandom.c"\n#endif\n') + # expat >= 2.9.0 moved xcslen/xcscmp/xcsncmp into a separate TU + # (xcs.c). Python's build system only compiles xmlparse.c, + # xmlrole.c, and xmltok.c, so pull xcs.c into xmlparse.c's TU to + # avoid undefined-reference failures when linking pyexpat. + if (expat_dir / "xcs.c").exists(): + f.write('#include "xcs.c"\n') # Update SBOM with correct checksums for updated expat files files_to_update = {} diff --git a/relenv/build/windows.py b/relenv/build/windows.py index 1a916b57..dd2b7ce6 100644 --- a/relenv/build/windows.py +++ b/relenv/build/windows.py @@ -446,6 +446,12 @@ def update_expat(dirs: Dirs, env: EnvMapping) -> None: f.write('#if defined(HAVE_ARC4RANDOM_BUF)\n#include "random_arc4random_buf.c"\n#endif\n') f.write('#if defined(HAVE_ARC4RANDOM)\n#include "random_arc4random.c"\n#endif\n') f.write('#if !defined(_WIN32) && defined(XML_DEV_URANDOM)\n#include "random_dev_urandom.c"\n#endif\n') + # expat >= 2.9.0 moved xcslen/xcscmp/xcsncmp into a separate TU + # (xcs.c). Python's build system only compiles xmlparse.c, + # xmlrole.c, and xmltok.c, so pull xcs.c into xmlparse.c's TU to + # avoid undefined-reference failures when linking pyexpat. + if (expat_dir / "xcs.c").exists(): + f.write('#include "xcs.c"\n') # Update SBOM with correct checksums for updated expat files files_to_update = {f"Modules/expat/{f.name}": f for f in updated_files}