diff --git a/doc/BUILD b/doc/BUILD index b6b44922b..e61f01e2c 100644 --- a/doc/BUILD +++ b/doc/BUILD @@ -18,6 +18,7 @@ _DOC_SRCS = { "swift_binary", "swift_compiler_plugin", "universal_swift_compiler_plugin", + "swift_compiler_plugin_import", "swift_cross_import_overlay", "swift_feature_allowlist", "swift_import", diff --git a/doc/doc.bzl b/doc/doc.bzl index 821ba8874..f9175dc36 100644 --- a/doc/doc.bzl +++ b/doc/doc.bzl @@ -64,6 +64,10 @@ load( _swift_compiler_plugin = "swift_compiler_plugin", _universal_swift_compiler_plugin = "universal_swift_compiler_plugin", ) +load( + "//swift:swift_compiler_plugin_import.bzl", + _swift_compiler_plugin_import = "swift_compiler_plugin_import", +) load( "//swift:swift_cross_import_overlay.bzl", _swift_cross_import_overlay = "swift_cross_import_overlay", @@ -118,6 +122,7 @@ SwiftToolchainInfo = _SwiftToolchainInfo swift_binary = _swift_binary swift_compiler_plugin = _swift_compiler_plugin universal_swift_compiler_plugin = _universal_swift_compiler_plugin +swift_compiler_plugin_import = _swift_compiler_plugin_import swift_cross_import_overlay = _swift_cross_import_overlay swift_feature_allowlist = _swift_feature_allowlist swift_import = _swift_import diff --git a/doc/rules.md b/doc/rules.md index baab8cb0d..382c2b4d3 100644 --- a/doc/rules.md +++ b/doc/rules.md @@ -17,6 +17,7 @@ On this page: * [swift_binary](#swift_binary) * [swift_compiler_plugin](#swift_compiler_plugin) * [universal_swift_compiler_plugin](#universal_swift_compiler_plugin) + * [swift_compiler_plugin_import](#swift_compiler_plugin_import) * [swift_cross_import_overlay](#swift_cross_import_overlay) * [swift_feature_allowlist](#swift_feature_allowlist) * [swift_import](#swift_import) @@ -166,6 +167,28 @@ swift_library( | swiftc_inputs | Additional files that are referenced using `$(location ...)` in attributes that support location expansion. | List of labels | optional | `[]` | + + +## swift_compiler_plugin_import + +
+swift_compiler_plugin_import(name, executable, module_names)
+
+ +Allows for a Swift compiler plugin to be loaded from a prebuilt executable or +some other binary-propagating rule, instead of building the plugin from source +using `swift_compiler_plugin`. + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| executable | The compiler plugin executable that will be passed to the Swift compiler when compiling any modules that depend on the plugin. This attribute may refer directly to an executable binary or to another rule that produces an executable binary. | Label | required | | +| module_names | The list of names of Swift modules in the plugin executable that provide implementations of plugin types, which the compiler uses to look up their implementations. | List of strings | required | | + + ## swift_cross_import_overlay @@ -243,23 +266,26 @@ package. ## swift_import
-swift_import(name, deps, data, archives, module_name, swiftdoc, swiftinterface, swiftmodule)
+swift_import(name, deps, data, archives, module_name, plugins, swiftdoc, swiftinterface,
+             swiftmodule)
 
-Allows for the use of Swift textual module interfaces or precompiled Swift modules as dependencies in other -`swift_library` and `swift_binary` targets. +Allows for the use of Swift textual module interfaces and/or precompiled Swift +modules as dependencies in other `swift_library` and `swift_binary` targets. -To use `swift_import` targets across Xcode versions and/or OS versions, it is required to use `.swiftinterface` files. -These can be produced by the pre-built target if built with: +To use `swift_import` targets across Xcode versions and/or OS versions, it is +required to use `.swiftinterface` files. These can be produced by the pre-built +target if built with: - `--features=swift.enable_library_evolution` - `--features=swift.emit_swiftinterface` -If the pre-built target supports `.private.swiftinterface` files, these can be used instead of `.swiftinterface` files -in the `swiftinterface` attribute. +If the pre-built target supports `.private.swiftinterface` files, these can be +used instead of `.swiftinterface` files in the `swiftinterface` attribute. To import pre-built Swift modules that use `@_spi` when using `swiftinterface`, -the `.private.swiftinterface` files are required in order to build any code that uses the API marked with `@_spi`. +the `.private.swiftinterface` files are required in order to build any code that +uses the API marked with `@_spi`. **ATTRIBUTES** @@ -271,6 +297,7 @@ the `.private.swiftinterface` files are required in order to build any code that | data | The list of files needed by this target at runtime.

Files and targets named in the `data` attribute will appear in the `*.runfiles` area of this target, if it has one. This may include data files needed by a binary or library, or other programs needed by it. | List of labels | optional | `[]` | | archives | The list of `.a` or `.lo` files provided to Swift targets that depend on this target. | List of labels | optional | `[]` | | module_name | The name of the module represented by this target. | String | required | | +| plugins | A list of `swift_compiler_plugin` targets that should be loaded by the compiler when compiling any modules that directly depend on this target. | List of labels | optional | `[]` | | swiftdoc | The `.swiftdoc` file provided to Swift targets that depend on this target. | Label | optional | `None` | | swiftinterface | The `.swiftinterface` file that defines the module interface for this target. May not be specified if `swiftmodule` is specified. | Label | optional | `None` | | swiftmodule | The `.swiftmodule` file provided to Swift targets that depend on this target. May not be specified if `swiftinterface` is specified. | Label | optional | `None` | diff --git a/swift/BUILD b/swift/BUILD index 71c222d7f..0239353f5 100644 --- a/swift/BUILD +++ b/swift/BUILD @@ -118,6 +118,14 @@ bzl_library( ], ) +bzl_library( + name = "swift_compiler_plugin_import", + srcs = ["swift_compiler_plugin_import.bzl"], + deps = [ + "//swift/internal:providers", + ], +) + bzl_library( name = "swift_cross_import_overlay", srcs = ["swift_cross_import_overlay.bzl"], @@ -293,6 +301,7 @@ bzl_library( ":swift_clang_module_aspect", ":swift_common", ":swift_compiler_plugin", + ":swift_compiler_plugin_import", ":swift_cross_import_overlay", ":swift_extract_symbol_graph", ":swift_feature_allowlist", diff --git a/swift/swift_compiler_plugin_import.bzl b/swift/swift_compiler_plugin_import.bzl new file mode 100644 index 000000000..e42c8aa36 --- /dev/null +++ b/swift/swift_compiler_plugin_import.bzl @@ -0,0 +1,58 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Implementation of the `swift_compiler_plugin_import` rule.""" + +load("//swift/internal:providers.bzl", "SwiftCompilerPluginInfo") + +def _swift_compiler_plugin_import_impl(ctx): + return [ + SwiftCompilerPluginInfo( + executable = ctx.executable.executable, + module_names = depset(ctx.attr.module_names), + ), + ] + +swift_compiler_plugin_import = rule( + attrs = { + "executable": attr.label( + allow_files = True, + cfg = "exec", + doc = """\ +The compiler plugin executable that will be passed to the Swift compiler when +compiling any modules that depend on the plugin. This attribute may refer +directly to an executable binary or to another rule that produces an executable +binary. +""", + executable = True, + mandatory = True, + ), + "module_names": attr.string_list( + allow_empty = False, + doc = """ +The list of names of Swift modules in the plugin executable that provide +implementations of plugin types, which the compiler uses to look up their +implementations. +""", + mandatory = True, + ), + }, + doc = """\ +Allows for a Swift compiler plugin to be loaded from a prebuilt executable or +some other binary-propagating rule, instead of building the plugin from source +using `swift_compiler_plugin`. +""", + implementation = _swift_compiler_plugin_import_impl, + provides = [SwiftCompilerPluginInfo], +) diff --git a/swift/swift_import.bzl b/swift/swift_import.bzl index 07c2c73ff..9a5aac2de 100644 --- a/swift/swift_import.bzl +++ b/swift/swift_import.bzl @@ -27,6 +27,7 @@ load( "get_cc_feature_configuration", ) load("//swift/internal:linking.bzl", "new_objc_provider") +load("//swift/internal:providers.bzl", "SwiftCompilerPluginInfo") load( "//swift/internal:toolchain_utils.bzl", "get_swift_toolchain", @@ -125,6 +126,11 @@ def _swift_import_impl(ctx): module_map = None, ), swift = create_swift_module_inputs( + plugins = [ + plugin[SwiftCompilerPluginInfo] + for plugin in ctx.attr.plugins + if SwiftCompilerPluginInfo in plugin + ], swiftdoc = swiftdoc, swiftinterface = swiftinterface, swiftmodule = swiftmodule, @@ -173,7 +179,8 @@ swift_import = rule( allow_empty = True, allow_files = ["a", "lo"], doc = """\ -The list of `.a` or `.lo` files provided to Swift targets that depend on this target. +The list of `.a` or `.lo` files provided to Swift targets that depend on this +target. """, mandatory = False, ), @@ -181,6 +188,14 @@ The list of `.a` or `.lo` files provided to Swift targets that depend on this ta doc = "The name of the module represented by this target.", mandatory = True, ), + "plugins": attr.label_list( + cfg = "exec", + doc = """\ +A list of `swift_compiler_plugin` targets that should be loaded by the compiler +when compiling any modules that directly depend on this target. +""", + providers = [[SwiftCompilerPluginInfo]], + ), "swiftdoc": attr.label( allow_single_file = ["swiftdoc"], doc = """\ @@ -209,20 +224,22 @@ May not be specified if `swiftinterface` is specified. }, ), doc = """\ -Allows for the use of Swift textual module interfaces or precompiled Swift modules as dependencies in other -`swift_library` and `swift_binary` targets. +Allows for the use of Swift textual module interfaces and/or precompiled Swift +modules as dependencies in other `swift_library` and `swift_binary` targets. -To use `swift_import` targets across Xcode versions and/or OS versions, it is required to use `.swiftinterface` files. -These can be produced by the pre-built target if built with: +To use `swift_import` targets across Xcode versions and/or OS versions, it is +required to use `.swiftinterface` files. These can be produced by the pre-built +target if built with: - `--features=swift.enable_library_evolution` - `--features=swift.emit_swiftinterface` -If the pre-built target supports `.private.swiftinterface` files, these can be used instead of `.swiftinterface` files -in the `swiftinterface` attribute. +If the pre-built target supports `.private.swiftinterface` files, these can be +used instead of `.swiftinterface` files in the `swiftinterface` attribute. To import pre-built Swift modules that use `@_spi` when using `swiftinterface`, -the `.private.swiftinterface` files are required in order to build any code that uses the API marked with `@_spi`. +the `.private.swiftinterface` files are required in order to build any code that +uses the API marked with `@_spi`. """, fragments = ["cpp"], implementation = _swift_import_impl,