@@ -345,6 +345,7 @@ def hack_props(
345345 td : pathlib .Path ,
346346 pcbuild_path : pathlib .Path ,
347347 arch : str ,
348+ python_version : str ,
348349):
349350 # TODO can we pass props into msbuild.exe?
350351
@@ -355,9 +356,14 @@ def hack_props(
355356 sqlite_version = DOWNLOADS ["sqlite" ]["version" ]
356357 xz_version = DOWNLOADS ["xz" ]["version" ]
357358 zlib_version = DOWNLOADS ["zlib" ]["version" ]
358- tcltk_commit = DOWNLOADS [ "tk-windows-bin-8612" ][ "git_commit" ]
359+
359360 mpdecimal_version = DOWNLOADS ["mpdecimal" ]["version" ]
360361
362+ if meets_python_minimum_version (python_version , "3.14" ):
363+ tcltk_commit = DOWNLOADS ["tk-windows-bin" ]["git_commit" ]
364+ else :
365+ tcltk_commit = DOWNLOADS ["tk-windows-bin-8612" ]["git_commit" ]
366+
361367 sqlite_path = td / ("sqlite-autoconf-%s" % sqlite_version )
362368 bzip2_path = td / ("bzip2-%s" % bzip2_version )
363369 libffi_path = td / "libffi"
@@ -487,6 +493,7 @@ def hack_project_files(
487493 td ,
488494 pcbuild_path ,
489495 build_directory ,
496+ python_version ,
490497 )
491498
492499 # Our SQLite directory is named weirdly. This throws off version detection
@@ -566,9 +573,13 @@ def hack_project_files(
566573 rb'<ClCompile Include="$(opensslIncludeDir)\openssl\applink.c">' ,
567574 )
568575
569- # We're still on the pre-built tk-windows-bin 8.6.12 which doesn't have a
570- # standalone zlib DLL. So remove references to it from 3.12+.
571- if meets_python_minimum_version (python_version , "3.12" ):
576+ # Python 3.12+ uses the the pre-built tk-windows-bin 8.6.12 which doesn't
577+ # have a standalone zlib DLL, so we remove references to it. For Python
578+ # 3.14+, we're using tk-windows-bin 8.6.14 which includes a prebuilt zlib
579+ # DLL, so we skip this patch there.
580+ if meets_python_minimum_version (
581+ python_version , "3.12"
582+ ) and meets_python_maximum_version (python_version , "3.13" ):
572583 static_replace_in_file (
573584 pcbuild_path / "_tkinter.vcxproj" ,
574585 rb'<_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDllName)" />' ,
@@ -1127,6 +1138,10 @@ def find_additional_dependencies(project: pathlib.Path):
11271138 if name == "openssl" :
11281139 name = openssl_entry
11291140
1141+ # On 3.14+, we use the latest tcl/tk version
1142+ if ext == "_tkinter" and python_majmin == "314" :
1143+ name = name .replace ("-8612" , "" )
1144+
11301145 download_entry = DOWNLOADS [name ]
11311146
11321147 # This will raise if no license metadata defined. This is
@@ -1196,9 +1211,6 @@ def build_cpython(
11961211
11971212 bzip2_archive = download_entry ("bzip2" , BUILD )
11981213 sqlite_archive = download_entry ("sqlite" , BUILD )
1199- tk_bin_archive = download_entry (
1200- "tk-windows-bin-8612" , BUILD , local_name = "tk-windows-bin.tar.gz"
1201- )
12021214 xz_archive = download_entry ("xz" , BUILD )
12031215 zlib_archive = download_entry ("zlib" , BUILD )
12041216
@@ -1210,6 +1222,17 @@ def build_cpython(
12101222 setuptools_wheel = download_entry ("setuptools" , BUILD )
12111223 pip_wheel = download_entry ("pip" , BUILD )
12121224
1225+ # On CPython 3.14+, we use the latest tcl/tk version which has additional runtime
1226+ # dependencies, so we are conservative and use the old version elsewhere.
1227+ if meets_python_minimum_version (python_version , "3.14" ):
1228+ tk_bin_archive = download_entry (
1229+ "tk-windows-bin" , BUILD , local_name = "tk-windows-bin.tar.gz"
1230+ )
1231+ else :
1232+ tk_bin_archive = download_entry (
1233+ "tk-windows-bin-8612" , BUILD , local_name = "tk-windows-bin.tar.gz"
1234+ )
1235+
12131236 # CPython 3.13+ no longer uses a bundled `mpdecimal` version so we build it
12141237 if meets_python_minimum_version (python_version , "3.13" ):
12151238 mpdecimal_archive = download_entry ("mpdecimal" , BUILD )
@@ -1690,6 +1713,7 @@ def main() -> None:
16901713 "cpython-3.11" ,
16911714 "cpython-3.12" ,
16921715 "cpython-3.13" ,
1716+ "cpython-3.14" ,
16931717 },
16941718 default = "cpython-3.11" ,
16951719 help = "Python distribution to build" ,
0 commit comments