From a81c59152799e96a9318ba2c6564a9aeb4d6b909 Mon Sep 17 00:00:00 2001 From: Tony Allevato Date: Mon, 16 Aug 2021 09:41:53 -0700 Subject: [PATCH] Make sure to pass strict dependency include paths from the `apple_common.Objc` provider when compiling the explicit module for a target. Also clarify the purpose of the `compilation_context` argument in `swift_common.create_clang_module` and how it should and should not be used. PiperOrigin-RevId: 391067469 --- swift/internal/providers.bzl | 25 ++++++++++-- swift/internal/swift_clang_module_aspect.bzl | 41 +++++++++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/swift/internal/providers.bzl b/swift/internal/providers.bzl index 9ccd7ee79..837a86619 100644 --- a/swift/internal/providers.bzl +++ b/swift/internal/providers.bzl @@ -299,11 +299,30 @@ def create_clang_module( precompiled_module = None): """Creates a value representing a Clang module used as a Swift dependency. + Note: The `compilation_context` argument of this function is primarily + intended to communicate information *to* the Swift build rules, not to + retrieve information *back out.* In most cases, it is better to depend on + the `CcInfo` provider propagated by a Swift target to collect transitive + C/Objective-C compilation information about that target. This is because the + context used when compiling the module itself may not be the same as the + context desired when depending on it. (For example, `apple_common.Objc` + supports "strict include paths" which are only propagated to direct + dependents.) + + One valid exception to the guidance above is retrieving the generated header + associated with a specific Swift module. Since the `CcInfo` provider + propagated by the library will have already merged them transitively (or, + in the case of a hypothetical custom rule that propagates multiple direct + modules, the `direct_public_headers` of the `CcInfo` would also have them + merged), it is acceptable to read the headers from the compilation context + of the module struct itself in order to associate them with the module that + generated them. + Args: compilation_context: A `CcCompilationContext` that contains the header - files, include paths, and other context necessary to compile targets - that depend on this module (if using the text module map instead of - the precompiled module). + files and other context (such as include paths, preprocessor + defines, and so forth) needed to compile this module as an explicit + module. module_map: The text module map file that defines this module. This argument may be specified as a `File` or as a `string`; in the latter case, it is assumed to be the path to a file that cannot diff --git a/swift/internal/swift_clang_module_aspect.bzl b/swift/internal/swift_clang_module_aspect.bzl index 72ac54e62..34ec60640 100644 --- a/swift/internal/swift_clang_module_aspect.bzl +++ b/swift/internal/swift_clang_module_aspect.bzl @@ -555,16 +555,45 @@ def _find_swift_interop_info(target, aspect_ctx): return interop_target[_SwiftInteropInfo], default_swift_infos return None, default_swift_infos +def _compilation_context_for_target(target): + """Gets the compilation context to use when compiling this target's module. + + This function also handles the special case of a target that propagates an + `apple_common.Objc` provider in addition to its `CcInfo` provider, where the + former contains strict include paths that must also be added when compiling + the module. + + Args: + target: The target to which the aspect is being applied. + + Returns: + A `CcCompilationContext` that contains the headers of the target being + compiled. + """ + if CcInfo not in target: + return None + + compilation_context = target[CcInfo].compilation_context + + if apple_common.Objc in target: + strict_includes = target[apple_common.Objc].strict_include + if strict_includes: + compilation_context = cc_common.merge_compilation_contexts( + compilation_contexts = [ + compilation_context, + cc_common.create_compilation_context( + includes = strict_includes, + ), + ], + ) + + return compilation_context + def _swift_clang_module_aspect_impl(target, aspect_ctx): # Do nothing if the target already propagates `SwiftInfo`. if SwiftInfo in target: return [] - if CcInfo in target: - compilation_context = target[CcInfo].compilation_context - else: - compilation_context = None - requested_features = aspect_ctx.features unsupported_features = aspect_ctx.disabled_features @@ -592,7 +621,7 @@ def _swift_clang_module_aspect_impl(target, aspect_ctx): if interop_info or apple_common.Objc in target or CcInfo in target: return _handle_module( aspect_ctx = aspect_ctx, - compilation_context = compilation_context, + compilation_context = _compilation_context_for_target(target), feature_configuration = feature_configuration, module_map_file = module_map_file, module_name = module_name,