Skip to content

Commit 680c227

Browse files
authored
Support tree artifact outputs in XCFramework rules (#2785)
Manual cherry-pick of: 3276c83 One thing i noticed was `upstream` is generating different static xcframeworks than we are, i didnt want to change that in this PR and not entirely sure which is correct. Test from upstream: ``` expected_directories = { "ios_static_xcframework.xcframework": [ "Info.plist", "ios-arm64/ios_static_xcframework.a", "ios-arm64/Headers/ios_static_xcframework/ios_static_xcframework.h", "ios-arm64/Headers/ios_static_xcframework/module.modulemap", "ios-arm64/Headers/ios_static_xcframework/shared.h", "ios-arm64_x86_64-simulator/ios_static_xcframework.a", "ios-arm64_x86_64-simulator/Headers/ios_static_xcframework/ios_static_xcframework.h", "ios-arm64_x86_64-simulator/Headers/ios_static_xcframework/module.modulemap", "ios-arm64_x86_64-simulator/Headers/ios_static_xcframework/shared.h", ], }, ``` Compared to what is created in `master` today: ``` expected_directories = { "ios_static_xcframework.xcframework": [ "Info.plist", "ios-arm64/ios_static_xcframework.framework/ios_static_xcframework", "ios-arm64/ios_static_xcframework.framework/Headers/ios_static_xcframework.h", "ios-arm64/ios_static_xcframework.framework/Headers/shared.h", "ios-arm64/ios_static_xcframework.framework/Modules/module.modulemap", "ios-arm64_x86_64-simulator/ios_static_xcframework.framework/ios_static_xcframework", "ios-arm64_x86_64-simulator/ios_static_xcframework.framework/Headers/ios_static_xcframework.h", "ios-arm64_x86_64-simulator/ios_static_xcframework.framework/Headers/shared.h", "ios-arm64_x86_64-simulator/ios_static_xcframework.framework/Modules/module.modulemap", ], }, ```
1 parent 99515aa commit 680c227

File tree

9 files changed

+358
-37
lines changed

9 files changed

+358
-37
lines changed

apple/internal/outputs.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def _archive(
3737
bundle_extension,
3838
bundle_name,
3939
label_name,
40+
output_discriminator = "",
4041
platform_prerequisites,
4142
predeclared_outputs,
4243
rule_descriptor):
@@ -53,6 +54,11 @@ def _archive(
5354
return actions.declare_directory(
5455
paths.join(root_path, archive_relative_path, bundle_name_with_extension),
5556
)
57+
if output_discriminator:
58+
return actions.declare_directory(paths.join(
59+
output_discriminator,
60+
bundle_name_with_extension,
61+
))
5662

5763
return actions.declare_directory(bundle_name_with_extension)
5864
return predeclared_outputs.archive

apple/internal/partials/apple_bundle_info.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def _apple_bundle_info_partial_impl(
4949
bundle_name = bundle_name,
5050
bundle_extension = bundle_extension,
5151
label_name = label_name,
52+
output_discriminator = output_discriminator,
5253
platform_prerequisites = platform_prerequisites,
5354
predeclared_outputs = predeclared_outputs,
5455
rule_descriptor = rule_descriptor,

apple/internal/partials/codesigning_dossier.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ def _codesigning_dossier_partial_impl(
315315
bundle_extension = bundle_extension,
316316
bundle_name = bundle_name,
317317
label_name = label_name,
318+
output_discriminator = output_discriminator,
318319
platform_prerequisites = platform_prerequisites,
319320
predeclared_outputs = predeclared_outputs,
320321
rule_descriptor = rule_descriptor,

apple/internal/processor.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ def _process(
753753
bundle_extension = bundle_extension,
754754
bundle_name = bundle_name,
755755
label_name = rule_label.name,
756+
output_discriminator = output_discriminator,
756757
platform_prerequisites = platform_prerequisites,
757758
predeclared_outputs = predeclared_outputs,
758759
rule_descriptor = rule_descriptor,

apple/internal/xcframework_rules.bzl

Lines changed: 103 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -422,20 +422,27 @@ def _create_xcframework_root_infoplist(
422422
def _create_xcframework_bundle(
423423
*,
424424
actions,
425+
apple_fragment,
426+
apple_mac_toolchain_info,
427+
apple_xplat_toolchain_info,
425428
bundle_name,
426-
bundletool,
427429
framework_archive_files,
428430
framework_archive_merge_files,
429431
framework_archive_merge_zips = [],
430432
label_name,
431433
output_archive,
432-
root_info_plist):
434+
root_info_plist,
435+
tree_artifact_enabled,
436+
xcode_config):
433437
"""Generates the bundle archive for an XCFramework.
434438
435439
Args:
436440
actions: The actions providerx from `ctx.actions`.
441+
apple_fragment: An Apple fragment (ctx.fragments.apple).
442+
apple_mac_toolchain_info: The `AppleMacToolsToolchainInfo` provider from the mac toolchain.
443+
apple_xplat_toolchain_info: The `AppleXPlatToolsToolchainInfo` provider from the xplat
444+
toolchain.
437445
bundle_name: The name of the XCFramework bundle.
438-
bundletool: A files to run for the bundle tool.
439446
framework_archive_files: A list of depsets referencing files to be used as inputs to the
440447
bundling action. This should include every archive referenced as a "src" of
441448
framework_archive_merge_zips.
@@ -451,6 +458,8 @@ def _create_xcframework_bundle(
451458
label_name: Name of the target being built.
452459
output_archive: The file representing the final bundled archive.
453460
root_info_plist: A `File` representing a fully formed root Info.plist for this XCFramework.
461+
tree_artifact_enabled: A boolean indicating whether tree artifact outputs are enabled.
462+
xcode_config: The `apple_common.XcodeVersionConfig` provider from the context.
454463
"""
455464
bundletool_control_file = intermediates.file(
456465
actions = actions,
@@ -471,17 +480,43 @@ def _create_xcframework_bundle(
471480
content = json.encode(bundletool_control),
472481
)
473482

474-
actions.run(
475-
arguments = [bundletool_control_file.path],
476-
executable = bundletool,
477-
inputs = depset(
478-
direct = [bundletool_control_file, root_info_plist],
479-
transitive = framework_archive_files,
480-
),
481-
mnemonic = "CreateXCFrameworkBundle",
482-
outputs = [output_archive],
483-
progress_message = "Bundling %s" % label_name,
484-
)
483+
if tree_artifact_enabled:
484+
bundletool = apple_mac_toolchain_info.bundletool_experimental
485+
apple_support.run(
486+
actions = actions,
487+
apple_fragment = apple_fragment,
488+
arguments = [bundletool_control_file.path],
489+
executable = bundletool,
490+
execution_requirements = {
491+
# Added so that the output of this action is not cached remotely, in case multiple
492+
# developers sign the same artifact with different identities.
493+
"no-remote": "1",
494+
# Unsure, but may be needed for keychain access, especially for files that live in
495+
# $HOME.
496+
"no-sandbox": "1",
497+
},
498+
inputs = depset(
499+
direct = [bundletool_control_file, root_info_plist],
500+
transitive = framework_archive_files,
501+
),
502+
mnemonic = "CreateXCFrameworkBundle",
503+
outputs = [output_archive],
504+
progress_message = "Bundling %s" % label_name,
505+
xcode_config = xcode_config,
506+
)
507+
else:
508+
bundletool = apple_xplat_toolchain_info.bundletool
509+
actions.run(
510+
arguments = [bundletool_control_file.path],
511+
executable = bundletool,
512+
inputs = depset(
513+
direct = [bundletool_control_file, root_info_plist],
514+
transitive = framework_archive_files,
515+
),
516+
mnemonic = "CreateXCFrameworkBundle",
517+
outputs = [output_archive],
518+
progress_message = "Bundling %s" % label_name,
519+
)
485520

486521
def _apple_xcframework_impl(ctx):
487522
"""Implementation of apple_xcframework."""
@@ -492,12 +527,18 @@ def _apple_xcframework_impl(ctx):
492527
cc_toolchain_forwarder = ctx.split_attr._cc_toolchain_forwarder
493528
executable_name = getattr(ctx.attr, "executable_name", bundle_name)
494529
deps = ctx.split_attr.deps
530+
xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig]
495531

532+
tree_artifact_enabled = False
533+
outputs_archive = ctx.outputs.archive
496534
if (apple_xplat_toolchain_info.build_settings.use_tree_artifacts_outputs or
497535
is_experimental_tree_artifact_enabled(config_vars = ctx.var)):
498-
fail("The apple_xcframework rule does not yet support the experimental tree artifact. " +
499-
"Please ensure that the `apple.experimental.tree_artifact_outputs` variable is not " +
500-
"set to 1 on the command line or in your active build configuration.")
536+
actions.write(
537+
output = ctx.outputs.archive,
538+
content = "This is a dummy file because tree artifacts are enabled",
539+
)
540+
tree_artifact_enabled = True
541+
outputs_archive = actions.declare_directory(bundle_name + ".xcframework")
501542

502543
# Add the disable_legacy_signing feature to the list of features
503544
# TODO(b/72148898): Remove this when dossier based signing becomes the default.
@@ -553,7 +594,7 @@ def _apple_xcframework_impl(ctx):
553594
deps = deps,
554595
label_name = label.name,
555596
link_result = link_result,
556-
xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig],
597+
xcode_config = xcode_config,
557598
)
558599

559600
available_libraries = []
@@ -741,10 +782,25 @@ def _apple_xcframework_impl(ctx):
741782
for provider in processor_result.providers:
742783
# Save the framework archive.
743784
if getattr(provider, "archive", None):
744-
# Repackage every archive found for bundle_merge_zips in the final bundler action.
745-
framework_archive_merge_zips.append(
746-
struct(src = provider.archive.path, dest = library_identifier),
747-
)
785+
# Repackage every archive found for bundle_merge_files or bundle_merge_zips in the
786+
# final bundler action, depending on whether tree artifacts are enabled.
787+
if tree_artifact_enabled:
788+
framework_archive_merge_files.append(
789+
struct(
790+
src = provider.archive.path,
791+
dest = paths.join(
792+
library_identifier,
793+
bundle_name + nested_bundle_extension,
794+
),
795+
),
796+
)
797+
else:
798+
framework_archive_merge_zips.append(
799+
struct(
800+
src = provider.archive.path,
801+
dest = library_identifier,
802+
),
803+
)
748804

749805
# Save a reference to those archives as file-friendly inputs to the bundler action.
750806
framework_archive_files.append(depset([provider.archive]))
@@ -775,25 +831,29 @@ def _apple_xcframework_impl(ctx):
775831
available_libraries = available_libraries,
776832
plisttool = apple_mac_toolchain_info.plisttool,
777833
rule_label = label,
778-
xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig],
834+
xcode_config = xcode_config,
779835
)
780836

781837
_create_xcframework_bundle(
782838
actions = actions,
839+
apple_fragment = ctx.fragments.apple,
840+
apple_mac_toolchain_info = apple_mac_toolchain_info,
841+
apple_xplat_toolchain_info = apple_xplat_toolchain_info,
783842
bundle_name = bundle_name,
784-
bundletool = apple_xplat_toolchain_info.bundletool,
785843
framework_archive_files = framework_archive_files,
786844
framework_archive_merge_files = framework_archive_merge_files,
787845
framework_archive_merge_zips = framework_archive_merge_zips,
788846
label_name = label.name,
789-
output_archive = ctx.outputs.archive,
847+
output_archive = outputs_archive,
790848
root_info_plist = root_info_plist,
849+
tree_artifact_enabled = tree_artifact_enabled,
850+
xcode_config = xcode_config,
791851
)
792852

793853
processor_output = [
794854
# Limiting the contents of AppleBundleInfo to what is necessary for testing and validation.
795855
new_applebundleinfo(
796-
archive = ctx.outputs.archive,
856+
archive = outputs_archive,
797857
bundle_extension = ".xcframework",
798858
bundle_id = nested_bundle_id,
799859
bundle_name = bundle_name,
@@ -803,7 +863,7 @@ def _apple_xcframework_impl(ctx):
803863
),
804864
new_applexcframeworkbundleinfo(),
805865
DefaultInfo(
806-
files = depset([ctx.outputs.archive], transitive = framework_output_files),
866+
files = depset([outputs_archive], transitive = framework_output_files),
807867
),
808868
OutputGroupInfo(
809869
**outputs.merge_output_groups(
@@ -970,9 +1030,19 @@ def _apple_static_xcframework_impl(ctx):
9701030
requested_features = ctx.features,
9711031
unsupported_features = ctx.disabled_features,
9721032
)
973-
outputs_archive = ctx.outputs.archive
9741033
xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig]
9751034

1035+
tree_artifact_enabled = False
1036+
outputs_archive = ctx.outputs.archive
1037+
if (apple_xplat_toolchain_info.build_settings.use_tree_artifacts_outputs or
1038+
is_experimental_tree_artifact_enabled(config_vars = ctx.var)):
1039+
actions.write(
1040+
output = ctx.outputs.archive,
1041+
content = "This is a dummy file because tree artifacts are enabled",
1042+
)
1043+
tree_artifact_enabled = True
1044+
outputs_archive = actions.declare_directory(bundle_name + ".xcframework")
1045+
9761046
archive_result = linking_support.register_static_library_archive_action(
9771047
ctx = ctx,
9781048
cc_toolchains = cc_toolchain_forwarder,
@@ -1145,13 +1215,17 @@ def _apple_static_xcframework_impl(ctx):
11451215

11461216
_create_xcframework_bundle(
11471217
actions = actions,
1218+
apple_fragment = apple_fragment,
1219+
apple_mac_toolchain_info = apple_mac_toolchain_info,
1220+
apple_xplat_toolchain_info = apple_xplat_toolchain_info,
11481221
bundle_name = bundle_name,
1149-
bundletool = apple_xplat_toolchain_info.bundletool,
11501222
framework_archive_files = framework_archive_files,
11511223
framework_archive_merge_files = framework_archive_merge_files,
11521224
label_name = label.name,
11531225
output_archive = outputs_archive,
11541226
root_info_plist = root_info_plist,
1227+
tree_artifact_enabled = tree_artifact_enabled,
1228+
xcode_config = xcode_config,
11551229
)
11561230

11571231
return [

test/starlark_tests/apple_static_xcframework_tests.bzl

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

1515
"""xcframework Starlark tests."""
1616

17+
load(
18+
"//apple/build_settings:build_settings.bzl",
19+
"build_settings_labels",
20+
)
1721
load(
1822
"//test/starlark_tests/rules:analysis_failure_message_test.bzl",
1923
"analysis_failure_message_test",
@@ -22,6 +26,10 @@ load(
2226
"//test/starlark_tests/rules:common_verification_tests.bzl",
2327
"archive_contents_test",
2428
)
29+
load(
30+
"//test/starlark_tests/rules:directory_test.bzl",
31+
"directory_test",
32+
)
2533
load(
2634
":common.bzl",
2735
"common",
@@ -283,6 +291,54 @@ def apple_static_xcframework_test_suite(name):
283291
tags = [name],
284292
)
285293

294+
directory_test(
295+
name = "{}_ios_static_library_xcframework_tree_artifact_test".format(name),
296+
build_settings = {
297+
build_settings_labels.use_tree_artifacts_outputs: "True",
298+
},
299+
target_under_test = "//test/starlark_tests/targets_under_test/apple:ios_static_xcframework",
300+
expected_directories = {
301+
"ios_static_xcframework.xcframework": [
302+
"Info.plist",
303+
"ios-arm64/ios_static_xcframework.framework/ios_static_xcframework",
304+
"ios-arm64/ios_static_xcframework.framework/Headers/ios_static_xcframework.h",
305+
"ios-arm64/ios_static_xcframework.framework/Headers/shared.h",
306+
"ios-arm64/ios_static_xcframework.framework/Modules/module.modulemap",
307+
"ios-arm64_x86_64-simulator/ios_static_xcframework.framework/ios_static_xcframework",
308+
"ios-arm64_x86_64-simulator/ios_static_xcframework.framework/Headers/ios_static_xcframework.h",
309+
"ios-arm64_x86_64-simulator/ios_static_xcframework.framework/Headers/shared.h",
310+
"ios-arm64_x86_64-simulator/ios_static_xcframework.framework/Modules/module.modulemap",
311+
],
312+
},
313+
tags = [name],
314+
)
315+
316+
directory_test(
317+
name = "{}_ios_static_framework_xcframework_tree_artifact_test".format(name),
318+
build_settings = {
319+
build_settings_labels.use_tree_artifacts_outputs: "True",
320+
},
321+
target_under_test = "//test/starlark_tests/targets_under_test/apple:ios_static_framework_xcframework_with_deps_resource_bundle",
322+
expected_directories = {
323+
"ios_static_framework_xcframework_with_deps_resource_bundle.xcframework": [
324+
"Info.plist",
325+
"ios-arm64/ios_static_framework_xcframework_with_deps_resource_bundle.framework/ios_static_framework_xcframework_with_deps_resource_bundle",
326+
"ios-arm64/ios_static_framework_xcframework_with_deps_resource_bundle.framework/Headers/ios_static_framework_xcframework_with_deps_resource_bundle.h",
327+
"ios-arm64/ios_static_framework_xcframework_with_deps_resource_bundle.framework/Headers/shared.h",
328+
"ios-arm64/ios_static_framework_xcframework_with_deps_resource_bundle.framework/Modules/module.modulemap",
329+
"ios-arm64/ios_static_framework_xcframework_with_deps_resource_bundle.framework/resource_bundle.bundle/custom_apple_resource_info.out",
330+
"ios-arm64/ios_static_framework_xcframework_with_deps_resource_bundle.framework/resource_bundle.bundle/Info.plist",
331+
"ios-x86_64-simulator/ios_static_framework_xcframework_with_deps_resource_bundle.framework/ios_static_framework_xcframework_with_deps_resource_bundle",
332+
"ios-x86_64-simulator/ios_static_framework_xcframework_with_deps_resource_bundle.framework/Headers/ios_static_framework_xcframework_with_deps_resource_bundle.h",
333+
"ios-x86_64-simulator/ios_static_framework_xcframework_with_deps_resource_bundle.framework/Headers/shared.h",
334+
"ios-x86_64-simulator/ios_static_framework_xcframework_with_deps_resource_bundle.framework/Modules/module.modulemap",
335+
"ios-x86_64-simulator/ios_static_framework_xcframework_with_deps_resource_bundle.framework/resource_bundle.bundle/custom_apple_resource_info.out",
336+
"ios-x86_64-simulator/ios_static_framework_xcframework_with_deps_resource_bundle.framework/resource_bundle.bundle/Info.plist",
337+
],
338+
},
339+
tags = [name],
340+
)
341+
286342
native.test_suite(
287343
name = name,
288344
tags = [name],

0 commit comments

Comments
 (0)