From 026130ceede5207e1fd7c7e6a0b3f1b9fe7cbb17 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Thu, 14 May 2026 08:11:17 -0700 Subject: [PATCH 1/4] Add test for objc_library modules interop --- test/fixtures/generated_header/BUILD | 39 +++++++++++++++++++ test/fixtures/generated_header/CDependency.h | 18 +++++++++ test/fixtures/generated_header/CDependency.m | 18 +++++++++ test/fixtures/generated_header/ObjcConsumer.m | 19 +++++++++ .../generated_header/UsesCDependency.swift | 23 +++++++++++ test/generated_header_tests.bzl | 10 +++++ 6 files changed, 127 insertions(+) create mode 100644 test/fixtures/generated_header/CDependency.h create mode 100644 test/fixtures/generated_header/CDependency.m create mode 100644 test/fixtures/generated_header/ObjcConsumer.m create mode 100644 test/fixtures/generated_header/UsesCDependency.swift diff --git a/test/fixtures/generated_header/BUILD b/test/fixtures/generated_header/BUILD index b87b2f80e..2ac414187 100644 --- a/test/fixtures/generated_header/BUILD +++ b/test/fixtures/generated_header/BUILD @@ -1,3 +1,8 @@ +load("@rules_cc//cc:objc_library.bzl", "objc_library") +load( + "//swift:swift_interop_hint.bzl", + "swift_interop_hint", +) load( "//swift:swift_library.bzl", "swift_library", @@ -55,3 +60,37 @@ swift_library( generates_header = False, tags = FIXTURE_TAGS, ) + +objc_library( + name = "c_dependency", + srcs = ["CDependency.m"], + hdrs = ["CDependency.h"], + aspect_hints = [":c_dependency_hint"], + tags = FIXTURE_TAGS, + target_compatible_with = ["@platforms//os:macos"], + deps = ["@system_sdk//:Foundation"], +) + +swift_interop_hint( + name = "c_dependency_hint", + module_name = "GeneratedHeaderCDependency", + tags = FIXTURE_TAGS, +) + +swift_library( + name = "generated_header_with_c_dep", + srcs = ["UsesCDependency.swift"], + generates_header = True, + tags = FIXTURE_TAGS, + target_compatible_with = ["@platforms//os:macos"], + deps = [":c_dependency"], +) + +objc_library( + name = "objc_consumer_of_generated_header", + srcs = ["ObjcConsumer.m"], + enable_modules = True, + tags = FIXTURE_TAGS, + target_compatible_with = ["@platforms//os:macos"], + deps = [":generated_header_with_c_dep"], +) diff --git a/test/fixtures/generated_header/CDependency.h b/test/fixtures/generated_header/CDependency.h new file mode 100644 index 000000000..ebb16d8d1 --- /dev/null +++ b/test/fixtures/generated_header/CDependency.h @@ -0,0 +1,18 @@ +// Copyright 2026 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@interface GHCBox : NSObject +@end diff --git a/test/fixtures/generated_header/CDependency.m b/test/fixtures/generated_header/CDependency.m new file mode 100644 index 000000000..df6e422d5 --- /dev/null +++ b/test/fixtures/generated_header/CDependency.m @@ -0,0 +1,18 @@ +// Copyright 2026 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "test/fixtures/generated_header/CDependency.h" + +@implementation GHCBox +@end diff --git a/test/fixtures/generated_header/ObjcConsumer.m b/test/fixtures/generated_header/ObjcConsumer.m new file mode 100644 index 000000000..48e96fc96 --- /dev/null +++ b/test/fixtures/generated_header/ObjcConsumer.m @@ -0,0 +1,19 @@ +// Copyright 2026 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "test/fixtures/generated_header/generated_header_with_c_dep-Swift.h" + +void useGeneratedHeader(GHUsesCDependency *object, NSObject *value) { + (void)[object box:value]; +} diff --git a/test/fixtures/generated_header/UsesCDependency.swift b/test/fixtures/generated_header/UsesCDependency.swift new file mode 100644 index 000000000..804156e71 --- /dev/null +++ b/test/fixtures/generated_header/UsesCDependency.swift @@ -0,0 +1,23 @@ +// Copyright 2026 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Foundation +import GeneratedHeaderCDependency + +@objc(GHUsesCDependency) +public class UsesCDependency: NSObject { + @objc public func box(_ value: NSObject) -> GHCBox { + fatalError("not implemented") + } +} diff --git a/test/generated_header_tests.bzl b/test/generated_header_tests.bzl index d09650da3..022597bd0 100644 --- a/test/generated_header_tests.bzl +++ b/test/generated_header_tests.bzl @@ -14,6 +14,7 @@ """Tests for `swift_library.generated_header`.""" +load("@bazel_skylib//rules:build_test.bzl", "build_test") load( "//test/rules:action_command_line_test.bzl", "make_action_command_line_test_rule", @@ -108,6 +109,15 @@ def generated_header_test_suite(name, tags = []): target_compatible_with = ["@platforms//os:macos"], ) + build_test( + name = "{}_objc_consumer_finds_generated_header_imports".format(name), + targets = [ + "//test/fixtures/generated_header:objc_consumer_of_generated_header", + ], + tags = all_tags, + target_compatible_with = ["@platforms//os:macos"], + ) + # Verify that no generated header is created if the target doesn't request # it. provider_test( From f379a3e7a8f675766d57f97467c1a1840894dfd7 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Thu, 14 May 2026 08:59:27 -0700 Subject: [PATCH 2/4] more levels --- test/fixtures/generated_header/BUILD | 26 +++++++++++++++++-- test/fixtures/generated_header/CDependency.h | 2 +- .../generated_header/CDependencyWrapper.m | 19 ++++++++++++++ .../GeneratedHeaderObjcWrapper.h | 17 ++++++++++++ .../GeneratedHeaderObjcWrapper.m | 23 ++++++++++++++++ test/fixtures/generated_header/ObjcConsumer.m | 6 ++--- 6 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 test/fixtures/generated_header/CDependencyWrapper.m create mode 100644 test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h create mode 100644 test/fixtures/generated_header/GeneratedHeaderObjcWrapper.m diff --git a/test/fixtures/generated_header/BUILD b/test/fixtures/generated_header/BUILD index 2ac414187..93c10cc72 100644 --- a/test/fixtures/generated_header/BUILD +++ b/test/fixtures/generated_header/BUILD @@ -66,11 +66,21 @@ objc_library( srcs = ["CDependency.m"], hdrs = ["CDependency.h"], aspect_hints = [":c_dependency_hint"], + enable_modules = True, tags = FIXTURE_TAGS, target_compatible_with = ["@platforms//os:macos"], deps = ["@system_sdk//:Foundation"], ) +objc_library( + name = "c_dependency_wrapper", + srcs = ["CDependencyWrapper.m"], + enable_modules = True, + tags = FIXTURE_TAGS, + target_compatible_with = ["@platforms//os:macos"], + deps = [":c_dependency"], +) + swift_interop_hint( name = "c_dependency_hint", module_name = "GeneratedHeaderCDependency", @@ -80,10 +90,22 @@ swift_interop_hint( swift_library( name = "generated_header_with_c_dep", srcs = ["UsesCDependency.swift"], + features = ["swift.propagate_generated_module_map"], generates_header = True, + module_name = "GeneratedHeaderWithCDep", tags = FIXTURE_TAGS, target_compatible_with = ["@platforms//os:macos"], - deps = [":c_dependency"], + deps = [":c_dependency_wrapper"], +) + +objc_library( + name = "generated_header_objc_wrapper", + srcs = ["GeneratedHeaderObjcWrapper.m"], + hdrs = ["GeneratedHeaderObjcWrapper.h"], + enable_modules = True, + tags = FIXTURE_TAGS, + target_compatible_with = ["@platforms//os:macos"], + deps = [":generated_header_with_c_dep"], ) objc_library( @@ -92,5 +114,5 @@ objc_library( enable_modules = True, tags = FIXTURE_TAGS, target_compatible_with = ["@platforms//os:macos"], - deps = [":generated_header_with_c_dep"], + deps = [":generated_header_objc_wrapper"], ) diff --git a/test/fixtures/generated_header/CDependency.h b/test/fixtures/generated_header/CDependency.h index ebb16d8d1..3d36b863c 100644 --- a/test/fixtures/generated_header/CDependency.h +++ b/test/fixtures/generated_header/CDependency.h @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import +@import Foundation; @interface GHCBox : NSObject @end diff --git a/test/fixtures/generated_header/CDependencyWrapper.m b/test/fixtures/generated_header/CDependencyWrapper.m new file mode 100644 index 000000000..0717ee57d --- /dev/null +++ b/test/fixtures/generated_header/CDependencyWrapper.m @@ -0,0 +1,19 @@ +// Copyright 2026 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "test/fixtures/generated_header/CDependency.h" + +void forceCDependencyWrapper(void) { + (void)[GHCBox class]; +} diff --git a/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h b/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h new file mode 100644 index 000000000..5f1d04ca4 --- /dev/null +++ b/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h @@ -0,0 +1,17 @@ +// Copyright 2026 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +void useGeneratedHeaderThroughWrapper(NSObject *object, NSObject *value); diff --git a/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.m b/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.m new file mode 100644 index 000000000..327424c7e --- /dev/null +++ b/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.m @@ -0,0 +1,23 @@ +// Copyright 2026 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h" + +@import GeneratedHeaderCDependency; +@import GeneratedHeaderWithCDep; + +void useGeneratedHeaderThroughWrapper(NSObject *object, NSObject *value) { + GHUsesCDependency *typedObject = (GHUsesCDependency *)object; + (void)[typedObject box:value]; +} diff --git a/test/fixtures/generated_header/ObjcConsumer.m b/test/fixtures/generated_header/ObjcConsumer.m index 48e96fc96..b90ef5f0e 100644 --- a/test/fixtures/generated_header/ObjcConsumer.m +++ b/test/fixtures/generated_header/ObjcConsumer.m @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "test/fixtures/generated_header/generated_header_with_c_dep-Swift.h" +#import "test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h" -void useGeneratedHeader(GHUsesCDependency *object, NSObject *value) { - (void)[object box:value]; +void useGeneratedHeader(NSObject *object, NSObject *value) { + useGeneratedHeaderThroughWrapper(object, value); } From 09ead73997e00bee3bc1fe31d339539c09767b30 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Thu, 14 May 2026 09:08:58 -0700 Subject: [PATCH 3/4] Revert "more levels" This reverts commit f379a3e7a8f675766d57f97467c1a1840894dfd7. --- test/fixtures/generated_header/BUILD | 26 ++----------------- test/fixtures/generated_header/CDependency.h | 2 +- .../generated_header/CDependencyWrapper.m | 19 -------------- .../GeneratedHeaderObjcWrapper.h | 17 ------------ .../GeneratedHeaderObjcWrapper.m | 23 ---------------- test/fixtures/generated_header/ObjcConsumer.m | 6 ++--- 6 files changed, 6 insertions(+), 87 deletions(-) delete mode 100644 test/fixtures/generated_header/CDependencyWrapper.m delete mode 100644 test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h delete mode 100644 test/fixtures/generated_header/GeneratedHeaderObjcWrapper.m diff --git a/test/fixtures/generated_header/BUILD b/test/fixtures/generated_header/BUILD index 93c10cc72..2ac414187 100644 --- a/test/fixtures/generated_header/BUILD +++ b/test/fixtures/generated_header/BUILD @@ -66,21 +66,11 @@ objc_library( srcs = ["CDependency.m"], hdrs = ["CDependency.h"], aspect_hints = [":c_dependency_hint"], - enable_modules = True, tags = FIXTURE_TAGS, target_compatible_with = ["@platforms//os:macos"], deps = ["@system_sdk//:Foundation"], ) -objc_library( - name = "c_dependency_wrapper", - srcs = ["CDependencyWrapper.m"], - enable_modules = True, - tags = FIXTURE_TAGS, - target_compatible_with = ["@platforms//os:macos"], - deps = [":c_dependency"], -) - swift_interop_hint( name = "c_dependency_hint", module_name = "GeneratedHeaderCDependency", @@ -90,22 +80,10 @@ swift_interop_hint( swift_library( name = "generated_header_with_c_dep", srcs = ["UsesCDependency.swift"], - features = ["swift.propagate_generated_module_map"], generates_header = True, - module_name = "GeneratedHeaderWithCDep", tags = FIXTURE_TAGS, target_compatible_with = ["@platforms//os:macos"], - deps = [":c_dependency_wrapper"], -) - -objc_library( - name = "generated_header_objc_wrapper", - srcs = ["GeneratedHeaderObjcWrapper.m"], - hdrs = ["GeneratedHeaderObjcWrapper.h"], - enable_modules = True, - tags = FIXTURE_TAGS, - target_compatible_with = ["@platforms//os:macos"], - deps = [":generated_header_with_c_dep"], + deps = [":c_dependency"], ) objc_library( @@ -114,5 +92,5 @@ objc_library( enable_modules = True, tags = FIXTURE_TAGS, target_compatible_with = ["@platforms//os:macos"], - deps = [":generated_header_objc_wrapper"], + deps = [":generated_header_with_c_dep"], ) diff --git a/test/fixtures/generated_header/CDependency.h b/test/fixtures/generated_header/CDependency.h index 3d36b863c..ebb16d8d1 100644 --- a/test/fixtures/generated_header/CDependency.h +++ b/test/fixtures/generated_header/CDependency.h @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -@import Foundation; +#import @interface GHCBox : NSObject @end diff --git a/test/fixtures/generated_header/CDependencyWrapper.m b/test/fixtures/generated_header/CDependencyWrapper.m deleted file mode 100644 index 0717ee57d..000000000 --- a/test/fixtures/generated_header/CDependencyWrapper.m +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2026 The Bazel Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import "test/fixtures/generated_header/CDependency.h" - -void forceCDependencyWrapper(void) { - (void)[GHCBox class]; -} diff --git a/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h b/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h deleted file mode 100644 index 5f1d04ca4..000000000 --- a/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2026 The Bazel Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import - -void useGeneratedHeaderThroughWrapper(NSObject *object, NSObject *value); diff --git a/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.m b/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.m deleted file mode 100644 index 327424c7e..000000000 --- a/test/fixtures/generated_header/GeneratedHeaderObjcWrapper.m +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2026 The Bazel Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import "test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h" - -@import GeneratedHeaderCDependency; -@import GeneratedHeaderWithCDep; - -void useGeneratedHeaderThroughWrapper(NSObject *object, NSObject *value) { - GHUsesCDependency *typedObject = (GHUsesCDependency *)object; - (void)[typedObject box:value]; -} diff --git a/test/fixtures/generated_header/ObjcConsumer.m b/test/fixtures/generated_header/ObjcConsumer.m index b90ef5f0e..48e96fc96 100644 --- a/test/fixtures/generated_header/ObjcConsumer.m +++ b/test/fixtures/generated_header/ObjcConsumer.m @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#import "test/fixtures/generated_header/GeneratedHeaderObjcWrapper.h" +#import "test/fixtures/generated_header/generated_header_with_c_dep-Swift.h" -void useGeneratedHeader(NSObject *object, NSObject *value) { - useGeneratedHeaderThroughWrapper(object, value); +void useGeneratedHeader(GHUsesCDependency *object, NSObject *value) { + (void)[object box:value]; } From 4c17ee7c93fc2c59ef3e4bf923deecc54d73d100 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Thu, 14 May 2026 09:42:09 -0700 Subject: [PATCH 4/4] potential fix --- swift/internal/compiling.bzl | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/swift/internal/compiling.bzl b/swift/internal/compiling.bzl index 96cec8aef..fcc6d695b 100644 --- a/swift/internal/compiling.bzl +++ b/swift/internal/compiling.bzl @@ -213,6 +213,37 @@ def create_compilation_context(defines, srcs, transitive_modules): swiftmodules = tuple(swiftmodules), ) +def _clang_module_map_info(swift_infos): + """Returns Clang module maps and include dirs from Swift deps.""" + + module_maps = [] + include_dirs = [] + seen_module_maps = {} + for swift_info in swift_infos: + for module in swift_info.direct_modules: + clang_module = module.clang + if not clang_module: + continue + + module_map = clang_module.module_map + if type(module_map) != "File": + continue + + if module_map.path in seen_module_maps: + continue + + seen_module_maps[module_map.path] = None + module_maps.append(module_map) + include_dirs.append(module_map.dirname) + + if not module_maps: + return None + + return struct( + include_dirs = include_dirs, + module_maps = module_maps, + ) + def compile_module_interface( *, actions, @@ -698,6 +729,13 @@ def compile( cc_info.compilation_context for cc_info in cc_infos ] + + generated_header_module_map_info = None + if generated_header_name: + generated_header_module_map_info = _clang_module_map_info( + generated_module_deps_swift_infos, + ) + merged_cc_info = cc_common.merge_cc_infos( cc_infos = cc_infos + private_cc_infos + implicit_cc_infos, @@ -913,6 +951,10 @@ to use swift_common.compile(include_dev_srch_paths = ...) instead.\ else: includes = [] + if generated_header_module_map_info: + public_hdrs.extend(generated_header_module_map_info.module_maps) + includes.extend(generated_header_module_map_info.include_dirs) + module_context = create_swift_module_context( name = module_name, clang = create_clang_module_inputs(