Skip to content

Commit 149e554

Browse files
allevatobrentleyjones
authored andcommitted
Implement compilation support for swift_module_mapping
PiperOrigin-RevId: 486694413 (cherry picked from commit ba41644) Signed-off-by: Brentley Jones <[email protected]>
1 parent c6d8d84 commit 149e554

File tree

10 files changed

+268
-24
lines changed

10 files changed

+268
-24
lines changed

doc/api.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -480,9 +480,9 @@ A provider whose type/layout is an implementation detail and should not
480480
## swift_common.create_swift_module
481481

482482
<pre>
483-
swift_common.create_swift_module(<a href="#swift_common.create_swift_module-swiftdoc">swiftdoc</a>, <a href="#swift_common.create_swift_module-swiftmodule">swiftmodule</a>, <a href="#swift_common.create_swift_module-ast_files">ast_files</a>, <a href="#swift_common.create_swift_module-defines">defines</a>, <a href="#swift_common.create_swift_module-generated_header">generated_header</a>,
484-
<a href="#swift_common.create_swift_module-indexstore">indexstore</a>, <a href="#swift_common.create_swift_module-plugins">plugins</a>, <a href="#swift_common.create_swift_module-swiftsourceinfo">swiftsourceinfo</a>, <a href="#swift_common.create_swift_module-swiftinterface">swiftinterface</a>,
485-
<a href="#swift_common.create_swift_module-private_swiftinterface">private_swiftinterface</a>, <a href="#swift_common.create_swift_module-const_protocols_to_gather">const_protocols_to_gather</a>)
483+
swift_common.create_swift_module(<a href="#swift_common.create_swift_module-ast_files">ast_files</a>, <a href="#swift_common.create_swift_module-const_protocols_to_gather">const_protocols_to_gather</a>, <a href="#swift_common.create_swift_module-defines">defines</a>, <a href="#swift_common.create_swift_module-generated_header">generated_header</a>,
484+
<a href="#swift_common.create_swift_module-indexstore">indexstore</a>, <a href="#swift_common.create_swift_module-original_module_name">original_module_name</a>, <a href="#swift_common.create_swift_module-plugins">plugins</a>, <a href="#swift_common.create_swift_module-private_swiftinterface">private_swiftinterface</a>,
485+
<a href="#swift_common.create_swift_module-swiftdoc">swiftdoc</a>, <a href="#swift_common.create_swift_module-swiftinterface">swiftinterface</a>, <a href="#swift_common.create_swift_module-swiftmodule">swiftmodule</a>, <a href="#swift_common.create_swift_module-swiftsourceinfo">swiftsourceinfo</a>)
486486
</pre>
487487

488488
Creates a value representing a Swift module use as a Swift dependency.
@@ -492,17 +492,18 @@ Creates a value representing a Swift module use as a Swift dependency.
492492

493493
| Name | Description | Default Value |
494494
| :------------- | :------------- | :------------- |
495-
| <a id="swift_common.create_swift_module-swiftdoc"></a>swiftdoc | The `.swiftdoc` file emitted by the compiler for this module. | none |
496-
| <a id="swift_common.create_swift_module-swiftmodule"></a>swiftmodule | The `.swiftmodule` file emitted by the compiler for this module. | none |
497495
| <a id="swift_common.create_swift_module-ast_files"></a>ast_files | A list of `File`s output from the `DUMP_AST` action. | `[]` |
496+
| <a id="swift_common.create_swift_module-const_protocols_to_gather"></a>const_protocols_to_gather | A list of protocol names from which constant values should be extracted from source code that takes this module as a *direct* dependency. | `[]` |
498497
| <a id="swift_common.create_swift_module-defines"></a>defines | A list of defines that will be provided as `copts` to targets that depend on this module. If omitted, the empty list will be used. | `[]` |
499498
| <a id="swift_common.create_swift_module-generated_header"></a>generated_header | A `File` representing the Swift generated header. | `None` |
500499
| <a id="swift_common.create_swift_module-indexstore"></a>indexstore | A `File` representing the directory that contains the index store data generated by the compiler if the `"swift.index_while_building"` feature is enabled, otherwise this will be `None`. | `None` |
500+
| <a id="swift_common.create_swift_module-original_module_name"></a>original_module_name | The original name of the module if it was changed by a module mapping; otherwise, `None`. | `None` |
501501
| <a id="swift_common.create_swift_module-plugins"></a>plugins | A list of `SwiftCompilerPluginInfo` providers representing compiler plugins that are required by this module and should be loaded by the compiler when this module is directly depended on. | `[]` |
502-
| <a id="swift_common.create_swift_module-swiftsourceinfo"></a>swiftsourceinfo | The `.swiftsourceinfo` file emitted by the compiler for this module. May be `None` if no source info file was emitted. | `None` |
503-
| <a id="swift_common.create_swift_module-swiftinterface"></a>swiftinterface | The `.swiftinterface` file emitted by the compiler for this module. May be `None` if no module interface file was emitted. | `None` |
504502
| <a id="swift_common.create_swift_module-private_swiftinterface"></a>private_swiftinterface | The `.private.swiftinterface` file emitted by the compiler for this module. May be `None` if no private module interface file was emitted. | `None` |
505-
| <a id="swift_common.create_swift_module-const_protocols_to_gather"></a>const_protocols_to_gather | A list of protocol names from which constant values should be extracted from source code that takes this module as a *direct* dependency. | `[]` |
503+
| <a id="swift_common.create_swift_module-swiftdoc"></a>swiftdoc | The `.swiftdoc` file emitted by the compiler for this module. | none |
504+
| <a id="swift_common.create_swift_module-swiftinterface"></a>swiftinterface | The `.swiftinterface` file emitted by the compiler for this module. May be `None` if no module interface file was emitted. | `None` |
505+
| <a id="swift_common.create_swift_module-swiftmodule"></a>swiftmodule | The `.swiftmodule` file emitted by the compiler for this module. | none |
506+
| <a id="swift_common.create_swift_module-swiftsourceinfo"></a>swiftsourceinfo | The `.swiftsourceinfo` file emitted by the compiler for this module. May be `None` if no source info file was emitted. | `None` |
506507

507508
**RETURNS**
508509

swift/internal/compiling.bzl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,14 @@ def compile(
479479
macros).
480480
"""
481481

482+
# Apply the module alias for the module being compiled, if present.
483+
module_alias = swift_toolchain.module_aliases.get(module_name)
484+
if module_alias:
485+
original_module_name = module_name
486+
module_name = module_alias
487+
else:
488+
original_module_name = None
489+
482490
# Collect the `SwiftInfo` providers that represent the dependencies of the
483491
# Objective-C generated header module -- this includes the dependencies of
484492
# the Swift module, plus any additional dependencies that the toolchain says
@@ -689,8 +697,9 @@ to use swift_common.compile(include_dev_srch_paths = ...) instead.\
689697
include_dev_srch_paths = include_dev_srch_paths_value,
690698
is_swift = True,
691699
module_name = module_name,
692-
package_name = package_name,
693700
objc_info = merged_objc_info,
701+
original_module_name = original_module_name,
702+
package_name = package_name,
694703
plugins = depset(used_plugins),
695704
source_files = srcs,
696705
target_label = feature_configuration._label,
@@ -824,6 +833,7 @@ to use swift_common.compile(include_dev_srch_paths = ...) instead.\
824833
defines = defines,
825834
generated_header = compile_outputs.generated_header_file,
826835
indexstore = compile_outputs.indexstore_directory,
836+
original_module_name = original_module_name,
827837
plugins = depset(plugins),
828838
private_swiftinterface = compile_outputs.private_swiftinterface_file,
829839
swiftdoc = compile_outputs.swiftdoc_file,

swift/internal/providers.bzl

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -148,44 +148,47 @@ def create_clang_module(
148148

149149
def create_swift_module(
150150
*,
151-
swiftdoc,
152-
swiftmodule,
153151
ast_files = [],
152+
const_protocols_to_gather = [],
154153
defines = [],
155154
generated_header = None,
156155
indexstore = None,
156+
original_module_name = None,
157157
plugins = [],
158-
swiftsourceinfo = None,
159-
swiftinterface = None,
160158
private_swiftinterface = None,
161-
const_protocols_to_gather = []):
159+
swiftdoc,
160+
swiftinterface = None,
161+
swiftmodule,
162+
swiftsourceinfo = None):
162163
"""Creates a value representing a Swift module use as a Swift dependency.
163164
164165
Args:
165-
swiftdoc: The `.swiftdoc` file emitted by the compiler for this module.
166-
swiftmodule: The `.swiftmodule` file emitted by the compiler for this
167-
module.
168166
ast_files: A list of `File`s output from the `DUMP_AST` action.
167+
const_protocols_to_gather: A list of protocol names from which constant
168+
values should be extracted from source code that takes this module
169+
as a *direct* dependency.
169170
defines: A list of defines that will be provided as `copts` to targets
170171
that depend on this module. If omitted, the empty list will be used.
171172
generated_header: A `File` representing the Swift generated header.
172173
indexstore: A `File` representing the directory that contains the index
173174
store data generated by the compiler if the
174175
`"swift.index_while_building"` feature is enabled, otherwise this
175176
will be `None`.
177+
original_module_name: The original name of the module if it was changed
178+
by a module mapping; otherwise, `None`.
176179
plugins: A list of `SwiftCompilerPluginInfo` providers representing
177180
compiler plugins that are required by this module and should be
178181
loaded by the compiler when this module is directly depended on.
179182
private_swiftinterface: The `.private.swiftinterface` file emitted by
180183
the compiler for this module. May be `None` if no private module
181184
interface file was emitted.
182-
swiftsourceinfo: The `.swiftsourceinfo` file emitted by the compiler for
183-
this module. May be `None` if no source info file was emitted.
185+
swiftdoc: The `.swiftdoc` file emitted by the compiler for this module.
184186
swiftinterface: The `.swiftinterface` file emitted by the compiler for
185187
this module. May be `None` if no module interface file was emitted.
186-
const_protocols_to_gather: A list of protocol names from which constant
187-
values should be extracted from source code that takes this module
188-
as a *direct* dependency.
188+
swiftmodule: The `.swiftmodule` file emitted by the compiler for this
189+
module.
190+
swiftsourceinfo: The `.swiftsourceinfo` file emitted by the compiler for
191+
this module. May be `None` if no source info file was emitted.
189192
190193
Returns:
191194
A `struct` containing the `ast_files`, `defines`, `indexstore,
@@ -194,16 +197,17 @@ def create_swift_module(
194197
"""
195198
return struct(
196199
ast_files = tuple(ast_files),
200+
const_protocols_to_gather = tuple(const_protocols_to_gather),
197201
defines = tuple(defines),
198202
generated_header = generated_header,
203+
indexstore = indexstore,
199204
plugins = plugins,
200205
private_swiftinterface = private_swiftinterface,
201-
indexstore = indexstore,
206+
original_module_name = original_module_name,
202207
swiftdoc = swiftdoc,
203208
swiftinterface = swiftinterface,
204209
swiftmodule = swiftmodule,
205210
swiftsourceinfo = swiftsourceinfo,
206-
const_protocols_to_gather = tuple(const_protocols_to_gather),
207211
)
208212

209213
def create_swift_info(

swift/toolchains/config/compile_config.bzl

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,10 @@ def compile_action_configs(
798798
],
799799
features = [SWIFT_FEATURE_VFSOVERLAY],
800800
),
801+
ActionConfigInfo(
802+
actions = [SWIFT_ACTION_COMPILE],
803+
configurators = [_module_aliases_configurator],
804+
),
801805
ActionConfigInfo(
802806
actions = [
803807
SWIFT_ACTION_COMPILE,
@@ -1717,6 +1721,44 @@ def _swift_module_search_path_map_fn(module):
17171721
else:
17181722
return None
17191723

1724+
def _module_alias_flags(name, original):
1725+
"""Returns compiler flags to set the given module alias."""
1726+
1727+
# TODO(b/257269318): Remove `-Xfrontend`; this is only needed to workaround
1728+
# a bug in toolchains still using the legacy C++ driver.
1729+
return [
1730+
"-Xfrontend",
1731+
"-module-alias",
1732+
"-Xfrontend",
1733+
"{original}={name}".format(
1734+
name = name,
1735+
original = original,
1736+
),
1737+
]
1738+
1739+
def _module_alias_map_fn(module):
1740+
"""Returns compiler flags to alias the given module.
1741+
1742+
This function is intended to be used as a mapping function for modules
1743+
passed into `Args.add_all`.
1744+
1745+
Args:
1746+
module: The module structure (as returned by
1747+
`swift_common.create_module`) extracted from the transitive
1748+
modules of a `SwiftInfo` provider.
1749+
1750+
Returns:
1751+
The flags to pass to the compiler to alias the given module, or `None`
1752+
if no alias applies.
1753+
"""
1754+
if module.swift and module.swift.original_module_name:
1755+
return _module_alias_flags(
1756+
original = module.swift.original_module_name,
1757+
name = module.name,
1758+
)
1759+
else:
1760+
return None
1761+
17201762
def _dependencies_swiftmodules_and_swiftdocs_configurator(prerequisites, args):
17211763
"""Adds `.swiftmodule` and `.swiftdoc` files from the transitive modules to search paths and action inputs."""
17221764
args.add_all(
@@ -1744,6 +1786,21 @@ def _dependencies_swiftmodules_configurator(prerequisites, args):
17441786
inputs = prerequisites.transitive_swiftmodules,
17451787
)
17461788

1789+
def _module_aliases_configurator(prerequisites, args):
1790+
"""Adds `-module-alias` flags for the active module mapping, if any."""
1791+
args.add_all(
1792+
prerequisites.transitive_modules,
1793+
map_each = _module_alias_map_fn,
1794+
)
1795+
1796+
if prerequisites.original_module_name:
1797+
args.add_all(
1798+
_module_alias_flags(
1799+
original = prerequisites.original_module_name,
1800+
name = prerequisites.module_name,
1801+
),
1802+
)
1803+
17471804
def _load_executable_plugin_map_fn(plugin):
17481805
"""Returns frontend flags to load compiler plugins."""
17491806
return [

test/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ load(":interop_hints_tests.bzl", "interop_hints_test_suite")
1313
load(":mainattr_tests.bzl", "mainattr_test_suite")
1414
load(":module_cache_settings_tests.bzl", "module_cache_settings_test_suite")
1515
load(":module_interface_tests.bzl", "module_interface_test_suite")
16+
load(":module_mapping_tests.bzl", "module_mapping_test_suite")
1617
load(":output_file_map_tests.bzl", "output_file_map_test_suite")
1718
load(":pch_output_dir_tests.bzl", "pch_output_dir_test_suite")
1819
load(":private_deps_tests.bzl", "private_deps_test_suite")
@@ -52,6 +53,8 @@ module_cache_settings_test_suite(name = "module_cache_settings")
5253

5354
module_interface_test_suite(name = "module_interface")
5455

56+
module_mapping_test_suite(name = "module_mapping")
57+
5558
output_file_map_test_suite(name = "output_file_map")
5659

5760
private_deps_test_suite(name = "private_deps")

test/fixtures/module_mapping/BUILD

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
load("//swift:swift_library.bzl", "swift_library")
2+
load("//swift:swift_module_mapping.bzl", "swift_module_mapping")
3+
load(
4+
"//test/fixtures:common.bzl",
5+
"FIXTURE_TAGS",
6+
)
7+
load(":apply_mapping.bzl", "apply_mapping")
8+
9+
package(
10+
default_testonly = True,
11+
default_visibility = ["//test:__subpackages__"],
12+
)
13+
14+
licenses(["notice"])
15+
16+
swift_library(
17+
name = "Common",
18+
srcs = ["Common.swift"],
19+
module_name = "Common",
20+
tags = FIXTURE_TAGS,
21+
)
22+
23+
swift_library(
24+
name = "MySDK",
25+
srcs = ["MySDK.swift"],
26+
module_name = "MySDK",
27+
tags = FIXTURE_TAGS,
28+
deps = [":Common"],
29+
)
30+
31+
swift_module_mapping(
32+
name = "MySDK_module_mapping",
33+
# This must not be testonly because it is used by the toolchain through the
34+
# `:module_mapping` label flag.
35+
testonly = False,
36+
aliases = {
37+
"Common": "MySDKInternal_Common",
38+
},
39+
)
40+
41+
# This is the target that will be tested in `module_mapping.bzl`, to force the
42+
# `MySDK` target to build in a configuration that sets the flag.
43+
apply_mapping(
44+
name = "MySDK_with_mapping",
45+
mapping = ":MySDK_module_mapping",
46+
target = ":MySDK",
47+
)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2022 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
public final class Cat {
16+
public class var standardIssue: Common.Cat { Common.Cat() }
17+
18+
public init() {}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2022 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import Common
16+
17+
public func makeStandardIssueCat() -> Common.Cat {
18+
return Common.Cat.standardIssue
19+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright 2022 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Rule and transition to force a specific module mapping in tests."""
16+
17+
def _apply_mapping_transition_impl(settings, attr):
18+
settings = dict(settings)
19+
settings["@build_bazel_rules_swift//swift:module_mapping"] = attr.mapping
20+
return settings
21+
22+
apply_mapping_transition = transition(
23+
implementation = _apply_mapping_transition_impl,
24+
inputs = [],
25+
outputs = ["@build_bazel_rules_swift//swift:module_mapping"],
26+
)
27+
28+
def _apply_mapping_impl(ctx):
29+
return [ctx.attr.target[0][DefaultInfo]]
30+
31+
apply_mapping = rule(
32+
attrs = {
33+
"mapping": attr.label(),
34+
"target": attr.label(cfg = apply_mapping_transition),
35+
"_allowlist_function_transition": attr.label(
36+
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
37+
),
38+
},
39+
implementation = _apply_mapping_impl,
40+
)

0 commit comments

Comments
 (0)