From 636f7e0b69ad896ef6d90003cf8af2c73ccc4225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Seweryn=20Plaz=CC=87uk?= Date: Thu, 11 Apr 2024 08:42:35 +0200 Subject: [PATCH 1/3] Allow to opt-out from library evolution --- apple/internal/partials/swift_framework.bzl | 27 +++++++++----- apple/internal/swift_info_support.bzl | 36 +++++++++++++++++-- apple/internal/transition_support.bzl | 33 ++++++++++++++--- .../targets_under_test/apple/BUILD | 3 +- 4 files changed, 83 insertions(+), 16 deletions(-) diff --git a/apple/internal/partials/swift_framework.bzl b/apple/internal/partials/swift_framework.bzl index f160e59195..4a586ceacf 100644 --- a/apple/internal/partials/swift_framework.bzl +++ b/apple/internal/partials/swift_framework.bzl @@ -70,14 +70,25 @@ issue with a reproducible error case. found_module_name = swift_module.name - bundle_interface = swift_info_support.declare_swiftinterface( - actions = actions, - arch = arch, - label_name = label_name, - output_discriminator = output_discriminator, - swiftinterface = swift_module.swift.swiftinterface, - ) - bundle_files.append((processor.location.bundle, modules_parent, depset([bundle_interface]))) + # A swiftinterface will not be present when library evolution is disabled, if so, fallback to swiftmodule. + if swift_module.swift.swiftinterface: + bundle_interface = swift_info_support.declare_swiftinterface( + actions = actions, + arch = arch, + label_name = label_name, + output_discriminator = output_discriminator, + swiftinterface = swift_module.swift.swiftinterface, + ) + bundle_files.append((processor.location.bundle, modules_parent, depset([bundle_interface]))) + else: + bundle_swiftmodule = swift_info_support.declare_swiftmodule( + actions = actions, + arch = arch, + label_name = label_name, + output_discriminator = output_discriminator, + swiftmodule = swift_module.swift.swiftmodule, + ) + bundle_files.append((processor.location.bundle, modules_parent, depset([bundle_swiftmodule]))) bundle_doc = swift_info_support.declare_swiftdoc( actions = actions, diff --git a/apple/internal/swift_info_support.bzl b/apple/internal/swift_info_support.bzl index 6531fecbb7..04c61894dc 100644 --- a/apple/internal/swift_info_support.bzl +++ b/apple/internal/swift_info_support.bzl @@ -81,8 +81,7 @@ swift_library dependencies.\ """, ) - if not all([module.name, module.swift.swiftdoc, module.swift.swiftinterface]): - fail( + if not all([module.name, module.swift.swiftdoc]) or not (module.swift.swiftmodule or module.swift.swiftinterface): fail( """\ error: Could not find all required artifacts and information to build a Swift framework. \ Please file an issue with a reproducible error case.\ @@ -246,6 +245,38 @@ def _declare_swiftinterface( ) return bundle_interface +def _declare_swiftmodule( + *, + actions, + arch, + label_name, + output_discriminator, + swiftmodule): + """Declares the swiftmodule for this Swift framework. + + Args: + actions: The actions provider from `ctx.actions`. + arch: The cpu architecture that the generated swiftdoc belongs to. + label_name: Name of the target being built. + output_discriminator: A string to differentiate between different target intermediate files + or `None`. + swiftmodule: A File referencing the swiftmodule file from a SwiftInfo provider. + + Returns: + A File referencing the intermediate swiftmodule. + """ + bundle_module = intermediates.file( + actions = actions, + target_name = label_name, + output_discriminator = output_discriminator, + file_name = "{}.swiftmodule".format(arch), + ) + actions.symlink( + target_file = swiftmodule, + output = bundle_module, + ) + return bundle_module + swift_info_support = struct( verify_found_module_name = _verify_found_module_name, modules_from_avoid_deps = _modules_from_avoid_deps, @@ -254,4 +285,5 @@ swift_info_support = struct( declare_generated_header = _declare_generated_header, declare_swiftdoc = _declare_swiftdoc, declare_swiftinterface = _declare_swiftinterface, + declare_swiftmodule = _declare_swiftmodule, ) diff --git a/apple/internal/transition_support.bzl b/apple/internal/transition_support.bzl index 113f23255a..12102ee10a 100644 --- a/apple/internal/transition_support.bzl +++ b/apple/internal/transition_support.bzl @@ -320,6 +320,7 @@ def _resolved_environment_arch_for_arch(*, arch, environment, platform_type): def _command_line_options_for_xcframework_platform( *, + attr, minimum_os_version, platform_attr, platform_type, @@ -328,6 +329,7 @@ def _command_line_options_for_xcframework_platform( """Generates a dictionary of command line options keyed by 1:2+ transition for this platform. Args: + attr: The attributes passed to the transition function. minimum_os_version: A string representing the minimum OS version specified for this platform, represented as a dotted version number (for example, `"9.0"`). platform_attr: The attribute for the apple platform specifying in dictionary form which @@ -361,7 +363,10 @@ def _command_line_options_for_xcframework_platform( environment = target_environment, platform_type = platform_type, ): _command_line_options( - emit_swiftinterface = True, + emit_swiftinterface = _should_emit_swiftinterface( + attr, + is_xcframework = True, + ), environment_arch = resolved_environment_arch, minimum_os_version = minimum_os_version, platform_type = platform_type, @@ -372,11 +377,28 @@ def _command_line_options_for_xcframework_platform( return output_dictionary +def _should_emit_swiftinterface(attr, is_xcframework = False): + """Determines if a .swiftinterface file should be generated for Swift dependencies. + + Needed until users of the framework rules are allowed to enable + library evolution on specific targets instead of having it automatically + applied to the entire dependency subgraph. + """ + + features = getattr(attr, "features", []) + if type(features) == "list" and "apple.no_legacy_swiftinterface" in features: + return False + + # iOS and tvOS static frameworks require underlying swift_library targets generate a Swift + # interface file. These rules define a private attribute called `_emitswiftinterface` that + # let's this transition flip rules_swift config down the build graph. + return is_xcframework or hasattr(attr, "_emitswiftinterface") + def _apple_rule_base_transition_impl(settings, attr): """Rule transition for Apple rules using Bazel CPUs and a valid Apple split transition.""" platform_type = attr.platform_type return _command_line_options( - emit_swiftinterface = hasattr(attr, "_emitswiftinterface"), + emit_swiftinterface = _should_emit_swiftinterface(attr), environment_arch = _environment_archs(platform_type, settings)[0], minimum_os_version = attr.minimum_os_version, platform_type = platform_type, @@ -447,7 +469,7 @@ def _apple_platforms_rule_base_transition_impl(settings, attr): environment_arch = _environment_archs(platform_type, settings)[0] return _command_line_options( apple_platforms = settings["//command_line_option:apple_platforms"], - emit_swiftinterface = hasattr(attr, "_emitswiftinterface"), + emit_swiftinterface = _should_emit_swiftinterface(attr), environment_arch = environment_arch, minimum_os_version = minimum_os_version, platform_type = platform_type, @@ -470,7 +492,7 @@ def _apple_platforms_rule_bundle_output_base_transition_impl(settings, attr): environment_arch = _environment_archs(platform_type, settings)[0] return _command_line_options( apple_platforms = settings["//command_line_option:apple_platforms"], - emit_swiftinterface = hasattr(attr, "_emitswiftinterface"), + emit_swiftinterface = _should_emit_swiftinterface(attr), environment_arch = environment_arch, force_bundle_outputs = True, minimum_os_version = minimum_os_version, @@ -550,7 +572,7 @@ def _apple_platform_split_transition_impl(settings, attr): # iOS and tvOS static frameworks require underlying swift_library targets generate a Swift # interface file. These rules define a private attribute called `_emitswiftinterface` that # let's this transition flip rules_swift config down the build graph. - emit_swiftinterface = hasattr(attr, "_emitswiftinterface") + emit_swiftinterface = _should_emit_swiftinterface(attr) if settings["//command_line_option:incompatible_enable_apple_toolchain_resolution"]: platforms = ( @@ -665,6 +687,7 @@ def _xcframework_transition_impl(settings, attr): target_environments.append("simulator") command_line_options = _command_line_options_for_xcframework_platform( + attr = attr, minimum_os_version = attr.minimum_os_versions.get(platform_type), platform_attr = getattr(attr, platform_type), platform_type = platform_type, diff --git a/test/starlark_tests/targets_under_test/apple/BUILD b/test/starlark_tests/targets_under_test/apple/BUILD index b32a5ef42c..0e6b2def37 100644 --- a/test/starlark_tests/targets_under_test/apple/BUILD +++ b/test/starlark_tests/targets_under_test/apple/BUILD @@ -1244,7 +1244,8 @@ swift_library( swift_library( name = "Swift3PFmwkWithGenHeader", srcs = ["DummyFmwk.swift"], - features = ["swift.enable_library_evolution"], + # Uncomment when rule no longer enforces library evolution + # features = ["swift.enable_library_evolution"], generates_header = True, module_name = "Swift3PFmwkWithGenHeader", tags = common.fixture_tags, From 824c87cdacb499f563581c562ed69a5112ea85b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Seweryn=20Plaz=CC=87uk?= Date: Mon, 1 Jul 2024 13:21:26 +0200 Subject: [PATCH 2/3] Run buildifier. --- apple/internal/swift_info_support.bzl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apple/internal/swift_info_support.bzl b/apple/internal/swift_info_support.bzl index 04c61894dc..22bf14ff64 100644 --- a/apple/internal/swift_info_support.bzl +++ b/apple/internal/swift_info_support.bzl @@ -81,7 +81,8 @@ swift_library dependencies.\ """, ) - if not all([module.name, module.swift.swiftdoc]) or not (module.swift.swiftmodule or module.swift.swiftinterface): fail( + if not all([module.name, module.swift.swiftdoc]) or not (module.swift.swiftmodule or module.swift.swiftinterface): + fail( """\ error: Could not find all required artifacts and information to build a Swift framework. \ Please file an issue with a reproducible error case.\ From d591334bb77becb8c18600d7d74ad68c2ef52b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Seweryn=20Plaz=CC=87uk?= Date: Mon, 1 Jul 2024 13:23:56 +0200 Subject: [PATCH 3/3] Tests adjustments. --- test/starlark_tests/targets_under_test/apple/BUILD | 5 ----- test/starlark_tests/targets_under_test/ios/BUILD | 4 ---- 2 files changed, 9 deletions(-) diff --git a/test/starlark_tests/targets_under_test/apple/BUILD b/test/starlark_tests/targets_under_test/apple/BUILD index 0e6b2def37..d45d9f3aed 100644 --- a/test/starlark_tests/targets_under_test/apple/BUILD +++ b/test/starlark_tests/targets_under_test/apple/BUILD @@ -863,9 +863,6 @@ apple_xcframework( name = "ios_swift_3p_xcframework_with_generated_header", bundle_id = "com.google.example", bundle_name = "Swift3PFmwkWithGenHeader", - # TODO(b/239957001): Remove this when the rule no longer forces library - # evolution. - features = ["apple.no_legacy_swiftinterface"], infoplists = [ "//test/starlark_tests/resources:Info.plist", ], @@ -1244,8 +1241,6 @@ swift_library( swift_library( name = "Swift3PFmwkWithGenHeader", srcs = ["DummyFmwk.swift"], - # Uncomment when rule no longer enforces library evolution - # features = ["swift.enable_library_evolution"], generates_header = True, module_name = "Swift3PFmwkWithGenHeader", tags = common.fixture_tags, diff --git a/test/starlark_tests/targets_under_test/ios/BUILD b/test/starlark_tests/targets_under_test/ios/BUILD index f397b2615b..029fbce194 100644 --- a/test/starlark_tests/targets_under_test/ios/BUILD +++ b/test/starlark_tests/targets_under_test/ios/BUILD @@ -3885,9 +3885,6 @@ ios_static_framework( ios_static_framework( name = "static_framework_with_generated_header", bundle_name = "SwiftStaticFmwkWithGenHeader", - # TODO(b/239957001): Remove this when the rule no longer forces library - # evolution. - features = ["apple.no_legacy_swiftinterface"], minimum_os_version = common.min_os_ios.baseline, tags = common.fixture_tags, deps = [":SwiftStaticFmwkWithGenHeader"], @@ -3985,7 +3982,6 @@ swift_library( swift_library( name = "SwiftStaticFmwkWithGenHeader", srcs = [":dummy_swift"], - features = ["swift.enable_library_evolution"], generates_header = True, module_name = "SwiftStaticFmwkWithGenHeader", tags = common.fixture_tags,