Skip to content

Commit

Permalink
Allow to opt-out from library evolution (#2484)
Browse files Browse the repository at this point in the history
As the title says. A followup on #2401 (closed as I reorganised my fork
a bit).
  • Loading branch information
sewerynplazuk authored Sep 25, 2024
1 parent 0309ba6 commit ccddf99
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 22 deletions.
27 changes: 19 additions & 8 deletions apple/internal/partials/swift_framework.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
35 changes: 34 additions & 1 deletion apple/internal/swift_info_support.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ swift_library dependencies.\
""",
)

if not all([module.name, module.swift.swiftdoc, module.swift.swiftinterface]):
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. \
Expand Down Expand Up @@ -246,6 +246,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,
Expand All @@ -254,4 +286,5 @@ swift_info_support = struct(
declare_generated_header = _declare_generated_header,
declare_swiftdoc = _declare_swiftdoc,
declare_swiftinterface = _declare_swiftinterface,
declare_swiftmodule = _declare_swiftmodule,
)
33 changes: 28 additions & 5 deletions apple/internal/transition_support.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 = (
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 0 additions & 4 deletions test/starlark_tests/targets_under_test/apple/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
],
Expand Down Expand Up @@ -1271,7 +1268,6 @@ swift_library(
swift_library(
name = "Swift3PFmwkWithGenHeader",
srcs = ["DummyFmwk.swift"],
features = ["swift.enable_library_evolution"],
generates_header = True,
module_name = "Swift3PFmwkWithGenHeader",
tags = common.fixture_tags,
Expand Down
4 changes: 0 additions & 4 deletions test/starlark_tests/targets_under_test/ios/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -4071,9 +4071,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"],
Expand Down Expand Up @@ -4171,7 +4168,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,
Expand Down

0 comments on commit ccddf99

Please sign in to comment.