From 7d38a392fa81c500af267369754610887d8c7e3f Mon Sep 17 00:00:00 2001 From: Yilei Yang Date: Tue, 24 Feb 2026 00:21:27 +0000 Subject: [PATCH] Build Python 3.14 free-threaded wheels. --- .github/workflows/ci.yml | 8 ++++++++ setup.py | 14 ++++++++++++-- source/module.c | 4 ++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e319e063..e1f12cb05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,8 @@ jobs: - cp311-cp311 - cp312-cp312 - cp313-cp313 + - cp314-cp314 + - cp314-cp314t permissions: id-token: write # This is required for requesting the JWT steps: @@ -81,6 +83,8 @@ jobs: - cp311-cp311 - cp312-cp312 - cp313-cp313 + - cp314-cp314 + - cp314-cp314t permissions: id-token: write # This is required for requesting the JWT steps: @@ -108,6 +112,8 @@ jobs: - cp311-cp311 - cp312-cp312 - cp313-cp313 + - cp314-cp314 + - cp314-cp314t permissions: id-token: write # This is required for requesting the JWT steps: @@ -133,6 +139,8 @@ jobs: - cp311-cp311 - cp312-cp312 - cp313-cp313 + - cp314-cp314 + - cp314-cp314t permissions: id-token: write # This is required for requesting the JWT steps: diff --git a/setup.py b/setup.py index 68e0f617b..ae00a7829 100644 --- a/setup.py +++ b/setup.py @@ -25,6 +25,9 @@ # sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET'). MACOS_DEPLOYMENT_TARGET_MIN = "10.15" +# True if this is a free-threaded Python build. +FREE_THREADED_BUILD = sysconfig.get_config_var("Py_GIL_DISABLED") + # This is the minimum version of the Windows SDK needed for schannel.h with SCH_CREDENTIALS and # TLS_PARAMETERS. These are required to build Windows Binaries with TLS 1.3 support. WINDOWS_SDK_VERSION_TLS1_3_SUPPORT = "10.0.17763.0" @@ -428,7 +431,10 @@ class bdist_wheel_abi3(bdist_wheel): def get_tag(self): python, abi, plat = super().get_tag() # on CPython, our wheels are abi3 and compatible back to 3.11 - if python.startswith("cp") and sys.version_info >= (3, 13): + # but free-threaded builds don't use limited API, so skip abi3 tag + if FREE_THREADED_BUILD: + return python, abi, plat + elif python.startswith("cp") and sys.version_info >= (3, 13): # 3.13 deprecates PyWeakref_GetObject(), adds alternative return "cp313", "abi3", plat elif python.startswith("cp") and sys.version_info >= (3, 11): @@ -532,7 +538,11 @@ def awscrt_ext(): extra_link_args += ['-Wl,--fatal-warnings'] # prefer building with stable ABI, so a wheel can work with multiple major versions - if sys.version_info >= (3, 13): + if FREE_THREADED_BUILD and sys.version_info[:2] == (3, 14): + # 3.14 free threaded (aka no gil) does not support limited api. + # disable it for now. 3.15 promises to support limited api + free threading combo + py_limited_api = False + elif sys.version_info >= (3, 13): # 3.13 deprecates PyWeakref_GetObject(), adds alternative define_macros.append(('Py_LIMITED_API', '0x030D0000')) py_limited_api = True diff --git a/source/module.c b/source/module.c index dd346747e..2c61da64b 100644 --- a/source/module.c +++ b/source/module.c @@ -1013,6 +1013,10 @@ PyMODINIT_FUNC PyInit__awscrt(void) { return NULL; } +#ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); +#endif + s_init_allocator(); /* Don't report this memory when dumping possible leaks. */