feat(#514): pass extra flags to clippy (#1264)
* feat(#514): pass extra flags to clippy
This change adds a new configuration rule, `clippy_flags`.
This rule allows you to override clippy flags that the
`rust_clippy_aspect` aspect and the `rust_clippy` rule use.
The flags affect all the targets.
Adding the configuration to `.bazelrc` allows you to have consistent
clippy settings for the whole team.
Example:
```
--@rules_rust//:clippy_flags=-D,clippy::all,-A,clippy::too_many_arguments
```
* sort dict entries
* Apply review feedback
* fail on unsupported clippy configuration
diff --git a/BUILD.bazel b/BUILD.bazel
index 281a3d8..260db43 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -1,5 +1,5 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
-load("//rust:defs.bzl", "capture_clippy_output", "error_format", "extra_exec_rustc_flags", "extra_rustc_flags")
+load("//rust:defs.bzl", "capture_clippy_output", "clippy_flags", "error_format", "extra_exec_rustc_flags", "extra_rustc_flags")
exports_files(["LICENSE"])
@@ -37,6 +37,14 @@
visibility = ["//visibility:public"],
)
+# This setting may be used to pass extra options to clippy from the command line.
+# It applies across all targets.
+clippy_flags(
+ name = "clippy_flags",
+ build_setting_default = [],
+ visibility = ["//visibility:public"],
+)
+
# This setting may be used to pass extra options to rustc from the command line
# in non-exec configuration.
# It applies across all targets whereas the rustc_flags option on targets applies only
diff --git a/rust/defs.bzl b/rust/defs.bzl
index dd1b445..8fef5af 100644
--- a/rust/defs.bzl
+++ b/rust/defs.bzl
@@ -21,6 +21,7 @@
load(
"//rust/private:clippy.bzl",
_capture_clippy_output = "capture_clippy_output",
+ _clippy_flags = "clippy_flags",
_rust_clippy = "rust_clippy",
_rust_clippy_aspect = "rust_clippy_aspect",
)
@@ -87,6 +88,9 @@
rust_doc_test = _rust_doc_test
# See @rules_rust//rust/private:rustdoc_test.bzl for a complete description.
+clippy_flags = _clippy_flags
+# See @rules_rust//rust/private:clippy.bzl for a complete description.
+
rust_clippy_aspect = _rust_clippy_aspect
# See @rules_rust//rust/private:clippy.bzl for a complete description.
diff --git a/rust/private/clippy.bzl b/rust/private/clippy.bzl
index d1464e9..29074f4 100644
--- a/rust/private/clippy.bzl
+++ b/rust/private/clippy.bzl
@@ -29,6 +29,22 @@
"find_toolchain",
)
+ClippyFlagsInfo = provider(
+ doc = "Pass each value as an additional flag to clippy invocations",
+ fields = {"clippy_flags": "List[string] Flags to pass to clippy"},
+)
+
+def _clippy_flags_impl(ctx):
+ return ClippyFlagsInfo(clippy_flags = ctx.build_setting_value)
+
+clippy_flags = rule(
+ doc = (
+ "Add custom clippy flags from the command line with `--@rules_rust//:clippy_flags`."
+ ),
+ implementation = _clippy_flags_impl,
+ build_setting = config.string_list(flag = True),
+)
+
def _get_clippy_ready_crate_info(target, aspect_ctx):
"""Check that a target is suitable for clippy and extract the `CrateInfo` provider from it.
@@ -106,12 +122,18 @@
if crate_info.is_test:
args.rustc_flags.add("--test")
+ clippy_flags = ctx.attr._clippy_flags[ClippyFlagsInfo].clippy_flags
+
# For remote execution purposes, the clippy_out file must be a sibling of crate_info.output
# or rustc may fail to create intermediate output files because the directory does not exist.
if ctx.attr._capture_output[CaptureClippyOutputInfo].capture_output:
clippy_out = ctx.actions.declare_file(ctx.label.name + ".clippy.out", sibling = crate_info.output)
args.process_wrapper_flags.add("--stderr-file", clippy_out.path)
+ if clippy_flags:
+ fail("""Combining @rules_rust//:clippy_flags with @rules_rust//:capture_clippy_output=true is currently not supported.
+See https://github.com/bazelbuild/rules_rust/pull/1264#discussion_r853241339 for more detail.""")
+
# If we are capturing the output, we want the build system to be able to keep going
# and consume the output. Some clippy lints are denials, so we treat them as warnings.
args.rustc_flags.add("-Wclippy::all")
@@ -121,10 +143,10 @@
clippy_out = ctx.actions.declare_file(ctx.label.name + ".clippy.ok", sibling = crate_info.output)
args.process_wrapper_flags.add("--touch-file", clippy_out.path)
- # Turn any warnings from clippy or rustc into an error, as otherwise
- # Bazel will consider the execution result of the aspect to be "success",
- # and Clippy won't be re-triggered unless the source file is modified.
- if "__bindgen" in ctx.rule.attr.tags:
+ if clippy_flags:
+ args.rustc_flags.extend(clippy_flags)
+
+ elif "__bindgen" in ctx.rule.attr.tags:
# bindgen-generated content is likely to trigger warnings, so
# only fail on clippy warnings
args.rustc_flags.add("-Dclippy::style")
@@ -132,7 +154,11 @@
args.rustc_flags.add("-Dclippy::complexity")
args.rustc_flags.add("-Dclippy::perf")
else:
- # fail on any warning
+ # The user didn't provide any clippy flags explicitly so we apply conservative defaults.
+
+ # Turn any warnings from clippy or rustc into an error, as otherwise
+ # Bazel will consider the execution result of the aspect to be "success",
+ # and Clippy won't be re-triggered unless the source file is modified.
args.rustc_flags.add("-Dwarnings")
# Upstream clippy requires one of these two filenames or it silently uses
@@ -177,6 +203,10 @@
),
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
+ "_clippy_flags": attr.label(
+ doc = "Arguments to pass to clippy",
+ default = Label("//:clippy_flags"),
+ ),
"_config": attr.label(
doc = "The `clippy.toml` file used for configuration",
allow_single_file = True,