From 2977c648fc5e7570e2bdbbd9ae7429d6713da04a Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 26 Mar 2026 12:42:52 +0800 Subject: [PATCH 1/6] Make the clean target more selective. --- Apple/__main__.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Apple/__main__.py b/Apple/__main__.py index 3261f368a88fc0..284c178f073a70 100644 --- a/Apple/__main__.py +++ b/Apple/__main__.py @@ -173,23 +173,27 @@ def all_host_triples(platform: str) -> list[str]: return triples -def clean(context: argparse.Namespace, target: str = "all") -> None: +def clean(context: argparse.Namespace, target: str | None = None) -> None: """The implementation of the "clean" command.""" # If we're explicitly targeting the build, there's no platform or # distribution artefacts. If we're cleaning tests, we keep all built # artefacts. Otherwise, the built artefacts must be dirty, so we remove # them. - if target not in {"build", "test"}: - paths = ["dist", context.platform] + list(HOSTS[context.platform]) - else: - paths = [] + if target is None: + target = context.host + + paths = [] if target in {"all", "build"}: paths.append("build") - if target in {"all", "hosts"}: - paths.extend(all_host_triples(context.platform)) - elif target not in {"build", "test", "package"}: + if target in {"all", "hosts", "package"}: + paths.append("dist") + paths.extend(list(HOSTS[context.platform])) + paths.append(context.platform) + if target != "package": + paths.extend(all_host_triples(context.platform)) + elif target not in {"build", "test"}: paths.append(target) if target in {"all", "hosts", "test"}: From 61b804334b14f03a0262718dcd6d9250fb5b4387 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 26 Mar 2026 12:45:25 +0800 Subject: [PATCH 2/6] Ensure that if --ci-mode isn't specified, a valid flag is passed. --- Apple/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apple/__main__.py b/Apple/__main__.py index 284c178f073a70..6c95232bd90fb2 100644 --- a/Apple/__main__.py +++ b/Apple/__main__.py @@ -832,7 +832,7 @@ def test(context: argparse.Namespace, host: str | None = None) -> None: # noqa: + [ "--", "test", - f"--{context.ci_mode}-ci", + f"--{context.ci_mode or 'fast'}-ci", "--single-process", "--no-randomize", # Timeout handling requires subprocesses; explicitly setting From 73a0a8e143528d1511f773df74df5bd45f3cf17d Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 26 Mar 2026 12:51:08 +0800 Subject: [PATCH 3/6] Allow cross-build directory to be customized. --- Apple/__main__.py | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/Apple/__main__.py b/Apple/__main__.py index 6c95232bd90fb2..9a940caf59dfc2 100644 --- a/Apple/__main__.py +++ b/Apple/__main__.py @@ -381,7 +381,8 @@ def configure_host_python( with group(f"Downloading dependencies ({host})"): if not prefix_dir.exists(): prefix_dir.mkdir() - unpack_deps(context.platform, host, prefix_dir, context.cache_dir) + cache_dir = context.cache_dir or CROSS_BUILD_DIR / "downloads" + unpack_deps(context.platform, host, prefix_dir, cache_dir) else: print("Dependencies already installed") @@ -898,7 +899,7 @@ def parse_args() -> argparse.Namespace: configure_build = subcommands.add_parser( "configure-build", help="Run `configure` for the build Python" ) - subcommands.add_parser( + make_build = subcommands.add_parser( "make-build", help="Run `make` for the build Python" ) configure_host = subcommands.add_parser( @@ -954,6 +955,31 @@ def parse_args() -> argparse.Namespace: ), ) + # --cross-build-dir argument + for cmd in [ + clean, + configure_build, + make_build, + configure_host, + make_host, + build, + package, + test, + ci, + ]: + cmd.add_argument( + "--cross-build-dir", + action="store", + default=os.environ.get("CROSS_BUILD_DIR"), + dest="cross_build_dir", + type=Path, + help=( + "Path to the cross-build directory " + f"(default: {CROSS_BUILD_DIR}). Can also be set " + "with the CROSS_BUILD_DIR environment variable." + ), + ) + # --clean option for cmd in [configure_build, configure_host, build, package, test, ci]: cmd.add_argument( @@ -968,7 +994,6 @@ def parse_args() -> argparse.Namespace: for cmd in [configure_host, build, ci]: cmd.add_argument( "--cache-dir", - default="./cross-build/downloads", help="The directory to store cached downloads.", ) @@ -1035,6 +1060,12 @@ def signal_handler(*args): # Process command line arguments context = parse_args() + + # Set the CROSS_BUILD_DIR if an argument was provided + if context.cross_build_dir: + global CROSS_BUILD_DIR + CROSS_BUILD_DIR = context.cross_build_dir.resolve() + dispatch: dict[str, Callable] = { "clean": clean, "configure-build": configure_build_python, From 1aec7ab4787e1ecf097dd8495f69237a6e25e0b5 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 26 Mar 2026 12:51:19 +0800 Subject: [PATCH 4/6] Add blurb. --- .../next/Build/2026-03-26-12-48-42.gh-issue-146446.0GyMu4.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Build/2026-03-26-12-48-42.gh-issue-146446.0GyMu4.rst diff --git a/Misc/NEWS.d/next/Build/2026-03-26-12-48-42.gh-issue-146446.0GyMu4.rst b/Misc/NEWS.d/next/Build/2026-03-26-12-48-42.gh-issue-146446.0GyMu4.rst new file mode 100644 index 00000000000000..40795650b53cbf --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-03-26-12-48-42.gh-issue-146446.0GyMu4.rst @@ -0,0 +1,2 @@ +The clean target for the Apple/iOS XCframework build script is now more +selective when targeting a single architecture. From 960376c15489c320b66f423e28e6513b9b25dd53 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 26 Mar 2026 13:08:04 +0800 Subject: [PATCH 5/6] Simplify implementation of clean handling. --- Apple/__main__.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Apple/__main__.py b/Apple/__main__.py index 9a940caf59dfc2..0cbf3653bc116f 100644 --- a/Apple/__main__.py +++ b/Apple/__main__.py @@ -175,25 +175,24 @@ def all_host_triples(platform: str) -> list[str]: def clean(context: argparse.Namespace, target: str | None = None) -> None: """The implementation of the "clean" command.""" + if target is None: + target = context.host + # If we're explicitly targeting the build, there's no platform or # distribution artefacts. If we're cleaning tests, we keep all built # artefacts. Otherwise, the built artefacts must be dirty, so we remove # them. - if target is None: - target = context.host - - paths = [] + if target not in {"build", "test"}: + paths = ["dist", context.platform] + list(HOSTS[context.platform]) + else: + paths = [] if target in {"all", "build"}: paths.append("build") - if target in {"all", "hosts", "package"}: - paths.append("dist") - paths.extend(list(HOSTS[context.platform])) - paths.append(context.platform) - if target != "package": - paths.extend(all_host_triples(context.platform)) - elif target not in {"build", "test"}: + if target in {"all", "hosts"}: + paths.extend(all_host_triples(context.platform)) + elif target not in {"build", "test", "package"}: paths.append(target) if target in {"all", "hosts", "test"}: From 34bff76583993bd95f0dc9190a70165fd70823a5 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 26 Mar 2026 14:45:19 +0800 Subject: [PATCH 6/6] Honor a CACHE_DIR environment variable for the cache dir. --- Apple/__main__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Apple/__main__.py b/Apple/__main__.py index 0cbf3653bc116f..0a8099e50f59c3 100644 --- a/Apple/__main__.py +++ b/Apple/__main__.py @@ -380,7 +380,11 @@ def configure_host_python( with group(f"Downloading dependencies ({host})"): if not prefix_dir.exists(): prefix_dir.mkdir() - cache_dir = context.cache_dir or CROSS_BUILD_DIR / "downloads" + cache_dir = ( + Path(context.cache_dir).resolve() + if context.cache_dir + else CROSS_BUILD_DIR / "downloads" + ) unpack_deps(context.platform, host, prefix_dir, cache_dir) else: print("Dependencies already installed") @@ -993,6 +997,7 @@ def parse_args() -> argparse.Namespace: for cmd in [configure_host, build, ci]: cmd.add_argument( "--cache-dir", + default=os.environ.get("CACHE_DIR"), help="The directory to store cached downloads.", )