Skip to content

Commit

Permalink
Make sure to pass strict dependency include paths from the `apple_com…
Browse files Browse the repository at this point in the history
…mon.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
(cherry picked from commit a81c591)

 Conflicts:
	swift/internal/swift_clang_module_aspect.bzl
  • Loading branch information
allevato authored and thii committed Aug 18, 2021
1 parent a4103f8 commit 4a38722
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 10 deletions.
22 changes: 21 additions & 1 deletion doc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,32 @@ swift_common.create_clang_module(<a href="#swift_common.create_clang_module-comp

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.


**PARAMETERS**


| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="swift_common.create_clang_module-compilation_context"></a>compilation_context | A <code>CcCompilationContext</code> 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). | none |
| <a id="swift_common.create_clang_module-compilation_context"></a>compilation_context | A <code>CcCompilationContext</code> that contains the header files and other context (such as include paths, preprocessor defines, and so forth) needed to compile this module as an explicit module. | none |
| <a id="swift_common.create_clang_module-module_map"></a>module_map | The text module map file that defines this module. This argument may be specified as a <code>File</code> or as a <code>string</code>; in the latter case, it is assumed to be the path to a file that cannot be provided as an action input because it is outside the workspace (for example, the module map for a module from an Xcode SDK). | none |
| <a id="swift_common.create_clang_module-precompiled_module"></a>precompiled_module | A <code>File</code> representing the precompiled module (<code>.pcm</code> file) if one was emitted for the module. This may be <code>None</code> if no explicit module was built for the module; in that case, targets that depend on the module will fall back to the text module map and headers. | <code>None</code> |

Expand Down
25 changes: 22 additions & 3 deletions swift/internal/providers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,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
Expand Down
41 changes: 35 additions & 6 deletions swift/internal/swift_clang_module_aspect.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -510,16 +510,45 @@ def _handle_module(

return providers

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

Expand Down Expand Up @@ -563,7 +592,7 @@ def _swift_clang_module_aspect_impl(target, aspect_ctx):
):
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,
Expand Down

0 comments on commit 4a38722

Please sign in to comment.