Skip to content
This repository was archived by the owner on Jan 25, 2024. It is now read-only.

Commit d8a381c

Browse files
allevatoswiple-rules-gardener
authored andcommitted
Disable layering checks when compiling the explicit module for a Swift generated header.
The Swift compiler determines which module to import a symbol from based on the module that defines that symbol. Due to modular re-exports (which are particularly common among system frameworks), this may not be the same framework that the user imported from Swift and added to their dependencies. (For example, most users will import and depend on `Foundation` to use `NSObject`, but Swift will import it from the module it is actually defined in, `ObjectiveC`.) PiperOrigin-RevId: 371919747
1 parent de9c4e1 commit d8a381c

File tree

1 file changed

+94
-10
lines changed

1 file changed

+94
-10
lines changed

swift/internal/compiling.bzl

Lines changed: 94 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,21 @@ def compile_action_configs(
362362
]
363363

364364
#### Flags controlling how Swift/Clang modular inputs are processed
365+
366+
def c_layering_check_configurator(prerequisites, args, *, strict):
367+
# We do not enforce layering checks for the Objective-C header generated
368+
# by Swift, because we don't have predictable control over the imports
369+
# that it generates. Due to modular re-exports (which are especially
370+
# common among system frameworks), it may generate an import declaration
371+
# for a particular symbol from a different module than the Swift code
372+
# imported it from.
373+
if not prerequisites.is_swift_generated_header:
374+
args.add(
375+
"-Xcc",
376+
"-fmodules-strict-decluse" if strict else "-fmodules-decluse",
377+
)
378+
return None
379+
365380
action_configs += [
366381
# Treat paths in .modulemap files as workspace-relative, not modulemap-
367382
# relative.
@@ -443,12 +458,10 @@ def compile_action_configs(
443458
swift_toolchain_config.action_config(
444459
actions = [swift_action_names.PRECOMPILE_C_MODULE],
445460
configurators = [
446-
# Enforce `use` declarations for user modules since we generate
447-
# those, but not for system modules since they typically do not
448-
# have the proper `use` decls.
449-
swift_toolchain_config.add_arg(
450-
"-Xcc",
451-
"-fmodules-decluse",
461+
lambda prerequisites, args: c_layering_check_configurator(
462+
prerequisites,
463+
args,
464+
strict = False,
452465
),
453466
],
454467
not_features = [
@@ -459,9 +472,10 @@ def compile_action_configs(
459472
swift_toolchain_config.action_config(
460473
actions = [swift_action_names.PRECOMPILE_C_MODULE],
461474
configurators = [
462-
swift_toolchain_config.add_arg(
463-
"-Xcc",
464-
"-fmodules-strict-decluse",
475+
lambda prerequisites, args: c_layering_check_configurator(
476+
prerequisites,
477+
args,
478+
strict = True,
465479
),
466480
],
467481
features = [SWIFT_FEATURE_LAYERING_CHECK],
@@ -1480,14 +1494,15 @@ def compile(
14801494
feature_configuration = feature_configuration,
14811495
feature_name = SWIFT_FEATURE_NO_GENERATED_MODULE_MAP,
14821496
):
1483-
precompiled_module = precompile_clang_module(
1497+
precompiled_module = _precompile_clang_module(
14841498
actions = actions,
14851499
bin_dir = bin_dir,
14861500
cc_compilation_context = cc_common.create_compilation_context(
14871501
headers = depset([compile_outputs.generated_header_file]),
14881502
),
14891503
feature_configuration = feature_configuration,
14901504
genfiles_dir = genfiles_dir,
1505+
is_swift_generated_header = True,
14911506
module_map_file = compile_outputs.generated_module_map_file,
14921507
module_name = module_name,
14931508
swift_info = create_swift_info(
@@ -1574,6 +1589,74 @@ def precompile_clang_module(
15741589
swift_info: A `SwiftInfo` provider that contains dependencies required
15751590
to compile this module.
15761591
1592+
Returns:
1593+
A `File` representing the precompiled module (`.pcm`) file, or `None` if
1594+
the toolchain or target does not support precompiled modules.
1595+
"""
1596+
return _precompile_clang_module(
1597+
actions = actions,
1598+
bin_dir = bin_dir,
1599+
cc_compilation_context = cc_compilation_context,
1600+
feature_configuration = feature_configuration,
1601+
genfiles_dir = genfiles_dir,
1602+
is_swift_generated_header = False,
1603+
module_map_file = module_map_file,
1604+
module_name = module_name,
1605+
swift_info = swift_info,
1606+
swift_toolchain = swift_toolchain,
1607+
target_name = target_name,
1608+
)
1609+
1610+
def _precompile_clang_module(
1611+
*,
1612+
actions,
1613+
cc_compilation_context,
1614+
feature_configuration,
1615+
is_swift_generated_header,
1616+
module_map_file,
1617+
module_name,
1618+
swift_toolchain,
1619+
target_name,
1620+
bin_dir = None,
1621+
genfiles_dir = None,
1622+
swift_info = None):
1623+
"""Precompiles an explicit Clang module that is compatible with Swift.
1624+
1625+
Args:
1626+
actions: The context's `actions` object.
1627+
cc_compilation_context: A `CcCompilationContext` that contains headers
1628+
and other information needed to compile this module. This
1629+
compilation context should contain all headers required to compile
1630+
the module, which includes the headers for the module itself *and*
1631+
any others that must be present on the file system/in the sandbox
1632+
for compilation to succeed. The latter typically refers to the set
1633+
of headers of the direct dependencies of the module being compiled,
1634+
which Clang needs to be physically present before it detects that
1635+
they belong to one of the precompiled module dependencies.
1636+
feature_configuration: A feature configuration obtained from
1637+
`swift_common.configure_features`.
1638+
is_swift_generated_header: If True, the action is compiling the
1639+
Objective-C header generated by the Swift compiler for a module.
1640+
module_map_file: A textual module map file that defines the Clang module
1641+
to be compiled.
1642+
module_name: The name of the top-level module in the module map that
1643+
will be compiled.
1644+
swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain.
1645+
target_name: The name of the target for which the code is being
1646+
compiled, which is used to determine unique file paths for the
1647+
outputs.
1648+
bin_dir: The Bazel `*-bin` directory root. If provided, its path is used
1649+
to store the cache for modules precompiled by Swift's ClangImporter,
1650+
and it is added to ClangImporter's header search paths for
1651+
compatibility with Bazel's C++ and Objective-C rules which support
1652+
includes of generated headers from that location.
1653+
genfiles_dir: The Bazel `*-genfiles` directory root. If provided, its
1654+
path is added to ClangImporter's header search paths for
1655+
compatibility with Bazel's C++ and Objective-C rules which support
1656+
inclusions of generated headers from that location.
1657+
swift_info: A `SwiftInfo` provider that contains dependencies required
1658+
to compile this module.
1659+
15771660
Returns:
15781661
A `File` representing the precompiled module (`.pcm`) file, or `None` if
15791662
the toolchain or target does not support precompiled modules.
@@ -1608,6 +1691,7 @@ def precompile_clang_module(
16081691
cc_info = CcInfo(compilation_context = cc_compilation_context),
16091692
genfiles_dir = genfiles_dir,
16101693
is_swift = False,
1694+
is_swift_generated_header = is_swift_generated_header,
16111695
module_name = module_name,
16121696
objc_include_paths_workaround = depset(),
16131697
objc_info = apple_common.new_objc_provider(),

0 commit comments

Comments
 (0)