@@ -370,7 +370,7 @@ def hack_props(
370
370
371
371
mpdecimal_version = DOWNLOADS ["mpdecimal" ]["version" ]
372
372
373
- if meets_python_minimum_version (python_version , "3.14" ):
373
+ if meets_python_minimum_version (python_version , "3.14" ) or arch == "arm64" :
374
374
tcltk_commit = DOWNLOADS ["tk-windows-bin" ]["git_commit" ]
375
375
else :
376
376
tcltk_commit = DOWNLOADS ["tk-windows-bin-8612" ]["git_commit" ]
@@ -464,6 +464,8 @@ def hack_props(
464
464
suffix = b"-x64"
465
465
elif arch == "win32" :
466
466
suffix = b""
467
+ elif arch == "arm64" :
468
+ suffix = b""
467
469
else :
468
470
raise Exception ("unhandled architecture: %s" % arch )
469
471
@@ -505,6 +507,7 @@ def hack_project_files(
505
507
build_directory : str ,
506
508
python_version : str ,
507
509
zlib_entry : str ,
510
+ arch : str ,
508
511
):
509
512
"""Hacks Visual Studio project files to work with our build."""
510
513
@@ -518,6 +521,17 @@ def hack_project_files(
518
521
zlib_entry ,
519
522
)
520
523
524
+ # `--include-tcltk` is forced off on arm64, undo that
525
+ # See https://github.com/python/cpython/pull/132650
526
+ try :
527
+ static_replace_in_file (
528
+ cpython_source_path / "PC" / "layout" / "main.py" ,
529
+ rb'if ns.arch in ("arm32", "arm64"):' ,
530
+ rb'if ns.arch == "arm32":' ,
531
+ )
532
+ except NoSearchStringError :
533
+ pass
534
+
521
535
# Our SQLite directory is named weirdly. This throws off version detection
522
536
# in the project file. Replace the parsing logic with a static string.
523
537
sqlite3_version = DOWNLOADS ["sqlite" ]["actual_version" ].encode ("ascii" )
@@ -603,14 +617,18 @@ def hack_project_files(
603
617
# have a standalone zlib DLL, so we remove references to it. For Python
604
618
# 3.14+, we're using tk-windows-bin 8.6.14 which includes a prebuilt zlib
605
619
# DLL, so we skip this patch there.
606
- if meets_python_minimum_version (
607
- python_version , "3.12"
608
- ) and meets_python_maximum_version (python_version , "3.13" ):
609
- static_replace_in_file (
610
- pcbuild_path / "_tkinter.vcxproj" ,
611
- rb'<_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDllName)" />' ,
612
- rb"" ,
613
- )
620
+ # On arm64, we use the new version of tk-windows-bin for all versions.
621
+ if meets_python_minimum_version (python_version , "3.12" ) and (
622
+ meets_python_maximum_version (python_version , "3.13" ) or arch == "arm64"
623
+ ):
624
+ try :
625
+ static_replace_in_file (
626
+ pcbuild_path / "_tkinter.vcxproj" ,
627
+ rb'<_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDllName)" />' ,
628
+ rb"" ,
629
+ )
630
+ except NoSearchStringError :
631
+ pass
614
632
615
633
# We don't need to produce python_uwp.exe and its *w variant. Or the
616
634
# python3.dll, pyshellext, or pylauncher.
@@ -730,9 +748,11 @@ def build_openssl_for_arch(
730
748
elif arch == "amd64" :
731
749
configure = "VC-WIN64A"
732
750
prefix = "64"
751
+ elif arch == "arm64" :
752
+ configure = "VC-WIN64-ARM"
753
+ prefix = "arm64"
733
754
else :
734
- print ("invalid architecture: %s" % arch )
735
- sys .exit (1 )
755
+ raise Exception ("unhandled architecture: %s" % arch )
736
756
737
757
# The official CPython OpenSSL builds hack ms/uplink.c to change the
738
758
# ``GetModuleHandle(NULL)`` invocation to load things from _ssl.pyd
@@ -780,6 +800,12 @@ def build_openssl_for_arch(
780
800
log ("copying %s to %s" % (source , dest ))
781
801
shutil .copyfile (source , dest )
782
802
803
+ # Copy `applink.c` to the include directory.
804
+ source_applink = source_root / "ms" / "applink.c"
805
+ dest_applink = install_root / "include" / "openssl" / "applink.c"
806
+ log ("copying %s to %s" % (source_applink , dest_applink ))
807
+ shutil .copyfile (source_applink , dest_applink )
808
+
783
809
784
810
def build_openssl (
785
811
entry : str ,
@@ -801,6 +827,7 @@ def build_openssl(
801
827
802
828
root_32 = td / "x86"
803
829
root_64 = td / "x64"
830
+ root_arm64 = td / "arm64"
804
831
805
832
if arch == "x86" :
806
833
root_32 .mkdir ()
@@ -824,13 +851,28 @@ def build_openssl(
824
851
root_64 ,
825
852
jom_archive = jom_archive ,
826
853
)
854
+ elif arch == "arm64" :
855
+ root_arm64 .mkdir ()
856
+ build_openssl_for_arch (
857
+ perl_path ,
858
+ "arm64" ,
859
+ openssl_archive ,
860
+ openssl_version ,
861
+ nasm_archive ,
862
+ root_arm64 ,
863
+ jom_archive = jom_archive ,
864
+ )
827
865
else :
828
- raise ValueError ("unhandled arch : %s" % arch )
866
+ raise Exception ("unhandled architecture : %s" % arch )
829
867
830
868
install = td / "out"
831
869
832
870
if arch == "x86" :
833
871
shutil .copytree (root_32 / "install" / "32" , install / "openssl" / "win32" )
872
+ elif arch == "arm64" :
873
+ shutil .copytree (
874
+ root_arm64 / "install" / "arm64" , install / "openssl" / "arm64"
875
+ )
834
876
else :
835
877
shutil .copytree (root_64 / "install" / "64" , install / "openssl" / "amd64" )
836
878
@@ -901,9 +943,14 @@ def build_libffi(
901
943
if arch == "x86" :
902
944
args .append ("-x86" )
903
945
artifacts_path = ffi_source_path / "i686-pc-cygwin"
904
- else :
946
+ elif arch == "arm64" :
947
+ args .append ("-arm64" )
948
+ artifacts_path = ffi_source_path / "aarch64-w64-cygwin"
949
+ elif arch == "amd64" :
905
950
args .append ("-x64" )
906
951
artifacts_path = ffi_source_path / "x86_64-w64-cygwin"
952
+ else :
953
+ raise Exception ("unhandled architecture: %s" % arch )
907
954
908
955
subprocess .run (args , env = env , check = True )
909
956
@@ -1069,8 +1116,10 @@ def find_additional_dependencies(project: pathlib.Path):
1069
1116
abi_platform = "win_amd64"
1070
1117
elif arch == "win32" :
1071
1118
abi_platform = "win32"
1119
+ elif arch == "arm64" :
1120
+ abi_platform = "win_arm64"
1072
1121
else :
1073
- raise ValueError ("unhandled arch : %s" % arch )
1122
+ raise Exception ("unhandled architecture : %s" % arch )
1074
1123
1075
1124
if freethreaded :
1076
1125
abi_tag = ".cp%st-%s" % (python_majmin , abi_platform )
@@ -1171,8 +1220,8 @@ def find_additional_dependencies(project: pathlib.Path):
1171
1220
if name == "zlib" :
1172
1221
name = zlib_entry
1173
1222
1174
- # On 3.14+, we use the latest tcl/tk version
1175
- if ext == "_tkinter" and python_majmin == "314" :
1223
+ # On 3.14+ and aarch64 , we use the latest tcl/tk version
1224
+ if ext == "_tkinter" and ( python_majmin == "314" or arch == "arm64" ) :
1176
1225
name = name .replace ("-8612" , "" )
1177
1226
1178
1227
download_entry = DOWNLOADS [name ]
@@ -1258,16 +1307,18 @@ def build_cpython(
1258
1307
setuptools_wheel = download_entry ("setuptools" , BUILD )
1259
1308
pip_wheel = download_entry ("pip" , BUILD )
1260
1309
1261
- # On CPython 3.14+, we use the latest tcl/tk version which has additional runtime
1262
- # dependencies, so we are conservative and use the old version elsewhere.
1263
- if meets_python_minimum_version (python_version , "3.14" ):
1264
- tk_bin_archive = download_entry (
1265
- "tk-windows-bin" , BUILD , local_name = "tk-windows-bin.tar.gz"
1266
- )
1267
- else :
1268
- tk_bin_archive = download_entry (
1269
- "tk-windows-bin-8612" , BUILD , local_name = "tk-windows-bin.tar.gz"
1270
- )
1310
+ # On CPython 3.14+, we use the latest tcl/tk version which has additional
1311
+ # runtime dependencies, so we are conservative and use the old version
1312
+ # elsewhere. The old version isn't built for arm64, so we use the new
1313
+ # version there too
1314
+ tk_bin_entry = (
1315
+ "tk-windows-bin"
1316
+ if meets_python_minimum_version (python_version , "3.14" ) or arch == "arm64"
1317
+ else "tk-windows-bin-8612"
1318
+ )
1319
+ tk_bin_archive = download_entry (
1320
+ tk_bin_entry , BUILD , local_name = "tk-windows-bin.tar.gz"
1321
+ )
1271
1322
1272
1323
# On CPython 3.14+, zstd is included
1273
1324
if meets_python_minimum_version (python_version , "3.14" ):
@@ -1297,8 +1348,11 @@ def build_cpython(
1297
1348
elif arch == "x86" :
1298
1349
build_platform = "win32"
1299
1350
build_directory = "win32"
1351
+ elif arch == "arm64" :
1352
+ build_platform = "arm64"
1353
+ build_directory = "arm64"
1300
1354
else :
1301
- raise ValueError ("unhandled arch : %s" % arch )
1355
+ raise Exception ("unhandled architecture : %s" % arch )
1302
1356
1303
1357
tempdir_opts = (
1304
1358
{"ignore_cleanup_errors" : True } if sys .version_info >= (3 , 12 ) else {}
@@ -1332,7 +1386,7 @@ def build_cpython(
1332
1386
1333
1387
# We need all the OpenSSL library files in the same directory to appease
1334
1388
# install rules.
1335
- openssl_arch = {"amd64" : "amd64" , "x86" : "win32" }[arch ]
1389
+ openssl_arch = {"amd64" : "amd64" , "x86" : "win32" , "arm64" : "arm64" }[arch ]
1336
1390
openssl_root = td / "openssl" / openssl_arch
1337
1391
openssl_bin_path = openssl_root / "bin"
1338
1392
openssl_lib_path = openssl_root / "lib"
@@ -1346,6 +1400,17 @@ def build_cpython(
1346
1400
log ("copying %s to %s" % (source , dest ))
1347
1401
shutil .copyfile (source , dest )
1348
1402
1403
+ # Delete the tk nmake helper, it's not needed and links msvc
1404
+ tcltk_commit : str = DOWNLOADS [tk_bin_entry ]["git_commit" ]
1405
+ tcltk_path = td / ("cpython-bin-deps-%s" % tcltk_commit )
1406
+ (
1407
+ tcltk_path
1408
+ / build_directory
1409
+ / "lib"
1410
+ / "nmake"
1411
+ / "x86_64-w64-mingw32-nmakehlp.exe"
1412
+ ).unlink ()
1413
+
1349
1414
cpython_source_path = td / ("Python-%s" % python_version )
1350
1415
pcbuild_path = cpython_source_path / "PCbuild"
1351
1416
@@ -1368,6 +1433,7 @@ def build_cpython(
1368
1433
build_directory ,
1369
1434
python_version = python_version ,
1370
1435
zlib_entry = zlib_entry ,
1436
+ arch = arch ,
1371
1437
)
1372
1438
1373
1439
if pgo :
@@ -1790,9 +1856,14 @@ def main() -> None:
1790
1856
if os .environ .get ("Platform" ) == "x86" :
1791
1857
target_triple = "i686-pc-windows-msvc"
1792
1858
arch = "x86"
1793
- else :
1859
+ elif os .environ .get ("Platform" ) == "arm64" :
1860
+ target_triple = "aarch64-pc-windows-msvc"
1861
+ arch = "arm64"
1862
+ elif os .environ .get ("Platform" ) == "x64" :
1794
1863
target_triple = "x86_64-pc-windows-msvc"
1795
1864
arch = "amd64"
1865
+ else :
1866
+ raise Exception ("unhandled architecture: %s" % os .environ .get ("Platform" ))
1796
1867
1797
1868
# TODO need better dependency checking.
1798
1869
0 commit comments