Skip to content
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
2 changes: 2 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build:clang-format-check --aspects //bazel/clang_format:clang_format_check.bzl%clang_format_check_aspect
build:clang-format-check --output_groups=report
27 changes: 27 additions & 0 deletions clang_format/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
load(":choose_clang_format.bzl", "choose_clang_format")

choose_clang_format(
name = "clang_format_bin",
visibility = ["//visibility:public"],
)

filegroup(
name = "_clang_format_bin",
srcs = [":clang_format_bin"],
)

sh_binary(
name = "clang_format",
srcs = [
"run_clang_format.sh",
],
args = [
"format_all",
"$(location :_clang_format_bin)",
],
data = [
":_clang_format_bin",
"//:clang_format_config",
],
visibility = ["//visibility:public"],
)
26 changes: 26 additions & 0 deletions clang_format/choose_clang_format.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
def _choose_clang_format(ctx):
out = ctx.actions.declare_file("clang_format_bin.sh")

ctx.actions.run_shell(
outputs = [out],
command = """
if command -v clang-format-14 &> /dev/null
then
echo clang-format-14 \\"\\$@\\" > {0}
elif command -v clang-format &> /dev/null
then
echo clang-format \\"\\$@\\" > {0}
else
err_msg='clang-format-14 / clang-format: command not found'
echo $err_msg
echo "echo "$err_msg">&2" >> {0}
echo "exit 1" >> {0}
fi
""".format(out.path),
)

return [DefaultInfo(files = depset([out]))]

choose_clang_format = rule(
implementation = _choose_clang_format,
)
60 changes: 60 additions & 0 deletions clang_format/clang_format_check.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
def _check_format(ctx, exe, config, infile, clang_format_bin):
output = ctx.actions.declare_file(infile.path + ".clang-format.txt")

args = ctx.actions.args()

args.add("check_file")
args.add(clang_format_bin.path)
args.add(infile.path)
args.add(output.path)

ctx.actions.run(
inputs = [clang_format_bin, infile, config],
outputs = [output],
executable = exe,
arguments = [args],
mnemonic = "ClangFormat",
progress_message = "Check clang-format on {}".format(infile.short_path),
)
return output

def _extract_files(ctx):
files = []
if hasattr(ctx.rule.attr, "srcs"):
for src in ctx.rule.attr.srcs:
files += [src for src in src.files.to_list() if src.is_source]

if hasattr(ctx.rule.attr, "hdrs"):
for hdr in ctx.rule.attr.hdrs:
files += [hdr for hdr in hdr.files.to_list() if hdr.is_source]

return files

def _clang_format_check_aspect_impl(target, ctx):
# if not a C/C++ target, we are not interested
if not CcInfo in target:
return []

exe = ctx.attr._clang_format.files_to_run
config = ctx.attr._clang_format_config.files.to_list()[0]
clang_format_bin = ctx.attr._clang_format_bin.files.to_list()[0]
files = _extract_files(ctx)

outputs = []
for file in files:
if file.basename.endswith((".c", ".h", ".cpp", ".cc", ".hpp")):
outputs.append(_check_format(ctx, exe, config, file, clang_format_bin))

return [
OutputGroupInfo(report = depset(direct = outputs)),
]

clang_format_check_aspect = aspect(
implementation = _clang_format_check_aspect_impl,
fragments = ["cpp"],
attrs = {
"_clang_format": attr.label(default = Label("//bazel/clang_format:clang_format")),
"_clang_format_config": attr.label(default = Label("//:clang_format_config")),
"_clang_format_bin": attr.label(default = Label("//bazel/clang_format:clang_format_bin")),
},
)
27 changes: 27 additions & 0 deletions clang_format/run_clang_format.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#! /bin/bash
# Usages:
# run_clang_format format_all <CLANG_FORMAT_BIN>
# run_clang_format check_file <CLANG_FORMAT_BIN> <INPUT> <OUTPUT>
set -ue

format_all() {
cd $BUILD_WORKSPACE_DIRECTORY
git ls-files '*.[ch]' '*.cpp' '*.cc' '*.hpp' | xargs $CLANG_FORMAT_BIN -i
}

check_file() {
INPUT=$1
OUTPUT=$2

$CLANG_FORMAT_BIN $INPUT --dry-run -Werror > $OUTPUT
}

ARG=$1
CLANG_FORMAT_BIN=$(realpath $2)
shift 2

if [ "$ARG" == "format_all" ]; then
format_all
elif [ "$ARG" == "check_file" ]; then
check_file "$@"
fi