From afff427a76b61554172448ad2514c5401fef74d2 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Wed, 28 Sep 2022 13:56:03 -0700 Subject: [PATCH] Fix LLDB expr evaluation for `swift_{binary,test}` targets only containing Swift in their `srcs` The `.swiftmodule` resulting from compilation of the target's sources was being ignored (since it cannot be a dependency of anything else), but it needs to be embedded as with any other `.swiftmodule` in order for LLDB to find it and initialize the AST context properly. PiperOrigin-RevId: 477544434 (cherry picked from commit c0cdb8b5a2100b3962993654f7409b80f3ce96f2) Signed-off-by: Brentley Jones --- swift/BUILD | 1 + swift/internal/BUILD | 1 + swift/internal/debugging.bzl | 3 +- swift/internal/linking.bzl | 240 +++++++++++++++++++++++++------- swift/swift_binary.bzl | 35 +---- swift/swift_compiler_plugin.bzl | 11 +- swift/swift_test.bzl | 40 ++---- 7 files changed, 215 insertions(+), 116 deletions(-) diff --git a/swift/BUILD b/swift/BUILD index b6f1771ef..bd87bf866 100644 --- a/swift/BUILD +++ b/swift/BUILD @@ -258,6 +258,7 @@ bzl_library( "//swift/internal:toolchain_utils", "//swift/internal:utils", "@bazel_skylib//lib:dicts", + "@bazel_skylib//lib:paths", ], ) diff --git a/swift/internal/BUILD b/swift/internal/BUILD index 5bdb932c0..8a1c4bd75 100644 --- a/swift/internal/BUILD +++ b/swift/internal/BUILD @@ -102,6 +102,7 @@ bzl_library( ":actions", ":feature_names", ":features", + "@bazel_skylib//lib:paths", ], ) diff --git a/swift/internal/debugging.bzl b/swift/internal/debugging.bzl index 19305231b..856546c1f 100644 --- a/swift/internal/debugging.bzl +++ b/swift/internal/debugging.bzl @@ -14,6 +14,7 @@ """Functions relating to debugging support during compilation and linking.""" +load("@bazel_skylib//lib:paths.bzl", "paths") load(":action_names.bzl", "SWIFT_ACTION_MODULEWRAP") load( ":actions.bzl", @@ -60,7 +61,7 @@ def ensure_swiftmodule_is_embedded( # to wrap the .swiftmodule file in a .o file that gets propagated to the # linker. modulewrap_obj = actions.declare_file( - "{}.modulewrap.o".format(label.name), + paths.replace_extension(swiftmodule.basename, ".modulewrap.o"), ) prerequisites = struct( object_file = modulewrap_obj, diff --git a/swift/internal/linking.bzl b/swift/internal/linking.bzl index c76d43be2..d0d9dea06 100644 --- a/swift/internal/linking.bzl +++ b/swift/internal/linking.bzl @@ -171,6 +171,108 @@ def configure_features_for_binary( unsupported_features = unsupported_features, ) +def _create_autolink_linking_context( + *, + actions, + compilation_outputs, + feature_configuration, + label, + name, + swift_toolchain): + """Creates a linking context that embeds a .swiftmodule for debugging. + + Args: + actions: The context's `actions` object. + compilation_outputs: A `CcCompilationOutputs` value containing the + object files to link. Typically, this is the second tuple element in + the value returned by `swift_common.compile`. + feature_configuration: A feature configuration obtained from + `swift_common.configure_features`. + label: The `Label` of the target being built. This is used as the owner + of the linker inputs created for post-compile actions (if any). + name: The name of the target being linked, which is used to derive the + output artifact. + swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain. + + Returns: + A valid `CcLinkingContext`, or `None` if no linking context was created. + """ + if compilation_outputs.objects and is_action_enabled( + action_name = SWIFT_ACTION_AUTOLINK_EXTRACT, + swift_toolchain = swift_toolchain, + ): + autolink_file = actions.declare_file( + "{}.autolink".format(name), + ) + register_autolink_extract_action( + actions = actions, + autolink_file = autolink_file, + feature_configuration = feature_configuration, + object_files = compilation_outputs.objects, + swift_toolchain = swift_toolchain, + ) + post_compile_linker_inputs = [ + cc_common.create_linker_input( + owner = label, + user_link_flags = depset( + ["@{}".format(autolink_file.path)], + ), + additional_inputs = depset([autolink_file]), + ), + ] + return cc_common.create_linking_context( + linker_inputs = depset(post_compile_linker_inputs), + ) + + return None + +def _create_embedded_debugging_linking_context( + *, + actions, + feature_configuration, + label, + module_context, + swift_toolchain): + """Creates a linking context that embeds a .swiftmodule for debugging. + + Args: + actions: The context's `actions` object. + feature_configuration: A feature configuration obtained from + `swift_common.configure_features`. + label: The `Label` of the target being built. This is used as the owner + of the linker inputs created for post-compile actions (if any). + module_context: The module context returned by `swift_common.compile` + containing information about the Swift module that was compiled. + Typically, this is the first tuple element in the value returned by + `swift_common.compile`. + swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain. + + Returns: + A valid `CcLinkingContext`, or `None` if no linking context was created. + """ + if ( + module_context and + module_context.swift and + should_embed_swiftmodule_for_debugging( + feature_configuration = feature_configuration, + module_context = module_context, + ) + ): + post_compile_linker_inputs = [ + ensure_swiftmodule_is_embedded( + actions = actions, + feature_configuration = feature_configuration, + label = label, + swiftmodule = module_context.swift.swiftmodule, + swift_toolchain = swift_toolchain, + ), + ] + return cc_common.create_linking_context( + linker_inputs = depset(post_compile_linker_inputs), + ) + + return None + def create_linking_context_from_compilation_outputs( *, actions, @@ -241,55 +343,29 @@ def create_linking_context_from_compilation_outputs( for cc_info in swift_toolchain.implicit_deps_providers.cc_infos ] - if module_context and module_context.swift: - post_compile_linker_inputs = [] - - # Ensure that the .swiftmodule file is embedded in the final library or - # binary for debugging purposes. - if should_embed_swiftmodule_for_debugging( - feature_configuration = feature_configuration, - module_context = module_context, - ): - post_compile_linker_inputs.append( - ensure_swiftmodule_is_embedded( - actions = actions, - feature_configuration = feature_configuration, - label = label, - swiftmodule = module_context.swift.swiftmodule, - swift_toolchain = swift_toolchain, - ), - ) + debugging_linking_context = _create_embedded_debugging_linking_context( + actions = actions, + feature_configuration = feature_configuration, + label = label, + module_context = module_context, + swift_toolchain = swift_toolchain, + ) + if debugging_linking_context: + extra_linking_contexts.append(debugging_linking_context) - # Invoke an autolink-extract action for toolchains that require it. - if is_action_enabled( - action_name = SWIFT_ACTION_AUTOLINK_EXTRACT, - swift_toolchain = swift_toolchain, - ): - autolink_file = actions.declare_file( - "{}.autolink".format(label.name), - ) - register_autolink_extract_action( - actions = actions, - autolink_file = autolink_file, - feature_configuration = feature_configuration, - object_files = compilation_outputs.objects, - swift_toolchain = swift_toolchain, - ) - post_compile_linker_inputs.append( - cc_common.create_linker_input( - owner = label, - user_link_flags = depset( - ["@{}".format(autolink_file.path)], - ), - additional_inputs = depset([autolink_file]), - ), - ) + if not name: + name = label.name - extra_linking_contexts.append( - cc_common.create_linking_context( - linker_inputs = depset(post_compile_linker_inputs), - ), - ) + autolink_linking_context = _create_autolink_linking_context( + actions = actions, + compilation_outputs = compilation_outputs, + feature_configuration = feature_configuration, + label = label, + name = name, + swift_toolchain = swift_toolchain, + ) + if autolink_linking_context: + extra_linking_contexts.append(autolink_linking_context) if not alwayslink: alwayslink = is_feature_enabled( @@ -328,9 +404,6 @@ def create_linking_context_from_compilation_outputs( ), ) - if not name: - name = label.name - if include_dev_srch_paths != None and is_test != None: fail("""\ Both `include_dev_srch_paths` and `is_test` cannot be specified. Please select \ @@ -498,10 +571,11 @@ def register_link_binary_action( actions, additional_inputs, additional_linking_contexts, - cc_feature_configuration, compilation_outputs, deps, + feature_configuration, name, + module_contexts, output_type, owner, stamp, @@ -516,12 +590,15 @@ def register_link_binary_action( scripts, and so forth. additional_linking_contexts: Additional linking contexts that provide libraries or flags that should be linked into the executable. - cc_feature_configuration: The C++ feature configuration to use when - constructing the action. compilation_outputs: A `CcCompilationOutputs` object containing object files that will be passed to the linker. deps: A list of targets representing additional libraries that will be passed to the linker. + feature_configuration: The Swift feature configuration. + module_contexts: A list of module contexts resulting from the + compilation of the sources in the binary target, which are embedded + in the binary for debugging if this is a debug build. This list may + be empty if the target had no sources of its own. name: The name of the target being linked, which is used to derive the output artifact. output_type: A string indicating the output type; "executable" or @@ -609,6 +686,59 @@ def register_link_binary_action( linking_contexts.extend(additional_linking_contexts) + for module_context in module_contexts: + debugging_linking_context = _create_embedded_debugging_linking_context( + actions = actions, + feature_configuration = feature_configuration, + label = owner, + module_context = module_context, + swift_toolchain = swift_toolchain, + ) + if debugging_linking_context: + linking_contexts.append(debugging_linking_context) + + autolink_linking_context = _create_autolink_linking_context( + actions = actions, + compilation_outputs = compilation_outputs, + feature_configuration = feature_configuration, + label = owner, + name = name, + swift_toolchain = swift_toolchain, + ) + if autolink_linking_context: + linking_contexts.append(autolink_linking_context) + + if is_feature_enabled( + feature_configuration = feature_configuration, + feature_name = SWIFT_FEATURE_LLD_GC_WORKAROUND, + ): + linking_contexts.append( + cc_common.create_linking_context( + linker_inputs = depset([ + cc_common.create_linker_input( + owner = owner, + user_link_flags = depset(["-Wl,-z,nostart-stop-gc"]), + ), + ]), + ), + ) + + if is_feature_enabled( + feature_configuration = feature_configuration, + feature_name = SWIFT_FEATURE_OBJC_LINK_FLAGS, + ): + # TODO: Remove once we can rely on folks using the new toolchain + linking_contexts.append( + cc_common.create_linking_context( + linker_inputs = depset([ + cc_common.create_linker_input( + owner = owner, + user_link_flags = depset(["-ObjC"]), + ), + ]), + ), + ) + # Collect linking contexts from any of the toolchain's implicit # dependencies. linking_contexts.extend([ @@ -621,7 +751,9 @@ def register_link_binary_action( additional_inputs = additional_inputs, cc_toolchain = swift_toolchain.cc_toolchain_info, compilation_outputs = compilation_outputs, - feature_configuration = cc_feature_configuration, + feature_configuration = get_cc_feature_configuration( + feature_configuration, + ), name = name, user_link_flags = user_link_flags, linking_contexts = linking_contexts, diff --git a/swift/swift_binary.bzl b/swift/swift_binary.bzl index 5a682a170..567ac5f71 100644 --- a/swift/swift_binary.bzl +++ b/swift/swift_binary.bzl @@ -105,40 +105,17 @@ def _swift_binary_impl(ctx): target_name = ctx.label.name, workspace_name = ctx.workspace_name, ) - module_context = compile_result.module_context - module_contexts.append(module_context) + module_contexts.append(compile_result.module_context) compilation_outputs = compile_result.compilation_outputs supplemental_outputs = compile_result.supplemental_outputs output_groups = supplemental_compilation_output_groups( supplemental_outputs, ) - - # Unlike `upstream`, we create a linking_context in order to support - # `autolink-extract`. See `a1395155c6a27d76aab5e1a93455259a0ac10b2f` and - # `93219a3b21390f212f5fd013e8db3654fd09814c`. - linking_context, _ = swift_common.create_linking_context_from_compilation_outputs( - actions = ctx.actions, - alwayslink = True, - compilation_outputs = compilation_outputs, - feature_configuration = feature_configuration, - include_dev_srch_paths = include_dev_srch_paths, - label = ctx.label, - linking_contexts = [ - dep[CcInfo].linking_context - for dep in ctx.attr.deps - if CcInfo in dep - ], - module_context = module_context, - swift_toolchain = swift_toolchain, - ) - additional_linking_contexts.append(linking_context) + else: + compilation_outputs = cc_common.create_compilation_outputs() additional_linking_contexts.append(malloc_linking_context(ctx)) - cc_feature_configuration = swift_common.cc_feature_configuration( - feature_configuration = feature_configuration, - ) - if swift_common.is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_ADD_TARGET_NAME_TO_OUTPUT, @@ -151,10 +128,10 @@ def _swift_binary_impl(ctx): actions = ctx.actions, additional_inputs = ctx.files.swiftc_inputs, additional_linking_contexts = additional_linking_contexts, - cc_feature_configuration = cc_feature_configuration, - # This is already collected from `linking_context`. - compilation_outputs = None, + feature_configuration = feature_configuration, + compilation_outputs = compilation_outputs, deps = ctx.attr.deps, + module_contexts = module_contexts, name = name, output_type = "executable", owner = ctx.label, diff --git a/swift/swift_compiler_plugin.bzl b/swift/swift_compiler_plugin.bzl index 70074c3a2..bab8ce3ea 100644 --- a/swift/swift_compiler_plugin.bzl +++ b/swift/swift_compiler_plugin.bzl @@ -62,6 +62,7 @@ def _swift_compiler_plugin_impl(ctx): deps = ctx.attr.deps srcs = ctx.files.srcs + module_contexts = [] if not srcs: fail("A compiler plugin must have at least one file in 'srcs'.") @@ -105,24 +106,22 @@ def _swift_compiler_plugin_impl(ctx): workspace_name = ctx.workspace_name, ) module_context = compile_result.module_context + module_contexts.append(module_context) compilation_outputs = compile_result.compilation_outputs supplemental_outputs = compile_result.supplemental_outputs - cc_feature_configuration = swift_common.cc_feature_configuration( - feature_configuration = feature_configuration, - ) - binary_linking_outputs = register_link_binary_action( actions = ctx.actions, additional_inputs = ctx.files.swiftc_inputs, additional_linking_contexts = [malloc_linking_context(ctx)], - cc_feature_configuration = cc_feature_configuration, compilation_outputs = compilation_outputs, deps = deps, + feature_configuration = feature_configuration, + module_contexts = module_contexts, name = ctx.label.name, output_type = "executable", - stamp = ctx.attr.stamp, owner = ctx.label, + stamp = ctx.attr.stamp, swift_toolchain = swift_toolchain, user_link_flags = expand_locations( ctx, diff --git a/swift/swift_test.bzl b/swift/swift_test.bzl index 01fab5bc4..4db222c94 100644 --- a/swift/swift_test.bzl +++ b/swift/swift_test.bzl @@ -15,9 +15,11 @@ """Implementation of the `swift_binary` and `swift_test` rules.""" load("@bazel_skylib//lib:dicts.bzl", "dicts") +load("@bazel_skylib//lib:paths.bzl", "paths") load("//swift/internal:env_expansion.bzl", "expanded_env") load( "//swift/internal:feature_names.bzl", + "SWIFT_FEATURE_ADD_TARGET_NAME_TO_OUTPUT", "SWIFT_FEATURE_BUNDLED_XCTESTS", ) load( @@ -338,42 +340,28 @@ def _swift_test_impl(ctx): module_contexts.append(module_context) compilation_outputs = compile_result.compilation_outputs all_supplemental_outputs.append(compile_result.supplemental_outputs) - - # Unlike `upstream`, we create a linking_context in order to support - # `autolink-extract`. See `a1395155c6a27d76aab5e1a93455259a0ac10b2f` and - # `93219a3b21390f212f5fd013e8db3654fd09814c`. - linking_context, _ = swift_common.create_linking_context_from_compilation_outputs( - actions = ctx.actions, - alwayslink = True, - compilation_outputs = compilation_outputs, - feature_configuration = feature_configuration, - include_dev_srch_paths = include_dev_srch_paths, - label = ctx.label, - linking_contexts = [ - dep[CcInfo].linking_context - for dep in ctx.attr.deps + extra_deps - if CcInfo in dep - ], - module_context = module_context, - swift_toolchain = swift_toolchain, - ) - additional_linking_contexts.append(linking_context) + else: + compilation_outputs = cc_common.create_compilation_outputs() additional_linking_contexts.append(malloc_linking_context(ctx)) - cc_feature_configuration = swift_common.cc_feature_configuration( + if swift_common.is_enabled( feature_configuration = feature_configuration, - ) + feature_name = SWIFT_FEATURE_ADD_TARGET_NAME_TO_OUTPUT, + ): + name = paths.join(ctx.label.name, ctx.label.name) + else: + name = ctx.label.name linking_outputs = register_link_binary_action( actions = ctx.actions, additional_inputs = ctx.files.swiftc_inputs, additional_linking_contexts = additional_linking_contexts, - cc_feature_configuration = cc_feature_configuration, - # This is already collected from `linking_context`. - compilation_outputs = None, + compilation_outputs = compilation_outputs, deps = ctx.attr.deps + extra_deps + extra_link_deps, - name = ctx.label.name, + feature_configuration = feature_configuration, + module_contexts = module_contexts, + name = name, output_type = "executable", owner = ctx.label, stamp = ctx.attr.stamp,