Skip to content

Commit 3328f9a

Browse files
luispadronbrentleyjones
authored andcommitted
Establish a private provider to relay archive-relative artifacts when building apps via tree artifact bundling.
Cherry-pick: 5931f36
1 parent a4912c6 commit 3328f9a

File tree

7 files changed

+197
-4
lines changed

7 files changed

+197
-4
lines changed

apple/internal/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ bzl_library(
460460
":experimental",
461461
":intermediates",
462462
":outputs",
463+
":providers",
463464
"//apple/internal/utils:bundle_paths",
464465
"//apple/internal/utils:defines",
465466
"@bazel_skylib//lib:partial",

apple/internal/processor.bzl

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ load(
9191
"//apple/internal:outputs.bzl",
9292
"outputs",
9393
)
94+
load(
95+
"//apple/internal:providers.bzl",
96+
"new_applebundlearchivesupportinfo",
97+
)
9498
load(
9599
"//apple/internal/utils:bundle_paths.bzl",
96100
"bundle_paths",
@@ -316,7 +320,7 @@ def _bundle_partial_outputs_files(
316320
for partial_output in partial_outputs:
317321
for location, parent_dir, files in getattr(partial_output, "bundle_files", []):
318322
if tree_artifact_is_enabled and location == _LOCATION_ENUM.archive:
319-
# Skip bundling archive related files, as we're only building the bundle directory.
323+
# These files get relayed via AppleBundleArchiveSupportInfo instead.
320324
continue
321325

322326
if trim_locales:
@@ -353,7 +357,7 @@ def _bundle_partial_outputs_files(
353357

354358
for location, parent_dir, zip_files in getattr(partial_output, "bundle_zips", []):
355359
if tree_artifact_is_enabled and location == _LOCATION_ENUM.archive:
356-
# Skip bundling archive related files, as we're only building the bundle directory.
360+
# These zips get relayed via AppleBundleArchiveSupportInfo instead.
357361
continue
358362

359363
parent_dir_is_valid = _is_parent_dir_valid(
@@ -505,6 +509,9 @@ def _bundle_post_process_and_sign(
505509
provisioning_profile: File for the provisioning profile.
506510
rule_descriptor: A rule descriptor for platform and product types from the rule context.
507511
rule_label: The label of the target being analyzed.
512+
513+
Returns:
514+
A List of providers if any were created during bundling. Can be an empty List.
508515
"""
509516
tree_artifact_is_enabled = is_experimental_tree_artifact_enabled(
510517
platform_prerequisites = platform_prerequisites,
@@ -515,13 +522,33 @@ def _bundle_post_process_and_sign(
515522
rule_descriptor = rule_descriptor,
516523
tree_artifact_is_enabled = tree_artifact_is_enabled,
517524
)
525+
bundling_providers = []
518526
signed_frameworks_depsets = []
519527
for partial_output in partial_outputs:
520528
if hasattr(partial_output, "signed_frameworks"):
521529
signed_frameworks_depsets.append(partial_output.signed_frameworks)
522530
transitive_signed_frameworks = depset(transitive = signed_frameworks_depsets)
523531

524532
if tree_artifact_is_enabled:
533+
bundle_files_for_xcarchive = []
534+
bundle_zips_for_xcarchive = []
535+
536+
for partial_output in partial_outputs:
537+
for location, parent_dir, files in getattr(partial_output, "bundle_files", []):
538+
if location == _LOCATION_ENUM.archive:
539+
bundle_files_for_xcarchive.append((parent_dir, files))
540+
541+
for location, parent_dir, zip_files in getattr(partial_output, "bundle_zips", []):
542+
if location == _LOCATION_ENUM.archive:
543+
bundle_zips_for_xcarchive.append((parent_dir, zip_files))
544+
545+
bundling_providers.append(
546+
new_applebundlearchivesupportinfo(
547+
bundle_files = bundle_files_for_xcarchive,
548+
bundle_zips = bundle_zips_for_xcarchive,
549+
),
550+
)
551+
525552
extra_input_files = []
526553

527554
if entitlements:
@@ -690,6 +717,8 @@ def _bundle_post_process_and_sign(
690717
signed_frameworks = transitive_signed_frameworks,
691718
)
692719

720+
return bundling_providers
721+
693722
def _process(
694723
*,
695724
actions,
@@ -746,6 +775,7 @@ def _process(
746775
"""
747776

748777
partial_outputs = [partial.call(p) for p in partials]
778+
providers = []
749779

750780
if bundle_post_process_and_sign:
751781
output_archive = outputs.archive(
@@ -757,7 +787,7 @@ def _process(
757787
predeclared_outputs = predeclared_outputs,
758788
rule_descriptor = rule_descriptor,
759789
)
760-
_bundle_post_process_and_sign(
790+
bundling_providers = _bundle_post_process_and_sign(
761791
actions = actions,
762792
apple_mac_toolchain_info = apple_mac_toolchain_info,
763793
apple_xplat_toolchain_info = apple_xplat_toolchain_info,
@@ -779,11 +809,11 @@ def _process(
779809
rule_descriptor = rule_descriptor,
780810
rule_label = rule_label,
781811
)
812+
providers.extend(bundling_providers)
782813
transitive_output_files = [depset([output_archive])]
783814
else:
784815
transitive_output_files = []
785816

786-
providers = []
787817
output_group_dicts = []
788818
for partial_output in partial_outputs:
789819
if hasattr(partial_output, "providers"):

apple/internal/providers.bzl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,23 @@ set to true for the extension but false for the application.
150150
init = _make_banned_init(provider_name = "AppleBundleInfo"),
151151
)
152152

153+
AppleBundleArchiveSupportInfo, new_applebundlearchivesupportinfo = provider(
154+
doc = "Provides supporting files to be embedded within an xcarchive bundle.",
155+
fields = {
156+
"bundle_files": """
157+
Required. A List of tuples of the format (parent_dir, files) where `parent_dir` is a String
158+
indicating the parent directory structure from the root of the archive to the desired output
159+
directory and `files` is a `depset` of `File`s referencing the files to be placed there.
160+
""",
161+
"bundle_zips": """
162+
Required. A List of tuples of the format (parent_dir, files) where `parent_dir` is a String
163+
indicating the parent directory structure from the root of the archive to the desired output
164+
directory and `files` is a `depset` of `File`s referencing the ZIP files to be extracted there.
165+
""",
166+
},
167+
init = _make_banned_init(provider_name = "AppleBundleArchiveSupportInfo"),
168+
)
169+
153170
AppleBundleVersionInfo, new_applebundleversioninfo = provider(
154171
doc = "Provides versioning information for an Apple bundle.",
155172
fields = {

test/starlark_tests/ios_extension_tests.bzl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ load(
1818
"//test/starlark_tests/rules:analysis_output_group_info_files_test.bzl",
1919
"analysis_output_group_info_files_test",
2020
)
21+
load(
22+
"//test/starlark_tests/rules:apple_bundle_archive_support_info_device_test.bzl",
23+
"apple_bundle_archive_support_info_device_test",
24+
)
2125
load(
2226
"//test/starlark_tests/rules:apple_dsym_bundle_info_test.bzl",
2327
"apple_dsym_bundle_info_test",
@@ -205,6 +209,12 @@ def ios_extension_test_suite(name):
205209
],
206210
tags = [name],
207211
)
212+
apple_bundle_archive_support_info_device_test(
213+
name = "{}_bundle_archive_support_contains_stub_executable_device_test".format(name),
214+
expected_archive_bundle_files = ["SwiftSupport/iphoneos/swiftlibs"],
215+
target_under_test = "//test/starlark_tests/targets_under_test/ios:app_with_swift_ext",
216+
tags = [name],
217+
)
208218
archive_contents_test(
209219
name = "{}_simulator_swift_dylibs_present".format(name),
210220
build_type = "simulator",

test/starlark_tests/ios_imessage_application_tests.bzl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
"""ios_imessage_application Starlark tests."""
1616

17+
load(
18+
"//test/starlark_tests/rules:apple_bundle_archive_support_info_device_test.bzl",
19+
"apple_bundle_archive_support_info_device_test",
20+
)
1721
load(
1822
"//test/starlark_tests/rules:apple_verification_test.bzl",
1923
"apple_verification_test",
@@ -89,6 +93,13 @@ def ios_imessage_application_test_suite(name):
8993
tags = [name],
9094
)
9195

96+
apple_bundle_archive_support_info_device_test(
97+
name = "{}_bundle_archive_support_contains_stub_executable_device_test".format(name),
98+
expected_archive_bundle_files = ["MessagesApplicationSupport/MessagesApplicationSupportStub"],
99+
target_under_test = "//test/starlark_tests/targets_under_test/ios:imessage_app",
100+
tags = [name],
101+
)
102+
92103
native.test_suite(
93104
name = name,
94105
tags = [name],
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Copyright 2024 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Starlark test rule for files found in AppleBundleArchiveSupportInfo fields."""
16+
17+
load(
18+
"@bazel_skylib//lib:new_sets.bzl",
19+
"sets",
20+
)
21+
load(
22+
"@bazel_skylib//lib:paths.bzl",
23+
"paths",
24+
)
25+
load(
26+
"@bazel_skylib//lib:unittest.bzl",
27+
"asserts",
28+
)
29+
load(
30+
"//apple/build_settings:build_settings.bzl",
31+
"build_settings_labels",
32+
)
33+
load(
34+
"//apple/internal:providers.bzl",
35+
"AppleBundleArchiveSupportInfo",
36+
) # buildifier: disable=bzl-visibility
37+
load(
38+
"//test/starlark_tests/rules:analysis_provider_test.bzl",
39+
"make_provider_test_rule",
40+
)
41+
42+
visibility("//test/starlark_tests/...")
43+
44+
def _assert_outputs_in_set(*, actual_outputs, env, expected_outputs):
45+
"""Assert the expected set of outputs is within actual_outputs."""
46+
47+
actual_set = sets.make(actual_outputs)
48+
expected_set = sets.make(expected_outputs)
49+
50+
asserts.set_equals(
51+
env,
52+
expected_set,
53+
sets.intersection(actual_set, expected_set),
54+
"{expected_list} not contained in {actual_list}".format(
55+
actual_list = sets.to_list(actual_set),
56+
expected_list = sets.to_list(expected_set),
57+
),
58+
)
59+
60+
def _assert_contains_expected_bundle_files_and_zips(
61+
ctx,
62+
env,
63+
apple_bundle_archive_support_info):
64+
"""Assert AppleBundleArchiveSupportInfo contains expected bundle files and zips."""
65+
66+
_assert_outputs_in_set(
67+
env = env,
68+
expected_outputs = ctx.attr.expected_archive_bundle_files,
69+
actual_outputs = [
70+
paths.join(parent_dir, file.basename)
71+
for parent_dir, files in apple_bundle_archive_support_info.bundle_files
72+
for file in files.to_list()
73+
],
74+
)
75+
76+
_assert_outputs_in_set(
77+
env = env,
78+
expected_outputs = ctx.attr.expected_archive_bundle_zips,
79+
actual_outputs = [
80+
paths.join(parent_dir, file.basename)
81+
for parent_dir, files in apple_bundle_archive_support_info.bundle_zips
82+
for file in files.to_list()
83+
],
84+
)
85+
86+
apple_bundle_archive_support_info_device_test = make_provider_test_rule(
87+
provider = AppleBundleArchiveSupportInfo,
88+
assertion_fn = _assert_contains_expected_bundle_files_and_zips,
89+
attrs = {
90+
"expected_archive_bundle_files": attr.string_list(
91+
mandatory = False,
92+
doc = """
93+
List of archive-relative bundle file paths expected as outputs of AppleBundleArchiveSupportInfo.
94+
""",
95+
),
96+
"expected_archive_bundle_zips": attr.string_list(
97+
mandatory = False,
98+
doc = """
99+
List of archive-relative bundle zip paths expected as outputs of AppleBundleArchiveSupportInfo.
100+
""",
101+
),
102+
},
103+
config_settings = {
104+
build_settings_labels.use_tree_artifacts_outputs: True,
105+
"//command_line_option:macos_cpus": "arm64,x86_64",
106+
"//command_line_option:ios_multi_cpus": "arm64",
107+
"//command_line_option:tvos_cpus": "arm64",
108+
"//command_line_option:visionos_cpus": "arm64",
109+
"//command_line_option:watchos_cpus": "arm64_32",
110+
},
111+
)

test/starlark_tests/watchos_application_tests.bzl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ load(
2222
"//test/starlark_tests/rules:analysis_target_actions_test.bzl",
2323
"analysis_target_actions_test",
2424
)
25+
load(
26+
"//test/starlark_tests/rules:apple_bundle_archive_support_info_device_test.bzl",
27+
"apple_bundle_archive_support_info_device_test",
28+
)
2529
load(
2630
"//test/starlark_tests/rules:apple_verification_test.bzl",
2731
"apple_verification_test",
@@ -132,6 +136,15 @@ def watchos_application_test_suite(name):
132136
tags = [name],
133137
)
134138

139+
# Tests that the WatchKit stub executable is referenced via the provider if we're building the
140+
# iOS companion app as a tree artifact.
141+
apple_bundle_archive_support_info_device_test(
142+
name = "{}_bundle_archive_support_contains_stub_executable_device_test".format(name),
143+
expected_archive_bundle_files = ["WatchKitSupport2/WK"],
144+
target_under_test = "//test/starlark_tests/targets_under_test/watchos:app_companion",
145+
tags = [name],
146+
)
147+
135148
# Test that the output multi-arch stub binary is identified as watchOS device via the Mach-O
136149
# load command LC_VERSION_MIN_WATCHOS for the arm64_32 binary slice, and that 64-bit archs are
137150
# eliminated.

0 commit comments

Comments
 (0)