Skip to content

Commit

Permalink
No public description
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 573783919
  • Loading branch information
allevato authored and swiple-rules-gardener committed Oct 16, 2023
1 parent 887031a commit 6cae838
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 24 deletions.
44 changes: 33 additions & 11 deletions swift/internal/providers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,47 @@ visibility([
"@build_bazel_rules_swift//swift/...",
])

SwiftCompilerPluginInfo = provider(
doc = "Information about compiler plugins, like macros.",
SwiftBinaryInfo = provider(
doc = """
Information about a binary target's module.
`swift_binary` and `swift_compiler_plugin` propagate this provider that wraps
`CcInfo` and `SwiftInfo` providers, instead of propagating them directly, so
that `swift_test` targets can depend on those binaries and test their modules
(similar to what Swift Package Manager allows) without allowing any
`swift_library` to depend on an arbitrary binary.
""",
fields = {
"cc_info": """\
A `CcInfo` provider containing the `swift_compiler_plugin`'s code compiled as a
static library, which is suitable for linking into a `swift_test` so that unit
tests can be written against it.
A `CcInfo` provider containing the binary's code compiled as a static library,
which is suitable for linking into a `swift_test` so that unit tests can be
written against it.
Notably, this `CcInfo`'s linking context does *not* contain the linker flags
used to alias the `main` entry point function, because the purpose of this
provider is to allow it to be linked into another binary that would provide its
own entry point instead.
""",
"swift_info": """\
A `SwiftInfo` provider representing the Swift module created by compiling the
target. This is used specifically by `swift_test` to allow test code to depend
on the binary's module without making it possible for arbitrary libraries or
binaries to depend on other binaries.
""",
},
)

SwiftCompilerPluginInfo = provider(
doc = """
Information about compiler plugins (like macros) that is needed by the compiler
when loading modules that declare those macros.
""",
fields = {
"executable": "A `File` representing the plugin's binary executable.",
"module_names": """\
A `depset` of strings denoting the names of the Swift modules that provide
plugin types looked up by the compiler. This currently contains a single
element, the name of the module created by the `swift_compiler_plugin` target.
""",
"swift_info": """\
A `SwiftInfo` provider representing the Swift module created by the
`swift_compiler_plugin` target. This is used specifically by `swift_test` to
allow test code to depend on the plugin's module without making it possible for
arbitrary libraries/binaries to depend on a plugin.
""",
},
)
Expand Down
75 changes: 68 additions & 7 deletions swift/swift_binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ load(
"@build_bazel_rules_swift//swift/internal:linking.bzl",
"binary_rule_attrs",
"configure_features_for_binary",
"create_linking_context_from_compilation_outputs",
"malloc_linking_context",
"register_link_binary_action",
)
Expand All @@ -32,6 +33,7 @@ load(
)
load(
"@build_bazel_rules_swift//swift/internal:providers.bzl",
"SwiftBinaryInfo",
"SwiftCompilerPluginInfo",
)
load(
Expand Down Expand Up @@ -70,6 +72,7 @@ def _swift_binary_impl(ctx):
module_name = ctx.attr.module_name
if not module_name:
module_name = derive_swift_module_name(ctx.label)
entry_point_function_name = "{}_main".format(module_name)

compile_result = compile(
actions = ctx.actions,
Expand All @@ -79,7 +82,15 @@ def _swift_binary_impl(ctx):
ctx,
ctx.attr.copts,
ctx.attr.swiftc_inputs,
),
) + [
# Use a custom entry point name so that the binary's code can
# also be linked into another process (like a test executable)
# without having its main function collide.
"-Xfrontend",
"-entry-point-function-name",
"-Xfrontend",
entry_point_function_name,
],
defines = ctx.attr.defines,
feature_configuration = feature_configuration,
module_name = module_name,
Expand All @@ -96,6 +107,8 @@ def _swift_binary_impl(ctx):
supplemental_outputs,
)
else:
compile_result = None
entry_point_function_name = None
compilation_outputs = cc_common.create_compilation_outputs()

# Apply the optional debugging outputs extension if the toolchain defines
Expand All @@ -109,6 +122,20 @@ def _swift_binary_impl(ctx):
additional_debug_outputs = []
variables_extension = {}

binary_link_flags = expand_locations(
ctx,
ctx.attr.linkopts,
ctx.attr.swiftc_inputs,
) + ctx.fragments.cpp.linkopts

# When linking the binary, make sure we use the correct entry point name.
if entry_point_function_name:
entry_point_linkopts = swift_toolchain.entry_point_linkopts_provider(
entry_point_name = entry_point_function_name,
).linkopts
else:
entry_point_linkopts = []

linking_outputs = register_link_binary_action(
actions = ctx.actions,
additional_inputs = ctx.files.swiftc_inputs,
Expand All @@ -122,15 +149,11 @@ def _swift_binary_impl(ctx):
output_type = "executable",
stamp = ctx.attr.stamp,
swift_toolchain = swift_toolchain,
user_link_flags = expand_locations(
ctx,
ctx.attr.linkopts,
ctx.attr.swiftc_inputs,
) + ctx.fragments.cpp.linkopts,
user_link_flags = binary_link_flags + entry_point_linkopts,
variables_extension = variables_extension,
)

return [
providers = [
DefaultInfo(
executable = linking_outputs.executable,
files = depset(
Expand All @@ -145,6 +168,44 @@ def _swift_binary_impl(ctx):
OutputGroupInfo(**output_groups),
]

# Only create a linking context and propagate `SwiftBinaryInfo` if this rule
# compiled something (i.e., it had sources). If it didn't, then there's
# nothing to allow testing against.
if compile_result:
linking_context, _ = (
create_linking_context_from_compilation_outputs(
actions = ctx.actions,
additional_inputs = ctx.files.swiftc_inputs,
alwayslink = True,
compilation_outputs = compilation_outputs,
feature_configuration = feature_configuration,
label = ctx.label,
linking_contexts = [
dep[CcInfo].linking_context
for dep in ctx.attr.deps
if CcInfo in dep
],
module_context = compile_result.module_context,
swift_toolchain = swift_toolchain,
# Exclude the entry point linkopts from this linking context,
# because it is meant to be used by other binary rules that
# provide their own entry point while linking this "binary" in
# as a library.
user_link_flags = binary_link_flags,
)
)
providers.append(SwiftBinaryInfo(
cc_info = CcInfo(
compilation_context = (
compile_result.module_context.clang.compilation_context
),
linking_context = linking_context,
),
swift_info = compile_result.swift_info,
))

return providers

swift_binary = rule(
attrs = dicts.add(
binary_rule_attrs(stamp_default = -1),
Expand Down
7 changes: 5 additions & 2 deletions swift/swift_compiler_plugin.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ load(
)
load(
"@build_bazel_rules_swift//swift/internal:providers.bzl",
"SwiftBinaryInfo",
"SwiftCompilerPluginInfo",
)
load(
Expand Down Expand Up @@ -179,14 +180,16 @@ def _swift_compiler_plugin_impl(ctx):
OutputGroupInfo(
**supplemental_compilation_output_groups(supplemental_outputs)
),
SwiftCompilerPluginInfo(
SwiftBinaryInfo(
cc_info = CcInfo(
compilation_context = module_context.clang.compilation_context,
linking_context = linking_context,
),
swift_info = compile_result.swift_info,
),
SwiftCompilerPluginInfo(
executable = binary_linking_outputs.executable,
module_names = depset([module_name]),
swift_info = compile_result.swift_info,
),
]

Expand Down
9 changes: 5 additions & 4 deletions swift/swift_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ load(
)
load(
"@build_bazel_rules_swift//swift/internal:providers.bzl",
"SwiftBinaryInfo",
"SwiftCompilerPluginInfo",
)
load(
Expand Down Expand Up @@ -323,8 +324,8 @@ def _swift_test_impl(ctx):
else:
additional_link_deps = []

# We also need to collect nested providers from `SwiftCompilerPluginInfo`
# since we support testing those.
# We also need to collect nested providers from `SwiftBinaryInfo` since we
# support testing those.
deps_compilation_contexts = []
deps_swift_infos = []
plugin_linking_contexts = []
Expand All @@ -333,8 +334,8 @@ def _swift_test_impl(ctx):
deps_compilation_contexts.append(dep[CcInfo].compilation_context)
if SwiftInfo in dep:
deps_swift_infos.append(dep[SwiftInfo])
if SwiftCompilerPluginInfo in dep:
plugin_info = dep[SwiftCompilerPluginInfo]
if SwiftBinaryInfo in dep:
plugin_info = dep[SwiftBinaryInfo]
deps_compilation_contexts.append(
plugin_info.cc_info.compilation_context,
)
Expand Down

1 comment on commit 6cae838

@brentleyjones
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.