Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure LLVM cc_toolchain included with Swift releases #1113

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ non_module_deps = use_extension("//swift:extensions.bzl", "non_module_deps")
use_repo(
non_module_deps,
"build_bazel_rules_swift_index_import",
"build_bazel_rules_swift_local_cc_config",
"build_bazel_rules_swift_local_config",
"com_github_apple_swift_log",
"com_github_apple_swift_nio",
Expand Down
11 changes: 0 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,6 @@ also ensure that the Swift compiler is available on your system path.
Copy the `WORKSPACE` snippet from [the releases
page](https://github.com/bazelbuild/rules_swift/releases).

### 3. Additional configuration (Linux only)

The `swift_binary` and `swift_test` rules expect to use `clang` as the driver
for linking, and they query the Bazel C++ API and CROSSTOOL to determine which
arguments should be passed to the linker. By default, the C++ toolchain used by
Bazel is `gcc`, so Swift users on Linux need to override this by setting the
environment variable `CC=clang` when invoking Bazel.

This step is not necessary for macOS users because the Xcode toolchain always
uses `clang`.

## Building with Custom Toolchains

**macOS hosts:** You can build with a custom Swift toolchain (downloaded
Expand Down
2 changes: 1 addition & 1 deletion swift/internal/linking.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ into the binary. Possible values are:
# Do not add references; temporary attribute for C++ toolchain
# Starlark migration.
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
default = Label("@build_bazel_rules_swift_local_cc_config//:toolchain"),
),
# A late-bound attribute denoting the value of the `--custom_malloc`
# command line flag (or None if the flag is not provided).
Expand Down
83 changes: 80 additions & 3 deletions swift/internal/swift_autoconfiguration.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ should be loaded here. Do not load anything else, even common libraries like
Skylib.
"""

load("@bazel_tools//tools/cpp:unix_cc_configure.bzl", "configure_unix_toolchain")
load("@bazel_tools//tools/cpp:windows_cc_configure.bzl", "configure_windows_toolchain")
load(
"@bazel_tools//tools/cpp:lib_cc_configure.bzl",
"get_cpu_value",
)
load(
"@build_bazel_rules_swift//swift/internal:feature_names.bzl",
"SWIFT_FEATURE_CODEVIEW_DEBUG_INFO",
Expand Down Expand Up @@ -256,6 +262,63 @@ def _normalized_linux_cpu(cpu):
return "x86_64"
return cpu

def _toolchain_root(repository_ctx):
path_to_swiftc = repository_ctx.which("swiftc")
if not path_to_swiftc:
fail("No 'swiftc' executable found in $PATH")
return path_to_swiftc.dirname

def _create_xcode_cc_toolchain(repository_ctx):
"""Creates BUILD alias for the C++ toolchain provided by apple_support

Args:
repository_ctx: The repository rule context.
"""

repository_ctx.file("BUILD", """
alias(
name = "toolchain",
actual = "@local_config_apple_cc//:toolchain",
visibility = ["//visibility:public"]
)
""")

def _toolchain_overriden_tools(toolchain_root, extension = ""):
tools = {
"ld": toolchain_root.get_child("lld" + extension),
"llvm-cov": toolchain_root.get_child("llvm-cov" + extension),
"llvm-profdata": toolchain_root.get_child("llvm-profdata" + extension),
"cpp": toolchain_root.get_child("clang-cpp" + extension),
"gcc": toolchain_root.get_child("clang" + extension),
}

# llvm-ar is not shipped before Swift 5.8
ar = toolchain_root.get_child("llvm-ar" + extension)
if ar.exists:
tools["ar"] = ar
return tools

def _create_linux_cc_toolchain(repository_ctx):
"""Creates BUILD targets for the Swift-provided C++ toolchain on Linux.

Args:
repository_ctx: The repository rule context.
"""

toolchain_root = _toolchain_root(repository_ctx)
cpu = get_cpu_value(repository_ctx)
configure_unix_toolchain(repository_ctx, cpu, overriden_tools = _toolchain_overriden_tools(toolchain_root))

def _create_windows_cc_toolchain(repository_ctx):
"""Creates BUILD targets for the Swift-provided C++ toolchain on Windows.

Args:
repository_ctx: The repository rule context.
"""

toolchain_root = _toolchain_root(repository_ctx)
configure_windows_toolchain(repository_ctx, overriden_tools = _toolchain_overriden_tools(toolchain_root, ".exe"))

def _create_linux_toolchain(repository_ctx):
"""Creates BUILD targets for the Swift toolchain on Linux.

Expand All @@ -266,6 +329,7 @@ def _create_linux_toolchain(repository_ctx):
if not path_to_swiftc:
fail("No 'swiftc' executable found in $PATH")

toolchain_root = _toolchain_root(repository_ctx)
root = path_to_swiftc.dirname.dirname
feature_values = _compute_feature_values(repository_ctx, path_to_swiftc)
version_file = _write_swift_version(repository_ctx, path_to_swiftc)
Expand Down Expand Up @@ -306,6 +370,7 @@ swift_toolchain(
for feature in feature_values
]),
root = root,
toolchain_root = toolchain_root,
version_file = version_file,
),
)
Expand Down Expand Up @@ -421,10 +486,16 @@ swift_toolchain(
),
)

def _swift_cc_autoconfiguration_impl(repository_ctx):
os_name = repository_ctx.os.name.lower()
if os_name.startswith("mac os"):
_create_xcode_cc_toolchain(repository_ctx)
elif os_name.startswith("windows"):
_create_windows_cc_toolchain(repository_ctx)
else:
_create_linux_cc_toolchain(repository_ctx)

def _swift_autoconfiguration_impl(repository_ctx):
# TODO(allevato): This is expedient and fragile. Use the
# platforms/toolchains APIs instead to define proper toolchains, and make it
# possible to support non-Xcode toolchains on macOS as well.
os_name = repository_ctx.os.name.lower()
if os_name.startswith("mac os"):
_create_xcode_toolchain(repository_ctx)
Expand All @@ -433,6 +504,12 @@ def _swift_autoconfiguration_impl(repository_ctx):
else:
_create_linux_toolchain(repository_ctx)

swift_cc_autoconfiguration = repository_rule(
environ = ["PATH"],
implementation = _swift_cc_autoconfiguration_impl,
local = True,
)

swift_autoconfiguration = repository_rule(
environ = ["CC", "PATH", "ProgramData", "Path"],
implementation = _swift_autoconfiguration_impl,
Expand Down
2 changes: 1 addition & 1 deletion swift/internal/swift_import.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ The `.swiftmodule` file provided to Swift targets that depend on this target.
mandatory = False,
),
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
default = Label("@build_bazel_rules_swift_local_cc_config//:toolchain"),
doc = """\
The C++ toolchain from which linking flags and other tools needed by the Swift
toolchain (such as `clang`) will be retrieved.
Expand Down
7 changes: 1 addition & 6 deletions swift/internal/swift_toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,6 @@ def _swift_toolchain_impl(ctx):
toolchain_root = ctx.attr.root
cc_toolchain = find_cpp_toolchain(ctx)

if "clang" not in cc_toolchain.compiler:
fail("Swift requires the configured CC toolchain to be LLVM (clang). " +
"Either use the locally installed LLVM by setting `CC=clang` in your environment " +
"before invoking Bazel, or configure a Bazel LLVM CC toolchain.")

if ctx.attr.os == "windows":
swift_linkopts_cc_info = _swift_windows_linkopts_cc_info(
ctx.attr.arch,
Expand Down Expand Up @@ -450,7 +445,7 @@ configuration options that are applied to targets on a per-package basis.
allow_single_file = True,
),
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
default = Label("@build_bazel_rules_swift_local_cc_config//:toolchain"),
doc = """\
The C++ toolchain from which other tools needed by the Swift toolchain (such as
`clang` and `ar`) will be retrieved.
Expand Down
2 changes: 1 addition & 1 deletion swift/internal/xcode_swift_toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ configuration options that are applied to targets on a per-package basis.
providers = [[SwiftPackageConfigurationInfo]],
),
"_cc_toolchain": attr.label(
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
default = Label("@build_bazel_rules_swift_local_cc_config//:toolchain"),
doc = """\
The C++ toolchain from which linking flags and other tools needed by the Swift
toolchain (such as `clang`) will be retrieved.
Expand Down
6 changes: 6 additions & 0 deletions swift/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load(
"@build_bazel_rules_swift//swift/internal:swift_autoconfiguration.bzl",
"swift_autoconfiguration",
"swift_cc_autoconfiguration",
)

def _maybe(repo_rule, name, **kwargs):
Expand Down Expand Up @@ -191,6 +192,11 @@ def swift_rules_dependencies(include_bzlmod_ready_dependencies = True):
sha256 = "28c1ffa39d99e74ed70623899b207b41f79214c498c603915aef55972a851a15",
)

_maybe(
swift_cc_autoconfiguration,
name = "build_bazel_rules_swift_local_cc_config",
)

_maybe(
swift_autoconfiguration,
name = "build_bazel_rules_swift_local_config",
Expand Down