Skip to content

Commit c83c18e

Browse files
fix: modulemaps behave like SPM (#1389)
* If a modulemap needs to be generated (i.e. one isn’t provided by the target), we always generate it instead of letting rules_swift generate it for Swift targets; this ensures we have consistent and non-duplicate modulemaps * Generated modulemaps are now nested in a similar way to rules_swift, preventing them from being picked up accidentally * We no longer generate a modulemap for Swift targets, and instead use the `swift.propagate_generated_module_map` feature * We no longer create another target for the Objective-C resource module accessor; this aligns with how SPM does it and removes another target that could try to generate a modulemap * The parent target for clang targets is now only an aggregator (i.e. it doesn’t have headers of its own), preventing it from complicating the build graph * The parent target for clang targets includes the generated modulemap as a child dep, removing the need to generate a noop modulemap * When detecting a custom modulemap, we only consider the public includes paths, preventing accidentally picking up errant modulemaps * We set `-fmodule-name` again Signed-off-by: Brentley Jones <[email protected]>
1 parent 64e6609 commit c83c18e

File tree

9 files changed

+224
-427
lines changed

9 files changed

+224
-427
lines changed

docs/internal_rules_and_macros_overview.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ On this page:
1717
## generate_modulemap
1818

1919
<pre>
20-
generate_modulemap(<a href="#generate_modulemap-name">name</a>, <a href="#generate_modulemap-deps">deps</a>, <a href="#generate_modulemap-hdrs">hdrs</a>, <a href="#generate_modulemap-module_name">module_name</a>, <a href="#generate_modulemap-noop">noop</a>)
20+
generate_modulemap(<a href="#generate_modulemap-name">name</a>, <a href="#generate_modulemap-deps">deps</a>, <a href="#generate_modulemap-hdrs">hdrs</a>, <a href="#generate_modulemap-module_name">module_name</a>)
2121
</pre>
2222

2323
Generate a modulemap for an Objective-C module.
@@ -31,7 +31,6 @@ Generate a modulemap for an Objective-C module.
3131
| <a id="generate_modulemap-deps"></a>deps | The module maps that this module uses. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
3232
| <a id="generate_modulemap-hdrs"></a>hdrs | The public headers for this module. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
3333
| <a id="generate_modulemap-module_name"></a>module_name | The name of the module. | String | optional | `""` |
34-
| <a id="generate_modulemap-noop"></a>noop | Designates whether a modulemap should be generated. If `False`, a modulemap is generated. If `True`, a modulemap file is not generated and the returned providers are empty. | Boolean | optional | `False` |
3534

3635

3736
<a id="resource_bundle_accessor"></a>

examples/firebase_example/.bazelrc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,3 @@ build --cxxopt='-std=gnu++14'
2020
# Firebase SPM support requires `-ObjC` linker option.
2121
# https://github.com/firebase/firebase-ios-sdk/blob/master/SwiftPackageManager.md#requirements
2222
build --linkopt='-ObjC'
23-
24-
# Use sandbox for rules_xcodeproj to avoid duplicate definition errors.
25-
build:rules_xcodeproj --spawn_strategy=remote,worker,sandboxed,local

swiftpkg/internal/clang_files.bzl

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,21 @@ def _is_hdr(path):
4242
_root, ext = paths.split_extension(path)
4343
return lists.contains(_HEADER_EXTS, ext)
4444

45-
def _is_include_hdr(path, public_includes = None):
45+
def _is_include_hdr(path, public_includes = []):
4646
"""Determines whether the path is a public header.
4747
4848
Args:
4949
path: A path `string` value.
5050
public_includes: Optional. A `sequence` of path `string` values that
51-
are used to identify public header files.
51+
are used to identify public header files.
5252
5353
Returns:
5454
A `bool` indicating whether the path is a public header.
5555
"""
5656
if not _is_hdr(path):
5757
return False
5858

59-
public_includes = [] if public_includes == None else public_includes
60-
if len(public_includes) > 0:
59+
if public_includes:
6160
for include_path in public_includes:
6261
if include_path[-1] != "/":
6362
include_path += "/"
@@ -94,18 +93,30 @@ def _find_magical_public_hdr_dir(path):
9493

9594
return None
9695

97-
def _is_public_modulemap(path):
96+
def _is_public_modulemap(path, public_includes = []):
9897
"""Determines whether the specified path is to a public `module.modulemap` file.
9998
10099
Args:
101100
path: A path `string`.
101+
public_includes: Optional. A `sequence` of path `string` values that
102+
are used to identify public header files.
102103
103104
Returns:
104105
A `bool` indicating whether the path is a public `module.modulemap`
105106
file.
106107
"""
107108
basename = paths.basename(path)
108-
return basename == "module.modulemap"
109+
if basename != "module.modulemap":
110+
return False
111+
112+
if public_includes:
113+
for public_include in public_includes:
114+
if path.startswith(public_include):
115+
return True
116+
elif _find_magical_public_hdr_dir(path) != None:
117+
return True
118+
119+
return False
109120

110121
def _get_hdr_paths_from_modulemap(repository_ctx, modulemap_path, module_name):
111122
"""Retrieves the list of headers declared in the specified modulemap file \
@@ -249,7 +260,10 @@ def _collect_files(
249260
sets.insert(srcs_set, path)
250261
elif lists.contains(_SRC_EXTS, ext):
251262
sets.insert(srcs_set, path)
252-
elif ext == ".modulemap" and _is_public_modulemap(path):
263+
elif ext == ".modulemap" and _is_public_modulemap(
264+
orig_path,
265+
public_includes = public_includes,
266+
):
253267
if modulemap != None:
254268
fail("Found multiple modulemap files. {first} {second}".format(
255269
first = modulemap,

swiftpkg/internal/generate_modulemap.bzl

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,13 @@ ModuleMapInfo = provider(
2020
def _generate_modulemap_impl(ctx):
2121
module_name = ctx.attr.module_name
2222

23-
# Decide whether we should generate the modulemap. If we do not generate
24-
# the modulemap, we still need to return expected providers.
25-
if ctx.attr.noop:
26-
return [
27-
DefaultInfo(files = depset([])),
28-
ModuleMapInfo(
29-
module_name = module_name,
30-
modulemap_file = None,
31-
),
32-
apple_common.new_objc_provider(
33-
module_map = depset([]),
34-
),
35-
CcInfo(
36-
compilation_context = cc_common.create_compilation_context(
37-
headers = depset([]),
38-
includes = depset([]),
39-
),
40-
),
41-
]
42-
4323
uses = [
4424
dep[ModuleMapInfo].module_name
4525
for dep in ctx.attr.deps
4626
if ModuleMapInfo in dep
4727
]
4828

49-
out_filename = "{}/module.modulemap".format(module_name)
29+
out_filename = "{}_modulemap/_/module.modulemap".format(ctx.attr.name)
5030
modulemap_file = ctx.actions.declare_file(out_filename)
5131

5232
hdrs = [
@@ -85,6 +65,7 @@ def _generate_modulemap_impl(ctx):
8565
CcInfo(
8666
compilation_context = cc_common.create_compilation_context(
8767
headers = depset(provider_hdr),
68+
direct_public_headers = provider_hdr,
8869
includes = depset([modulemap_file.dirname]),
8970
),
9071
),
@@ -106,14 +87,6 @@ generate_modulemap = rule(
10687
"module_name": attr.string(
10788
doc = "The name of the module.",
10889
),
109-
"noop": attr.bool(
110-
doc = """\
111-
Designates whether a modulemap should be generated. If `False`, a modulemap is \
112-
generated. If `True`, a modulemap file is not generated and the returned \
113-
providers are empty.\
114-
""",
115-
default = False,
116-
),
11790
},
11891
doc = "Generate a modulemap for an Objective-C module.",
11992
)

swiftpkg/internal/pkginfo_target_deps.bzl

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,19 @@ load("@cgrindel_bazel_starlib//bzllib:defs.bzl", "bazel_labels", "lists")
44
load(":bazel_repo_names.bzl", "bazel_repo_names")
55
load(":bzl_selects.bzl", "bzl_selects")
66
load(":pkginfo_dependencies.bzl", "pkginfo_dependencies")
7-
load(":pkginfo_targets.bzl", "pkginfo_targets")
87

98
# This value is used to group Bazel select conditions
109
_target_dep_kind = "_target_dep"
1110

12-
def _src_type_for_target(target):
13-
# Check Objc first. It will have a clang_src_info and an objc_src_info.
14-
if target.swift_src_info:
15-
return src_types.swift
16-
elif target.objc_src_info:
17-
return src_types.objc
18-
elif target.clang_src_info:
19-
return src_types.clang
20-
return src_types.unknown
21-
22-
def _modulemap_label_for_target(repo_name, target):
23-
return bazel_labels.new(
24-
name = pkginfo_targets.modulemap_label_name(target.label.name),
25-
repository_name = repo_name,
26-
package = target.label.package,
27-
)
28-
2911
def _labels_for_target(repo_name, target):
30-
labels = [
12+
return [
3113
bazel_labels.new(
3214
name = target.label.name,
3315
repository_name = repo_name,
3416
package = target.label.package,
3517
),
3618
]
3719

38-
src_type = _src_type_for_target(target)
39-
if src_type == src_types.objc:
40-
# If the dep is an objc, return the real Objective-C target, not the Swift
41-
# module alias. This is part of a workaround for Objective-C modules not
42-
# being able to `@import` modules from other Objective-C modules.
43-
# See `swiftpkg_build_files.bzl` for more information.
44-
labels.append(_modulemap_label_for_target(repo_name, target))
45-
46-
elif (src_type == src_types.swift and
47-
target.swift_src_info.has_objc_directive):
48-
# If an Objc module wants to @import a Swift module, it will need the
49-
# modulemap target.
50-
labels.append(_modulemap_label_for_target(repo_name, target))
51-
52-
return labels
53-
5420
def _resolve_by_name(pkg_ctx, name):
5521
repo_name = bazel_repo_names.normalize(pkg_ctx.repo_name)
5622

swiftpkg/internal/pkginfo_targets.bzl

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ _modulemap_suffix = "_modulemap"
77
_resource_bundle_suffix = "_resource_bundle"
88
_objc_resource_bundle_accessor_hdr_suffix = "_objc_resource_bundle_accessor_hdr"
99
_objc_resource_bundle_accessor_impl_suffix = "_objc_resource_bundle_accessor_impl"
10-
_objc_resource_bundle_accessor_library_suffix = "_objc_resource_bundle_accessor_library"
1110
_resource_bundle_accessor_suffix = "_resource_bundle_accessor"
1211
_resource_bundle_infoplist_suffix = "_resource_bundle_infoplist"
1312
_swift_hint_suffix = "_swift_hint"
@@ -197,17 +196,6 @@ def _objc_resource_bundle_accessor_impl_label_name(target_name):
197196
"""
198197
return target_name + _objc_resource_bundle_accessor_impl_suffix
199198

200-
def _objc_resource_bundle_accessor_library_label_name(target_name):
201-
"""Returns the name of the related `objc_library` target.
202-
203-
Args:
204-
target_name: The publicly advertised name for the Swift target.
205-
206-
Returns:
207-
The name of the `objc_library` as a `string`.
208-
"""
209-
return target_name + _objc_resource_bundle_accessor_library_suffix
210-
211199
def _resource_bundle_accessor_label_name(target_name):
212200
"""Returns the name of the related `resource_bundle_accessor` target.
213201
@@ -287,7 +275,6 @@ def make_pkginfo_targets(bazel_labels):
287275
modulemap_label_name = _modulemap_label_name,
288276
objc_resource_bundle_accessor_hdr_label_name = _objc_resource_bundle_accessor_hdr_label_name,
289277
objc_resource_bundle_accessor_impl_label_name = _objc_resource_bundle_accessor_impl_label_name,
290-
objc_resource_bundle_accessor_library_label_name = _objc_resource_bundle_accessor_library_label_name,
291278
resource_bundle_accessor_label_name = _resource_bundle_accessor_label_name,
292279
resource_bundle_infoplist_label_name = _resource_bundle_infoplist_label_name,
293280
resource_bundle_label_name = _resource_bundle_label_name,

0 commit comments

Comments
 (0)