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

Commit

Permalink
Disable layering checks when compiling the explicit module for a Swif…
Browse files Browse the repository at this point in the history
…t 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
  • Loading branch information
allevato authored and swiple-rules-gardener committed May 4, 2021
1 parent de9c4e1 commit d8a381c
Showing 1 changed file with 94 additions and 10 deletions.
104 changes: 94 additions & 10 deletions swift/internal/compiling.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,21 @@ def compile_action_configs(
]

#### Flags controlling how Swift/Clang modular inputs are processed

def c_layering_check_configurator(prerequisites, args, *, strict):
# We do not enforce layering checks for the Objective-C header generated
# by Swift, because we don't have predictable control over the imports
# that it generates. Due to modular re-exports (which are especially
# common among system frameworks), it may generate an import declaration
# for a particular symbol from a different module than the Swift code
# imported it from.
if not prerequisites.is_swift_generated_header:
args.add(
"-Xcc",
"-fmodules-strict-decluse" if strict else "-fmodules-decluse",
)
return None

action_configs += [
# Treat paths in .modulemap files as workspace-relative, not modulemap-
# relative.
Expand Down Expand Up @@ -443,12 +458,10 @@ def compile_action_configs(
swift_toolchain_config.action_config(
actions = [swift_action_names.PRECOMPILE_C_MODULE],
configurators = [
# Enforce `use` declarations for user modules since we generate
# those, but not for system modules since they typically do not
# have the proper `use` decls.
swift_toolchain_config.add_arg(
"-Xcc",
"-fmodules-decluse",
lambda prerequisites, args: c_layering_check_configurator(
prerequisites,
args,
strict = False,
),
],
not_features = [
Expand All @@ -459,9 +472,10 @@ def compile_action_configs(
swift_toolchain_config.action_config(
actions = [swift_action_names.PRECOMPILE_C_MODULE],
configurators = [
swift_toolchain_config.add_arg(
"-Xcc",
"-fmodules-strict-decluse",
lambda prerequisites, args: c_layering_check_configurator(
prerequisites,
args,
strict = True,
),
],
features = [SWIFT_FEATURE_LAYERING_CHECK],
Expand Down Expand Up @@ -1480,14 +1494,15 @@ def compile(
feature_configuration = feature_configuration,
feature_name = SWIFT_FEATURE_NO_GENERATED_MODULE_MAP,
):
precompiled_module = precompile_clang_module(
precompiled_module = _precompile_clang_module(
actions = actions,
bin_dir = bin_dir,
cc_compilation_context = cc_common.create_compilation_context(
headers = depset([compile_outputs.generated_header_file]),
),
feature_configuration = feature_configuration,
genfiles_dir = genfiles_dir,
is_swift_generated_header = True,
module_map_file = compile_outputs.generated_module_map_file,
module_name = module_name,
swift_info = create_swift_info(
Expand Down Expand Up @@ -1574,6 +1589,74 @@ def precompile_clang_module(
swift_info: A `SwiftInfo` provider that contains dependencies required
to compile this module.
Returns:
A `File` representing the precompiled module (`.pcm`) file, or `None` if
the toolchain or target does not support precompiled modules.
"""
return _precompile_clang_module(
actions = actions,
bin_dir = bin_dir,
cc_compilation_context = cc_compilation_context,
feature_configuration = feature_configuration,
genfiles_dir = genfiles_dir,
is_swift_generated_header = False,
module_map_file = module_map_file,
module_name = module_name,
swift_info = swift_info,
swift_toolchain = swift_toolchain,
target_name = target_name,
)

def _precompile_clang_module(
*,
actions,
cc_compilation_context,
feature_configuration,
is_swift_generated_header,
module_map_file,
module_name,
swift_toolchain,
target_name,
bin_dir = None,
genfiles_dir = None,
swift_info = None):
"""Precompiles an explicit Clang module that is compatible with Swift.
Args:
actions: The context's `actions` object.
cc_compilation_context: A `CcCompilationContext` that contains headers
and other information needed to compile this module. This
compilation context should contain all headers required to compile
the module, which includes the headers for the module itself *and*
any others that must be present on the file system/in the sandbox
for compilation to succeed. The latter typically refers to the set
of headers of the direct dependencies of the module being compiled,
which Clang needs to be physically present before it detects that
they belong to one of the precompiled module dependencies.
feature_configuration: A feature configuration obtained from
`swift_common.configure_features`.
is_swift_generated_header: If True, the action is compiling the
Objective-C header generated by the Swift compiler for a module.
module_map_file: A textual module map file that defines the Clang module
to be compiled.
module_name: The name of the top-level module in the module map that
will be compiled.
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.
bin_dir: The Bazel `*-bin` directory root. If provided, its path is used
to store the cache for modules precompiled by Swift's ClangImporter,
and it is added to ClangImporter's header search paths for
compatibility with Bazel's C++ and Objective-C rules which support
includes of generated headers from that location.
genfiles_dir: The Bazel `*-genfiles` directory root. If provided, its
path is added to ClangImporter's header search paths for
compatibility with Bazel's C++ and Objective-C rules which support
inclusions of generated headers from that location.
swift_info: A `SwiftInfo` provider that contains dependencies required
to compile this module.
Returns:
A `File` representing the precompiled module (`.pcm`) file, or `None` if
the toolchain or target does not support precompiled modules.
Expand Down Expand Up @@ -1608,6 +1691,7 @@ def precompile_clang_module(
cc_info = CcInfo(compilation_context = cc_compilation_context),
genfiles_dir = genfiles_dir,
is_swift = False,
is_swift_generated_header = is_swift_generated_header,
module_name = module_name,
objc_include_paths_workaround = depset(),
objc_info = apple_common.new_objc_provider(),
Expand Down

0 comments on commit d8a381c

Please sign in to comment.