77import subprocess
88import sys
99import sysconfig
10- from os .path import relpath
10+ from os .path import basename , relpath
1111from pathlib import Path
12+ from tempfile import TemporaryDirectory
1213
1314SCRIPT_NAME = Path (__file__ ).name
1415CHECKOUT = Path (__file__ ).resolve ().parent .parent
@@ -102,11 +103,17 @@ def unpack_deps(host):
102103 for name_ver in ["bzip2-1.0.8-1" , "libffi-3.4.4-2" , "openssl-3.0.13-1" ,
103104 "sqlite-3.45.1-0" , "xz-5.4.6-0" ]:
104105 filename = f"{ name_ver } -{ host } .tar.gz"
105- run ([ "wget" , f"{ deps_url } /{ name_ver } /{ filename } " ] )
106+ download ( f"{ deps_url } /{ name_ver } /{ filename } " )
106107 run (["tar" , "-xf" , filename ])
107108 os .remove (filename )
108109
109110
111+ def download (url , target_dir = "." ):
112+ out_path = f"{ target_dir } /{ basename (url )} "
113+ run (["curl" , "-Lf" , "-o" , out_path , url ])
114+ return out_path
115+
116+
110117def configure_host_python (context ):
111118 host_dir = subdir (context .host , clean = context .clean )
112119
@@ -160,6 +167,30 @@ def clean_all(context):
160167 delete_if_exists (CROSS_BUILD_DIR )
161168
162169
170+ # To avoid distributing compiled artifacts without corresponding source code,
171+ # the Gradle wrapper is not included in the CPython repository. Instead, we
172+ # extract it from the Gradle release.
173+ def setup_testbed (context ):
174+ ver_long = "8.7.0"
175+ ver_short = ver_long .removesuffix (".0" )
176+ testbed_dir = CHECKOUT / "Android/testbed"
177+
178+ for filename in ["gradlew" , "gradlew.bat" ]:
179+ out_path = download (
180+ f"https://raw.githubusercontent.com/gradle/gradle/v{ ver_long } /{ filename } " ,
181+ testbed_dir )
182+ os .chmod (out_path , 0o755 )
183+
184+ with TemporaryDirectory (prefix = SCRIPT_NAME ) as temp_dir :
185+ os .chdir (temp_dir )
186+ bin_zip = download (
187+ f"https://services.gradle.org/distributions/gradle-{ ver_short } -bin.zip" )
188+ outer_jar = f"gradle-{ ver_short } /lib/plugins/gradle-wrapper-{ ver_short } .jar"
189+ run (["unzip" , bin_zip , outer_jar ])
190+ run (["unzip" , "-o" , "-d" , f"{ testbed_dir } /gradle/wrapper" , outer_jar ,
191+ "gradle-wrapper.jar" ])
192+
193+
163194def main ():
164195 parser = argparse .ArgumentParser ()
165196 subcommands = parser .add_subparsers (dest = "subcommand" )
@@ -173,8 +204,11 @@ def main():
173204 help = "Run `configure` for Android" )
174205 make_host = subcommands .add_parser ("make-host" ,
175206 help = "Run `make` for Android" )
176- clean = subcommands .add_parser ("clean" , help = "Delete files and directories "
177- "created by this script" )
207+ subcommands .add_parser (
208+ "clean" , help = "Delete the cross-build directory" )
209+ subcommands .add_parser (
210+ "setup-testbed" , help = "Download the testbed Gradle wrapper" )
211+
178212 for subcommand in build , configure_build , configure_host :
179213 subcommand .add_argument (
180214 "--clean" , action = "store_true" , default = False , dest = "clean" ,
@@ -194,7 +228,8 @@ def main():
194228 "configure-host" : configure_host_python ,
195229 "make-host" : make_host_python ,
196230 "build" : build_all ,
197- "clean" : clean_all }
231+ "clean" : clean_all ,
232+ "setup-testbed" : setup_testbed }
198233 dispatch [context .subcommand ](context )
199234
200235
0 commit comments