From 91e40440189b03f38a1e96c9d47239db176ed0e8 Mon Sep 17 00:00:00 2001 From: "Jonathan J. Helmus" Date: Thu, 15 Oct 2026 12:24:32 -0500 Subject: [PATCH 1/4] Switch to util-linux libuuid, version 2.42 * libuuid: 1.0.3 ->2.42.4 Switch to building libuuid from the util-linux project. This project is active where as the sourceforge project has not been updated in 2014. Set configuration options (--local-state-dir, --enabled-libuuid-force-uuidd) so that UUID generation has a high likelyhood of being generated in a multiprocessing-safe manner. This cannot be ensured it depends on run-time settings on the host system. --- LICENSE.libuuid.txt | 6 +++++- cpython-unix/build-uuid.sh | 28 +++++++++++++++++++++++----- pythonbuild/disttests/__init__.py | 13 +++++++++++++ pythonbuild/downloads.json | 8 ++++---- scripts/update_downloads.py | 27 ++++++++++++++++++++++++++- 5 files changed, 71 insertions(+), 11 deletions(-) diff --git a/LICENSE.libuuid.txt b/LICENSE.libuuid.txt index ec87a77f1..be748a370 100644 --- a/LICENSE.libuuid.txt +++ b/LICENSE.libuuid.txt @@ -1,4 +1,5 @@ -Copyright (C) 1996, 1997 Theodore Ts'o. +Copyright (C) 1996, 1997, 1998, 1999, 2007 Theodore Ts'o. +Copyright (C) 2017 Philip Prindeville. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -25,3 +26,6 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +libuuid also includes MD5 code written by Colin Plumb and SHA-1 code written +by Steve Reid, which their authors placed in the public domain. diff --git a/cpython-unix/build-uuid.sh b/cpython-unix/build-uuid.sh index b3f185fd6..69c1a58bf 100755 --- a/cpython-unix/build-uuid.sh +++ b/cpython-unix/build-uuid.sh @@ -9,19 +9,37 @@ ROOT=$(pwd) export PATH=${TOOLS_PATH}/${TOOLCHAIN}/bin:${TOOLS_PATH}/host/bin:$PATH -tar -xf "libuuid-${UUID_VERSION}.tar.gz" -pushd "libuuid-${UUID_VERSION}" +tar -xf "util-linux-${UUID_VERSION}.tar.xz" +pushd "util-linux-${UUID_VERSION}" CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" -# Error by default in Clang 16. -CFLAGS="${CFLAGS} -Wno-error=implicit-function-declaration" +UUID_CONFIGURE_FLAGS=() +if [[ "${TARGET_TRIPLE}" == *-linux-* ]]; then + UUID_CONFIGURE_FLAGS+=(--enable-libuuid-force-uuidd) +fi CFLAGS="${CFLAGS}" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \ --build="${BUILD_TRIPLE}" \ --host="${TARGET_TRIPLE}" \ --prefix=/tools/deps \ - --disable-shared + --localstatedir=/var \ + --libdir=/tools/deps/lib \ + --disable-all-programs \ + --enable-libuuid \ + --disable-libblkid \ + --disable-libfdisk \ + --disable-liblastlog2 \ + --disable-libmount \ + --disable-libsmartcols \ + --disable-nls \ + --disable-asciidoc \ + --disable-dependency-tracking \ + --without-python \ + --without-systemd \ + --disable-shared \ + --enable-static \ + "${UUID_CONFIGURE_FLAGS[@]}" make -j "${NUM_CPUS}" make -j "${NUM_CPUS}" install DESTDIR="${ROOT}/out" diff --git a/pythonbuild/disttests/__init__.py b/pythonbuild/disttests/__init__.py index 7df8abb94..5e8c85424 100644 --- a/pythonbuild/disttests/__init__.py +++ b/pythonbuild/disttests/__init__.py @@ -45,6 +45,19 @@ class TestPythonInterpreter(unittest.TestCase): + @unittest.skipUnless( + sys.platform in ("darwin", "linux"), "bundled libuuid is used on Unix" + ) + def test_uuid_generate_time_safe(self): + import _uuid + import uuid + + self.assertTrue(_uuid.has_uuid_generate_time_safe) + data, status = _uuid.generate_time_safe() + self.assertEqual(uuid.UUID(bytes=data).version, 1) + self.assertIn(status, (0, -1)) + self.assertIn(uuid.uuid1().is_safe, (uuid.SafeUUID.safe, uuid.SafeUUID.unsafe)) + @unittest.skipUnless(os.name == "nt", "Windows executable names") def test_windows_executables(self): build_options = os.environ["BUILD_OPTIONS"].split("+") diff --git a/pythonbuild/downloads.json b/pythonbuild/downloads.json index 393722093..1d5d41d77 100644 --- a/pythonbuild/downloads.json +++ b/pythonbuild/downloads.json @@ -427,10 +427,10 @@ "license_file": "LICENSE.tcl.txt" }, "uuid": { - "url": "https://sourceforge.net/projects/libuuid/files/libuuid-1.0.3.tar.gz", - "size": 318256, - "sha256": "46af3275291091009ad7f1b899de3d0cea0252737550e7919d17237997db5644", - "version": "1.0.3", + "url": "https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.42/util-linux-2.42.4.tar.xz", + "size": 10729748, + "sha256": "fbd62a100ab7bb8746ba0661255c3c48185b1e9021507c624da01fbc696330ec", + "version": "2.42.4", "library_names": [ "uuid" ], diff --git a/scripts/update_downloads.py b/scripts/update_downloads.py index e408a4e38..99f45d3ba 100644 --- a/scripts/update_downloads.py +++ b/scripts/update_downloads.py @@ -169,6 +169,31 @@ def releases(self, client: HttpClient) -> Iterable[Release]: yield Release(version, url) +@dataclasses.dataclass(frozen=True) +class UtilLinuxDiscovery: + """Find stable util-linux tarballs in the newest release series.""" + + index_url: str = "https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/" + + def releases(self, client: HttpClient) -> Iterable[Release]: + series = HtmlDiscovery( + self.index_url, r"^v(?P[0-9]+\.[0-9]+)/$" + ).releases(client) + for release in sorted( + series, key=lambda item: Version(item.version), reverse=True + ): + files = list( + HtmlDiscovery( + release.url, + rf"^util-linux-(?P{re.escape(release.version)}" + r"(?:\.[0-9]+)?)\.tar\.xz$", + ).releases(client) + ) + if files: + yield from files + return + + @dataclasses.dataclass(frozen=True) class GitHubReleaseDiscovery: """Discover release artifacts using the GitHub releases API.""" @@ -394,6 +419,7 @@ def xorg_policy(category: str, name: str, extension: str = "tar.gz") -> Policy: artifact_url="https://prdownloads.sourceforge.net/tcl/tk{version}-src.tar.gz", series=2, ), + "uuid": Policy(UtilLinuxDiscovery()), "x11-util-macros": xorg_policy("util", "util-macros"), "xcb-proto": html_policy( "https://xcb.freedesktop.org/dist/", @@ -428,7 +454,6 @@ def xorg_policy(category: str, name: str, extension: str = "tar.gz") -> Policy: "tix": "source dependency snapshot", "tk-windows-bin-904": "commit-pinned CPython binary dependency", "tk-windows-bin-8615": "commit-pinned CPython binary dependency", - "uuid": "inactive upstream project", "zlib-ng": "CPython source-deps snapshot must follow the upstream release", "zstd": "CPython source-deps snapshot must follow the upstream release", } From 33cac97c2540bcf9ec2d243db4c61d3bf519ffef Mon Sep 17 00:00:00 2001 From: "Jonathan J. Helmus" Date: Fri, 16 Oct 2026 16:11:43 -0500 Subject: [PATCH 2/4] disable check for linux headers on musl --- cpython-unix/build-uuid.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cpython-unix/build-uuid.sh b/cpython-unix/build-uuid.sh index 69c1a58bf..ff48a26ea 100755 --- a/cpython-unix/build-uuid.sh +++ b/cpython-unix/build-uuid.sh @@ -19,6 +19,13 @@ if [[ "${TARGET_TRIPLE}" == *-linux-* ]]; then UUID_CONFIGURE_FLAGS+=(--enable-libuuid-force-uuidd) fi +# The util-linux configure script requires Linux headers globally, but libuuid +# does not use linux/version.h. Keep HAVE_LINUX_VERSION_H undefined while +# bypassing that check for musl; recheck this when updating util-linux. +if [[ "${TARGET_TRIPLE}" == *-linux-musl* ]]; then + export ac_cv_header_linux_version_h=unknown +fi + CFLAGS="${CFLAGS}" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \ --build="${BUILD_TRIPLE}" \ --host="${TARGET_TRIPLE}" \ From ff62499f8aec0ee3233ef00f88d368a239852e8c Mon Sep 17 00:00:00 2001 From: "Jonathan J. Helmus" Date: Fri, 16 Oct 2026 16:32:06 -0500 Subject: [PATCH 3/4] disable year2038 for armv7 --- cpython-unix/build-uuid.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpython-unix/build-uuid.sh b/cpython-unix/build-uuid.sh index ff48a26ea..f50f92243 100755 --- a/cpython-unix/build-uuid.sh +++ b/cpython-unix/build-uuid.sh @@ -19,6 +19,14 @@ if [[ "${TARGET_TRIPLE}" == *-linux-* ]]; then UUID_CONFIGURE_FLAGS+=(--enable-libuuid-force-uuidd) fi +# The ARMv7 GNU toolchains use glibc with 32-bit time_t. Keep the existing +# compatibility baseline even though timestamps after 2038 are not supported. +case "${TARGET_TRIPLE}" in + armv7-unknown-linux-gnueabi|armv7-unknown-linux-gnueabihf) + UUID_CONFIGURE_FLAGS+=(--disable-year2038) + ;; +esac + # The util-linux configure script requires Linux headers globally, but libuuid # does not use linux/version.h. Keep HAVE_LINUX_VERSION_H undefined while # bypassing that check for musl; recheck this when updating util-linux. From 5ee2eef9b821ed414196b2b9d80974810ff28890 Mon Sep 17 00:00:00 2001 From: "Jonathan J. Helmus" Date: Fri, 16 Oct 2026 16:39:54 -0500 Subject: [PATCH 4/4] lint --- pythonbuild/disttests/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonbuild/disttests/__init__.py b/pythonbuild/disttests/__init__.py index 5e8c85424..2061e0c10 100644 --- a/pythonbuild/disttests/__init__.py +++ b/pythonbuild/disttests/__init__.py @@ -49,7 +49,7 @@ class TestPythonInterpreter(unittest.TestCase): sys.platform in ("darwin", "linux"), "bundled libuuid is used on Unix" ) def test_uuid_generate_time_safe(self): - import _uuid + import _uuid # type: ignore import uuid self.assertTrue(_uuid.has_uuid_generate_time_safe)