Skip to content
This repository was archived by the owner on Jan 25, 2024. It is now read-only.

Commit bf5fccc

Browse files
allevatoswiple-rules-gardener
authored andcommitted
Modernize xcode_swift_toolchain features and linkopts.
This change adds the search path for StoreKitTest/XCTest now available on watchOS in Xcode 12.5, and retires a number of workarounds and/or conditional code paths that are for older versions of Xcode that we don't care about anymore. For example, statically linking the Swift runtime is no longer supported on Darwin with modern versions of Xcode. PiperOrigin-RevId: 377920556
1 parent a5eb357 commit bf5fccc

File tree

1 file changed

+67
-114
lines changed

1 file changed

+67
-114
lines changed

swift/internal/xcode_swift_toolchain.bzl

Lines changed: 67 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -117,45 +117,59 @@ def _command_line_objc_copts(compilation_mode, objc_fragment):
117117
clang_copts = objc_fragment.copts + legacy_copts
118118
return [copt for copt in clang_copts if copt != "-g"]
119119

120-
def _platform_developer_framework_dir(apple_toolchain, apple_fragment):
120+
def _platform_developer_framework_dir(
121+
apple_toolchain,
122+
apple_fragment,
123+
xcode_config):
121124
"""Returns the Developer framework directory for the platform.
122125
123126
Args:
124127
apple_fragment: The `apple` configuration fragment.
125128
apple_toolchain: The `apple_common.apple_toolchain()` object.
129+
xcode_config: The Xcode configuration.
126130
127131
Returns:
128132
The path to the Developer framework directory for the platform if one
129133
exists, otherwise `None`.
130134
"""
135+
136+
# All platforms have a `Developer/Library/Frameworks` directory in their
137+
# platform root, except for watchOS prior to Xcode 12.5.
131138
platform_type = apple_fragment.single_arch_platform.platform_type
132-
if platform_type == apple_common.platform_type.watchos:
139+
if (
140+
platform_type == apple_common.platform_type.watchos and
141+
not _is_xcode_at_least_version(xcode_config, "12.5")
142+
):
133143
return None
134144

135-
# All platforms except watchOS have a `Developer/Library/Frameworks`
136-
# directory in their platform root.
137145
return apple_toolchain.platform_developer_framework_dir(apple_fragment)
138146

139-
def _sdk_developer_framework_dir(apple_toolchain, apple_fragment):
147+
def _sdk_developer_framework_dir(apple_toolchain, apple_fragment, xcode_config):
140148
"""Returns the Developer framework directory for the SDK.
141149
142150
Args:
143151
apple_fragment: The `apple` configuration fragment.
144152
apple_toolchain: The `apple_common.apple_toolchain()` object.
153+
xcode_config: The Xcode configuration.
145154
146155
Returns:
147156
The path to the Developer framework directory for the SDK if one
148157
exists, otherwise `None`.
149158
"""
159+
160+
# All platforms have a `Developer/Library/Frameworks` directory in their SDK
161+
# root except for macOS (all versions of Xcode so far), and watchOS (prior
162+
# to Xcode 12.5).
150163
platform_type = apple_fragment.single_arch_platform.platform_type
151-
if platform_type in (
152-
apple_common.platform_type.macos,
153-
apple_common.platform_type.watchos,
164+
if (
165+
platform_type == apple_common.platform_type.macos or
166+
(
167+
platform_type == apple_common.platform_type.watchos and
168+
not _is_xcode_at_least_version(xcode_config, "12.5")
169+
)
154170
):
155171
return None
156172

157-
# All platforms except macOS and watchOS have a
158-
# `Developer/Library/Frameworks` directory in their SDK root.
159173
return paths.join(apple_toolchain.sdk_dir(), "Developer/Library/Frameworks")
160174

161175
def _default_linker_opts(
@@ -189,76 +203,37 @@ def _default_linker_opts(
189203
platform_developer_framework_dir = _platform_developer_framework_dir(
190204
apple_toolchain,
191205
apple_fragment,
206+
xcode_config,
192207
)
193208
sdk_developer_framework_dir = _sdk_developer_framework_dir(
194209
apple_toolchain,
195210
apple_fragment,
211+
xcode_config,
196212
)
197-
linkopts = []
198-
199-
uses_runtime_in_os = _is_xcode_at_least_version(xcode_config, "10.2")
200-
if uses_runtime_in_os:
201-
# Starting with Xcode 10.2, Apple forbids statically linking to the
202-
# Swift runtime. The libraries are distributed with the OS and located
203-
# in /usr/lib/swift.
204-
swift_subdir = "swift"
205-
linkopts.append("-Wl,-rpath,/usr/lib/swift")
206-
elif is_static:
207-
# This branch and the branch below now only support Xcode 10.1 and
208-
# below. Eventually, once we drop support for those versions, they can
209-
# be deleted.
210-
swift_subdir = "swift_static"
211-
linkopts.extend([
212-
"-Wl,-force_load_swift_libs",
213-
"-framework",
214-
"Foundation",
215-
"-lstdc++",
216-
])
217-
else:
218-
swift_subdir = "swift"
219-
220-
swift_lib_dir = (
221-
"{developer_dir}/Toolchains/{toolchain}.xctoolchain/" +
222-
"usr/lib/{swift_subdir}/{platform}"
223-
).format(
224-
developer_dir = apple_toolchain.developer_dir(),
225-
platform = platform.name_in_plist.lower(),
226-
swift_subdir = swift_subdir,
227-
toolchain = "XcodeDefault",
228-
)
229-
230-
# TODO(b/128303533): It's possible to run Xcode 10.2 on a version of macOS
231-
# 10.14.x that does not yet include `/usr/lib/swift`. Later Xcode 10.2 betas
232-
# have deleted the `swift_static` directory, so we must manually add the
233-
# dylibs to the binary's rpath or those binaries won't be able to run at
234-
# all. This is added after `/usr/lib/swift` above so the system versions
235-
# will always be preferred if they are present. This workaround can be
236-
# removed once Xcode 10.2 and macOS 10.14.4 are out of beta.
237-
if uses_runtime_in_os and platform == apple_common.platform.macos:
238-
linkopts.append("-Wl,-rpath,{}".format(swift_lib_dir))
239-
240-
linkopts.extend(
241-
[
242-
"-F{}".format(path)
243-
for path in compact([
244-
platform_developer_framework_dir,
245-
sdk_developer_framework_dir,
246-
])
247-
] + [
248-
"-L{}".format(swift_lib_dir),
249-
# TODO(b/112000244): These should get added by the C++ Starlark API,
250-
# but we're using the "c++-link-executable" action right now instead
251-
# of "objc-executable" because the latter requires additional
252-
# variables not provided by cc_common. Figure out how to handle this
253-
# correctly.
254-
"-ObjC",
255-
"-Wl,-objc_abi_version,2",
256-
],
213+
swift_lib_dir = paths.join(
214+
apple_toolchain.developer_dir(),
215+
"Toolchains/XcodeDefault.xctoolchain/usr/lib/swift",
216+
platform.name_in_plist.lower(),
257217
)
258218

259-
use_system_swift_libs = _is_xcode_at_least_version(xcode_config, "11.0")
260-
if use_system_swift_libs:
261-
linkopts.append("-L/usr/lib/swift")
219+
linkopts = [
220+
"-F{}".format(path)
221+
for path in compact([
222+
platform_developer_framework_dir,
223+
sdk_developer_framework_dir,
224+
])
225+
] + [
226+
"-Wl,-rpath,/usr/lib/swift",
227+
"-L{}".format(swift_lib_dir),
228+
"-L/usr/lib/swift",
229+
# TODO(b/112000244): These should get added by the C++ Starlark API,
230+
# but we're using the "c++-link-executable" action right now instead
231+
# of "objc-executable" because the latter requires additional
232+
# variables not provided by cc_common. Figure out how to handle this
233+
# correctly.
234+
"-ObjC",
235+
"-Wl,-objc_abi_version,2",
236+
]
262237

263238
# Frameworks in the platform's developer frameworks directory (like XCTest,
264239
# but also StoreKitTest on macOS) contain the actual binary for that
@@ -331,7 +306,8 @@ def _all_action_configs(
331306
apple_toolchain,
332307
generated_header_rewriter,
333308
needs_resource_directory,
334-
target_triple):
309+
target_triple,
310+
xcode_config):
335311
"""Returns the action configurations for the Swift toolchain.
336312
337313
Args:
@@ -348,17 +324,20 @@ def _all_action_configs(
348324
needs_resource_directory: If True, the toolchain needs the resource
349325
directory passed explicitly to the compiler.
350326
target_triple: The target triple.
327+
xcode_config: The Xcode configuration.
351328
352329
Returns:
353330
The action configurations for the Swift toolchain.
354331
"""
355332
platform_developer_framework_dir = _platform_developer_framework_dir(
356333
apple_toolchain,
357334
apple_fragment,
335+
xcode_config,
358336
)
359337
sdk_developer_framework_dir = _sdk_developer_framework_dir(
360338
apple_toolchain,
361339
apple_fragment,
340+
xcode_config,
362341
)
363342
developer_framework_dirs = compact([
364343
platform_developer_framework_dir,
@@ -472,7 +451,6 @@ def _all_tool_configs(
472451
generated_header_rewriter,
473452
swift_executable,
474453
toolchain_root,
475-
use_param_file,
476454
xcode_config):
477455
"""Returns the tool configurations for the Swift toolchain.
478456
@@ -487,8 +465,6 @@ def _all_tool_configs(
487465
swift_executable: A custom Swift driver executable to be used during the
488466
build, if provided.
489467
toolchain_root: The root directory of the toolchain, if provided.
490-
use_param_file: If True, actions should have their arguments written to
491-
param files.
492468
xcode_config: The `apple_common.XcodeVersionConfig` provider.
493469
494470
Returns:
@@ -514,7 +490,7 @@ def _all_tool_configs(
514490
execution_requirements = execution_requirements,
515491
swift_executable = swift_executable,
516492
toolchain_root = toolchain_root,
517-
use_param_file = use_param_file,
493+
use_param_file = True,
518494
worker_mode = "persistent",
519495
),
520496
}
@@ -528,25 +504,13 @@ def _all_tool_configs(
528504
execution_requirements = execution_requirements,
529505
swift_executable = swift_executable,
530506
toolchain_root = toolchain_root,
531-
use_param_file = use_param_file,
507+
use_param_file = True,
532508
worker_mode = "wrap",
533509
)
534510
)
535511

536512
return tool_configs
537513

538-
def _is_macos(platform):
539-
"""Returns `True` if the given platform is macOS.
540-
541-
Args:
542-
platform: An `apple_platform` value describing the platform for which a
543-
target is being built.
544-
545-
Returns:
546-
`True` if the given platform is macOS.
547-
"""
548-
return platform.platform_type == apple_common.platform_type.macos
549-
550514
def _is_xcode_at_least_version(xcode_config, desired_version):
551515
"""Returns True if we are building with at least the given Xcode version.
552516
@@ -661,31 +625,20 @@ def _xcode_swift_toolchain_impl(ctx):
661625
cpp_fragment = ctx.fragments.cpp,
662626
) + features_from_swiftcopts(swiftcopts = ctx.fragments.swift.copts())
663627
requested_features.extend(ctx.features)
664-
requested_features.append(SWIFT_FEATURE_BUNDLED_XCTESTS)
665628
requested_features.extend(
666629
_features_for_bitcode_mode(apple_fragment.bitcode_mode),
667630
)
668-
669-
# TODO(b/142867898): Added to match existing Bazel Objective-C module map
670-
# behavior; remove it when possible.
671-
requested_features.append(SWIFT_FEATURE_MODULE_MAP_NO_PRIVATE_HEADERS)
672-
673-
# Xcode 10.0 implies Swift 4.2.
674-
if _is_xcode_at_least_version(xcode_config, "10.0"):
675-
use_param_file = True
676-
requested_features.append(SWIFT_FEATURE_ENABLE_BATCH_MODE)
677-
requested_features.append(SWIFT_FEATURE_USE_RESPONSE_FILES)
678-
else:
679-
use_param_file = False
680-
681-
# Xcode 10.2 implies Swift 5.0.
682-
if _is_xcode_at_least_version(xcode_config, "10.2"):
683-
requested_features.append(SWIFT_FEATURE_DEBUG_PREFIX_MAP)
684-
685-
# Xcode 11.0 implies Swift 5.1.
686-
if _is_xcode_at_least_version(xcode_config, "11.0"):
687-
requested_features.append(SWIFT_FEATURE_SUPPORTS_LIBRARY_EVOLUTION)
688-
requested_features.append(SWIFT_FEATURE_SUPPORTS_PRIVATE_DEPS)
631+
requested_features.extend([
632+
SWIFT_FEATURE_BUNDLED_XCTESTS,
633+
SWIFT_FEATURE_ENABLE_BATCH_MODE,
634+
SWIFT_FEATURE_USE_RESPONSE_FILES,
635+
SWIFT_FEATURE_DEBUG_PREFIX_MAP,
636+
SWIFT_FEATURE_SUPPORTS_LIBRARY_EVOLUTION,
637+
SWIFT_FEATURE_SUPPORTS_PRIVATE_DEPS,
638+
# TODO(b/142867898): Added to match existing Bazel Objective-C module
639+
# map behavior; remove it when possible.
640+
SWIFT_FEATURE_MODULE_MAP_NO_PRIVATE_HEADERS,
641+
])
689642

690643
# Xcode 12.5 implies Swift 5.4.
691644
if _is_xcode_at_least_version(xcode_config, "12.5"):
@@ -702,7 +655,6 @@ def _xcode_swift_toolchain_impl(ctx):
702655
generated_header_rewriter = generated_header_rewriter,
703656
swift_executable = swift_executable,
704657
toolchain_root = toolchain_root,
705-
use_param_file = use_param_file,
706658
xcode_config = xcode_config,
707659
)
708660
all_action_configs = _all_action_configs(
@@ -716,6 +668,7 @@ def _xcode_swift_toolchain_impl(ctx):
716668
generated_header_rewriter = generated_header_rewriter,
717669
needs_resource_directory = swift_executable or toolchain_root,
718670
target_triple = target,
671+
xcode_config = xcode_config,
719672
)
720673

721674
# Xcode toolchains don't pass any files explicitly here because they're

0 commit comments

Comments
 (0)