Skip to content

Commit 0618c50

Browse files
committed
Configure LLVM cc_toolchain included with Swift releases
1 parent df21d3f commit 0618c50

8 files changed

+91
-23
lines changed

MODULE.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ non_module_deps = use_extension("//swift:extensions.bzl", "non_module_deps")
1919
use_repo(
2020
non_module_deps,
2121
"build_bazel_rules_swift_index_import",
22+
"build_bazel_rules_swift_local_cc_config",
2223
"build_bazel_rules_swift_local_config",
2324
"com_github_apple_swift_log",
2425
"com_github_apple_swift_nio",

README.md

-11
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,6 @@ also ensure that the Swift compiler is available on your system path.
6565
Copy the `WORKSPACE` snippet from [the releases
6666
page](https://github.com/bazelbuild/rules_swift/releases).
6767

68-
### 3. Additional configuration (Linux only)
69-
70-
The `swift_binary` and `swift_test` rules expect to use `clang` as the driver
71-
for linking, and they query the Bazel C++ API and CROSSTOOL to determine which
72-
arguments should be passed to the linker. By default, the C++ toolchain used by
73-
Bazel is `gcc`, so Swift users on Linux need to override this by setting the
74-
environment variable `CC=clang` when invoking Bazel.
75-
76-
This step is not necessary for macOS users because the Xcode toolchain always
77-
uses `clang`.
78-
7968
## Building with Custom Toolchains
8069

8170
**macOS hosts:** You can build with a custom Swift toolchain (downloaded

swift/internal/linking.bzl

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ into the binary. Possible values are:
110110
# Do not add references; temporary attribute for C++ toolchain
111111
# Starlark migration.
112112
"_cc_toolchain": attr.label(
113-
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
113+
default = Label("@build_bazel_rules_swift_local_cc_config//:toolchain"),
114114
),
115115
# A late-bound attribute denoting the value of the `--custom_malloc`
116116
# command line flag (or None if the flag is not provided).

swift/internal/swift_autoconfiguration.bzl

+80-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ should be loaded here. Do not load anything else, even common libraries like
2424
Skylib.
2525
"""
2626

27+
load("@bazel_tools//tools/cpp:unix_cc_configure.bzl", "configure_unix_toolchain")
28+
load("@bazel_tools//tools/cpp:windows_cc_configure.bzl", "configure_windows_toolchain")
29+
load(
30+
"@bazel_tools//tools/cpp:lib_cc_configure.bzl",
31+
"get_cpu_value",
32+
)
2733
load(
2834
"@build_bazel_rules_swift//swift/internal:feature_names.bzl",
2935
"SWIFT_FEATURE_CODEVIEW_DEBUG_INFO",
@@ -256,6 +262,63 @@ def _normalized_linux_cpu(cpu):
256262
return "x86_64"
257263
return cpu
258264

265+
def _toolchain_root(repository_ctx):
266+
path_to_swiftc = repository_ctx.which("swiftc")
267+
if not path_to_swiftc:
268+
fail("No 'swiftc' executable found in $PATH")
269+
return path_to_swiftc.dirname
270+
271+
def _create_xcode_cc_toolchain(repository_ctx):
272+
"""Creates BUILD alias for the C++ toolchain provided by apple_support
273+
274+
Args:
275+
repository_ctx: The repository rule context.
276+
"""
277+
278+
repository_ctx.file("BUILD", """
279+
alias(
280+
name = "toolchain",
281+
actual = "@local_config_apple_cc//:toolchain",
282+
visibility = ["//visibility:public"]
283+
)
284+
""")
285+
286+
def _toolchain_overriden_tools(toolchain_root, extension = ""):
287+
tools = {
288+
"ld": toolchain_root.get_child("lld" + extension),
289+
"llvm-cov": toolchain_root.get_child("llvm-cov" + extension),
290+
"llvm-profdata": toolchain_root.get_child("llvm-profdata" + extension),
291+
"cpp": toolchain_root.get_child("clang-cpp" + extension),
292+
"gcc": toolchain_root.get_child("clang" + extension),
293+
}
294+
295+
# llvm-ar is not shipped before Swift 5.8
296+
ar = toolchain_root.get_child("llvm-ar" + extension)
297+
if ar.exists:
298+
tools["ar"] = ar
299+
return tools
300+
301+
def _create_linux_cc_toolchain(repository_ctx):
302+
"""Creates BUILD targets for the Swift-provided C++ toolchain on Linux.
303+
304+
Args:
305+
repository_ctx: The repository rule context.
306+
"""
307+
308+
toolchain_root = _toolchain_root(repository_ctx)
309+
cpu = get_cpu_value(repository_ctx)
310+
configure_unix_toolchain(repository_ctx, cpu, overriden_tools = _toolchain_overriden_tools(toolchain_root))
311+
312+
def _create_windows_cc_toolchain(repository_ctx):
313+
"""Creates BUILD targets for the Swift-provided C++ toolchain on Windows.
314+
315+
Args:
316+
repository_ctx: The repository rule context.
317+
"""
318+
319+
toolchain_root = _toolchain_root(repository_ctx)
320+
configure_windows_toolchain(repository_ctx, overriden_tools = _toolchain_overriden_tools(toolchain_root, ".exe"))
321+
259322
def _create_linux_toolchain(repository_ctx):
260323
"""Creates BUILD targets for the Swift toolchain on Linux.
261324
@@ -266,6 +329,7 @@ def _create_linux_toolchain(repository_ctx):
266329
if not path_to_swiftc:
267330
fail("No 'swiftc' executable found in $PATH")
268331

332+
toolchain_root = _toolchain_root(repository_ctx)
269333
root = path_to_swiftc.dirname.dirname
270334
feature_values = _compute_feature_values(repository_ctx, path_to_swiftc)
271335
version_file = _write_swift_version(repository_ctx, path_to_swiftc)
@@ -306,6 +370,7 @@ swift_toolchain(
306370
for feature in feature_values
307371
]),
308372
root = root,
373+
toolchain_root = toolchain_root,
309374
version_file = version_file,
310375
),
311376
)
@@ -421,10 +486,16 @@ swift_toolchain(
421486
),
422487
)
423488

489+
def _swift_cc_autoconfiguration_impl(repository_ctx):
490+
os_name = repository_ctx.os.name.lower()
491+
if os_name.startswith("mac os"):
492+
_create_xcode_cc_toolchain(repository_ctx)
493+
elif os_name.startswith("windows"):
494+
_create_windows_cc_toolchain(repository_ctx)
495+
else:
496+
_create_linux_cc_toolchain(repository_ctx)
497+
424498
def _swift_autoconfiguration_impl(repository_ctx):
425-
# TODO(allevato): This is expedient and fragile. Use the
426-
# platforms/toolchains APIs instead to define proper toolchains, and make it
427-
# possible to support non-Xcode toolchains on macOS as well.
428499
os_name = repository_ctx.os.name.lower()
429500
if os_name.startswith("mac os"):
430501
_create_xcode_toolchain(repository_ctx)
@@ -433,6 +504,12 @@ def _swift_autoconfiguration_impl(repository_ctx):
433504
else:
434505
_create_linux_toolchain(repository_ctx)
435506

507+
swift_cc_autoconfiguration = repository_rule(
508+
environ = ["PATH"],
509+
implementation = _swift_cc_autoconfiguration_impl,
510+
local = True,
511+
)
512+
436513
swift_autoconfiguration = repository_rule(
437514
environ = ["CC", "PATH", "ProgramData", "Path"],
438515
implementation = _swift_autoconfiguration_impl,

swift/internal/swift_import.bzl

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ The `.swiftmodule` file provided to Swift targets that depend on this target.
172172
mandatory = False,
173173
),
174174
"_cc_toolchain": attr.label(
175-
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
175+
default = Label("@build_bazel_rules_swift_local_cc_config//:toolchain"),
176176
doc = """\
177177
The C++ toolchain from which linking flags and other tools needed by the Swift
178178
toolchain (such as `clang`) will be retrieved.

swift/internal/swift_toolchain.bzl

+1-6
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,6 @@ def _swift_toolchain_impl(ctx):
274274
toolchain_root = ctx.attr.root
275275
cc_toolchain = find_cpp_toolchain(ctx)
276276

277-
if "clang" not in cc_toolchain.compiler:
278-
fail("Swift requires the configured CC toolchain to be LLVM (clang). " +
279-
"Either use the locally installed LLVM by setting `CC=clang` in your environment " +
280-
"before invoking Bazel, or configure a Bazel LLVM CC toolchain.")
281-
282277
if ctx.attr.os == "windows":
283278
swift_linkopts_cc_info = _swift_windows_linkopts_cc_info(
284279
ctx.attr.arch,
@@ -450,7 +445,7 @@ configuration options that are applied to targets on a per-package basis.
450445
allow_single_file = True,
451446
),
452447
"_cc_toolchain": attr.label(
453-
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
448+
default = Label("@build_bazel_rules_swift_local_cc_config//:toolchain"),
454449
doc = """\
455450
The C++ toolchain from which other tools needed by the Swift toolchain (such as
456451
`clang` and `ar`) will be retrieved.

swift/internal/xcode_swift_toolchain.bzl

+1-1
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ configuration options that are applied to targets on a per-package basis.
800800
providers = [[SwiftPackageConfigurationInfo]],
801801
),
802802
"_cc_toolchain": attr.label(
803-
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
803+
default = Label("@build_bazel_rules_swift_local_cc_config//:toolchain"),
804804
doc = """\
805805
The C++ toolchain from which linking flags and other tools needed by the Swift
806806
toolchain (such as `clang`) will be retrieved.

swift/repositories.bzl

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
1818
load(
1919
"@build_bazel_rules_swift//swift/internal:swift_autoconfiguration.bzl",
2020
"swift_autoconfiguration",
21+
"swift_cc_autoconfiguration",
2122
)
2223

2324
def _maybe(repo_rule, name, **kwargs):
@@ -191,6 +192,11 @@ def swift_rules_dependencies(include_bzlmod_ready_dependencies = True):
191192
sha256 = "28c1ffa39d99e74ed70623899b207b41f79214c498c603915aef55972a851a15",
192193
)
193194

195+
_maybe(
196+
swift_cc_autoconfiguration,
197+
name = "build_bazel_rules_swift_local_cc_config",
198+
)
199+
194200
_maybe(
195201
swift_autoconfiguration,
196202
name = "build_bazel_rules_swift_local_config",

0 commit comments

Comments
 (0)