diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2025-06-12 11:42:47 +0200 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2025-06-13 12:19:02 +0200 |
commit | d46051807e37bd1e28a4c6ecd60d3a9f92103cc7 (patch) | |
tree | 9ddc088cd29e866f1d70384dd95066aba60820a3 | |
parent | 551a068668cd08ae5025aa05eacd6eb934ca9c4b (diff) | |
download | justbuild-d46051807e37bd1e28a4c6ecd60d3a9f92103cc7.tar.gz |
Add a lint target for clang-tidy
... using the already-committed configuration file and the
version of clang-tidy that was imported from the toolchain.
-rw-r--r-- | etc/defaults/lint/TARGETS.just | 3 | ||||
-rw-r--r-- | lint/TARGETS | 43 | ||||
-rwxr-xr-x | lint/run_clang_tidy.py | 53 | ||||
-rwxr-xr-x | lint/summary.py | 50 |
4 files changed, 149 insertions, 0 deletions
diff --git a/etc/defaults/lint/TARGETS.just b/etc/defaults/lint/TARGETS.just new file mode 100644 index 00000000..de52b000 --- /dev/null +++ b/etc/defaults/lint/TARGETS.just @@ -0,0 +1,3 @@ +{ "defaults": + {"type": "defaults", "base": [["CC", "defaults"], ["shell", "defaults"]]} +} diff --git a/lint/TARGETS b/lint/TARGETS new file mode 100644 index 00000000..a5456c85 --- /dev/null +++ b/lint/TARGETS @@ -0,0 +1,43 @@ +{ "": + { "type": "install" + , "tainted": ["lint", "test"] + , "dirs": [["LINT: clang-tidy", "clang-tidy"]] + } +, "clang toolchain": + { "type": "configure" + , "arguments_config": ["TOOLCHAIN_CONFIG"] + , "target": ["@", "clang", "", "toolchain"] + , "config": + { "type": "`" + , "$1": + { "TOOLCHAIN_CONFIG": + { "type": "," + , "$1": + { "type": "map_union" + , "$1": + [ { "type": "var" + , "name": "TOOLCHAIN_CONFIG" + , "default": {"type": "empty_map"} + } + , {"type": "'", "$1": {"INCLUDE_LINTER": true}} + ] + } + } + } + } + } +, "clang": {"type": "install", "dirs": [["clang toolchain", "toolchain"]]} +, "LINT: clang-tidy": + { "type": ["@", "rules", "lint", "targets"] + , "tainted": ["test"] + , "name": ["clang-tidy"] + , "linter": ["run_clang_tidy.py"] + , "summarizer": ["summary.py"] + , "config": [["@", "src", "", ".clang-tidy"], "clang"] + , "targets": + [ ["@", "src", "src/buildtool/main", "just"] + , ["@", "src", "src/other_tools/just_mr", "just-mr"] + , ["@", "tests", "", "ALL"] + ] + } +} diff --git a/lint/run_clang_tidy.py b/lint/run_clang_tidy.py new file mode 100755 index 00000000..3fb8a595 --- /dev/null +++ b/lint/run_clang_tidy.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# Copyright 2025 Huawei Cloud Computing Technology Co., Ltd. +# +# 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. + +import json +import os +import shutil +import subprocess +import sys + + +def dump_meta(src, cmd): + OUT = os.environ.get("OUT") + if OUT: + with open(os.path.join(OUT, "config.json"), "w") as f: + json.dump({"src": src, "cmd": cmd}, f) + + +def run_lint(src, cmd): + dump_meta(src, cmd) + config = os.environ.get("CONFIG") + shutil.copyfile(os.path.join(config, ".clang-tidy"), ".clang-tidy") + extra = ["-Wno-unused-command-line-argument"] + if src.endswith(".tpp"): + extra += ["-x", "c++"] + db = [{ + "directory": os.getcwd(), + "arguments": cmd[:1] + extra + cmd[1:], + "file": src + }] + with open("compile_commands.json", "w") as f: + json.dump(db, f) + new_cmd = [ + os.path.join(config, "toolchain", "bin", "clang-tidy"), + src, + ] + print("Running cmd %r with db %r" % (new_cmd, db), file=sys.stderr) + return subprocess.run(new_cmd).returncode + + +if __name__ == "__main__": + sys.exit(run_lint(sys.argv[1], sys.argv[2:])) diff --git a/lint/summary.py b/lint/summary.py new file mode 100755 index 00000000..ca7445db --- /dev/null +++ b/lint/summary.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# Copyright 2025 Huawei Cloud Computing Technology Co., Ltd. +# +# 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. + +import json +import os +import sys + +FAILED = {} + +for lint in sorted(os.listdir()): + if os.path.isdir(lint): + with open(os.path.join(lint, "result")) as f: + result = f.read().strip() + if result != "PASS": + record = {} + with open(os.path.join(lint, "out/config.json")) as f: + record["config"] = json.load(f) + with open(os.path.join(lint, "stdout")) as f: + log = f.read() + with open(os.path.join(lint, "stderr")) as f: + log += f.read() + record["log"] = log + FAILED[lint] = record + +with open(os.path.join(os.environ.get("OUT"), "failures.json"), "w") as f: + json.dump(FAILED, f) + +failures = list(FAILED.keys()) + +for f in failures: + src = FAILED[f]["config"]["src"] + log = FAILED[f]["log"] + + print("%s %s" % (f, src)) + print("".join([" " + line + "\n" for line in log.splitlines()])) + +if failures: + sys.exit(1) |