@@ -150,7 +150,7 @@ def find_vswhere():
150
150
return vswhere
151
151
152
152
153
- def find_msbuild ( ):
153
+ def find_vs_path ( path ):
154
154
vswhere = find_vswhere ()
155
155
156
156
p = subprocess .check_output (
@@ -169,7 +169,7 @@ def find_msbuild():
169
169
# Strictly speaking the output may not be UTF-8.
170
170
p = pathlib .Path (p .strip ().decode ("utf-8" ))
171
171
172
- p = p / "MSBuild" / "Current" / "Bin" / "MSBuild.exe"
172
+ p = p / path
173
173
174
174
if not p .exists ():
175
175
print ("%s does not exist" % p )
@@ -178,6 +178,15 @@ def find_msbuild():
178
178
return p
179
179
180
180
181
+ def find_msbuild ():
182
+ return find_vs_path (pathlib .Path ("MSBuild" ) / "Current" / "Bin" / "MSBuild.exe" )
183
+
184
+
185
+ def find_vcvarsall_path ():
186
+ """Find path to vcvarsall.bat"""
187
+ return find_vs_path (pathlib .Path ("VC" ) / "Auxiliary" / "Build" / "vcvarsall.bat" )
188
+
189
+
181
190
def find_vctools_path ():
182
191
vswhere = find_vswhere ()
183
192
@@ -1071,6 +1080,9 @@ def run_msbuild(
1071
1080
"/property:OverrideVersion=%s" % python_version ,
1072
1081
]
1073
1082
1083
+ if not python_version .startswith ("3.7" ):
1084
+ args .append ("/property:IncludeCTypes=true" )
1085
+
1074
1086
exec_and_log (args , str (pcbuild_path ), os .environ )
1075
1087
1076
1088
@@ -1194,6 +1206,50 @@ def build_openssl(perl_path: pathlib.Path, arch: str, profile: str):
1194
1206
create_tar_from_directory (fh , install )
1195
1207
1196
1208
1209
+ def build_libffi (
1210
+ build_dir : pathlib .Path , arch : str , prepare_ffi : pathlib .Path , sh_exe : pathlib .Path
1211
+ ):
1212
+ ffi_source_path = build_dir / "libffi"
1213
+
1214
+ # As of April 15, 2020, the libffi source release on GitHub doesn't
1215
+ # have patches that we need to build. https://bugs.python.org/issue40293
1216
+ # tracks getting a proper release. Until then, git clone the repo.
1217
+ subprocess .run (
1218
+ [
1219
+ "git.exe" ,
1220
+ "clone" ,
1221
+ "--single-branch" ,
1222
+ "--branch" ,
1223
+ "libffi" ,
1224
+ "https://github.com/python/cpython-source-deps.git" ,
1225
+ str (ffi_source_path ),
1226
+ ],
1227
+ check = True ,
1228
+ )
1229
+
1230
+ subprocess .run (
1231
+ ["git.exe" , "checkout" , "ed22026f39b37f892ded95d7b30e77dfb5126334" ],
1232
+ cwd = ffi_source_path ,
1233
+ check = True ,
1234
+ )
1235
+
1236
+ # We build libffi by running the build script that CPython ships.
1237
+ env = dict (os .environ )
1238
+ env ["LIBFFI_SOURCE" ] = str (ffi_source_path )
1239
+ env ["VCVARSALL" ] = str (find_vcvarsall_path ())
1240
+ env ["SH" ] = str (sh_exe )
1241
+
1242
+ args = [str (prepare_ffi ), "-pdb" ]
1243
+ if arch == "x86" :
1244
+ args .append ("-x86" )
1245
+ else :
1246
+ args .append ("-x64" )
1247
+
1248
+ # Running the build script from Python will install the files into the
1249
+ # appropriate directory.
1250
+ subprocess .run (args , env = env , check = True )
1251
+
1252
+
1197
1253
RE_ADDITIONAL_DEPENDENCIES = re .compile (
1198
1254
"<AdditionalDependencies>([^<]+)</AdditionalDependencies>"
1199
1255
)
@@ -1249,6 +1305,7 @@ def collect_python_build_artifacts(
1249
1305
"_testconsole" ,
1250
1306
"_testembed" ,
1251
1307
"_testimportmultiple" ,
1308
+ "_testinternalcapi" ,
1252
1309
"_testmultiphase" ,
1253
1310
"xxlimited" ,
1254
1311
}
@@ -1481,7 +1538,7 @@ def find_additional_dependencies(project: pathlib.Path):
1481
1538
return res
1482
1539
1483
1540
1484
- def build_cpython (python_entry_name : str , arch : str , profile ):
1541
+ def build_cpython (python_entry_name : str , arch : str , sh_exe , profile ):
1485
1542
static = profile == "static"
1486
1543
pgo = "-pgo" in profile
1487
1544
@@ -1545,6 +1602,16 @@ def build_cpython(python_entry_name: str, arch: str, profile):
1545
1602
with zipfile .ZipFile (setuptools_archive ) as zf :
1546
1603
zf .extractall (td )
1547
1604
1605
+ cpython_source_path = td / ("Python-%s" % python_version )
1606
+ pcbuild_path = cpython_source_path / "PCBuild"
1607
+
1608
+ prepare_libffi = pcbuild_path / "prepare_libffi.bat"
1609
+
1610
+ if prepare_libffi .exists ():
1611
+ assert sh_exe
1612
+
1613
+ build_libffi (td , arch , prepare_libffi , sh_exe )
1614
+
1548
1615
# We need all the OpenSSL library files in the same directory to appease
1549
1616
# install rules.
1550
1617
if not static :
@@ -1879,9 +1946,14 @@ def main():
1879
1946
default = "static" ,
1880
1947
help = "How to compile Python" ,
1881
1948
)
1949
+ parser .add_argument ("--sh" , help = "Path to sh.exe in a cygwin or mingw installation" )
1882
1950
1883
1951
args = parser .parse_args ()
1884
1952
1953
+ if args .python == "cpython-3.8" and not args .sh :
1954
+ print ("--sh required when building Python 3.8+" )
1955
+ return 1
1956
+
1885
1957
now = datetime .datetime .utcnow ()
1886
1958
1887
1959
log_path = BUILD / "build.log"
@@ -1899,7 +1971,9 @@ def main():
1899
1971
build_openssl (perl_path , arch , profile = args .profile )
1900
1972
1901
1973
LOG_PREFIX [0 ] = "cpython"
1902
- tar_path = build_cpython (args .python , arch , profile = args .profile )
1974
+ tar_path = build_cpython (
1975
+ args .python , arch , sh_exe = pathlib .Path (args .sh ), profile = args .profile
1976
+ )
1903
1977
1904
1978
compress_python_archive (
1905
1979
tar_path , DIST , "%s-%s" % (tar_path .stem , now .strftime ("%Y%m%dT%H%M" )),
0 commit comments