diff --git a/swift/internal/compiling.bzl b/swift/internal/compiling.bzl index d4d554a9c..06ec270cf 100644 --- a/swift/internal/compiling.bzl +++ b/swift/internal/compiling.bzl @@ -25,8 +25,7 @@ load( "run_toolchain_action", "swift_action_names", ) -load(":autolinking.bzl", "register_autolink_extract_action") -load(":debugging.bzl", "ensure_swiftmodule_is_embedded") +load(":debugging.bzl", "should_embed_swiftmodule_for_debugging") load(":derived_files.bzl", "derived_files") load( ":feature_names.bzl", @@ -49,7 +48,6 @@ load( "SWIFT_FEATURE_INDEX_WHILE_BUILDING", "SWIFT_FEATURE_LAYERING_CHECK", "SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD", - "SWIFT_FEATURE_NO_EMBED_DEBUG_MODULE", "SWIFT_FEATURE_NO_GENERATED_MODULE_MAP", "SWIFT_FEATURE_OPT", "SWIFT_FEATURE_OPT_USES_OSIZE", @@ -67,11 +65,17 @@ load( ) load(":features.bzl", "are_all_features_enabled", "is_feature_enabled") load(":module_maps.bzl", "write_module_map") -load(":providers.bzl", "SwiftInfo", "create_swift_info") +load( + ":providers.bzl", + "SwiftInfo", + "create_clang_module", + "create_module", + "create_swift_info", + "create_swift_module", +) load(":toolchain_config.bzl", "swift_toolchain_config") load( ":utils.bzl", - "collect_cc_libraries", "compact", "compilation_context_for_explicit_module_compilation", "get_providers", @@ -1193,7 +1197,7 @@ def _collect_clang_module_inputs( # Add the module map, which we use for both implicit and explicit module # builds. module_map = clang_module.module_map - if not module.is_system and not types.is_string(module_map): + if not module.is_system and type(module_map) == "File": direct_inputs.append(module_map) if prefer_precompiled_modules: @@ -1231,14 +1235,15 @@ def _clang_modulemap_dependency_args(module, ignore_system = True): A list of arguments, possibly empty, to pass to `swiftc` (without the `-Xcc` prefix). """ - if module.is_system and ignore_system: + module_map = module.clang.module_map + + if (module.is_system and ignore_system) or not module_map: return [] - module_map = module.clang.module_map - if types.is_string(module_map): - module_map_path = module_map - else: + if type(module_map) == "File": module_map_path = module_map.path + else: + module_map_path = module_map return ["-fmodule-map-file={}".format(module_map_path)] @@ -1901,35 +1906,52 @@ def compile( else: precompiled_module = None - # As part of the full compilation flow, register additional post-compile - # actions that toolchains may conditionally support for their target - # platform, like module-wrap or autolink-extract. - post_compile_results = _register_post_compile_actions( - actions = actions, - compile_outputs = compile_outputs, - feature_configuration = feature_configuration, - module_name = module_name, - swift_toolchain = swift_toolchain, - target_name = target_name, + if compile_outputs.generated_header_file: + module_headers = [compile_outputs.generated_header_file] + else: + module_headers = [] + + if defines or module_headers: + direct_cc_infos = [ + CcInfo(compilation_context = cc_common.create_compilation_context( + defines = depset(defines), + headers = depset(module_headers), + includes = depset([bin_dir.path]), + )), + ] + else: + direct_cc_infos = [] + + compilation_context = cc_common.merge_cc_infos( + cc_infos = [dep[CcInfo] for dep in deps if CcInfo in dep], + direct_cc_infos = direct_cc_infos, + ).compilation_context + + module_context = create_module( + name = module_name, + clang = create_clang_module( + compilation_context = compilation_context, + module_map = compile_outputs.generated_module_map_file, + precompiled_module = precompiled_module, + ), + is_system = False, + swift = create_swift_module( + defines = defines, + swift_ast_file = compile_outputs.ast_files, + swift_index_store = compile_outputs.indexstore_directory, + swiftdoc = compile_outputs.swiftdoc_file, + swiftinterface = compile_outputs.swiftinterface_file, + swiftmodule = compile_outputs.swiftmodule_file, + ), ) - return struct( - ast_files = compile_outputs.ast_files, - generated_header = compile_outputs.generated_header_file, - generated_module_map = compile_outputs.generated_module_map_file, - indexstore = compile_outputs.indexstore_directory, - linker_flags = post_compile_results.linker_flags, - linker_inputs = post_compile_results.linker_inputs, - object_files = ( - compile_outputs.object_files + - post_compile_results.additional_object_files - ), - precompiled_module = precompiled_module, - swiftdoc = compile_outputs.swiftdoc_file, - swiftinterface = compile_outputs.swiftinterface_file, - swiftmodule = compile_outputs.swiftmodule_file, + compilation_outputs = cc_common.create_compilation_outputs( + objects = depset(compile_outputs.object_files), + pic_objects = depset(compile_outputs.object_files), ) + return module_context, compilation_outputs + def precompile_clang_module( *, actions, @@ -2488,186 +2510,104 @@ def _merge_targets_providers( swift_info = create_swift_info(swift_infos = swift_infos), ) -def _register_post_compile_actions( - actions, - compile_outputs, - feature_configuration, - module_name, - swift_toolchain, - target_name): - """Register additional post-compile actions used by some toolchains. - - Args: - actions: The context's `actions` object. - compile_outputs: The result of an earlier call to - `_declare_compile_outputs`. - feature_configuration: A feature configuration obtained from - `swift_common.configure_features`. - module_name: The name of the Swift module being compiled. This must be - present and valid; use `swift_common.derive_module_name` to generate - a default from the target's label if needed. - swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain. - target_name: The name of the target for which the code is being - compiled, which is used to determine unique file paths for the - outputs. - - Returns: - A `struct` with the following fields: - - * `additional_object_files`: A `list` of additional object files that - were produced as outputs of the post-compile actions and should be - linked into a binary. - * `linker_flags`: A `list` of flags that should be propagated up to - the linker invocation of any binary that depends on the target this - was compiled for. - * `linker_inputs`: A `list` of `File`s referenced by `linker_flags`. - """ - additional_object_files = [] - - # Ensure that the .swiftmodule file is embedded in the final library or - # binary for debugging purposes. - linker_flags = [] - linker_inputs = [] - should_embed_swiftmodule_for_debugging = ( - _is_debugging(feature_configuration = feature_configuration) and - not is_feature_enabled( - feature_configuration = feature_configuration, - feature_name = SWIFT_FEATURE_NO_EMBED_DEBUG_MODULE, - ) - ) - if should_embed_swiftmodule_for_debugging: - module_embed_results = ensure_swiftmodule_is_embedded( - actions = actions, - feature_configuration = feature_configuration, - swiftmodule = compile_outputs.swiftmodule_file, - swift_toolchain = swift_toolchain, - target_name = target_name, - ) - linker_flags.extend(module_embed_results.linker_flags) - linker_inputs.extend(module_embed_results.linker_inputs) - additional_object_files.extend(module_embed_results.objects_to_link) - - # Invoke an autolink-extract action for toolchains that require it. - if is_action_enabled( - action_name = swift_action_names.AUTOLINK_EXTRACT, - swift_toolchain = swift_toolchain, - ): - autolink_file = derived_files.autolink_flags( - actions = actions, - target_name = target_name, - ) - register_autolink_extract_action( - actions = actions, - autolink_file = autolink_file, - feature_configuration = feature_configuration, - module_name = module_name, - object_files = compile_outputs.object_files, - swift_toolchain = swift_toolchain, - ) - linker_flags.append("@{}".format(autolink_file.path)) - linker_inputs.append(autolink_file) - - return struct( - additional_object_files = additional_object_files, - linker_flags = linker_flags, - linker_inputs = linker_inputs, - ) - def new_objc_provider( + *, + additional_link_inputs = [], + additional_objc_infos = [], deps, - link_inputs, - linkopts, - module_map, - static_archives, - swiftmodules, - objc_header = None, - objc_providers = []): + feature_configuration, + libraries_to_link, + module_context, + user_link_flags = []): """Creates an `apple_common.Objc` provider for a Swift target. Args: + additional_link_inputs: Additional linker input files that should be + propagated to dependents. + additional_objc_infos: Additional `apple_common.Objc` providers from + transitive dependencies not provided by the `deps` argument. deps: The dependencies of the target being built, whose `Objc` providers will be passed to the new one in order to propagate the correct transitive fields. - link_inputs: Additional linker input files that should be propagated to - dependents. - linkopts: Linker options that should be propagated to dependents. - module_map: The module map generated for the Swift target's Objective-C - header, if any. - static_archives: A list (typically of one element) of the static - archives (`.a` files) containing the target's compiled code. - swiftmodules: A list (typically of one element) of the `.swiftmodule` - files for the compiled target. - objc_header: The generated Objective-C header for the Swift target. If - `None`, no headers will be propagated. This header is only needed - for Swift code that defines classes that should be exposed to - Objective-C. - objc_providers: Additional `apple_common.Objc` providers from transitive - dependencies not provided by the `deps` argument. + feature_configuration: The Swift feature configuration. + libraries_to_link: A list (typically of one element) of the + `LibraryToLink` objects from which the static archives (`.a` files) + containing the target's compiled code will be retrieved. + module_context: The module context as returned by + `swift_common.compile`. + user_link_flags: Linker options that should be propagated to dependents. Returns: An `apple_common.Objc` provider that should be returned by the calling rule. """ - all_objc_providers = get_providers(deps, apple_common.Objc) + objc_providers - objc_provider_args = { - "link_inputs": depset(direct = swiftmodules + link_inputs), - "providers": all_objc_providers, - } - # The link action registered by `apple_binary` only looks at `Objc` - # providers, not `CcInfo`, for libraries to link. Until that rule is - # migrated over, we need to collect libraries from `CcInfo` (which will - # include Swift and C++) and put them into the new `Objc` provider. + # The link action registered by `apple_common.link_multi_arch_binary` only + # looks at `Objc` providers, not `CcInfo`, for libraries to link. + # Dependencies from an `objc_library` to a `cc_library` are handled as a + # special case, but other `cc_library` dependencies (such as `swift_library` + # to `cc_library`) would be lost since they do not receive the same + # treatment. Until those special cases are resolved via the unification of + # the Obj-C and C++ rules, we need to collect libraries from `CcInfo` and + # put them into the new `Objc` provider. transitive_cc_libs = [] for cc_info in get_providers(deps, CcInfo): - static_libs = collect_cc_libraries( - cc_info = cc_info, - include_static = True, - ) + static_libs = [] + for linker_input in cc_info.linking_context.linker_inputs.to_list(): + for library_to_link in linker_input.libraries: + library = library_to_link.static_library + if library: + static_libs.append(library) transitive_cc_libs.append(depset(static_libs, order = "topological")) - objc_provider_args["library"] = depset( - static_archives, - transitive = transitive_cc_libs, - order = "topological", - ) - - if objc_header: - objc_provider_args["header"] = depset(direct = [objc_header]) - if linkopts: - objc_provider_args["linkopt"] = depset(direct = linkopts, order = "topological") - force_loaded_libraries = [ - archive - for archive in static_archives - if archive.basename.endswith(".lo") - ] - if force_loaded_libraries: - objc_provider_args["force_load_library"] = depset( - direct = force_loaded_libraries, - ) + direct_libraries = [] + force_load_libraries = [] - # In addition to the generated header's module map, we must re-propagate the - # direct deps' Objective-C module maps to dependents, because those Swift - # modules still need to see them. We need to construct a new transitive objc - # provider to get the correct strict propagation behavior. - transitive_objc_provider_args = {"providers": all_objc_providers} - if module_map: - transitive_objc_provider_args["module_map"] = depset( - direct = [module_map], - ) + for library_to_link in libraries_to_link: + library = library_to_link.static_library + if library: + direct_libraries.append(library) + if library_to_link.alwayslink: + force_load_libraries.append(library) - transitive_objc = apple_common.new_objc_provider( - **transitive_objc_provider_args + if feature_configuration and should_embed_swiftmodule_for_debugging( + feature_configuration = feature_configuration, + module_context = module_context, + ): + module_file = module_context.swift.swiftmodule + debug_link_flags = ["-Wl,-add_ast_path,{}".format(module_file.path)] + debug_link_inputs = [module_file] + else: + debug_link_flags = [] + debug_link_inputs = [] + + return apple_common.new_objc_provider( + force_load_library = depset( + force_load_libraries, + order = "topological", + ), + header = depset( + module_context.clang.compilation_context.direct_headers, + ), + library = depset( + direct_libraries, + transitive = transitive_cc_libs, + order = "topological", + ), + link_inputs = depset(additional_link_inputs + debug_link_inputs), + linkopt = depset(user_link_flags + debug_link_flags), + providers = get_providers( + deps, + apple_common.Objc, + ) + additional_objc_infos, ) - objc_provider_args["module_map"] = transitive_objc.module_map - - return apple_common.new_objc_provider(**objc_provider_args) -def output_groups_from_compilation_outputs(compilation_outputs): - """Returns a dictionary of output groups from Swift compilation outputs. +def output_groups_from_module_context(module_context): + """Returns a dictionary of output groups from a Swift module context. Args: - compilation_outputs: The result of calling `swift_common.compile`. + module_context: The value in the first element of the tuple returned by + `swift_common.compile`. Returns: A `dict` whose keys are the names of output groups and values are @@ -2676,34 +2616,32 @@ def output_groups_from_compilation_outputs(compilation_outputs): """ output_groups = {} - if compilation_outputs.ast_files: - output_groups["swift_ast_file"] = depset( - compilation_outputs.ast_files, - ) + if module_context.swift: + swift_module = module_context.swift - if compilation_outputs.indexstore: - output_groups["swift_index_store"] = depset([ - compilation_outputs.indexstore, - ]) + if swift_module.ast_files: + output_groups["swift_ast_file"] = depset( + compilation_outputs.ast_files, + ) - if compilation_outputs.swiftdoc: - output_groups["swiftdoc"] = depset([ - compilation_outputs.swiftdoc, - ]) + if swift_module.indexstore: + output_groups["swift_index_store"] = depset([ + compilation_outputs.indexstore, + ]) - if compilation_outputs.swiftinterface: - output_groups["swiftinterface"] = depset([ - compilation_outputs.swiftinterface, - ]) + if swift_module.swiftdoc: + output_groups["swiftdoc"] = depset([ + compilation_outputs.swiftdoc, + ]) - if compilation_outputs.swiftmodule: - output_groups["swiftmodule"] = depset([ - compilation_outputs.swiftmodule, - ]) + if swift_module.swiftinterface: + output_groups["swiftinterface"] = depset([ + swift_module.swiftinterface, + ]) return output_groups -def swift_library_output_map(name, alwayslink): +def swift_library_output_map(name): """Returns the dictionary of implicit outputs for a `swift_library`. This function is used to specify the `outputs` of the `swift_library` rule; @@ -2712,16 +2650,12 @@ def swift_library_output_map(name, alwayslink): Args: name: The name of the target being built. - alwayslink: Indicates whether the object files in the library should - always be always be linked into any binaries that depend on it, even - if some contain no symbols referenced by the binary. Returns: The implicit outputs dictionary for a `swift_library`. """ - extension = "lo" if alwayslink else "a" return { - "archive": "lib{}.{}".format(name, extension), + "archive": "lib{}.a".format(name), } def _index_store_path_overridden(copts): @@ -2892,26 +2826,3 @@ def _safe_int(s): if s[i] < "0" or s[i] > "9": return None return int(s) - -def _is_debugging(feature_configuration): - """Returns `True` if the current compilation mode produces debug info. - - We replicate the behavior of the C++ build rules for Swift, which are - described here: - https://docs.bazel.build/versions/master/user-manual.html#flag--compilation_mode - - Args: - feature_configuration: The feature configuration. - - Returns: - `True` if the current compilation mode produces debug info. - """ - return ( - is_feature_enabled( - feature_configuration = feature_configuration, - feature_name = SWIFT_FEATURE_DBG, - ) or is_feature_enabled( - feature_configuration = feature_configuration, - feature_name = SWIFT_FEATURE_FASTBUILD, - ) - ) diff --git a/swift/internal/debugging.bzl b/swift/internal/debugging.bzl index a8db75c9c..5560e7d73 100644 --- a/swift/internal/debugging.bzl +++ b/swift/internal/debugging.bzl @@ -16,13 +16,20 @@ load(":actions.bzl", "run_toolchain_action", "swift_action_names") load(":derived_files.bzl", "derived_files") +load( + ":feature_names.bzl", + "SWIFT_FEATURE_DBG", + "SWIFT_FEATURE_FASTBUILD", + "SWIFT_FEATURE_NO_EMBED_DEBUG_MODULE", +) +load(":features.bzl", "is_feature_enabled") load(":toolchain_config.bzl", "swift_toolchain_config") def ensure_swiftmodule_is_embedded( actions, feature_configuration, + label, swiftmodule, - target_name, swift_toolchain): """Ensures that a `.swiftmodule` file is embedded in a library or binary. @@ -33,35 +40,23 @@ def ensure_swiftmodule_is_embedded( Args: actions: The object used to register actions. feature_configuration: The Swift feature configuration. + label: The `Label` of the target being built. swiftmodule: The `.swiftmodule` file to be wrapped. - target_name: The name of the target being built. swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain. Returns: - A `struct` containing three fields: - - * `linker_flags`: A list of additional flags that should be propagated - to the linker. - * `linker_inputs`: A list of additional inputs that are not necessarily - object files, but which are referenced in `linker_flags` and should - therefore be passed to the linker. - * `objects_to_link`: A list of `.o` files that should be included in the - static archive or binary that represents the module. + A `LinkerInput` containing any flags and/or input files that should be + propagated to the linker to embed the `.swiftmodule` as debugging + information in the binary. """ - linker_flags = [] - linker_inputs = [] - objects_to_link = [] - if swift_toolchain.object_format == "elf": # For ELF-format binaries, we need to invoke a Swift modulewrap action # to wrap the .swiftmodule file in a .o file that gets propagated to the # linker. modulewrap_obj = derived_files.modulewrap_object( actions, - target_name = target_name, + target_name = label.name, ) - objects_to_link.append(modulewrap_obj) - _register_modulewrap_action( actions = actions, feature_configuration = feature_configuration, @@ -69,19 +64,27 @@ def ensure_swiftmodule_is_embedded( swiftmodule = swiftmodule, swift_toolchain = swift_toolchain, ) - elif swift_toolchain.object_format == "macho": - linker_flags.append("-Wl,-add_ast_path,{}".format(swiftmodule.path)) - linker_inputs.append(swiftmodule) - else: - fail("Internal error: Unexpected object format '{}'.".format( - swift_toolchain.object_format, - )) - - return struct( - linker_flags = linker_flags, - linker_inputs = linker_inputs, - objects_to_link = objects_to_link, - ) + + # Passing the `.o` file directly to the linker ensures that it links to + # the binary even if nothing else references it. + return cc_common.create_linker_input( + additional_inputs = depset([modulewrap_obj]), + owner = label, + user_link_flags = depset([modulewrap_obj.path]), + ) + + if swift_toolchain.object_format == "macho": + return cc_common.create_linker_input( + owner = label, + user_link_flags = depset([ + "-Wl,-add_ast_path,{}".format(swiftmodule.path), + ]), + additional_inputs = depset([swiftmodule]), + ) + + fail("Internal error: Unexpected object format '{}'.".format( + swift_toolchain.object_format, + )) def modulewrap_action_configs(): """Returns the list of action configs needed to perform module wrapping. @@ -102,6 +105,52 @@ def modulewrap_action_configs(): ), ] +def should_embed_swiftmodule_for_debugging( + feature_configuration, + module_context): + """Returns True if the configuration wants modules embedded for debugging. + + Args: + feature_configuration: The Swift feature configuration. + module_context: The module context returned by `swift_common.compile`. + + Returns: + True if the `.swiftmodule` should be embedded by the linker for + debugging. + """ + return ( + module_context.swift and + module_context.swift.swiftmodule and + _is_debugging(feature_configuration = feature_configuration) and + not is_feature_enabled( + feature_configuration = feature_configuration, + feature_name = SWIFT_FEATURE_NO_EMBED_DEBUG_MODULE, + ) + ) + +def _is_debugging(feature_configuration): + """Returns `True` if the current compilation mode produces debug info. + + We replicate the behavior of the C++ build rules for Swift, which are + described here: + https://docs.bazel.build/versions/master/user-manual.html#flag--compilation_mode + + Args: + feature_configuration: The feature configuration. + + Returns: + `True` if the current compilation mode produces debug info. + """ + return ( + is_feature_enabled( + feature_configuration = feature_configuration, + feature_name = SWIFT_FEATURE_DBG, + ) or is_feature_enabled( + feature_configuration = feature_configuration, + feature_name = SWIFT_FEATURE_FASTBUILD, + ) + ) + def _modulewrap_input_configurator(prerequisites, args): """Configures the inputs of the modulewrap action.""" swiftmodule_file = prerequisites.swiftmodule_file diff --git a/swift/internal/linking.bzl b/swift/internal/linking.bzl index 08699878a..bef77acd1 100644 --- a/swift/internal/linking.bzl +++ b/swift/internal/linking.bzl @@ -19,7 +19,150 @@ load( "@bazel_tools//tools/build_defs/cc:action_names.bzl", "CPP_LINK_STATIC_LIBRARY_ACTION_NAME", ) +load(":actions.bzl", "is_action_enabled", "swift_action_names") +load(":autolinking.bzl", "register_autolink_extract_action") +load( + ":debugging.bzl", + "ensure_swiftmodule_is_embedded", + "should_embed_swiftmodule_for_debugging", +) load(":derived_files.bzl", "derived_files") +load(":features.bzl", "get_cc_feature_configuration") + +def create_linking_context_from_compilation_outputs( + *, + actions, + additional_inputs = [], + alwayslink = False, + compilation_outputs, + feature_configuration, + label, + linking_contexts = [], + module_context, + name = None, + swift_toolchain, + user_link_flags = []): + """Creates a linking context from the outputs of a Swift compilation. + + On some platforms, this function will spawn additional post-compile actions + for the module in order to add their outputs to the linking context. For + example, if the toolchain that requires a "module-wrap" invocation to embed + the `.swiftmodule` into an object file for debugging purposes, or if it + extracts auto-linking information from the object files to generate a linker + command line parameters file, those actions will be created here. + + Args: + actions: The context's `actions` object. + additional_inputs: A `list` of `File`s containing any additional files + that are referenced by `user_link_flags` and therefore need to be + propagated up to the linker. + alwayslink: If True, any binary that depends on the providers returned + by this function will link in all of the library's object files, + even if some contain no symbols referenced by the binary. + 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), and + the label's name component also determines the name of the artifact + unless it is overridden by the `name` argument. + linking_contexts: A `list` of `CcLinkingContext`s containing libraries + from dependencies. + name: A string that is used to derive the name of the library or + libraries linked by this function. If this is not provided or is a + falsy value, the name component of the `label` argument is used. + 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. + user_link_flags: A `list` of strings containing additional flags that + will be passed to the linker for any binary that links with the + returned linking context. + + Returns: + A tuple of `(CcLinkingContext, CcLinkingOutputs)` containing the linking + context to be propagated by the caller's `CcInfo` provider and the + artifact representing the library that was linked, respectively. + """ + extra_linking_contexts = [ + cc_info.linking_context + 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, + ), + ) + + # Invoke an autolink-extract action for toolchains that require it. + if is_action_enabled( + action_name = swift_action_names.AUTOLINK_EXTRACT, + swift_toolchain = swift_toolchain, + ): + autolink_file = derived_files.autolink_flags( + actions = actions, + target_name = label.name, + ) + register_autolink_extract_action( + actions = actions, + autolink_file = autolink_file, + feature_configuration = feature_configuration, + module_name = module_context.name, + 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]), + ), + ) + + extra_linking_contexts.append( + cc_common.create_linking_context( + linker_inputs = depset(post_compile_linker_inputs), + ), + ) + + if not name: + name = label.name + + return cc_common.create_linking_context_from_compilation_outputs( + actions = actions, + feature_configuration = get_cc_feature_configuration( + feature_configuration, + ), + cc_toolchain = swift_toolchain.cc_toolchain_info, + compilation_outputs = compilation_outputs, + name = name, + user_link_flags = user_link_flags, + linking_contexts = linking_contexts + extra_linking_contexts, + alwayslink = alwayslink, + additional_inputs = additional_inputs, + disallow_static_libraries = False, + disallow_dynamic_library = True, + grep_includes = None, + ) def _register_static_library_link_action( actions, @@ -93,101 +236,15 @@ def _register_static_library_link_action( progress_message = "Linking {}".format(output.short_path), ) -def create_linker_input( - *, - actions, - alwayslink, - cc_feature_configuration, - compilation_outputs, - is_dynamic, - is_static, - library_name, - objects, - owner, - swift_toolchain, - additional_inputs = [], - user_link_flags = []): - """Creates a linker input for a library to link and additional inputs/flags. - - Args: - 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. - 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 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: - # TODO(b/70228246): Implement this. - pass - - if is_static: - static_library = derived_files.static_archive( - actions = actions, - alwayslink = alwayslink, - link_name = library_name, - ) - _register_static_library_link_action( - actions = actions, - cc_feature_configuration = cc_feature_configuration, - objects = objects, - output = static_library, - swift_toolchain = swift_toolchain, - ) - else: - static_library = None - - 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( actions, additional_inputs, additional_linking_contexts, cc_feature_configuration, + compilation_outputs, deps, grep_includes, name, - objects, output_type, owner, stamp, @@ -204,12 +261,13 @@ def register_link_binary_action( 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. grep_includes: Used internally only. name: The name of the target being linked, which is used to derive the output artifact. - 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. @@ -274,10 +332,7 @@ def register_link_binary_action( actions = actions, additional_inputs = additional_inputs, cc_toolchain = swift_toolchain.cc_toolchain_info, - compilation_outputs = cc_common.create_compilation_outputs( - objects = depset(objects), - pic_objects = depset(objects), - ), + compilation_outputs = compilation_outputs, feature_configuration = cc_feature_configuration, name = name, user_link_flags = user_link_flags, diff --git a/swift/internal/swift_binary_test.bzl b/swift/internal/swift_binary_test.bzl index 868f9ccad..d115fe855 100644 --- a/swift/internal/swift_binary_test.bzl +++ b/swift/internal/swift_binary_test.bzl @@ -15,7 +15,7 @@ """Implementation of the `swift_binary` and `swift_test` rules.""" load("@bazel_skylib//lib:dicts.bzl", "dicts") -load(":compiling.bzl", "output_groups_from_compilation_outputs") +load(":compiling.bzl", "output_groups_from_module_context") load(":derived_files.bzl", "derived_files") load(":feature_names.bzl", "SWIFT_FEATURE_BUNDLED_XCTESTS") load(":linking.bzl", "register_link_binary_action") @@ -170,9 +170,6 @@ def _swift_linking_rule_impl( cc_feature_configuration = swift_common.cc_feature_configuration( feature_configuration = feature_configuration, ) - compilation_outputs = None - objects_to_link = [] - output_groups = {} srcs = ctx.files.srcs user_link_flags = list(linkopts) @@ -185,7 +182,7 @@ def _swift_linking_rule_impl( copts = expand_locations(ctx, ctx.attr.copts, ctx.attr.swiftc_inputs) - compilation_outputs = swift_common.compile( + module_context, compilation_outputs = swift_common.compile( actions = ctx.actions, additional_inputs = additional_inputs, bin_dir = ctx.bin_dir, @@ -200,13 +197,13 @@ def _swift_linking_rule_impl( target_name = ctx.label.name, workspace_name = ctx.workspace_name, ) - user_link_flags.extend(compilation_outputs.linker_flags) - objects_to_link.extend(compilation_outputs.object_files) - additional_inputs_to_linker.extend(compilation_outputs.linker_inputs) - - output_groups = output_groups_from_compilation_outputs( - compilation_outputs = compilation_outputs, + output_groups = output_groups_from_module_context( + module_context = module_context, ) + else: + module_context = None + compilation_outputs = cc_common.create_compilation_outputs() + output_groups = {} # Collect linking contexts from any of the toolchain's implicit # dependencies. @@ -232,10 +229,10 @@ def _swift_linking_rule_impl( additional_inputs = additional_inputs_to_linker, additional_linking_contexts = additional_linking_contexts, cc_feature_configuration = cc_feature_configuration, + compilation_outputs = compilation_outputs, deps = ctx.attr.deps, grep_includes = ctx.file._grep_includes, name = ctx.label.name, - objects = objects_to_link, output_type = "executable", owner = ctx.label, stamp = ctx.attr.stamp, diff --git a/swift/internal/swift_common.bzl b/swift/internal/swift_common.bzl index 985103abc..4d7ea12c9 100644 --- a/swift/internal/swift_common.bzl +++ b/swift/internal/swift_common.bzl @@ -41,6 +41,7 @@ load( "get_cc_feature_configuration", "is_feature_enabled", ) +load(":linking.bzl", "create_linking_context_from_compilation_outputs") load( ":providers.bzl", "create_clang_module", @@ -58,6 +59,7 @@ swift_common = struct( compile = compile, configure_features = configure_features, create_clang_module = create_clang_module, + create_linking_context_from_compilation_outputs = create_linking_context_from_compilation_outputs, create_module = create_module, create_swift_info = create_swift_info, create_swift_interop_info = create_swift_interop_info, diff --git a/swift/internal/swift_grpc_library.bzl b/swift/internal/swift_grpc_library.bzl index 91babff32..68fb832a2 100644 --- a/swift/internal/swift_grpc_library.bzl +++ b/swift/internal/swift_grpc_library.bzl @@ -19,14 +19,13 @@ load("@bazel_skylib//lib:dicts.bzl", "dicts") load( ":compiling.bzl", "new_objc_provider", - "output_groups_from_compilation_outputs", + "output_groups_from_module_context", ) load( ":feature_names.bzl", "SWIFT_FEATURE_ENABLE_TESTING", "SWIFT_FEATURE_GENERATE_FROM_RAW_PROTO_FILES", ) -load(":linking.bzl", "create_linker_input") load( ":proto_gen_utils.bzl", "declare_generated_files", @@ -36,12 +35,7 @@ load( ) load(":providers.bzl", "SwiftInfo", "SwiftProtoInfo", "SwiftToolchainInfo") load(":swift_common.bzl", "swift_common") -load( - ":utils.bzl", - "compact", - "create_cc_info", - "get_providers", -) +load(":utils.bzl", "compact", "get_providers") def _register_grpcswift_generate_action( label, @@ -279,7 +273,7 @@ def _swift_grpc_library_impl(ctx): module_name = swift_common.derive_module_name(ctx.label) - compilation_outputs = swift_common.compile( + module_context, compilation_outputs = swift_common.compile( actions = ctx.actions, bin_dir = ctx.bin_dir, copts = ["-parse-as-library"], @@ -293,64 +287,57 @@ def _swift_grpc_library_impl(ctx): workspace_name = ctx.workspace_name, ) - linker_input, library_to_link = create_linker_input( - actions = ctx.actions, - alwayslink = False, - cc_feature_configuration = swift_common.cc_feature_configuration( + linking_context, linking_output = ( + swift_common.create_linking_context_from_compilation_outputs( + actions = ctx.actions, + compilation_outputs = compilation_outputs, 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, + label = ctx.label, + linking_contexts = [ + dep[CcInfo].linking_context + for dep in compile_deps + if CcInfo in dep + ], + module_context = module_context, + swift_toolchain = swift_toolchain, + ) ) providers = [ DefaultInfo( files = depset(direct = generated_files + compact([ - compilation_outputs.swiftdoc, - compilation_outputs.swiftmodule, - library_to_link.pic_static_library, + module_context.swift.swiftdoc, + module_context.swift.swiftmodule, + linking_output.library_to_link.pic_static_library, + linking_output.library_to_link.static_library, ])), ), - OutputGroupInfo(**output_groups_from_compilation_outputs( - compilation_outputs = compilation_outputs, + OutputGroupInfo(**output_groups_from_module_context( + module_context = module_context, )), - create_cc_info( - cc_infos = get_providers(compile_deps, CcInfo), - compilation_outputs = compilation_outputs, - linker_inputs = [linker_input], + CcInfo( + compilation_context = module_context.clang.compilation_context, + linking_context = linking_context, ), deps[0][SwiftProtoInfo], swift_common.create_swift_info( - modules = [ - swift_common.create_module( - name = module_name, - swift = swift_common.create_swift_module( - swiftdoc = compilation_outputs.swiftdoc, - swiftmodule = compilation_outputs.swiftmodule, - ), - ), - ], + modules = [module_context], swift_infos = get_providers(compile_deps, SwiftInfo), ), ] # Propagate an `objc` provider if the toolchain supports Objective-C - # interop, which ensures that the libraries get linked into `apple_binary` - # targets properly. + # interop, which ensures that the libraries get linked via + # `apple_common.link_multi_arch_binary`. if swift_toolchain.supports_objc_interop: providers.append(new_objc_provider( + additional_objc_infos = ( + swift_toolchain.implicit_deps_providers.objc_infos + ), deps = compile_deps, - link_inputs = compilation_outputs.linker_inputs, - linkopts = compilation_outputs.linker_flags, - module_map = compilation_outputs.generated_module_map, - static_archives = compact([library_to_link.pic_static_library]), - swiftmodules = [compilation_outputs.swiftmodule], - objc_header = compilation_outputs.generated_header, + feature_configuration = feature_configuration, + module_context = module_context, + libraries_to_link = [linking_output.library_to_link], )) return providers diff --git a/swift/internal/swift_import.bzl b/swift/internal/swift_import.bzl index 079feeb3a..f4e77bcd9 100644 --- a/swift/internal/swift_import.bzl +++ b/swift/internal/swift_import.bzl @@ -19,7 +19,7 @@ load(":attrs.bzl", "swift_common_rule_attrs") load(":compiling.bzl", "new_objc_provider") load(":providers.bzl", "SwiftInfo") load(":swift_common.bzl", "swift_common") -load(":utils.bzl", "compact", "create_cc_info", "get_providers") +load(":utils.bzl", "compact", "get_providers") def _swift_import_impl(ctx): archives = ctx.files.archives @@ -38,17 +38,37 @@ def _swift_import_impl(ctx): unsupported_features = ctx.disabled_features, ) + libraries_to_link = [ + 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 - ]), + libraries = depset(libraries_to_link), + ) + linking_context = cc_common.create_linking_context( + linker_inputs = depset([linker_input]), + ) + cc_info = cc_common.merge_cc_infos( + direct_cc_infos = [CcInfo(linking_context = linking_context)], + cc_infos = [dep[CcInfo] for dep in deps if CcInfo in dep], + ) + + module_context = swift_common.create_module( + name = ctx.attr.module_name, + clang = swift_common.create_clang_module( + compilation_context = cc_info.compilation_context, + module_map = None, + ), + swift = swift_common.create_swift_module( + swiftdoc = swiftdoc, + swiftmodule = swiftmodule, + ), ) providers = [ @@ -60,10 +80,7 @@ def _swift_import_impl(ctx): files = ctx.files.data, ), ), - create_cc_info( - cc_infos = get_providers(deps, CcInfo), - linker_inputs = [linker_input], - ), + cc_info, # Propagate an `Objc` provider so that Apple-specific rules like # apple_binary` will link the imported library properly. Typically we'd # want to only propagate this if the toolchain reports that it supports @@ -72,23 +89,12 @@ def _swift_import_impl(ctx): # ignored on non-Apple platforms anyway. new_objc_provider( deps = deps, - link_inputs = [], - linkopts = [], - module_map = None, - objc_header = None, - static_archives = archives, - swiftmodules = [swiftmodule], + feature_configuration = None, + libraries_to_link = libraries_to_link, + module_context = module_context, ), swift_common.create_swift_info( - modules = [ - swift_common.create_module( - name = ctx.attr.module_name, - swift = swift_common.create_swift_module( - swiftdoc = swiftdoc, - swiftmodule = swiftmodule, - ), - ), - ], + modules = [module_context], swift_infos = get_providers(deps, SwiftInfo), ), ] diff --git a/swift/internal/swift_library.bzl b/swift/internal/swift_library.bzl index de5bc9d09..5b461b33b 100644 --- a/swift/internal/swift_library.bzl +++ b/swift/internal/swift_library.bzl @@ -23,7 +23,7 @@ load( load( ":compiling.bzl", "new_objc_provider", - "output_groups_from_compilation_outputs", + "output_groups_from_module_context", "swift_library_output_map", ) load( @@ -32,14 +32,12 @@ load( "SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION", "SWIFT_FEATURE_SUPPORTS_PRIVATE_DEPS", ) -load(":linking.bzl", "create_linker_input") load(":providers.bzl", "SwiftInfo", "SwiftToolchainInfo") load(":swift_clang_module_aspect.bzl", "swift_clang_module_aspect") load(":swift_common.bzl", "swift_common") load( ":utils.bzl", "compact", - "create_cc_info", "expand_locations", "expand_make_variables", "get_providers", @@ -172,7 +170,7 @@ def _swift_library_impl(ctx): attr = "generated_header_name", ) - compilation_outputs = swift_common.compile( + module_context, compilation_outputs = swift_common.compile( actions = ctx.actions, additional_inputs = additional_inputs, bin_dir = ctx.bin_dir, @@ -190,43 +188,42 @@ def _swift_library_impl(ctx): workspace_name = ctx.workspace_name, ) - # If a module was created for the generated header, propagate it as well so - # that it is passed as a module input to upstream compilation actions. - if compilation_outputs.generated_module_map: - clang_module = swift_common.create_clang_module( - compilation_context = cc_common.create_compilation_context( - headers = depset([compilation_outputs.generated_header]), - ), - module_map = compilation_outputs.generated_module_map, - precompiled_module = compilation_outputs.precompiled_module, - ) - else: - clang_module = None - - 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( + linking_context, linking_output = ( + swift_common.create_linking_context_from_compilation_outputs( + actions = ctx.actions, + additional_inputs = additional_inputs, + alwayslink = ctx.attr.alwayslink, + compilation_outputs = compilation_outputs, 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, + label = ctx.label, + linking_contexts = [ + dep[CcInfo].linking_context + for dep in deps + private_deps + if CcInfo in dep + ], + module_context = module_context, + swift_toolchain = swift_toolchain, + user_link_flags = linkopts, + ) ) + # Include the generated header (if any) as a rule output, so that a user + # building the target can see its path and view it easily. + generated_header_file = None + if generated_header_name: + for file in module_context.clang.compilation_context.direct_headers: + if file.basename == generated_header_name: + generated_header_file = file + break + direct_output_files = compact([ - compilation_outputs.generated_header, - compilation_outputs.precompiled_module, - compilation_outputs.swiftdoc, - compilation_outputs.swiftinterface, - compilation_outputs.swiftmodule, - library_to_link.pic_static_library, + generated_header_file, + module_context.clang.precompiled_module, + module_context.swift.swiftdoc, + module_context.swift.swiftinterface, + module_context.swift.swiftmodule, + linking_output.library_to_link.static_library, + linking_output.library_to_link.pic_static_library, ]) implicit_deps_providers = swift_toolchain.implicit_deps_providers @@ -239,19 +236,12 @@ def _swift_library_impl(ctx): files = ctx.files.data, ), ), - OutputGroupInfo(**output_groups_from_compilation_outputs( - compilation_outputs = compilation_outputs, + OutputGroupInfo(**output_groups_from_module_context( + module_context = module_context, )), - create_cc_info( - cc_infos = get_providers(deps, CcInfo), - compilation_outputs = compilation_outputs, - defines = ctx.attr.defines, - includes = [ctx.bin_dir.path], - linker_inputs = [linker_input], - private_cc_infos = ( - get_providers(private_deps, CcInfo) + - implicit_deps_providers.cc_infos - ), + CcInfo( + compilation_context = module_context.clang.compilation_context, + linking_context = linking_context, ), coverage_common.instrumented_files_info( ctx, @@ -260,18 +250,7 @@ def _swift_library_impl(ctx): source_attributes = ["srcs"], ), swift_common.create_swift_info( - modules = [ - swift_common.create_module( - name = module_name, - clang = clang_module, - swift = swift_common.create_swift_module( - defines = ctx.attr.defines, - swiftdoc = compilation_outputs.swiftdoc, - swiftinterface = compilation_outputs.swiftinterface, - swiftmodule = compilation_outputs.swiftmodule, - ), - ), - ], + modules = [module_context], # Note that private_deps are explicitly omitted here; they should # not propagate. swift_infos = get_providers(deps, SwiftInfo), @@ -283,18 +262,17 @@ def _swift_library_impl(ctx): # targets. if swift_toolchain.supports_objc_interop: providers.append(new_objc_provider( + additional_link_inputs = additional_inputs, + additional_objc_infos = implicit_deps_providers.objc_infos, # We must include private_deps here because some of the information # propagated here is related to linking. # TODO(allevato): This means we can't yet completely avoid # propagating headers/module maps from impl-only Obj-C dependencies. deps = deps + private_deps, - link_inputs = compilation_outputs.linker_inputs + additional_inputs, - linkopts = compilation_outputs.linker_flags + linkopts, - module_map = compilation_outputs.generated_module_map, - static_archives = compact([library_to_link.pic_static_library]), - swiftmodules = [compilation_outputs.swiftmodule], - objc_header = compilation_outputs.generated_header, - objc_providers = implicit_deps_providers.objc_infos, + feature_configuration = feature_configuration, + module_context = module_context, + libraries_to_link = [linking_output.library_to_link], + user_link_flags = linkopts, )) return providers diff --git a/swift/internal/swift_module_alias.bzl b/swift/internal/swift_module_alias.bzl index 1fca5452b..bcb62439c 100644 --- a/swift/internal/swift_module_alias.bzl +++ b/swift/internal/swift_module_alias.bzl @@ -15,16 +15,11 @@ """Implementation of the `swift_module_alias` rule.""" load("@bazel_skylib//lib:dicts.bzl", "dicts") -load( - ":compiling.bzl", - "new_objc_provider", - "output_groups_from_compilation_outputs", -) +load(":compiling.bzl", "new_objc_provider", "output_groups_from_module_context") load(":derived_files.bzl", "derived_files") -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") +load(":utils.bzl", "compact", "get_providers") def _swift_module_alias_impl(ctx): deps = ctx.attr.deps @@ -59,7 +54,7 @@ def _swift_module_alias_impl(ctx): unsupported_features = ctx.disabled_features, ) - compilation_outputs = swift_common.compile( + module_context, compilation_outputs = swift_common.compile( actions = ctx.actions, bin_dir = ctx.bin_dir, copts = ["-parse-as-library"], @@ -73,55 +68,45 @@ def _swift_module_alias_impl(ctx): workspace_name = ctx.workspace_name, ) - linker_input, library_to_link = create_linker_input( - actions = ctx.actions, - alwayslink = False, - cc_feature_configuration = swift_common.cc_feature_configuration( + linking_context, linking_output = ( + swift_common.create_linking_context_from_compilation_outputs( + actions = ctx.actions, + compilation_outputs = compilation_outputs, 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, + label = ctx.label, + linking_contexts = [ + dep[CcInfo].linking_context + for dep in deps + if CcInfo in dep + ], + module_context = module_context, + swift_toolchain = swift_toolchain, + ) ) providers = [ DefaultInfo( files = depset(compact([ - compilation_outputs.swiftdoc, - compilation_outputs.swiftmodule, - compilation_outputs.swiftinterface, - library_to_link.dynamic_library, - library_to_link.pic_static_library, + module_context.swift.swiftdoc, + module_context.swift.swiftinterface, + module_context.swift.swiftmodule, + linking_output.library_to_link.pic_static_library, + linking_output.library_to_link.static_library, ])), ), - OutputGroupInfo(**output_groups_from_compilation_outputs( - compilation_outputs = compilation_outputs, + OutputGroupInfo(**output_groups_from_module_context( + module_context = module_context, )), coverage_common.instrumented_files_info( ctx, dependency_attributes = ["deps"], ), - create_cc_info( - cc_infos = get_providers(deps, CcInfo), - compilation_outputs = compilation_outputs, - includes = [ctx.bin_dir.path], - linker_inputs = [linker_input], + CcInfo( + compilation_context = module_context.clang.compilation_context, + linking_context = linking_context, ), swift_common.create_swift_info( - modules = [ - swift_common.create_module( - name = module_name, - swift = swift_common.create_swift_module( - swiftdoc = compilation_outputs.swiftdoc, - swiftmodule = compilation_outputs.swiftmodule, - swiftinterface = compilation_outputs.swiftinterface, - ), - ), - ], + modules = [module_context], swift_infos = get_providers(deps, SwiftInfo), ), ] @@ -131,13 +116,13 @@ def _swift_module_alias_impl(ctx): # targets. if swift_toolchain.supports_objc_interop: providers.append(new_objc_provider( + additional_objc_infos = ( + swift_toolchain.implicit_deps_providers.objc_infos + ), deps = deps, - link_inputs = compilation_outputs.linker_inputs, - linkopts = compilation_outputs.linker_flags, - module_map = compilation_outputs.generated_module_map, - static_archives = compact([library_to_link.pic_static_library]), - swiftmodules = [compilation_outputs.swiftmodule], - objc_header = compilation_outputs.generated_header, + feature_configuration = feature_configuration, + module_context = module_context, + libraries_to_link = [linking_output.library_to_link], )) return providers diff --git a/swift/internal/swift_protoc_gen_aspect.bzl b/swift/internal/swift_protoc_gen_aspect.bzl index 9103266a5..be618a733 100644 --- a/swift/internal/swift_protoc_gen_aspect.bzl +++ b/swift/internal/swift_protoc_gen_aspect.bzl @@ -18,7 +18,7 @@ load("@rules_proto//proto:defs.bzl", "ProtoInfo") load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") load(":attrs.bzl", "swift_config_attrs") -load(":compiling.bzl", "output_groups_from_compilation_outputs") +load(":compiling.bzl", "new_objc_provider", "output_groups_from_module_context") load( ":feature_names.bzl", "SWIFT_FEATURE_EMIT_SWIFTINTERFACE", @@ -26,7 +26,6 @@ load( "SWIFT_FEATURE_ENABLE_TESTING", "SWIFT_FEATURE_GENERATE_FROM_RAW_PROTO_FILES", ) -load(":linking.bzl", "create_linker_input") load( ":proto_gen_utils.bzl", "declare_generated_files", @@ -36,12 +35,7 @@ load( ) load(":providers.bzl", "SwiftInfo", "SwiftProtoInfo", "SwiftToolchainInfo") load(":swift_common.bzl", "swift_common") -load( - ":utils.bzl", - "compact", - "create_cc_info", - "get_providers", -) +load(":utils.bzl", "get_providers") # The paths of proto files bundled with the runtime. This is mainly the well # known type protos, but also includes descriptor.proto to make generation of @@ -412,7 +406,7 @@ def _swift_protoc_gen_aspect_impl(target, aspect_ctx): module_name = swift_common.derive_module_name(target.label) - compilation_outputs = swift_common.compile( + module_context, compilation_outputs = swift_common.compile( actions = aspect_ctx.actions, bin_dir = aspect_ctx.bin_dir, copts = ["-parse-as-library"], @@ -426,22 +420,24 @@ def _swift_protoc_gen_aspect_impl(target, aspect_ctx): workspace_name = aspect_ctx.workspace_name, ) - linker_input, library_to_link = create_linker_input( - actions = aspect_ctx.actions, - alwayslink = False, - cc_feature_configuration = swift_common.cc_feature_configuration( + linking_context, linking_output = ( + swift_common.create_linking_context_from_compilation_outputs( + actions = aspect_ctx.actions, + compilation_outputs = compilation_outputs, 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, + label = target.label, + linking_contexts = [ + dep[CcInfo].linking_context + for dep in proto_deps + support_deps + if CcInfo in dep + ], + module_context = module_context, + # 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. + name = "{}.swift".format(target.label.name), + swift_toolchain = swift_toolchain, + ) ) # It's bad practice to attach providers you don't own to other targets, @@ -457,7 +453,7 @@ def _swift_protoc_gen_aspect_impl(target, aspect_ctx): # `SwiftProtoCcInfo`. Finally, the `swift_proto_library` rule will # extract the `CcInfo` from the `SwiftProtoCcInfo` of its single # dependency and propagate that safely up the tree. - cc_infos = ( + transitive_cc_infos = ( get_providers(proto_deps, SwiftProtoCcInfo, _extract_cc_info) + get_providers(support_deps, CcInfo) ) @@ -472,64 +468,40 @@ def _swift_protoc_gen_aspect_impl(target, aspect_ctx): _extract_objc_info, ) + get_providers(support_deps, apple_common.Objc) - objc_info_args = {} - if compilation_outputs.generated_header: - objc_info_args["header"] = depset([ - compilation_outputs.generated_header, - ]) - if library_to_link.pic_static_library: - objc_info_args["library"] = depset( - [library_to_link.pic_static_library], - order = "topological", - ) - if compilation_outputs.linker_flags: - objc_info_args["linkopt"] = depset( - compilation_outputs.linker_flags, - ) - if compilation_outputs.generated_module_map: - objc_info_args["module_map"] = depset([ - compilation_outputs.generated_module_map, - ]) - - linker_inputs = compilation_outputs.linker_inputs + compact([ - compilation_outputs.swiftmodule, - ]) - if linker_inputs: - objc_info_args["link_inputs"] = depset(linker_inputs) - - includes = [aspect_ctx.bin_dir.path] - objc_info = apple_common.new_objc_provider( - providers = objc_infos, - **objc_info_args + objc_info = new_objc_provider( + additional_objc_infos = ( + objc_infos + + swift_toolchain.implicit_deps_providers.objc_infos + ), + # We pass an empty list here because we already extracted the + # `Objc` providers from `SwiftProtoCcInfo` above. + deps = [], + feature_configuration = feature_configuration, + module_context = module_context, + libraries_to_link = [linking_output.library_to_link], ) else: includes = None objc_info = None + cc_info = CcInfo( + compilation_context = module_context.clang.compilation_context, + linking_context = linking_context, + ) + providers = [ - OutputGroupInfo(**output_groups_from_compilation_outputs( - compilation_outputs = compilation_outputs, + OutputGroupInfo(**output_groups_from_module_context( + module_context = module_context, )), SwiftProtoCcInfo( - cc_info = create_cc_info( - cc_infos = cc_infos, - compilation_outputs = compilation_outputs, - includes = includes, - linker_inputs = [linker_input], + cc_info = cc_common.merge_cc_infos( + direct_cc_infos = [cc_info], + cc_infos = transitive_cc_infos, ), objc_info = objc_info, ), swift_common.create_swift_info( - modules = [ - swift_common.create_module( - name = module_name, - swift = swift_common.create_swift_module( - swiftdoc = compilation_outputs.swiftdoc, - swiftmodule = compilation_outputs.swiftmodule, - swiftinterface = compilation_outputs.swiftinterface, - ), - ), - ], + modules = [module_context], swift_infos = get_providers( proto_deps + support_deps, SwiftInfo, @@ -545,15 +517,13 @@ def _swift_protoc_gen_aspect_impl(target, aspect_ctx): pbswift_files = [] if swift_toolchain.supports_objc_interop: - objc_providers = get_providers( - proto_deps, - SwiftProtoCcInfo, - _extract_objc_info, - ) - objc_provider = apple_common.new_objc_provider( - providers = objc_providers, + objc_info = apple_common.new_objc_provider( + providers = get_providers( + proto_deps, + SwiftProtoCcInfo, + _extract_objc_info, + ), ) - objc_info = objc_provider else: objc_info = None diff --git a/swift/internal/utils.bzl b/swift/internal/utils.bzl index da5c0c758..466175d07 100644 --- a/swift/internal/utils.bzl +++ b/swift/internal/utils.bzl @@ -17,48 +17,6 @@ load(":providers.bzl", "SwiftInfo") load("@bazel_skylib//lib:paths.bzl", "paths") -def collect_cc_libraries( - cc_info, - include_dynamic = False, - include_interface = False, - include_pic_static = False, - include_static = False): - """Returns a list of libraries referenced in the given `CcInfo` provider. - - Args: - cc_info: The `CcInfo` provider whose libraries should be returned. - include_dynamic: True if dynamic libraries should be included in the - list. - include_interface: True if interface libraries should be included in the - list. - include_pic_static: True if PIC static libraries should be included in - the list. If there is no PIC library, the non-PIC library will be - used instead. - include_static: True if non-PIC static libraries should be included in - the list. - - Returns: - The list of libraries built or depended on by the given provier. - """ - 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) - elif library.static_library: - libraries.append(library.static_library) - elif include_static and library.static_library: - libraries.append(library.static_library) - - if include_dynamic and library.dynamic_library: - libraries.append(library.dynamic_library) - if include_interface and library.interface_library: - libraries.append(library.interface_library) - - return libraries - def collect_implicit_deps_providers( targets, additional_cc_infos = [], @@ -112,69 +70,6 @@ def compact(sequence): """ return [item for item in sequence if item != None] -def create_cc_info( - *, - cc_infos = [], - compilation_outputs = None, - defines = [], - includes = [], - linker_inputs = [], - private_cc_infos = []): - """Creates a `CcInfo` provider from Swift compilation info and deps. - - Args: - cc_infos: A list of `CcInfo` providers from public dependencies, whose - compilation and linking contexts should both be merged into the new - provider. - compilation_outputs: The compilation outputs from a Swift compile - action, as returned by `swift_common.compile`, or None. - defines: The list of compiler defines to insert into the compilation - context. - 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 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 - be excluded. - - Returns: - A new `CcInfo`. - """ - all_headers = [] - if compilation_outputs: - all_headers = compact([compilation_outputs.generated_header]) - - local_cc_infos = [ - CcInfo( - linking_context = cc_common.create_linking_context( - linker_inputs = depset(linker_inputs), - ), - compilation_context = cc_common.create_compilation_context( - defines = depset(defines), - headers = depset(all_headers), - includes = depset(includes), - ), - ), - ] - - if private_cc_infos: - # Merge the private deps' CcInfos, but discard the compilation context - # and only propagate the linking context. - full_private_cc_info = cc_common.merge_cc_infos( - cc_infos = private_cc_infos, - ) - local_cc_infos.append(CcInfo( - linking_context = full_private_cc_info.linking_context, - )) - - return cc_common.merge_cc_infos( - cc_infos = cc_infos, - direct_cc_infos = local_cc_infos, - ) - def compilation_context_for_explicit_module_compilation( compilation_contexts, deps): diff --git a/test/private_deps_tests.bzl b/test/private_deps_tests.bzl index e594cb852..6085f5e96 100644 --- a/test/private_deps_tests.bzl +++ b/test/private_deps_tests.bzl @@ -97,7 +97,7 @@ def private_deps_test_suite(name = "private_deps"): "/test/fixtures/private_deps/public_cc.swift.modulemap", "-/test/fixtures/private_deps/private_cc.swift.modulemap", ], - field = "transitive_modules.clang!.module_map", + field = "transitive_modules.clang!.module_map!", provider = "SwiftInfo", tags = [name], target_under_test = "@build_bazel_rules_swift//test/fixtures/private_deps:client_cc_deps",