Set up Rust linting and cargo-raze in CI
Change-Id: I4c7e603302a1033d5e5141466c4cc5a6131c6e35
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
diff --git a/Cargo.toml b/Cargo.toml
index 4d31a6d..fe957f9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -85,6 +85,7 @@
# which avoid build.rs in cargo-raze itself or elsewhere. rules_rust is another
# place to look.
# https://github.com/bazelbuild/rules_rust/blob/main/bindgen/raze/Cargo.toml
+# https://github.com/google/cargo-raze/blob/main/impl/Cargo.toml
default_gen_buildrs = true
[package.metadata.raze.crates.cxx.'*']
diff --git a/build_tests/hello_lib.rs b/build_tests/hello_lib.rs
index 6374ce6..4f1e16f 100644
--- a/build_tests/hello_lib.rs
+++ b/build_tests/hello_lib.rs
@@ -1,10 +1,12 @@
pub struct Greeter {
- greeting: String,
+ greeting: String,
}
impl Greeter {
pub fn new(greeting: &str) -> Greeter {
- Greeter { greeting: greeting.to_string(), }
+ Greeter {
+ greeting: greeting.to_string(),
+ }
}
pub fn greet(&self, thing: &str) -> String {
diff --git a/build_tests/rust_hello.rs b/build_tests/rust_hello.rs
index 6c6bf9f..110b96e 100644
--- a/build_tests/rust_hello.rs
+++ b/build_tests/rust_hello.rs
@@ -5,17 +5,17 @@
}
fn main() {
- let hello = hello_lib::Greeter::new("Hello");
- println!("{},\n{}", hello.greet("world"), hello.greet("bazel"));
+ let hello = hello_lib::Greeter::new("Hello");
+ println!("{},\n{}", hello.greet("world"), hello.greet("bazel"));
- let mut numbers = Vec::new();
- for i in 1..=10 {
- numbers.push(i);
- }
- println!("{:?}", numbers);
+ let mut numbers = Vec::new();
+ for i in 1..=10 {
+ numbers.push(i);
+ }
+ println!("{:?}", numbers);
- let words = vec!["foo", "bar", "baz"];
- println!("{:?}", words);
+ let words = vec!["foo", "bar", "baz"];
+ println!("{:?}", words);
- println!("sqrt(4) = {}", unsafe { sqrt(4.0) });
+ println!("sqrt(4) = {}", unsafe { sqrt(4.0) });
}
diff --git a/third_party/cargo_raze/cargo_raze.patch b/third_party/cargo_raze/cargo_raze.patch
index 54cd9d5..306fcf3 100644
--- a/third_party/cargo_raze/cargo_raze.patch
+++ b/third_party/cargo_raze/cargo_raze.patch
@@ -39,12 +39,20 @@
],
}),
includes = ["zlib/include/"],
-@@ -28,6 +28,7 @@ genrule(
+@@ -28,6 +28,15 @@ genrule(
srcs = _ZLIB_HEADERS,
outs = _ZLIB_PREFIXED_HEADERS,
cmd = "cp $(SRCS) $(@D)/zlib/include/",
+ visibility = ["//visibility:public"],
)
++
++genrule(
++ name = "dep_z_include",
++ visibility = ["//visibility:public"],
++ outs = ["dep_z_include.env"],
++ srcs = [":copy_public_headers"],
++ cmd = "echo 'DEP_Z_INCLUDE=$${pwd}/'\"$$(dirname \"$$(echo \"$(locations :copy_public_headers)\" | awk '{ print $$1 }')\")\" > $@",
++)
cc_library(
@@ -130,19 +138,21 @@
[package.metadata.raze.crates.openssl.'*']
additional_deps = ["@cargo_raze__openssl//:openssl"]
-@@ -106,6 +106,7 @@ additional_deps = ["@cargo_raze__libgit2
+@@ -106,6 +106,8 @@ additional_deps = ["@cargo_raze__libgit2
build_data_dependencies = [
"@cargo_raze__libssh2//:libssh2",
"@cargo_raze__openssl//:openssl",
+ "@cargo_raze__zlib//:copy_public_headers",
]
additional_deps = ["@cargo_raze__libssh2//:libssh2"]
++# TODO(Brian): Set buildrs_additional_environment_variables for upstreaming.
--- third_party/cargo/remote/BUILD.libz-sys-1.1.2.bazel 2022-02-04 00:45:43.779201978 -0800
+++ third_party/cargo/remote/BUILD.libz-sys-1.1.2.bazel 2022-02-04 00:45:57.151816346 -0800
-@@ -57,6 +57,7 @@ rust_library(
+@@ -57,6 +57,8 @@ rust_library(
# buildifier: leave-alone
++ dep_env_files = ["@cargo_raze__zlib//:dep_z_include"],
deps = [
"@cargo_raze__libc__0_2_92//:libc",
+ "@cargo_raze__zlib//:zlib",
@@ -152,15 +162,6 @@
--- third_party/cargo/remote/BUILD.libssh2-sys-0.2.21.bazel 2022-02-04 00:54:43.031966734 -0800
+++ third_party/cargo/remote/BUILD.libssh2-sys-0.2.21.bazel 2022-02-04 00:54:44.272023742 -0800
-@@ -41,6 +41,8 @@ cargo_build_script(
- name = "libssh2_sys_build_script",
- srcs = glob(["**/*.rs"]),
- build_script_env = {
-+ # TODO: Custom rule that does the copy and exports a Make variable with the folder?
-+ "DEP_Z_INCLUDE": "${pwd}/bazel-out/k8-fastbuild/bin/external/cargo_raze__zlib/zlib/include",
- },
- crate_features = [
- ],
@@ -48,6 +48,7 @@ cargo_build_script(
data = glob(["**"]) + [
"@cargo_raze__libssh2//:libssh2",
@@ -182,3 +183,15 @@
"i686-unknown-freebsd",
"powerpc-unknown-linux-gnu",
+--- impl/BUILD.bazel 2022-05-30 01:37:24.111005507 -0700
++++ impl/BUILD.bazel 2022-05-30 01:37:22.778944267 -0700
+@@ -26,6 +26,9 @@ rust_binary(
+ edition = "2018",
+ proc_macro_deps = all_crate_deps(proc_macro = True),
+ deps = [":cargo_raze"] + all_crate_deps(),
++ # TODO: Make Rust play happy with pic vs nopic. Details at:
++ # https://github.com/bazelbuild/rules_rust/issues/118
++ rustc_flags = ["-Crelocation-model=static"],
+ )
+
+ _TEST_DATA = glob(["src/**/*.template"]) + [
diff --git a/third_party/rules_rust/rust/private/rust.bzl b/third_party/rules_rust/rust/private/rust.bzl
index 58cc9c4..ad2fba8 100644
--- a/third_party/rules_rust/rust/private/rust.bzl
+++ b/third_party/rules_rust/rust/private/rust.bzl
@@ -270,6 +270,7 @@
ctx = ctx,
attr = ctx.attr,
toolchain = toolchain,
+ dep_env_files = ctx.files.dep_env_files,
crate_info = rust_common.create_crate_info(
name = crate_name,
type = crate_type,
@@ -534,6 +535,14 @@
"""),
allow_files = True,
),
+ "dep_env_files": attr.label_list(
+ doc = dedent("""\
+ Files containing additional environment variables to set for build scripts of direct dependencies.
+
+ See `rustc_env_files` for formatting details.
+ """),
+ allow_files = True,
+ ),
"rustc_flags": attr.string_list(
doc = dedent("""\
List of compiler flags passed to `rustc`.
diff --git a/third_party/rules_rust/rust/private/rustc.bzl b/third_party/rules_rust/rust/private/rustc.bzl
index 596c10d..0c3df5e 100644
--- a/third_party/rules_rust/rust/private/rustc.bzl
+++ b/third_party/rules_rust/rust/private/rustc.bzl
@@ -124,6 +124,7 @@
return False
def collect_deps(
+ ctx,
deps,
proc_macro_deps,
aliases,
@@ -200,6 +201,21 @@
transitive_crates_depset = depset(transitive = transitive_crates)
+ dep_env = None
+ dep_env_files = list(ctx.files.dep_env_files)
+ if build_info:
+ if build_info.dep_env:
+ dep_env_files.append(build_info.dep_env)
+ if len(dep_env_files) > 1:
+ dep_env = ctx.actions.declare_file("_depenv/" + crate_info.output.basename)
+ ctx.actions.run_shell(
+ outputs = [dep_env],
+ inputs = dep_env_files,
+ cmd = ["cat"] + [f.path for f in dep_env_files] + [">", dep_env.path],
+ )
+ elif dep_env_files:
+ dep_env = dep_env_files[0]
+
return (
rust_common.dep_info(
direct_crates = depset(direct_crates),
@@ -211,7 +227,7 @@
transitive_crate_outputs = depset(transitive = transitive_crate_outputs),
transitive_build_infos = depset(transitive = transitive_build_infos),
link_search_path_files = depset(transitive = transitive_link_search_paths),
- dep_env = build_info.dep_env if build_info else None,
+ dep_env = dep_env,
),
build_info,
depset(transitive = linkstamps),
@@ -819,6 +835,7 @@
crate_info,
output_hash = None,
rust_flags = [],
+ dep_env_files = [],
force_all_deps_direct = False):
"""Create and run a rustc compile action based on the current rule's attributes
@@ -841,6 +858,7 @@
cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
dep_info, build_info, linkstamps = collect_deps(
+ ctx = ctx,
deps = crate_info.deps,
proc_macro_deps = crate_info.proc_macro_deps,
aliases = crate_info.aliases,
diff --git a/tools/lint/BUILD b/tools/lint/BUILD
index 743c852..57d4e08 100644
--- a/tools/lint/BUILD
+++ b/tools/lint/BUILD
@@ -12,6 +12,17 @@
)
sh_binary(
+ name = "rustfmt",
+ srcs = ["rustfmt.sh"],
+ data = [
+ "@rust//:rustfmt",
+ ],
+ deps = [
+ "@bazel_tools//tools/bash/runfiles",
+ ],
+)
+
+sh_binary(
name = "buildifier",
srcs = ["buildifier.sh"],
data = [
@@ -44,9 +55,12 @@
":buildifier",
":gofmt",
":prettier",
+ ":rustfmt",
"//:gazelle-runner",
"//tools/go:mirror_go_repos",
"//tools/go:tweak_gazelle_go_deps",
+ "//tools/rust:tweak_cargo_raze_output",
+ "@cargo_raze//:raze",
"@go_sdk//:bin/go",
],
env = {
diff --git a/tools/lint/run-ci.sh b/tools/lint/run-ci.sh
index 0576110..a036c06 100755
--- a/tools/lint/run-ci.sh
+++ b/tools/lint/run-ci.sh
@@ -33,7 +33,7 @@
"${go}" mod tidy -e
}
-update_repos() {
+update_go_repos() {
# Clear out the go_deps.bzl file so that gazelle won't hesitate to update
# it. Without this step gazelle would never try to remove a dependency.
cat > "${BUILD_WORKSPACE_DIRECTORY}"/go_deps.bzl <<EOF
@@ -60,6 +60,27 @@
./tools/go/mirror_go_repos --prune
}
+rustfmt() {
+ ./tools/lint/rustfmt
+}
+
+cargo_raze() {
+ local -r cargo_raze="$(readlink -f external/cargo_raze/impl/cargo_raze_bin)"
+ export CARGO="$(readlink -f external/rust/bin/cargo)"
+ export RUSTC="$(readlink -f external/rust/bin/rustc)"
+ cd "${BUILD_WORKSPACE_DIRECTORY}"
+ # Note we don't run with --generate-lockfile here. If there's a new
+ # dependency, we don't want to download it, just failing with an error
+ # is sufficient.
+ "${cargo_raze}" --manifest-path=Cargo.toml
+}
+
+tweak_cargo_raze() {
+ local -r tweaker="$(readlink -f tools/rust/tweak_cargo_raze_output)"
+ cd "${BUILD_WORKSPACE_DIRECTORY}"
+ "${tweaker}" .
+}
+
buildifier() {
./tools/lint/buildifier
}
@@ -80,10 +101,13 @@
readonly -a LINTERS=(
gofmt
gomod
- update_repos
+ update_go_repos
gazelle
tweak_gazelle_go_deps
clean_up_go_mirrors
+ rustfmt
+ cargo_raze
+ tweak_cargo_raze
buildifier
prettier
git_status_is_clean # This must the last linter.
@@ -91,8 +115,12 @@
failure=0
for linter in "${LINTERS[@]}"; do
+ echo "Running ${linter}..." >&2
if ! (eval "${linter}"); then
+ echo "LINTER FAILURE: ${linter}" >&2
failure=1
+ else
+ echo "${linter} succeeded" >&2
fi
done
diff --git a/tools/lint/rustfmt.sh b/tools/lint/rustfmt.sh
new file mode 100755
index 0000000..57ce64f
--- /dev/null
+++ b/tools/lint/rustfmt.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# --- begin runfiles.bash initialization v2 ---
+# Copy-pasted from the Bazel Bash runfiles library v2.
+set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
+source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
+ source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
+ source "$0.runfiles/$f" 2>/dev/null || \
+ source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
+ source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
+ { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
+# --- end runfiles.bash initialization v2 ---
+
+readonly RUSTFMT="$(rlocation rust/bin/rustfmt)"
+
+# Run everything from the root of the tree.
+cd "${BUILD_WORKSPACE_DIRECTORY}"
+
+# Find all the Rust files in the repo.
+rust_files=($(git ls-tree --name-only --full-tree -r @ \
+ | grep -v '^third_party/' \
+ | (grep '\.rs$' || :)))
+
+# If we have any Rust files, format them.
+if ((${#rust_files[@]} > 0)); then
+ exec "${RUSTFMT}" "${rust_files[@]}"
+fi