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

Support bzlmod #1528

Merged
merged 3 commits into from
Mar 29, 2023
Merged
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
6 changes: 6 additions & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,12 @@ tasks:
- "//..."
build_flags: *aspects_flags
soft_fail: yes
ubuntu2004_examples_bzlmod:
name: Bzlmod Examples
platform: ubuntu2004
working_directory: examples/bzlmod/hello_world
build_targets:
- "//..."
rbe_ubuntu1604_examples:
name: Examples
platform: rbe_ubuntu1604
Expand Down
17 changes: 17 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module(
name = "rules_rust",
version = "0.20.0",
)
cameron-martin marked this conversation as resolved.
Show resolved Hide resolved

print("WARNING: The rules_rust Bazel module is still highly experimental and subject to change at any time. Only use it to try out bzlmod for now.") # buildifier: disable=print

bazel_dep(name = "platforms", version = "0.0.5")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "bazel_skylib", version = "1.2.0")
bazel_dep(name = "apple_support", version = "1.3.1")

internal_deps = use_extension("//rust/private:extensions.bzl", "internal_deps")
use_repo(
internal_deps,
"rules_rust_tinyjson",
)
1 change: 1 addition & 0 deletions examples/bzlmod/hello_world/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_enable_bzlmod
1 change: 1 addition & 0 deletions examples/bzlmod/hello_world/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/bazel-*
13 changes: 13 additions & 0 deletions examples/bzlmod/hello_world/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_doc")

package(default_visibility = ["//visibility:public"])

rust_binary(
name = "hello_world",
srcs = ["src/main.rs"],
)

rust_doc(
name = "hello_world_doc",
crate = ":hello_world",
)
19 changes: 19 additions & 0 deletions examples/bzlmod/hello_world/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module(
name = "hello_world",
version = "1.0",
)

bazel_dep(name = "rules_rust", version = "0.9.0")
local_path_override(
module_name = "rules_rust",
path = "../../..",
)

rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for being late here. Do we want rules_rust to register a default toolchain so that users don't have to do toolchain registration in their MODULE.bazel file at all? (of course, they can still do it to use their desired toolchain version).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently only the toolchains declared in the top level module are registered. There was an unresolved discussion on whether this was the correct thing to do here, but currently the toolchain that rules_rust defines would not get registered.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks!

rust.toolchain(edition = "2021")
use_repo(
rust,
"rust_toolchains",
)

register_toolchains("@rust_toolchains//:all")
Empty file.
17 changes: 17 additions & 0 deletions examples/bzlmod/hello_world/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2015 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.

fn main() {
println!("Hello, world!");
}
42 changes: 42 additions & 0 deletions rust/extensions.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"Module extensions for using rules_rust with bzlmod"

load(
"//rust/private:repository_utils.bzl",
"DEFAULT_EXTRA_TARGET_TRIPLES",
"DEFAULT_NIGHTLY_VERSION",
"DEFAULT_STATIC_RUST_URL_TEMPLATES",
)
load(":repositories.bzl", "rust_register_toolchains")

def _rust_impl(ctx):
mod = ctx.modules[0]
for toolchain in mod.tags.toolchain:
rust_register_toolchains(
dev_components = toolchain.dev_components,
edition = toolchain.edition,
allocator_library = toolchain.allocator_library,
rustfmt_version = toolchain.rustfmt_version,
rust_analyzer_version = toolchain.rust_analyzer_version,
sha256s = toolchain.sha256s,
extra_target_triples = toolchain.extra_target_triples,
urls = toolchain.urls,
versions = toolchain.versions,
register_toolchains = False,
)

rust_toolchain = tag_class(attrs = {
"allocator_library": attr.string(),
"dev_components": attr.bool(default = False),
"edition": attr.string(),
"extra_target_triples": attr.string_list(default = DEFAULT_EXTRA_TARGET_TRIPLES),
"rust_analyzer_version": attr.string(),
"rustfmt_version": attr.string(default = DEFAULT_NIGHTLY_VERSION),
"sha256s": attr.string_dict(),
"urls": attr.string_list(default = DEFAULT_STATIC_RUST_URL_TEMPLATES),
"versions": attr.string_list(default = []),
})

rust = module_extension(
implementation = _rust_impl,
tag_classes = {"toolchain": rust_toolchain},
)
12 changes: 12 additions & 0 deletions rust/private/extensions.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""Bzlmod module extensions that are only used internally"""

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("//rust/private:repository_utils.bzl", "TINYJSON_KWARGS")

def _internal_deps_impl(_module_ctx):
http_archive(**TINYJSON_KWARGS)

internal_deps = module_extension(
doc = "Dependencies for rules_rust",
implementation = _internal_deps_impl,
)
98 changes: 86 additions & 12 deletions rust/private/repository_utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,21 @@ load(
"system_to_staticlib_ext",
"system_to_stdlib_linkflags",
)
load("//rust/private:common.bzl", "DEFAULT_NIGHTLY_ISO_DATE")

DEFAULT_TOOLCHAIN_NAME_PREFIX = "toolchain_for"
DEFAULT_STATIC_RUST_URL_TEMPLATES = ["https://static.rust-lang.org/dist/{}.tar.gz"]
DEFAULT_NIGHTLY_VERSION = "nightly/{}".format(DEFAULT_NIGHTLY_ISO_DATE)
DEFAULT_EXTRA_TARGET_TRIPLES = ["wasm32-unknown-unknown", "wasm32-wasi"]

TINYJSON_KWARGS = dict(
name = "rules_rust_tinyjson",
sha256 = "1a8304da9f9370f6a6f9020b7903b044aa9ce3470f300a1fba5bc77c78145a16",
url = "https://crates.io/api/v1/crates/tinyjson/2.3.0/download",
strip_prefix = "tinyjson-2.3.0",
type = "tar.gz",
build_file = "@rules_rust//util/process_wrapper:BUILD.tinyjson.bazel",
)

_build_file_for_compiler_template = """\
filegroup(
Expand Down Expand Up @@ -220,15 +232,15 @@ load("@rules_rust//rust:toolchain.bzl", "rust_toolchain")

rust_toolchain(
name = "{toolchain_name}",
rust_doc = "@{workspace_name}//:rustdoc",
rust_std = "@{workspace_name}//:rust_std-{target_triple}",
rustc = "@{workspace_name}//:rustc",
rust_doc = "//:rustdoc",
cameron-martin marked this conversation as resolved.
Show resolved Hide resolved
rust_std = "//:rust_std-{target_triple}",
rustc = "//:rustc",
rustfmt = {rustfmt_label},
cargo = "@{workspace_name}//:cargo",
clippy_driver = "@{workspace_name}//:clippy_driver_bin",
cargo = "//:cargo",
clippy_driver = "//:clippy_driver_bin",
llvm_cov = {llvm_cov_label},
llvm_profdata = {llvm_profdata_label},
rustc_lib = "@{workspace_name}//:rustc_lib",
rustc_lib = "//:rustc_lib",
allocator_library = {allocator_library},
binary_ext = "{binary_ext}",
staticlib_ext = "{staticlib_ext}",
Expand All @@ -243,7 +255,6 @@ rust_toolchain(
"""

def BUILD_for_rust_toolchain(
workspace_name,
name,
exec_triple,
target_triple,
Expand All @@ -255,7 +266,6 @@ def BUILD_for_rust_toolchain(
"""Emits a toolchain declaration to match an existing compiler and stdlib.

Args:
workspace_name (str): The name of the workspace that this toolchain resides in
name (str): The name of the toolchain declaration
exec_triple (triple): The rust-style target that this compiler runs on
target_triple (triple): The rust-style target triple of the tool
Expand All @@ -276,19 +286,18 @@ def BUILD_for_rust_toolchain(

rustfmt_label = "None"
if include_rustfmt:
rustfmt_label = "\"@{workspace_name}//:rustfmt_bin\"".format(workspace_name = workspace_name)
rustfmt_label = "\"//:rustfmt_bin\""
llvm_cov_label = "None"
llvm_profdata_label = "None"
if include_llvm_tools:
llvm_cov_label = "\"@{workspace_name}//:llvm_cov_bin\"".format(workspace_name = workspace_name)
llvm_profdata_label = "\"@{workspace_name}//:llvm_profdata_bin\"".format(workspace_name = workspace_name)
llvm_cov_label = "\"//:llvm_cov_bin\""
llvm_profdata_label = "\"//:llvm_profdata_bin\""
allocator_library_label = "None"
if allocator_library:
allocator_library_label = "\"{allocator_library}\"".format(allocator_library = allocator_library)

return _build_file_for_rust_toolchain_template.format(
toolchain_name = name,
workspace_name = workspace_name,
binary_ext = system_to_binary_ext(target_triple.system),
staticlib_ext = system_to_staticlib_ext(target_triple.system),
dylib_ext = system_to_dylib_ext(target_triple.system),
Expand Down Expand Up @@ -774,3 +783,68 @@ def select_rust_version(versions):
current = ver

return current

_build_file_for_toolchain_hub_template = """
toolchain(
name = "{name}",
exec_compatible_with = {exec_constraint_sets_serialized},
target_compatible_with = {target_constraint_sets_serialized},
toolchain = "{toolchain}",
toolchain_type = "{toolchain_type}",
visibility = ["//visibility:public"],
)
"""

def BUILD_for_toolchain_hub(
toolchain_names,
toolchain_labels,
toolchain_types,
target_compatible_with,
exec_compatible_with):
return "\n".join([_build_file_for_toolchain_hub_template.format(
name = toolchain_name,
exec_constraint_sets_serialized = json.encode(exec_compatible_with[toolchain_name]),
target_constraint_sets_serialized = json.encode(target_compatible_with[toolchain_name]),
toolchain = toolchain_labels[toolchain_name],
toolchain_type = toolchain_types[toolchain_name],
) for toolchain_name in toolchain_names])

def _toolchain_repository_hub_impl(repository_ctx):
repository_ctx.file("WORKSPACE.bazel", """workspace(name = "{}")""".format(
repository_ctx.name,
))

repository_ctx.file("BUILD.bazel", BUILD_for_toolchain_hub(
toolchain_names = repository_ctx.attr.toolchain_names,
toolchain_labels = repository_ctx.attr.toolchain_labels,
toolchain_types = repository_ctx.attr.toolchain_types,
target_compatible_with = repository_ctx.attr.target_compatible_with,
exec_compatible_with = repository_ctx.attr.exec_compatible_with,
))

toolchain_repository_hub = repository_rule(
doc = (
"Generates a toolchain-bearing repository that declares a set of other toolchains from other " +
"repositories. This exists to allow registering a set of toolchains in one go with the `:all` target."
),
attrs = {
"exec_compatible_with": attr.string_list_dict(
doc = "A list of constraints for the execution platform for this toolchain, keyed by toolchain name.",
mandatory = True,
),
"target_compatible_with": attr.string_list_dict(
doc = "A list of constraints for the target platform for this toolchain, keyed by toolchain name.",
mandatory = True,
),
"toolchain_labels": attr.string_dict(
doc = "The name of the toolchain implementation target, keyed by toolchain name.",
mandatory = True,
),
"toolchain_names": attr.string_list(mandatory = True),
"toolchain_types": attr.string_dict(
doc = "The toolchain type of the toolchain to declare, keyed by toolchain name.",
mandatory = True,
),
},
implementation = _toolchain_repository_hub_impl,
)
Loading