Skip to content

Commit 140074e

Browse files
[3.13] gh-146450: Normalise feature set of Android build script with other platform build scripts (GH-146451) (#148066)
Allows for cleaning a subset of targets, customization of the download cache and cross-build directories, and modifies the build command to allow 'all', 'build' and 'hosts' targets. (cherry picked from commit b8470de) Co-authored-by: Russell Keith-Magee <russell@keith-magee.com>
1 parent 9ff5845 commit 140074e

File tree

2 files changed

+112
-30
lines changed

2 files changed

+112
-30
lines changed

Android/android.py

Lines changed: 110 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -205,38 +205,48 @@ def make_build_python(context):
205205
#
206206
# If you're a member of the Python core team, and you'd like to be able to push
207207
# these tags yourself, please contact Malcolm Smith or Russell Keith-Magee.
208-
def unpack_deps(host, prefix_dir):
208+
def unpack_deps(host, prefix_dir, cache_dir):
209209
os.chdir(prefix_dir)
210210
deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download"
211211
for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.0.19-1",
212212
"sqlite-3.50.4-0", "xz-5.4.6-1"]:
213213
filename = f"{name_ver}-{host}.tar.gz"
214-
download(f"{deps_url}/{name_ver}/{filename}")
215-
shutil.unpack_archive(filename)
216-
os.remove(filename)
214+
out_path = download(f"{deps_url}/{name_ver}/{filename}", cache_dir)
215+
shutil.unpack_archive(out_path)
217216

218217

219-
def download(url, target_dir="."):
220-
out_path = f"{target_dir}/{basename(url)}"
221-
run(["curl", "-Lf", "--retry", "5", "--retry-all-errors", "-o", out_path, url])
218+
def download(url, cache_dir):
219+
out_path = cache_dir / basename(url)
220+
cache_dir.mkdir(parents=True, exist_ok=True)
221+
if not out_path.is_file():
222+
run(["curl", "-Lf", "--retry", "5", "--retry-all-errors", "-o", out_path, url])
223+
else:
224+
print(f"Using cached version of {basename(url)}")
222225
return out_path
223226

224227

225-
def configure_host_python(context):
228+
def configure_host_python(context, host=None):
229+
if host is None:
230+
host = context.host
226231
if context.clean:
227-
clean(context.host)
232+
clean(host)
228233

229-
host_dir = subdir(context.host, create=True)
234+
host_dir = subdir(host, create=True)
230235
prefix_dir = host_dir / "prefix"
231236
if not prefix_dir.exists():
232237
prefix_dir.mkdir()
233-
unpack_deps(context.host, prefix_dir)
238+
cache_dir = (
239+
Path(context.cache_dir).resolve()
240+
if context.cache_dir
241+
else CROSS_BUILD_DIR / "downloads"
242+
)
243+
unpack_deps(host, prefix_dir, cache_dir)
234244

235245
os.chdir(host_dir)
236246
command = [
237247
# Basic cross-compiling configuration
238248
relpath(PYTHON_DIR / "configure"),
239-
f"--host={context.host}",
249+
f"--host={host}",
240250
f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}",
241251
f"--with-build-python={build_python_path()}",
242252
"--without-ensurepip",
@@ -252,14 +262,16 @@ def configure_host_python(context):
252262

253263
if context.args:
254264
command.extend(context.args)
255-
run(command, host=context.host)
265+
run(command, host=host)
256266

257267

258-
def make_host_python(context):
268+
def make_host_python(context, host=None):
269+
if host is None:
270+
host = context.host
259271
# The CFLAGS and LDFLAGS set in android-env include the prefix dir, so
260272
# delete any previous Python installation to prevent it being used during
261273
# the build.
262-
host_dir = subdir(context.host)
274+
host_dir = subdir(host)
263275
prefix_dir = host_dir / "prefix"
264276
for pattern in ("include/python*", "lib/libpython*", "lib/python*"):
265277
delete_glob(f"{prefix_dir}/{pattern}")
@@ -278,20 +290,28 @@ def make_host_python(context):
278290
)
279291

280292

281-
def build_all(context):
282-
steps = [configure_build_python, make_build_python, configure_host_python,
283-
make_host_python]
284-
for step in steps:
285-
step(context)
293+
def build_targets(context):
294+
if context.target in {"all", "build"}:
295+
configure_build_python(context)
296+
make_build_python(context)
297+
298+
for host in HOSTS:
299+
if context.target in {"all", "hosts", host}:
300+
configure_host_python(context, host)
301+
make_host_python(context, host)
286302

287303

288304
def clean(host):
289305
delete_glob(CROSS_BUILD_DIR / host)
290306

291307

292-
def clean_all(context):
293-
for host in HOSTS + ["build"]:
294-
clean(host)
308+
def clean_targets(context):
309+
if context.target in {"all", "build"}:
310+
clean("build")
311+
312+
for host in HOSTS:
313+
if context.target in {"all", "hosts", host}:
314+
clean(host)
295315

296316

297317
def setup_ci():
@@ -853,31 +873,85 @@ def add_parser(*args, **kwargs):
853873

854874
# Subcommands
855875
build = add_parser(
856-
"build", help="Run configure-build, make-build, configure-host and "
857-
"make-host")
876+
"build",
877+
help="Run configure and make for the selected target"
878+
)
858879
configure_build = add_parser(
859880
"configure-build", help="Run `configure` for the build Python")
860-
add_parser(
881+
make_build = add_parser(
861882
"make-build", help="Run `make` for the build Python")
862883
configure_host = add_parser(
863884
"configure-host", help="Run `configure` for Android")
864885
make_host = add_parser(
865886
"make-host", help="Run `make` for Android")
866887

867-
add_parser("clean", help="Delete all build directories")
888+
clean = add_parser(
889+
"clean",
890+
help="Delete build directories for the selected target"
891+
)
892+
868893
add_parser("build-testbed", help="Build the testbed app")
869894
test = add_parser("test", help="Run the testbed app")
870895
package = add_parser("package", help="Make a release package")
871896
ci = add_parser("ci", help="Run build, package and test")
872897
env = add_parser("env", help="Print environment variables")
873898

874899
# Common arguments
900+
# --cross-build-dir argument
901+
for cmd in [
902+
clean,
903+
configure_build,
904+
make_build,
905+
configure_host,
906+
make_host,
907+
build,
908+
package,
909+
test,
910+
ci,
911+
]:
912+
cmd.add_argument(
913+
"--cross-build-dir",
914+
action="store",
915+
default=os.environ.get("CROSS_BUILD_DIR"),
916+
dest="cross_build_dir",
917+
type=Path,
918+
help=(
919+
"Path to the cross-build directory "
920+
f"(default: {CROSS_BUILD_DIR}). Can also be set "
921+
"with the CROSS_BUILD_DIR environment variable."
922+
),
923+
)
924+
925+
# --cache-dir option
926+
for cmd in [configure_host, build, ci]:
927+
cmd.add_argument(
928+
"--cache-dir",
929+
default=os.environ.get("CACHE_DIR"),
930+
help="The directory to store cached downloads.",
931+
)
932+
933+
# --clean option
875934
for subcommand in [build, configure_build, configure_host, ci]:
876935
subcommand.add_argument(
877936
"--clean", action="store_true", default=False, dest="clean",
878937
help="Delete the relevant build directories first")
879938

880-
host_commands = [build, configure_host, make_host, package, ci]
939+
# Allow "all", "build" and "hosts" targets for some commands
940+
for subcommand in [clean, build]:
941+
subcommand.add_argument(
942+
"target",
943+
nargs="?",
944+
default="all",
945+
choices=["all", "build", "hosts"] + HOSTS,
946+
help=(
947+
"The host triplet (e.g., aarch64-linux-android), "
948+
"or 'build' for just the build platform, or 'hosts' for all "
949+
"host platforms, or 'all' for the build platform and all "
950+
"hosts. Defaults to 'all'"
951+
),
952+
)
953+
954+
host_commands = [configure_host, make_host, package, ci]
881955
if in_source_tree:
882956
host_commands.append(env)
883957
for subcommand in host_commands:
@@ -939,13 +1013,19 @@ def main():
9391013
stream.reconfigure(line_buffering=True)
9401014

9411015
context = parse_args()
1016+
1017+
# Set the CROSS_BUILD_DIR if an argument was provided
1018+
if context.cross_build_dir:
1019+
global CROSS_BUILD_DIR
1020+
CROSS_BUILD_DIR = context.cross_build_dir.resolve()
1021+
9421022
dispatch = {
9431023
"configure-build": configure_build_python,
9441024
"make-build": make_build_python,
9451025
"configure-host": configure_host_python,
9461026
"make-host": make_host_python,
947-
"build": build_all,
948-
"clean": clean_all,
1027+
"build": build_targets,
1028+
"clean": clean_targets,
9491029
"build-testbed": build_testbed,
9501030
"test": run_testbed,
9511031
"package": package,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The Android build script was modified to improve parity with other platform
2+
build scripts.

0 commit comments

Comments
 (0)