Skip to content

Use standard extension configuration for CPython 3.12+ - #1180

Merged
jjhelmus merged 25 commits into
mainfrom
jjh/standard_mod_config_312
Aug 20, 2026
Merged

Use standard extension configuration for CPython 3.12+#1180
jjhelmus merged 25 commits into
mainfrom
jjh/standard_mod_config_312

Conversation

@jjhelmus

@jjhelmus jjhelmus commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Switch CPython 3.12+ builds to the upstream Setup.stdlib extension-building mechanism while preserving the existing static/shared linkage behavior.

  • Build pkgconf on macOS so that bundled dependencies can be discovered and configured.
  • Generate a minimal Setup.local for shared and disabled overrides on CPython 3.12+.
  • Restore CPython’s post-build extension checks and remove obsolete patches/workarounds.
  • Preserve SQLite extension loading and macOS symbol hiding.
  • Explicitly disable the clinic test and xxlimited_3_13 extensions. c.f. Enable _testclinic, _testclinic_limited and xxlimited_3_13 #1185

With this change, extension-modules.yml is still used for the following in CPython 3.12:

  • Disabling modules
  • Specifying static vs shared linkage
  • Validating the extension modules specified in the CPython source archive.
  • Constructing PYTHON.json

Constructing PYTHON.json for CPython 3.12+ from other sources is a needed follow up.

Makes various patches unnecessary:

Configuration can now appropriately detect SIMD support in the toolchain and adjusts libhacl flags accordingly.

This does not add shared extension suggested in #227. This could be done with a small change as a follow up.

@jjhelmus
jjhelmus force-pushed the jjh/standard_mod_config_312 branch from 2bc109e to 059aed0 Compare July 21, 2026 15:03
Comment thread src/validation.rs Outdated
Configure pkgconf to report the temporary directories of the prefix that
is used on macOS during CPython builds.
Build standard-library extensions through CPython's configure and
Setup.stdlib mechanism for Python 3.12 and newer.
Default to statically linking these modules into libpython/python with a
few overrides speficied in a Setup.local file created from
extension-modules.yaml.

This allows CPython's extension checks to run.

Python 3.11 and 3.10 contrinue to use the existing process to configure
and build extension modules.
Configuration correctly detect the SIMD support in the toolchain and
applies the appropiate flags when building libhacl.
@jjhelmus

jjhelmus commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

With MODULE_BUILDTYPE=static set CPython 3.12+ still builds a handful of extensions modules as shared, specifically:

  • _ctypes_test
  • _testimportmultiple
  • _testmultiphase
  • _testsinglephase
  • xxlimited
  • xxlimited_35
  • xxlimited_3_13

Using the custom configuration the last three of these are disabled and not built. The first four are build as shared modules except for static builds where they are statically linked. Because of the behavior of Setup.stdlib.in theses three need to be included in Setup.local to restore the static linkage. This should be revisited as disabling these in the static builds may be more prudent.

The existing behavior for 3.10 and 3.11 is to include a shared module, #1222 which is retained.
No shared modules are included in 3.12+ which is replicated here and validated.

…stdlib.in

A handful of modules are marked as always building shared which causes
these to be built as shared modules in the static builds.
@jjhelmus
jjhelmus force-pushed the jjh/standard_mod_config_312 branch from 5bcf925 to a77eb2c Compare August 18, 2026 18:32
@jjhelmus
jjhelmus requested a review from EliteTK August 18, 2026 20:19
@jjhelmus

Copy link
Copy Markdown
Contributor Author

This is ready for a review.

There is follow up work to construct PYTHON.json from source artifacts rather than from extension-modules.yml for 3.12+ as the yaml file is no longer the source of truth.

This could be done in this PR, in a stacked PR, or as a fast follow. I'd prefer merging this and following with another PR to avoid a long running branch. The work for building PYTHON.json without the yaml file is straightforward but benefits from refactoring the long derive_setup_local function for clarity.

Comment on lines -644 to -649
# ./configure tries to auto-detect whether it can build 128-bit and 256-bit SIMD helpers for HACL,
# but on x86-64 that requires v2 and v3 respectively, and on arm64 the performance is bad as noted
# in the comments, so just don't even try. (We should check if we can make this conditional)
if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then
patch -p1 -i "${ROOT}/patch-python-configure-hacl-no-simd.patch"
fi

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this resolved?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Portions of this comment are incorrect, the behavior of configure is safe.

The check that configure performs is to determine if the compiler supports the necessary flags (-msse, -mavx2, etc) to allow the SIMD helpers to be built.

On Linux x86-64 these flags are supported by LLVM so the helpers are built:

cpython-3.14> checking whether C compiler accepts -msse -msse2 -msse3 -msse4.1 -msse4.2...
cpython-3.14> yes
cpython-3.14> checking for HACL* SIMD128 implementation...
cpython-3.14> standard
cpython-3.14> checking whether C compiler accepts -mavx2...
cpython-3.14> yes
cpython-3.14> checking for HACL* SIMD256 implementation...
cpython-3.14> standard

A runtime check is performed before dispatching to these function, the availability of these helpers does not change the baseline x86-64 requirement.

On macOS arm64 the check fails and the SIMD helpers are not built:

cpython-3.14> checking whether C compiler accepts -msse -msse2 -msse3 -msse4.1 -msse4.2... no
cpython-3.14> checking whether C compiler accepts -mavx2... no

On macOS x86-64 the check succeeds and the universal2 versions of the SIMD helpers are built. The universal2 wrapper prevents the SIMD implementations from being included when building the arm64 portion of the universal2 library but this never comes into play because only the x86-64 portion of the library is built.

cpython-3.14> checking whether C compiler accepts -msse -msse2 -msse3 -msse4.1 -msse4.2... yes
cpython-3.14> checking for HACL* SIMD128 implementation... universal2
cpython-3.14> checking whether C compiler accepts -mavx2... yes
cpython-3.14> checking for HACL* SIMD256 implementation... universal2

The runtime check is done so these helpers are only used when the host indicates support. When running on native x86-64 hardware this depends on the host CPU. When running on Apple Silicon under Rosetta2, the behavior depends on what features Rosetta advertises. The performance is intended by upstream and can be optimized by the user by using to the build that matches the host architecture.

Comment on lines -1115 to -1116
# See https://github.com/python/cpython/issues/145810#issuecomment-4068139183
replace_in_all("-LModules/_hacl", "")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This flag is no longer being added to LDFLAGS (see the removal of lines 388-394) so it no longer leaks into sysconfig.

@jjhelmus jjhelmus Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For verification I checked the cpython-3.14-x86_64-unknown-linux-gnu-pgo+lto artifact:

❯ unzip cpython-3.14-x86_64-unknown-linux-gnu-pgo+lto.zip
...
❯ tar xf cpython-3.14.7-x86_64-unknown-linux-gnu-pgo+lto-20260818T1407.tar.zst
❯ cd python/install
❯ rg LModules/_hacl

❯

The pattern that used to be replaced does not appear in sysconfig or elsewhere.

Comment thread cpython-unix/build-tcl.sh Outdated
# CPython uses the macOS SDK's zlib without a zlib.pc file. Keep the -lz in
# Libs.private, but do not make pkg-config require the missing metadata.
if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
sed -i '' -e 's/ zlib >= 1.2.3//' tcl.pc.in

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be using a patch here instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be accomplished by a patch but I think that setting TCLTK_CFLAGS and TCLTK_LIBS when building CPython on macOS is cleaner. That approach makes this change unnecessary, matches how CPython's macOS installer builds _tkinter and removes the need for pkgconfig entirely.

@jjhelmus jjhelmus Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not remove the need for pkgconfig, it is still used to find other libraries such as libffi. Directly configuring Tcl/Tk on macOS could be done or pkgconfig can be used with this patch. There are tradeoffs with both options but I'm going to go with patching the pkgconfig file here so that no change is needed when upgrading Tcl/Tk versions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now done via an inline patch.

Comment thread cpython-unix/build-tk.sh Outdated
Comment on lines +36 to +37
sed -i '/^Requires: /a\
Requires.private: x11' tk.pc.in

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now done via an inline patch.

@jjhelmus
jjhelmus requested a review from zanieb August 19, 2026 20:43
@jjhelmus
jjhelmus merged commit 5b84e8e into main Aug 20, 2026
257 checks passed
@jjhelmus
jjhelmus deleted the jjh/standard_mod_config_312 branch August 20, 2026 13:40
@jjhelmus

Copy link
Copy Markdown
Contributor Author

Reported the missing Libs.private in tk.pc.in upstream, https://core.tcl-lang.org/tk/tktview/3e5d09f0e49755b2c6d9a7a5b94c990968bb9734

The modification to tcl.pc.in is specific to the use case of using the macOS SDK which does not provide pkg-config files. As such this does not warrant a report upstream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch:all Select all architectures platform:darwin Specific to the macOS platform platform:linux Specific to the Linux platform python:3.10 python:3.11 python:3.12 python:3.14

Projects

None yet

2 participants