Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Swift build rules to the new C++ LinkerInput APIs. #521

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 42 additions & 27 deletions swift/internal/linking.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -94,41 +94,49 @@ def _register_static_library_link_action(
progress_message = "Linking {}".format(output.short_path),
)

def register_libraries_to_link(
owning_label,
def create_linker_input(
*,
actions,
alwayslink,
cc_feature_configuration,
compilation_outputs,
is_dynamic,
is_static,
library_name,
objects,
owner,
swift_toolchain,
user_link_flags,
additional_inputs):
"""Declares the requested libraries and registers actions to link them.
additional_inputs = [],
user_link_flags = []):
"""Creates a linker input for a library to link and additional inputs/flags.

Args:
owning_label: Label executing rule (i.e., ctx.label).
actions: The object used to register actions.
alwayslink: If True, create a static library that should be
always-linked (having a `.lo` extension instead of `.a`). This
argument is ignored if `is_static` is False.
cc_feature_configuration: The C++ feature configuration to use when
constructing the action.
compilation_outputs: The compilation outputs from a Swift compile
action, as returned by `swift_common.compile`, or None.
is_dynamic: If True, declare and link a dynamic library.
is_static: If True, declare and link a static library.
library_name: The basename (without extension) of the libraries to
declare.
objects: A list of `File`s denoting object (`.o`) files that will be
linked.
owner: The `Label` of the target that owns this linker input.
swift_toolchain: The Swift toolchain provider to use when constructing
the action.
user_link_flags: Extra link flags to be passed with the library.
additional_inputs: Extra inputs for a link action involving the library.
additional_inputs: A list of extra `File` inputs passed to the linking
action.
user_link_flags: A list of extra flags to pass to the linking command.

Returns:
A `LinkerInput` object containing the libraries that were created.
A tuple containing two elements:

1. A `LinkerInput` object containing the library that was created.
2. The single `LibraryToLink` object that is inside the linker input.
"""
dynamic_library = None
if is_dynamic:
Expand All @@ -151,21 +159,26 @@ def register_libraries_to_link(
else:
static_library = None

return cc_common.create_linker_input(
owner = owning_label,
libraries = depset(direct = [
cc_common.create_library_to_link(
actions = actions,
alwayslink = alwayslink,
cc_toolchain = swift_toolchain.cc_toolchain_info,
feature_configuration = cc_feature_configuration,
pic_static_library = static_library,
dynamic_library = dynamic_library,
),
]),
additional_inputs = depset(direct = additional_inputs),
user_link_flags = depset(direct = user_link_flags),
library_to_link = cc_common.create_library_to_link(
actions = actions,
alwayslink = alwayslink,
cc_toolchain = swift_toolchain.cc_toolchain_info,
feature_configuration = cc_feature_configuration,
pic_static_library = static_library,
dynamic_library = dynamic_library,
)
linker_input = cc_common.create_linker_input(
owner = owner,
libraries = depset([library_to_link]),
additional_inputs = depset(
compilation_outputs.linker_inputs + additional_inputs,
),
user_link_flags = depset(
compilation_outputs.linker_flags + user_link_flags,
),
)

return linker_input, library_to_link

def register_link_binary_action(
owning_label,
Expand All @@ -178,6 +191,7 @@ def register_link_binary_action(
name,
objects,
output_type,
owner,
stamp,
swift_toolchain,
user_link_flags):
Expand All @@ -201,6 +215,7 @@ def register_link_binary_action(
objects: A list of object (.o) files that will be passed to the linker.
output_type: A string indicating the output type; "executable" or
"dynamic_library".
owner: The `Label` of the target that owns this linker input.
stamp: A tri-state value (-1, 0, or 1) that specifies whether link
stamping is enabled. See `cc_common.link` for details about the
behavior of this argument.
Expand Down Expand Up @@ -246,12 +261,12 @@ def register_link_binary_action(

linking_contexts.append(
cc_common.create_linking_context(
linker_inputs = depset(direct = [
linker_inputs = depset([
cc_common.create_linker_input(
owner = owning_label,
user_link_flags = depset(direct = dep_link_flags),
owner = owner,
user_link_flags = depset(dep_link_flags),
),
])
]),
),
)

Expand Down
1 change: 1 addition & 0 deletions swift/internal/swift_binary_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ def _swift_linking_rule_impl(
name = ctx.label.name,
objects = objects_to_link,
output_type = "executable",
owner = ctx.label,
stamp = ctx.attr.stamp,
swift_toolchain = swift_toolchain,
user_link_flags = user_link_flags,
Expand Down
7 changes: 4 additions & 3 deletions swift/internal/swift_grpc_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ load(
"SWIFT_FEATURE_GENERATE_FROM_RAW_PROTO_FILES",
"SWIFT_FEATURE_NO_GENERATED_HEADER",
)
load(":linking.bzl", "register_libraries_to_link")
load(":linking.bzl", "create_linker_input")
load(
":proto_gen_utils.bzl",
"declare_generated_files",
Expand Down Expand Up @@ -293,17 +293,18 @@ def _swift_grpc_library_impl(ctx):
target_name = ctx.label.name,
)

linker_input = register_libraries_to_link(
owning_label = ctx.label,
linker_input, library_to_link = create_linker_input(
actions = ctx.actions,
alwayslink = False,
cc_feature_configuration = swift_common.cc_feature_configuration(
feature_configuration = feature_configuration,
),
compilation_outputs = compilation_outputs,
is_dynamic = False,
is_static = True,
library_name = ctx.label.name,
objects = compilation_outputs.object_files,
owner = ctx.label,
swift_toolchain = swift_toolchain,
additional_inputs = compilation_outputs.linker_inputs,
user_link_flags = compilation_outputs.linker_flags,
Expand Down
27 changes: 13 additions & 14 deletions swift/internal/swift_import.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,18 @@ def _swift_import_impl(ctx):
unsupported_features = ctx.disabled_features,
)

linker_inputs = [
cc_common.create_linker_input(
libraries = depset(direct = [
cc_common.create_library_to_link(
actions = ctx.actions,
cc_toolchain = cc_toolchain,
feature_configuration = cc_feature_configuration,
static_library = archive,
)
for archive in archives
]),
),
]
linker_input = cc_common.create_linker_input(
owner = ctx.label,
libraries = depset([
cc_common.create_library_to_link(
actions = ctx.actions,
cc_toolchain = cc_toolchain,
feature_configuration = cc_feature_configuration,
static_library = archive,
)
for archive in archives
]),
)

providers = [
DefaultInfo(
Expand All @@ -63,7 +62,7 @@ def _swift_import_impl(ctx):
),
create_cc_info(
cc_infos = get_providers(deps, CcInfo),
linker_inputs = linker_inputs,
linker_inputs = [linker_input],
),
# Propagate an `Objc` provider so that Apple-specific rules like
# apple_binary` will link the imported library properly. Typically we'd
Expand Down
9 changes: 5 additions & 4 deletions swift/internal/swift_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ load(
"SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION",
"SWIFT_FEATURE_SUPPORTS_PRIVATE_DEPS",
)
load(":linking.bzl", "register_libraries_to_link")
load(":linking.bzl", "create_linker_input")
load(":providers.bzl", "SwiftInfo", "SwiftToolchainInfo")
load(":swift_common.bzl", "swift_common")
load(
Expand Down Expand Up @@ -179,20 +179,21 @@ def _swift_library_impl(ctx):
else:
clang_module = None

linker_input = register_libraries_to_link(
owning_label = ctx.label,
linker_input, library_to_link = create_linker_input(
actions = ctx.actions,
additional_inputs = additional_inputs,
alwayslink = ctx.attr.alwayslink,
cc_feature_configuration = swift_common.cc_feature_configuration(
feature_configuration = feature_configuration,
),
compilation_outputs = compilation_outputs,
is_dynamic = False,
is_static = True,
library_name = ctx.label.name,
objects = compilation_outputs.object_files,
owner = ctx.label,
swift_toolchain = swift_toolchain,
user_link_flags = linkopts,
additional_inputs = compilation_outputs.linker_inputs,
)

direct_output_files = compact([
Expand Down
7 changes: 4 additions & 3 deletions swift/internal/swift_module_alias.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ load(
"output_groups_from_compilation_outputs",
)
load(":derived_files.bzl", "derived_files")
load(":linking.bzl", "register_libraries_to_link")
load(":linking.bzl", "create_linker_input")
load(":providers.bzl", "SwiftInfo", "SwiftToolchainInfo")
load(":swift_common.bzl", "swift_common")
load(":utils.bzl", "compact", "create_cc_info", "get_providers")
Expand Down Expand Up @@ -72,17 +72,18 @@ def _swift_module_alias_impl(ctx):
target_name = ctx.label.name,
)

linker_input = register_libraries_to_link(
owning_label = ctx.label,
linker_input, library_to_link = create_linker_input(
actions = ctx.actions,
alwayslink = False,
cc_feature_configuration = swift_common.cc_feature_configuration(
feature_configuration = feature_configuration,
),
compilation_outputs = compilation_outputs,
is_dynamic = False,
is_static = True,
library_name = ctx.label.name,
objects = compilation_outputs.object_files,
owner = ctx.label,
swift_toolchain = swift_toolchain,
additional_inputs = compilation_outputs.linker_inputs,
)
Expand Down
7 changes: 4 additions & 3 deletions swift/internal/swift_protoc_gen_aspect.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ load(
"SWIFT_FEATURE_GENERATE_FROM_RAW_PROTO_FILES",
"SWIFT_FEATURE_NO_GENERATED_HEADER",
)
load(":linking.bzl", "register_libraries_to_link")
load(":linking.bzl", "create_linker_input")
load(
":proto_gen_utils.bzl",
"declare_generated_files",
Expand Down Expand Up @@ -428,20 +428,21 @@ def _swift_protoc_gen_aspect_impl(target, aspect_ctx):
target_name = target.label.name,
)

linker_input = register_libraries_to_link(
owning_label = aspect_ctx.label,
linker_input, library_to_link = create_linker_input(
actions = aspect_ctx.actions,
alwayslink = False,
cc_feature_configuration = swift_common.cc_feature_configuration(
feature_configuration = feature_configuration,
),
compilation_outputs = compilation_outputs,
is_dynamic = False,
is_static = True,
# Prevent conflicts with C++ protos in the same output directory,
# which use the `lib{name}.a` pattern. This will produce
# `lib{name}.swift.a` instead.
library_name = "{}.swift".format(target.label.name),
objects = compilation_outputs.object_files,
owner = target.label,
swift_toolchain = swift_toolchain,
additional_inputs = compilation_outputs.linker_inputs,
user_link_flags = compilation_outputs.linker_flags,
Expand Down
10 changes: 6 additions & 4 deletions swift/internal/utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ def collect_cc_libraries(
"""
libraries = []

for li in cc_info.linking_context.linker_inputs.to_list():
for library in li.libraries:
for linker_input in cc_info.linking_context.linker_inputs.to_list():
for library in linker_input.libraries:
if include_pic_static:
if library.pic_static_library:
libraries.append(library.pic_static_library)
Expand All @@ -69,6 +69,7 @@ def compact(sequence):
return [item for item in sequence if item != None]

def create_cc_info(
*,
cc_infos = [],
compilation_outputs = None,
defines = [],
Expand All @@ -88,7 +89,8 @@ def create_cc_info(
includes: The list of include paths to insert into the compilation
context.
linker_inputs: A list of `LinkerInput` objects that represent the
libraries that should be linked into the final binary.
libraries that should be linked into the final binary as well as any
additional inputs and flags that should be passed to the linker.
private_cc_infos: A list of `CcInfo` providers from private
(implementation-only) dependencies, whose linking contexts should be
merged into the new provider but whose compilation contexts should
Expand All @@ -104,7 +106,7 @@ def create_cc_info(
local_cc_infos = [
CcInfo(
linking_context = cc_common.create_linking_context(
linker_inputs = depset(direct = linker_inputs),
linker_inputs = depset(linker_inputs),
),
compilation_context = cc_common.create_compilation_context(
defines = depset(defines),
Expand Down
10 changes: 6 additions & 4 deletions test/rules/provider_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,16 @@ def _evaluate_field(env, source, field):
)
return _EVALUATE_FIELD_FAILED

expanded = []
# If the elements are lists or depsets, flatten the whole thing into
# a single list.
flattened = []
for item in source:
item = _normalize_collection(item)
if types.is_list(item):
expanded.extend(item)
flattened.extend(item)
else:
expanded.append(item)
source = [getattr(item, component, None) for item in expanded]
flattened.append(item)
source = [getattr(item, component, None) for item in flattened]
if filter_nones:
source = [item for item in source if item != None]
else:
Expand Down