Skip to content

Commit 567bc09

Browse files
committed
Establish a private provider to relay archive-relative artifacts when building apps via tree artifact bundling.
Cherry-pick: 5931f36
1 parent 281186e commit 567bc09

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
@@ -473,6 +473,7 @@ bzl_library(
473473
":experimental",
474474
":intermediates",
475475
":outputs",
476+
":providers",
476477
"//apple/internal/utils:bundle_paths",
477478
"//apple/internal/utils:defines",
478479
"@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(
@@ -503,6 +507,9 @@ def _bundle_post_process_and_sign(
503507
provisioning_profile: File for the provisioning profile.
504508
rule_descriptor: A rule descriptor for platform and product types from the rule context.
505509
rule_label: The label of the target being analyzed.
510+
511+
Returns:
512+
A List of providers if any were created during bundling. Can be an empty List.
506513
"""
507514
tree_artifact_is_enabled = is_experimental_tree_artifact_enabled(
508515
platform_prerequisites = platform_prerequisites,
@@ -513,13 +520,33 @@ def _bundle_post_process_and_sign(
513520
rule_descriptor = rule_descriptor,
514521
tree_artifact_is_enabled = tree_artifact_is_enabled,
515522
)
523+
bundling_providers = []
516524
signed_frameworks_depsets = []
517525
for partial_output in partial_outputs:
518526
if hasattr(partial_output, "signed_frameworks"):
519527
signed_frameworks_depsets.append(partial_output.signed_frameworks)
520528
transitive_signed_frameworks = depset(transitive = signed_frameworks_depsets)
521529

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

525552
if entitlements:
@@ -688,6 +715,8 @@ def _bundle_post_process_and_sign(
688715
signed_frameworks = transitive_signed_frameworks,
689716
)
690717

718+
return bundling_providers
719+
691720
def _process(
692721
*,
693722
actions,
@@ -744,6 +773,7 @@ def _process(
744773
"""
745774

746775
partial_outputs = [partial.call(p) for p in partials]
776+
providers = []
747777

748778
if bundle_post_process_and_sign:
749779
output_archive = outputs.archive(
@@ -755,7 +785,7 @@ def _process(
755785
predeclared_outputs = predeclared_outputs,
756786
rule_descriptor = rule_descriptor,
757787
)
758-
_bundle_post_process_and_sign(
788+
bundling_providers = _bundle_post_process_and_sign(
759789
actions = actions,
760790
apple_mac_toolchain_info = apple_mac_toolchain_info,
761791
apple_xplat_toolchain_info = apple_xplat_toolchain_info,
@@ -777,11 +807,11 @@ def _process(
777807
rule_descriptor = rule_descriptor,
778808
rule_label = rule_label,
779809
)
810+
providers.extend(bundling_providers)
780811
transitive_output_files = [depset([output_archive])]
781812
else:
782813
transitive_output_files = []
783814

784-
providers = []
785815
output_group_dicts = []
786816
for partial_output in partial_outputs:
787817
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)