-
Notifications
You must be signed in to change notification settings - Fork 441
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
Executable target for rustfmt #388
Comments
It should be somewhere under the toolchain repository ( |
Here are some simple cross-platform rules you can use. Put the following in a .bzl file: def _rustfmt_impl(ctx):
toolchain = ctx.toolchains["@io_bazel_rules_rust//rust:toolchain"]
script_name = ctx.label.name + "_script"
rustfmt = toolchain.rustfmt.path
if ctx.attr.is_windows:
script_name += ".bat"
rustfmt = "@" + rustfmt.replace("/", "\\")
script = ctx.actions.declare_file(script_name)
args = [f.path for f in ctx.files.srcs]
if ctx.attr.fix:
mode = "--emit files"
else:
mode = "--check"
ctx.actions.write(
output = script,
content = "{rustfmt} {mode} --edition {edition} {files}".format(
rustfmt = rustfmt,
edition = toolchain.default_edition,
files = " ".join(args),
mode = mode,
),
)
runfiles = ctx.runfiles(files = ctx.files.srcs + [toolchain.rustfmt])
return [DefaultInfo(runfiles = runfiles, executable = script)]
_ATTRS = {
"srcs": attr.label_list(allow_files = True),
"is_windows": attr.bool(mandatory = True),
"fix": attr.bool(mandatory = True),
}
_rustfmt_test = rule(
implementation = _rustfmt_impl,
test = True,
toolchains = [
"@io_bazel_rules_rust//rust:toolchain",
],
attrs = _ATTRS,
)
_rustfmt_fix = rule(
implementation = _rustfmt_impl,
executable = True,
toolchains = [
"@io_bazel_rules_rust//rust:toolchain",
],
attrs = _ATTRS,
)
def rustfmt_test(name, srcs, **kwargs):
_rustfmt_test(
name = name,
srcs = srcs,
testonly = True,
fix = False,
is_windows = select({
"@bazel_tools//src/conditions:host_windows": True,
"//conditions:default": False,
}),
**kwargs
)
def rustfmt_fix(name, srcs, **kwargs):
# don't match //package/...
tags = kwargs.get("tags", [])
tags.append("manual")
_rustfmt_fix(
name = name,
srcs = srcs,
tags = tags,
fix = True,
is_windows = select({
"@bazel_tools//src/conditions:host_windows": True,
"//conditions:default": False,
}),
**kwargs
) Then you can add the following to your BUILD: load(":defs.bzl", "rustfmt_fix", "rustfmt_test")
rustfmt_test(
name = "format",
srcs = glob([
"src/**/*.rs",
]),
)
rustfmt_fix(
name = "format_fix",
srcs = glob([
"src/**/*.rs",
]),
) To check if your files are formatted:
To fix any files that are formatted incorrectly:
@mfarrugi If there is interest in integrating this into this repo, please let me know. It probably won't work if there are thousands of files matched by the glob. |
@dae I think that'd be useful to incorporate, but I imagine it probably working as an aspect, similar to the clippy integration. That way you could run: bazel build --aspects=@io_bazel_rules_rust//rust:rust.bzl%rust_rustfmt_aspect //... |
Otherwise I see it being difficult to manage the editions, and the number of files. |
Another reason for this: my_rule( # genrule, cargo_build_script, etc.
...,
data = ["@io_bazel_rules_rust//:rustfmt"],
) Without any data dependency, it appears to be implicitly nonhermetic—it |
You can already do this in the platform-specific toolchains, we make executable targets like rules_rust/rust/repositories.bzl Lines 248 to 254 in f33e3b3
|
Yep! I saw that, indeed. But directly depending on a platform-specific |
We could maybe add to alias(
name = "rustfmt",
actual = select({
"@io_bazel_rules_rust//rust/platform:osx": "@rust_darwin_x86_64//:rustfmt",
"@io_bazel_rules_rust//rust/platform:linux": "@rust_linux_x86_64//:rustfmt",
...
}),
) so that there's a single target you can point at which acts differently depending on your platform? |
However using It seems worth noting as well that the protoc execpath is a full path, not just a partial relative path, e.g |
Interesting - can you try either
Yeah, this is expected - build scripts run in $CARGO_MANIFEST_DIR instead of the exec root, to maximise compatibility with cargo, so we need to use absolute paths because execpaths would be relative to the wrong directory. The alternative is to run build scripts in the exec root, but then most build scripts which try to read files will be broken - both options are bad :) |
Thanks -- |
I love the idea of a |
This is a dupe of #87. Closing in favor of the one that has the most history. |
We would like to run
rustfmt
directly through bazel to check formatting from our CI system. For example:bazel run @io_bazel_rules_rust//:rustfmt --
. Is this somehow possible?The text was updated successfully, but these errors were encountered: