Skip to content

Commit 83ee46c

Browse files
[3.14] gh-146450: Normalise feature set of Android build script with other platform build scripts (GH-146451) (#148065)
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 ab3d37f commit 83ee46c

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
@@ -210,38 +210,48 @@ def make_build_python(context):
210210
#
211211
# If you're a member of the Python core team, and you'd like to be able to push
212212
# these tags yourself, please contact Malcolm Smith or Russell Keith-Magee.
213-
def unpack_deps(host, prefix_dir):
213+
def unpack_deps(host, prefix_dir, cache_dir):
214214
os.chdir(prefix_dir)
215215
deps_url = "https://github.com/beeware/cpython-android-source-deps/releases/download"
216216
for name_ver in ["bzip2-1.0.8-3", "libffi-3.4.4-3", "openssl-3.0.19-1",
217217
"sqlite-3.50.4-0", "xz-5.4.6-1", "zstd-1.5.7-2"]:
218218
filename = f"{name_ver}-{host}.tar.gz"
219-
download(f"{deps_url}/{name_ver}/{filename}")
220-
shutil.unpack_archive(filename)
221-
os.remove(filename)
219+
out_path = download(f"{deps_url}/{name_ver}/{filename}", cache_dir)
220+
shutil.unpack_archive(out_path)
222221

223222

224-
def download(url, target_dir="."):
225-
out_path = f"{target_dir}/{basename(url)}"
226-
run(["curl", "-Lf", "--retry", "5", "--retry-all-errors", "-o", out_path, url])
223+
def download(url, cache_dir):
224+
out_path = cache_dir / basename(url)
225+
cache_dir.mkdir(parents=True, exist_ok=True)
226+
if not out_path.is_file():
227+
run(["curl", "-Lf", "--retry", "5", "--retry-all-errors", "-o", out_path, url])
228+
else:
229+
print(f"Using cached version of {basename(url)}")
227230
return out_path
228231

229232

230-
def configure_host_python(context):
233+
def configure_host_python(context, host=None):
234+
if host is None:
235+
host = context.host
231236
if context.clean:
232-
clean(context.host)
237+
clean(host)
233238

234-
host_dir = subdir(context.host, create=True)
239+
host_dir = subdir(host, create=True)
235240
prefix_dir = host_dir / "prefix"
236241
if not prefix_dir.exists():
237242
prefix_dir.mkdir()
238-
unpack_deps(context.host, prefix_dir)
243+
cache_dir = (
244+
Path(context.cache_dir).resolve()
245+
if context.cache_dir
246+
else CROSS_BUILD_DIR / "downloads"
247+
)
248+
unpack_deps(host, prefix_dir, cache_dir)
239249

240250
os.chdir(host_dir)
241251
command = [
242252
# Basic cross-compiling configuration
243253
relpath(PYTHON_DIR / "configure"),
244-
f"--host={context.host}",
254+
f"--host={host}",
245255
f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}",
246256
f"--with-build-python={build_python_path()}",
247257
"--without-ensurepip",
@@ -257,14 +267,16 @@ def configure_host_python(context):
257267

258268
if context.args:
259269
command.extend(context.args)
260-
run(command, host=context.host)
270+
run(command, host=host)
261271

262272

263-
def make_host_python(context):
273+
def make_host_python(context, host=None):
274+
if host is None:
275+
host = context.host
264276
# The CFLAGS and LDFLAGS set in android-env include the prefix dir, so
265277
# delete any previous Python installation to prevent it being used during
266278
# the build.
267-
host_dir = subdir(context.host)
279+
host_dir = subdir(host)
268280
prefix_dir = host_dir / "prefix"
269281
for pattern in ("include/python*", "lib/libpython*", "lib/python*"):
270282
delete_glob(f"{prefix_dir}/{pattern}")
@@ -283,20 +295,28 @@ def make_host_python(context):
283295
)
284296

285297

286-
def build_all(context):
287-
steps = [configure_build_python, make_build_python, configure_host_python,
288-
make_host_python]
289-
for step in steps:
290-
step(context)
298+
def build_targets(context):
299+
if context.target in {"all", "build"}:
300+
configure_build_python(context)
301+
make_build_python(context)
302+
303+
for host in HOSTS:
304+
if context.target in {"all", "hosts", host}:
305+
configure_host_python(context, host)
306+
make_host_python(context, host)
291307

292308

293309
def clean(host):
294310
delete_glob(CROSS_BUILD_DIR / host)
295311

296312

297-
def clean_all(context):
298-
for host in HOSTS + ["build"]:
299-
clean(host)
313+
def clean_targets(context):
314+
if context.target in {"all", "build"}:
315+
clean("build")
316+
317+
for host in HOSTS:
318+
if context.target in {"all", "hosts", host}:
319+
clean(host)
300320

301321

302322
def setup_ci():
@@ -858,31 +878,85 @@ def add_parser(*args, **kwargs):
858878

859879
# Subcommands
860880
build = add_parser(
861-
"build", help="Run configure-build, make-build, configure-host and "
862-
"make-host")
881+
"build",
882+
help="Run configure and make for the selected target"
883+
)
863884
configure_build = add_parser(
864885
"configure-build", help="Run `configure` for the build Python")
865-
add_parser(
886+
make_build = add_parser(
866887
"make-build", help="Run `make` for the build Python")
867888
configure_host = add_parser(
868889
"configure-host", help="Run `configure` for Android")
869890
make_host = add_parser(
870891
"make-host", help="Run `make` for Android")
871892

872-
add_parser("clean", help="Delete all build directories")
893+
clean = add_parser(
894+
"clean",
895+
help="Delete build directories for the selected target"
896+
)
897+
873898
add_parser("build-testbed", help="Build the testbed app")
874899
test = add_parser("test", help="Run the testbed app")
875900
package = add_parser("package", help="Make a release package")
876901
ci = add_parser("ci", help="Run build, package and test")
877902
env = add_parser("env", help="Print environment variables")
878903

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

885-
host_commands = [build, configure_host, make_host, package, ci]
944+
# Allow "all", "build" and "hosts" targets for some commands
945+
for subcommand in [clean, build]:
946+
subcommand.add_argument(
947+
"target",
948+
nargs="?",
949+
default="all",
950+
choices=["all", "build", "hosts"] + HOSTS,
951+
help=(
952+
"The host triplet (e.g., aarch64-linux-android), "
953+
"or 'build' for just the build platform, or 'hosts' for all "
954+
"host platforms, or 'all' for the build platform and all "
955+
"hosts. Defaults to 'all'"
956+
),
957+
)
958+
959+
host_commands = [configure_host, make_host, package, ci]
886960
if in_source_tree:
887961
host_commands.append(env)
888962
for subcommand in host_commands:
@@ -944,13 +1018,19 @@ def main():
9441018
stream.reconfigure(line_buffering=True)
9451019

9461020
context = parse_args()
1021+
1022+
# Set the CROSS_BUILD_DIR if an argument was provided
1023+
if context.cross_build_dir:
1024+
global CROSS_BUILD_DIR
1025+
CROSS_BUILD_DIR = context.cross_build_dir.resolve()
1026+
9471027
dispatch = {
9481028
"configure-build": configure_build_python,
9491029
"make-build": make_build_python,
9501030
"configure-host": configure_host_python,
9511031
"make-host": make_host_python,
952-
"build": build_all,
953-
"clean": clean_all,
1032+
"build": build_targets,
1033+
"clean": clean_targets,
9541034
"build-testbed": build_testbed,
9551035
"test": run_testbed,
9561036
"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)