Skip to content

Commit f3e3155

Browse files
authored
fix: correct issues with modulemap generation (#1360)
Fixes duplicate definition errors caused by custom/generated modulemap files.
1 parent 6a78a6d commit f3e3155

File tree

10 files changed

+114
-45
lines changed

10 files changed

+114
-45
lines changed

docs/faq.md

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
* [After running `//:swift_update_pkgs`, I see a `.build` directory. What is it? Do I need it?](#after-running-swift_update_pkgs-i-see-a-build-directory-what-is-it-do-i-need-it)
1414
* [Does the Gazelle plugin run Swift package manager with every execution?](#does-the-gazelle-plugin-run-swift-package-manager-with-every-execution)
1515
* [Can I store the Swift dependency files in a sub-package (i.e., not in the root of the workspace)?](#can-i-store-the-swift-dependency-files-in-a-sub-package-ie-not-in-the-root-of-the-workspace)
16-
* [My project builds successfully with `bazel build ...`, but it does not build when using `rules_xcodeproj`. How can I fix this?](#my-project-builds-successfully-with-bazel-build--but-it-does-not-build-when-using-rules_xcodeproj-how-can-i-fix-this)
1716
* [Why does this happen?](#why-does-this-happen)
1817
* [How do I handle the error `Unable to resolve byName reference XXX in @swiftpkg_yyy.`?](#how-do-i-handle-the-error-unable-to-resolve-byname-reference-xxx-in-swiftpkg_yyy)
1918
* [How do I fix this issue?](#how-do-i-fix-this-issue)
@@ -94,21 +93,6 @@ the source files that exist in your project to generate the Bazel build files.
9493
Yes. The [vapor example] demonstrates storing the Swift dependency files in a sub-package called
9594
`swift`.
9695

97-
## My project builds successfully with `bazel build ...`, but it does not build when using `rules_xcodeproj`. How can I fix this?
98-
99-
tl;dr Add the following to your `.bazelrc`.
100-
101-
```
102-
# Ensure that sandboxed is added to the spawn strategy list when building with
103-
# rules_xcodeproj.
104-
build:rules_xcodeproj --spawn_strategy=remote,worker,sandboxed,local
105-
```
106-
107-
Alternatively, you can use the [--strategy_regexp] flag to target the relevant targets. For
108-
instance, if `Sources/BranchSDK/BNCContentDiscoveryManager.m` is not building properly, you can
109-
specify `--strategy_regexp="Compiling Sources/BranchSDK/.*=sandboxed"` to use the `sandboxed` strategy
110-
for that file. The regular expression matches on the _description_ for the action.
111-
11296
### Why does this happen?
11397

11498
This can happen with some Swift packages (e.g. `firebase-ios-sdk`). [rules_xcodeproj removes the

examples/firebase_example/.bazelrc

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import %workspace%/../../ci.bazelrc
77
# Try to import a local.rc file; typically, written by CI
88
try-import %workspace%/../../local.bazelrc
99

10-
# NOTE: Puposefully not specifying --copt='-std=c99' as it is applied to
11-
# objc_library targets that contain Objective-C++ files. Tried using
10+
# NOTE: Puposefully not specifying --copt='-std=c99' as it is applied to
11+
# objc_library targets that contain Objective-C++ files. Tried using
1212
# --per_file_copt to exclude .mm files, but did not have success.
1313
# https://stackoverflow.com/questions/40260242/how-to-set-c-standard-version-when-build-with-bazel/43388168#43388168
1414
#
@@ -20,16 +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 the sandbox for rules_xcodeproj-specific builds. rules_xcodeproj removes
25-
# the sandboxed spawn strategy (--spawn_strategy=remote,worker,local) by
26-
# default to speed up builds. However, to support setting C/C++ language
27-
# standard flags per target
28-
# (https://github.com/cgrindel/rules_swift_package_manager/issues/1079), we
29-
# need to generate multiple {cc,objc}_library targets based upon the type of
30-
# source files (e.g. C, C++, ObjC, ObjC++). When builds occur outside of the
31-
# sandbox, we can experience "error: duplicate interface definition for class
32-
# 'XXX'" errors. Until we can address the underlying error, clients that use
33-
# rules_swift_package_manager with rules_xcodeproj may need to use sandbox
34-
# builds.
35-
common:rules_xcodeproj --spawn_strategy=remote,worker,sandboxed,local

examples/interesting_deps/BUILD.bazel

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary")
2+
load("@build_bazel_rules_apple//apple:macos.bzl", "macos_unit_test")
23
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_binary")
34
load("@cgrindel_bazel_starlib//bzltidy:defs.bzl", "tidy")
45

@@ -46,6 +47,19 @@ swift_binary(
4647
],
4748
)
4849

50+
objc_library(
51+
name = "objc_test.lib",
52+
srcs = ["objc_test.m"],
53+
enable_modules = True,
54+
deps = ["@swiftpkg_ocmock//:OCMock"],
55+
)
56+
57+
macos_unit_test(
58+
name = "objc_test",
59+
minimum_os_version = "10.15",
60+
deps = [":objc_test.lib"],
61+
)
62+
4963
sh_test(
5064
name = "simple_test",
5165
srcs = ["simple_test.sh"],

examples/interesting_deps/MODULE.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ bazel_dep(
2323
version = "2.2.4",
2424
repo_name = "build_bazel_rules_swift",
2525
)
26+
bazel_dep(
27+
name = "rules_apple",
28+
version = "3.6.0",
29+
repo_name = "build_bazel_rules_apple",
30+
)
2631

2732
bazel_dep(
2833
name = "bazel_skylib_gazelle_plugin",
@@ -70,6 +75,7 @@ use_repo(
7075
"swiftpkg_cocoalumberjack",
7176
"swiftpkg_geoswift",
7277
"swiftpkg_libwebp_xcode",
78+
"swiftpkg_ocmock",
7379
"swiftpkg_opencombine",
7480
"swiftpkg_swift_log",
7581
)

examples/interesting_deps/Package.resolved

Lines changed: 15 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/interesting_deps/Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ let package = Package(
1010
.package(url: "https://github.com/OpenCombine/OpenCombine", from: "0.14.0"),
1111
.package(url: "https://github.com/SDWebImage/libwebp-Xcode.git", from: "1.3.2"),
1212
.package(url: "https://github.com/apple/swift-log", from: "1.6.2"),
13+
.package(url: "https://github.com/erikdoe/ocmock", from: "3.9.0"),
1314
]
1415
)

examples/interesting_deps/do_test

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
set -o errexit -o nounset -o pipefail
44

5-
# Use the Bazel binary specified by the integration test. Otherise, fall back
5+
# Use the Bazel binary specified by the integration test. Otherwise, fall back
66
# to bazel.
77
bazel="${BIT_BAZEL_BINARY:-bazel}"
88

@@ -12,5 +12,7 @@ bazel="${BIT_BAZEL_BINARY:-bazel}"
1212
# Test resolving the package via the `swift_package` repo.
1313
"${bazel}" run @swift_package//:resolve
1414

15-
# Ensure that it builds and tests pass
16-
"${bazel}" test //...
15+
# Ensure that it builds in both sandbox and local strategies.
16+
# This tests issues with modulemap include/generation.
17+
"${bazel}" test //... --spawn_strategy=sandboxed,local
18+
"${bazel}" test //... --spawn_strategy=local
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#import <OCMock/OCMock.h>
2+
3+
@import Foundation;
4+
@import XCTest;
5+
6+
@interface ObjcTest : XCTestCase
7+
@end
8+
9+
@implementation ObjcTest
10+
11+
- (void)testMock {
12+
OCMockObject *mock = [OCMockObject mockForClass:[NSObject class]];
13+
XCTAssertNotNil(mock);
14+
}
15+
16+
@end

swiftpkg/internal/swiftpkg_build_files.bzl

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ def _c_child_library(
229229
rule_kind,
230230
srcs,
231231
language_standard = None,
232+
modulemap_path = None,
232233
res_copts = None):
233234
child_attrs = dicts.omit(attrs, ["data"])
234235
child_copts = list(attrs.get("copts", []))
@@ -238,6 +239,8 @@ def _c_child_library(
238239
if language_standard:
239240
child_copts.append("-std={}".format(language_standard))
240241
child_attrs["copts"] = child_copts
242+
if modulemap_path:
243+
child_attrs["module_map"] = modulemap_path
241244
return build_decls.new(
242245
rule_kind,
243246
name,
@@ -434,8 +437,8 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target):
434437
modulemap_target_name = pkginfo_targets.modulemap_label_name(bzl_target_name)
435438
noop_modulemap = clang_src_info.modulemap_path != None
436439
modulemap_attrs = {
437-
"deps": bzl_selects.to_starlark(modulemap_deps),
438-
"hdrs": clang_src_info.hdrs,
440+
"deps": [] if noop_modulemap else bzl_selects.to_starlark(modulemap_deps),
441+
"hdrs": [] if noop_modulemap else clang_src_info.hdrs,
439442
"module_name": target.c99name,
440443
"noop": noop_modulemap,
441444
"visibility": ["//:__subpackages__"],
@@ -448,6 +451,23 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target):
448451
),
449452
)
450453

454+
# Create an interop hint for any custom or generated modulemap.
455+
# `module_map` attr of `objc_library` is being removed.
456+
aspect_hint_target_name = pkginfo_targets.swift_hint_label_name(
457+
bzl_target_name,
458+
)
459+
load_stmts.append(swift_interop_hint_load_stmt)
460+
decls.append(
461+
build_decls.new(
462+
kind = swift_kinds.interop_hint,
463+
name = aspect_hint_target_name,
464+
attrs = {
465+
"module_map": clang_src_info.modulemap_path if clang_src_info.modulemap_path else modulemap_target_name,
466+
"module_name": target.c99name,
467+
},
468+
),
469+
)
470+
451471
if clang_src_info.organized_srcs.objc_srcs:
452472
child_name = "{}_objc".format(bzl_target_name)
453473
child_dep_names.append(child_name)
@@ -461,6 +481,7 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target):
461481
clang_src_info.organized_srcs.objc_srcs +
462482
clang_src_info.organized_srcs.other_srcs,
463483
language_standard = pkg_ctx.pkg_info.c_language_standard,
484+
modulemap_path = clang_src_info.modulemap_path,
464485
res_copts = res_copts,
465486
),
466487
)
@@ -477,18 +498,20 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target):
477498
clang_src_info.organized_srcs.objcxx_srcs +
478499
clang_src_info.organized_srcs.other_srcs,
479500
language_standard = pkg_ctx.pkg_info.cxx_language_standard,
501+
modulemap_path = clang_src_info.modulemap_path,
480502
res_copts = res_copts,
481503
),
482504
)
483505

484506
# Add the objc_library that brings all of the child targets together.
485507
uber_attrs = dicts.omit(attrs, ["srcs", "copts"]) | {
508+
"aspect_hints": [aspect_hint_target_name],
486509
"deps": [
487510
":{}".format(dname)
488511
for dname in child_dep_names
489512
],
513+
"module_name": target.c99name,
490514
}
491-
uber_attrs["module_name"] = target.c99name
492515
decls.append(
493516
build_decls.new(
494517
objc_kinds.library,
@@ -502,6 +525,8 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target):
502525
bzl_target_name,
503526
)
504527
aspect_hint_attrs = {"module_name": target.c99name}
528+
if clang_src_info.modulemap_path:
529+
aspect_hint_attrs["module_map"] = clang_src_info.modulemap_path
505530

506531
load_stmts = [swift_interop_hint_load_stmt]
507532
decls.append(

swiftpkg/tests/swiftpkg_build_files_tests.bzl

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ swift_interop_hint(
621621
msg = "Objc target",
622622
name = "ObjcLibrary",
623623
exp = """\
624+
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_interop_hint")
624625
load("@rules_swift_package_manager//swiftpkg:build_defs.bzl", "generate_modulemap")
625626
626627
generate_modulemap(
@@ -634,6 +635,7 @@ generate_modulemap(
634635
635636
objc_library(
636637
name = "ObjcLibrary.rspm",
638+
aspect_hints = ["ObjcLibrary.rspm_swift_hint"],
637639
deps = [":ObjcLibrary.rspm_objc"],
638640
enable_modules = True,
639641
hdrs = ["include/external.h"],
@@ -698,25 +700,33 @@ objc_library(
698700
textual_hdrs = ["src/foo.m"],
699701
visibility = ["//:__subpackages__"],
700702
)
703+
704+
swift_interop_hint(
705+
name = "ObjcLibrary.rspm_swift_hint",
706+
module_map = "ObjcLibrary.rspm_modulemap",
707+
module_name = "ObjcLibrary",
708+
)
701709
""",
702710
),
703711
struct(
704712
msg = "Objc target with a modulemap",
705713
name = "ObjcLibraryWithModulemap",
706714
exp = """\
715+
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_interop_hint")
707716
load("@rules_swift_package_manager//swiftpkg:build_defs.bzl", "generate_modulemap")
708717
709718
generate_modulemap(
710719
name = "ObjcLibraryWithModulemap.rspm_modulemap",
711-
deps = ["@swiftpkg_mypackage//:ObjcLibraryDep.rspm_modulemap"],
712-
hdrs = ["include/external.h"],
720+
deps = [],
721+
hdrs = [],
713722
module_name = "ObjcLibraryWithModulemap",
714723
noop = True,
715724
visibility = ["//:__subpackages__"],
716725
)
717726
718727
objc_library(
719728
name = "ObjcLibraryWithModulemap.rspm",
729+
aspect_hints = ["ObjcLibraryWithModulemap.rspm_swift_hint"],
720730
deps = [":ObjcLibraryWithModulemap.rspm_objc"],
721731
enable_modules = True,
722732
hdrs = ["include/external.h"],
@@ -758,6 +768,7 @@ objc_library(
758768
enable_modules = True,
759769
hdrs = ["include/external.h"],
760770
includes = ["include"],
771+
module_map = "include/module.modulemap",
761772
sdk_frameworks = select({
762773
"@rules_swift_package_manager//config_settings/spm/platform:ios": [
763774
"Foundation",
@@ -781,6 +792,12 @@ objc_library(
781792
textual_hdrs = ["src/foo.m"],
782793
visibility = ["//:__subpackages__"],
783794
)
795+
796+
swift_interop_hint(
797+
name = "ObjcLibraryWithModulemap.rspm_swift_hint",
798+
module_map = "include/module.modulemap",
799+
module_name = "ObjcLibraryWithModulemap",
800+
)
784801
""",
785802
),
786803
struct(
@@ -931,6 +948,7 @@ swift_library(
931948
name = "ObjcLibraryWithResources",
932949
exp = """\
933950
load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_bundle")
951+
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_interop_hint")
934952
load("@rules_swift_package_manager//swiftpkg:build_defs.bzl", "generate_modulemap", "objc_resource_bundle_accessor_hdr", "objc_resource_bundle_accessor_impl", "resource_bundle_infoplist")
935953
936954
apple_resource_bundle(
@@ -952,6 +970,7 @@ generate_modulemap(
952970
953971
objc_library(
954972
name = "ObjcLibraryWithResources.rspm",
973+
aspect_hints = ["ObjcLibraryWithResources.rspm_swift_hint"],
955974
data = [":ObjcLibraryWithResources.rspm_resource_bundle"],
956975
deps = [":ObjcLibraryWithResources.rspm_objc"],
957976
enable_modules = True,
@@ -1039,6 +1058,12 @@ resource_bundle_infoplist(
10391058
name = "ObjcLibraryWithResources.rspm_resource_bundle_infoplist",
10401059
region = "en",
10411060
)
1061+
1062+
swift_interop_hint(
1063+
name = "ObjcLibraryWithResources.rspm_swift_hint",
1064+
module_map = "ObjcLibraryWithResources.rspm_modulemap",
1065+
module_name = "ObjcLibraryWithResources",
1066+
)
10421067
""",
10431068
),
10441069
]

0 commit comments

Comments
 (0)