Skip to content

Commit de6a519

Browse files
stravinskiiswiple-rules-gardener
authored andcommitted
Added support for automatic modulemap generation
Replaces public_hdrs bundling to use the framework_header_modulemap_partial to generate modulemaps and umbrella headers for each XCFramework library. PiperOrigin-RevId: 440923000
1 parent bf57dd3 commit de6a519

File tree

5 files changed

+217
-20
lines changed

5 files changed

+217
-20
lines changed

apple/internal/BUILD

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ bzl_library(
107107
],
108108
)
109109

110+
bzl_library(
111+
name = "cc_info_support",
112+
srcs = ["cc_info_support.bzl"],
113+
visibility = [
114+
"//apple:__subpackages__",
115+
],
116+
)
117+
110118
bzl_library(
111119
name = "codesigning_support",
112120
srcs = ["codesigning_support.bzl"],
@@ -530,6 +538,7 @@ bzl_library(
530538
],
531539
deps = [
532540
":apple_product_type",
541+
":cc_info_support",
533542
":experimental",
534543
":intermediates",
535544
":linking_support",

apple/internal/cc_info_support.bzl

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Copyright 2022 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Support methods for handling artifacts from CcInfo providers."""
16+
17+
def _get_all_deps(*, deps, split_deps_keys = []):
18+
"""Returns a list of all dependencies from a Label list and optional split attribute keys.
19+
20+
Args:
21+
deps: Label list of (split) dependencies to traverse.
22+
split_deps_keys: (optional) List of split attribute keys to use on split deps.
23+
24+
Returns:
25+
List of all dependencies. If split_deps_keys is not provided, return deps.
26+
"""
27+
if type(deps) == "list":
28+
return deps
29+
30+
if not split_deps_keys:
31+
return deps.values()
32+
33+
all_deps = []
34+
for split_deps_key in split_deps_keys:
35+
all_deps += deps[split_deps_key]
36+
return all_deps
37+
38+
def _get_sdk_frameworks(*, deps, split_deps_keys = []):
39+
"""Returns a depset of SDK frameworks linked to dependencies.
40+
41+
Args:
42+
deps: Label list of (split) dependencies to traverse.
43+
split_deps_keys: (optional) List of split attribute keys to use on split deps.
44+
Returns
45+
Depset of SDK framework strings linked to dependencies.
46+
"""
47+
all_deps = _get_all_deps(deps = deps, split_deps_keys = split_deps_keys)
48+
49+
sdk_frameworks = []
50+
for dep in all_deps:
51+
if not CcInfo in dep:
52+
continue
53+
for linker_input in dep[CcInfo].linking_context.linker_inputs.to_list():
54+
for index, user_link_flag in enumerate(linker_input.user_link_flags):
55+
if user_link_flag == "-framework":
56+
sdk_frameworks.append(linker_input.user_link_flags[index + 1])
57+
58+
return depset(sdk_frameworks)
59+
60+
def _get_sdk_dylibs(*, deps, split_deps_keys = []):
61+
"""Returns a depset of SDK dylibs linked to dependencies.
62+
63+
Args:
64+
deps: Label list of (split) dependencies to traverse.
65+
split_deps_keys: (optional) List of split attribute keys to use on split deps.
66+
Returns
67+
Depset of SDK framework strings linked to dependencies.
68+
"""
69+
all_deps = _get_all_deps(deps = deps, split_deps_keys = split_deps_keys)
70+
71+
sdk_dylibs = []
72+
for dep in all_deps:
73+
if not CcInfo in dep:
74+
continue
75+
76+
for linker_input in dep[CcInfo].linking_context.linker_inputs.to_list():
77+
for user_link_flag in linker_input.user_link_flags:
78+
if user_link_flag.startswith("-l"):
79+
sdk_dylibs.append("lib" + user_link_flag[2:])
80+
81+
return depset(sdk_dylibs)
82+
83+
cc_info_support = struct(
84+
get_sdk_dylibs = _get_sdk_dylibs,
85+
get_sdk_frameworks = _get_sdk_frameworks,
86+
)

apple/internal/xcframework_rules.bzl

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ load(
2222
"@build_bazel_rules_apple//apple/internal:apple_product_type.bzl",
2323
"apple_product_type",
2424
)
25+
load(
26+
"@build_bazel_rules_apple//apple/internal:cc_info_support.bzl",
27+
"cc_info_support",
28+
)
2529
load(
2630
"@build_bazel_rules_apple//apple/internal:experimental.bzl",
2731
"is_experimental_tree_artifact_enabled",
@@ -88,6 +92,7 @@ load(
8892
)
8993
load("@build_bazel_rules_swift//swift:swift.bzl", "SwiftInfo")
9094
load("@bazel_skylib//lib:dicts.bzl", "dicts")
95+
load("@bazel_skylib//lib:partial.bzl", "partial")
9196
load("@bazel_skylib//lib:paths.bzl", "paths")
9297

9398
def _group_link_outputs_by_library_identifier(
@@ -165,8 +170,16 @@ def _group_link_outputs_by_library_identifier(
165170
bitcode_symbol_maps = {}
166171
dsym_binaries = {}
167172
linkmaps = {}
173+
split_attr_keys = []
168174
for link_output in link_outputs:
169175
architectures.append(link_output.architecture)
176+
split_attr_keys.append(
177+
transition_support.xcframework_split_attr_key(
178+
cpu = link_output.architecture,
179+
environment = link_output.environment,
180+
platform_type = link_output.platform,
181+
),
182+
)
170183

171184
# static library linking does not support bitcode, dsym, and linkmaps yet.
172185
if linking_type == "binary":
@@ -191,6 +204,7 @@ def _group_link_outputs_by_library_identifier(
191204
environment = environment,
192205
linkmaps = linkmaps,
193206
platform = platform,
207+
split_attr_keys = split_attr_keys,
194208
)
195209

196210
return link_outputs_by_library_identifier
@@ -491,24 +505,14 @@ def _apple_xcframework_impl(ctx):
491505
framework_output_groups = []
492506

493507
for library_identifier, link_output in link_outputs_by_library_identifier.items():
494-
split_attr_keys = []
495-
for architecture in link_output.architectures:
496-
split_attr_keys.append(
497-
transition_support.xcframework_split_attr_key(
498-
cpu = architecture,
499-
environment = link_output.environment,
500-
platform_type = link_output.platform,
501-
),
502-
)
503-
504508
binary_artifact = link_output.binary
505509

506510
rule_descriptor = rule_support.rule_descriptor_no_ctx(
507511
link_output.platform,
508512
apple_product_type.framework,
509513
)
510514
uses_swift = False
511-
for split_attr_key in split_attr_keys:
515+
for split_attr_key in link_output.split_attr_keys:
512516
if swift_support.uses_swift(ctx.split_attr.deps[split_attr_key]):
513517
uses_swift = True
514518

@@ -540,18 +544,18 @@ def _apple_xcframework_impl(ctx):
540544
resource_deps = _unioned_attrs(
541545
attr_names = ["data", "deps"],
542546
split_attr = ctx.split_attr,
543-
split_attr_keys = split_attr_keys,
547+
split_attr_keys = link_output.split_attr_keys,
544548
)
545549

546550
top_level_infoplists = resources.collect(
547551
attr = ctx.split_attr,
548552
res_attrs = ["infoplists"],
549-
split_attr_keys = split_attr_keys,
553+
split_attr_keys = link_output.split_attr_keys,
550554
)
551555
top_level_resources = resources.collect(
552556
attr = ctx.split_attr,
553557
res_attrs = ["data"],
554-
split_attr_keys = split_attr_keys,
558+
split_attr_keys = link_output.split_attr_keys,
555559
)
556560

557561
processor_partials = [
@@ -938,13 +942,31 @@ def _apple_static_xcframework_impl(ctx):
938942
))
939943
framework_archive_files.append(depset([binary_artifact]))
940944

941-
# Include public headers on XCFramework bundle.
942-
for public_header in ctx.attr.public_hdrs:
943-
framework_archive_files.append(public_header.files)
944-
for public_header_file in public_header.files.to_list():
945+
# Generate headers & modulemaps, and bundle using custom bundler.
946+
sdk_frameworks = cc_info_support.get_sdk_frameworks(
947+
deps = ctx.split_attr.deps,
948+
split_deps_keys = link_output.split_attr_keys,
949+
)
950+
sdk_dylibs = cc_info_support.get_sdk_dylibs(
951+
deps = ctx.split_attr.deps,
952+
split_deps_keys = link_output.split_attr_keys,
953+
)
954+
framework_header_modulemap = partial.call(partials.framework_header_modulemap_partial(
955+
actions = actions,
956+
bundle_name = bundle_name,
957+
hdrs = ctx.files.public_hdrs,
958+
label_name = label.name,
959+
output_discriminator = library_identifier,
960+
umbrella_header = None,
961+
sdk_frameworks = sdk_frameworks,
962+
sdk_dylibs = sdk_dylibs,
963+
))
964+
for _, _, files in framework_header_modulemap.bundle_files:
965+
framework_archive_files.append(files)
966+
for file in files.to_list():
945967
framework_archive_merge_files.append(struct(
946-
src = public_header_file.path,
947-
dest = paths.join(library_identifier, "Headers", public_header_file.basename),
968+
src = file.path,
969+
dest = paths.join(library_identifier, "Headers", file.basename),
948970
))
949971

950972
# Save additional library details for the XCFramework's root info plist.

test/starlark_tests/apple_static_xcframework_tests.bzl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,12 @@ def apple_static_xcframework_test_suite(name):
5454
target_under_test = "//test/starlark_tests/targets_under_test/apple:ios_static_xcframework",
5555
contains = [
5656
"$BUNDLE_ROOT/ios-arm64/Headers/shared.h",
57+
"$BUNDLE_ROOT/ios-arm64/Headers/ios_static_xcframework.h",
58+
"$BUNDLE_ROOT/ios-arm64/Headers/module.modulemap",
5759
"$BUNDLE_ROOT/ios-arm64/ios_static_xcframework_ios_device.a",
5860
"$BUNDLE_ROOT/ios-arm64_x86_64-simulator/Headers/shared.h",
61+
"$BUNDLE_ROOT/ios-arm64_x86_64-simulator/Headers/ios_static_xcframework.h",
62+
"$BUNDLE_ROOT/ios-arm64_x86_64-simulator/Headers/module.modulemap",
5963
"$BUNDLE_ROOT/ios-arm64_x86_64-simulator/ios_static_xcframework_ios_simulator.a",
6064
"$BUNDLE_ROOT/Info.plist",
6165
],
@@ -83,6 +87,33 @@ def apple_static_xcframework_test_suite(name):
8387
tags = [name],
8488
)
8589

90+
archive_contents_test(
91+
name = "{}_objc_generated_modulemap_file_content_test".format(name),
92+
build_type = "device",
93+
target_under_test = "//test/starlark_tests/targets_under_test/apple:ios_static_xcfmwk_with_objc_sdk_dylibs_and_and_sdk_frameworks",
94+
text_test_file = "$BUNDLE_ROOT/ios-arm64/Headers/module.modulemap",
95+
text_test_values = [
96+
"framework module ios_static_xcfmwk_with_objc_sdk_dylibs_and_and_sdk_frameworks",
97+
"umbrella header \"ios_static_xcfmwk_with_objc_sdk_dylibs_and_and_sdk_frameworks.h\"",
98+
"link \"c++\"",
99+
"link \"sqlite3\"",
100+
],
101+
tags = [name],
102+
)
103+
104+
archive_contents_test(
105+
name = "{}_swift_generated_modulemap_file_content_test".format(name),
106+
build_type = "device",
107+
target_under_test = "//test/starlark_tests/targets_under_test/apple:ios_static_xcfmwk_with_swift_sdk_dylibs_and_and_sdk_frameworks",
108+
text_test_file = "$BUNDLE_ROOT/ios-arm64/Headers/module.modulemap",
109+
text_test_values = [
110+
"framework module ios_static_xcfmwk_with_swift_sdk_dylibs_and_and_sdk_frameworks",
111+
"umbrella header \"ios_static_xcfmwk_with_swift_sdk_dylibs_and_and_sdk_frameworks.h\"",
112+
"link \"c++\"",
113+
],
114+
tags = [name],
115+
)
116+
86117
# Verifies that the include scanning feature builds for the given XCFramework rule.
87118
archive_contents_test(
88119
name = "{}_ios_arm64_cc_include_scanning_test".format(name),

test/starlark_tests/targets_under_test/apple/BUILD

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,25 @@ objc_library(
242242
tags = TARGETS_UNDER_TEST_TAGS,
243243
)
244244

245+
objc_library(
246+
name = "objc_lib_with_sdk_dylibs_and_sdk_framework",
247+
srcs = [
248+
"//test/starlark_tests/resources:shared.h",
249+
"//test/starlark_tests/resources:shared.m",
250+
],
251+
linkopts = ["-lc++"],
252+
sdk_dylibs = ["libsqlite3"],
253+
sdk_frameworks = ["UIKit"],
254+
tags = TARGETS_UNDER_TEST_TAGS,
255+
)
256+
257+
swift_library(
258+
name = "swift_lib_with_sdk_dylib",
259+
srcs = ["//test/testdata/sources:main.swift"],
260+
linkopts = ["-lc++"],
261+
tags = TARGETS_UNDER_TEST_TAGS,
262+
)
263+
245264
swift_library(
246265
name = "swift_fmwk_lib",
247266
srcs = [
@@ -602,6 +621,36 @@ apple_static_xcframework(
602621
deps = [":StaticFmwkUpperLib"],
603622
)
604623

624+
apple_static_xcframework(
625+
name = "ios_static_xcfmwk_with_objc_sdk_dylibs_and_and_sdk_frameworks",
626+
ios = {
627+
"device": ["arm64"],
628+
},
629+
minimum_os_versions = {
630+
"ios": "8.0",
631+
},
632+
public_hdrs = [
633+
"//test/starlark_tests/resources:shared.h",
634+
],
635+
tags = TARGETS_UNDER_TEST_TAGS,
636+
deps = [":objc_lib_with_sdk_dylibs_and_sdk_framework"],
637+
)
638+
639+
apple_static_xcframework(
640+
name = "ios_static_xcfmwk_with_swift_sdk_dylibs_and_and_sdk_frameworks",
641+
ios = {
642+
"device": ["arm64"],
643+
},
644+
minimum_os_versions = {
645+
"ios": "8.0",
646+
},
647+
public_hdrs = [
648+
"//test/starlark_tests/resources:shared.h",
649+
],
650+
tags = TARGETS_UNDER_TEST_TAGS,
651+
deps = [":swift_lib_with_sdk_dylib"],
652+
)
653+
605654
genrule(
606655
name = "dummy_fmwk_objc_hdr",
607656
outs = ["DummyFmwk.h"],

0 commit comments

Comments
 (0)