summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author24bit-xjkp <[email protected]>2025-09-21 17:44:10 +0800
committer24bit-xjkp <[email protected]>2025-09-21 17:44:10 +0800
commit586e243c43e58399042c863c64ccb7a89a622cbd (patch)
treeca6ac46aad3618c37af96b26eb10bd10a909b510
parentf9bc475a5ba47b954d23d16c71a4b6bbd4cb6ca4 (diff)
feat(clang-tidy): Improve clang-tidy support
1. Improve "compdb" option, supporting the directory containing the json db file. This will shorten the command line since "compile_commands.json" is a long name. 2. Use `opt.compdb` instead of `option.get("compdb")` because `option.get` doesn't work and returns a nil in this scope. I don't know the reason. 3. Motivated by the python script `run-clang-tidy` in llvm project, each clang-tidy subprocess new only processes a source file and use multi-process to implement parallel analysis based on `async.runjobs` 4. Use `os.execv` instead of `os.vrunv` since diagnoses are always wanted in static analysis. 5. Add a timer for check action.
-rw-r--r--xmake/modules/private/check/checkers/clang/tidy.lua65
1 files changed, 26 insertions, 39 deletions
diff --git a/xmake/modules/private/check/checkers/clang/tidy.lua b/xmake/modules/private/check/checkers/clang/tidy.lua
index e9fb9e60b..4a185e705 100644
--- a/xmake/modules/private/check/checkers/clang/tidy.lua
+++ b/xmake/modules/private/check/checkers/clang/tidy.lua
@@ -33,6 +33,7 @@ import("private.action.require.impl.install_packages")
-- the clang.tidy options
local options = {
{"l", "list", "k", nil, "Show the clang-tidy checks list."},
+ {"v", "verbose", "k", nil, "Show verbose output."},
{"j", "jobs", "kv", tostring(os.default_njob()),
"Set the number of parallel check jobs."},
{"q", "quiet", "k", nil, "Run clang-tidy in quiet mode."},
@@ -40,8 +41,8 @@ local options = {
{nil, "fix_errors", "k", nil, "Apply suggested errors fixes."},
{nil, "fix_notes", "k", nil, "Apply suggested notes fixes."},
{nil, "create", "k", nil, "Create a .clang-tidy file."},
- {nil, "configfile", "kv", nil, "Specify the path of .clang-tidy or custom config file"},
- {nil, "compdb", "kv", nil, "Specify the path of the compile_commands.json file"},
+ {nil, "configfile", "kv", nil, "Specify the path of .clang-tidy or custom config file."},
+ {nil, "compdb", "kv", nil, "Specify the path of the compile_commands.json file or the directory containing the file."},
{nil, "checks", "kv", nil, "Set the given checks.",
"e.g.",
" - xmake check clang.tidy --checks=\"*\""},
@@ -83,19 +84,6 @@ function _add_target_files(sourcefiles, target)
end
end
-function _run_clang_tidy(clang_tidy, argv, opt)
- -- https://github.com/llvm/llvm-project/pull/120547
- if clang_tidy.version and semver.compare(clang_tidy.version, "19.1.6") > 0 and #argv > 10 then
- local argsfile = os.tmpfile() .. ".args.txt"
- io.writefile(argsfile, os.args(argv))
- argv = {"@" .. argsfile}
- os.vrunv(clang_tidy.program, argv, opt)
- os.rm(argsfile)
- else
- os.vrunv(clang_tidy.program, argv, opt)
- end
-end
-
-- check sourcefiles
function _check_sourcefiles(clang_tidy, sourcefiles, opt)
opt = opt or {}
@@ -124,30 +112,24 @@ function _check_sourcefiles(clang_tidy, sourcefiles, opt)
table.insert(argv, "--quiet")
end
- -- split sourcefiles
- local arguments_maxn = 32
- local sourcefiles_argv = {}
local sourcefiles_jobs = {}
for _, sourcefile in ipairs(sourcefiles) do
if not path.is_absolute(sourcefile) then
sourcefile = path.absolute(sourcefile, projectdir)
end
- table.insert(sourcefiles_argv, sourcefile)
- if #sourcefiles_argv >= arguments_maxn then
- table.insert(sourcefiles_jobs, sourcefiles_argv)
- sourcefiles_argv = {}
- end
- end
- if #sourcefiles_argv > 0 then
- table.insert(sourcefiles_jobs, sourcefiles_argv)
+ local source_files_argv = table.join(argv, {sourcefile})
+ table.insert(sourcefiles_jobs, {sourcefile, source_files_argv})
end
+ local analyze_time = os.mclock()
-- run clang-tidy
runjobs("checker.tidy", function (index, total, opt)
- local tidy_argv = sourcefiles_jobs[index]
- progress.show(index * 100 / total, "clang-tidy.analyzing %s .. %d", tidy_argv[1], #tidy_argv)
- _run_clang_tidy(clang_tidy, tidy_argv, {curdir = projectdir})
+ local sourcefile, tidy_argv = table.unpack(sourcefiles_jobs[index])
+ progress.show(index * 100 / total, "clang-tidy.analyzing %s", sourcefile)
+ os.execv(clang_tidy.program, tidy_argv, {curdir = projectdir})
end, {total = #sourcefiles_jobs, comax = opt.jobs or os.default_njob()})
+ analyze_time = os.mclock() - analyze_time
+ progress.show(100, "${color.success}clang-tidy.analyzed %d files, spent %.3fs", #sourcefiles_jobs, analyze_time / 1000)
end
-- do check
@@ -155,8 +137,8 @@ function _check(clang_tidy, opt)
opt = opt or {}
-- generate compile_commands.json first
- local filepath = option.get("compdb")
- if not filepath then
+ local db_path = opt.compdb
+ if not db_path then
-- @see https://github.com/xmake-io/xmake/issues/5583#issuecomment-2337696628
local outputdir
local extraconf = project.extraconf("target.rules", "plugin.compile_commands.autoupdate")
@@ -164,19 +146,25 @@ function _check(clang_tidy, opt)
outputdir = extraconf.outputdir
end
if outputdir then
- filepath = path.join(outputdir, "compile_commands.json")
+ db_path = path.join(outputdir, "compile_commands.json")
end
end
- if not filepath then
- filepath = "compile_commands.json"
+ if not db_path then
+ db_path = "compile_commands.json"
+ end
+ if os.isdir(db_path) then
+ local db_file_path = path.join(db_path, "compile_commands.json")
+ if os.isfile(db_file_path) then
+ db_path = db_file_path
+ end
end
- if not os.isfile(filepath) then
+ if not os.isfile(db_path) then
local outputdir = os.tmpfile() .. ".dir"
- local filename = path.filename(filepath)
- filepath = outputdir and path.join(outputdir, filename) or filename
+ local filename = path.filename(db_path)
+ db_path = outputdir and path.join(outputdir, filename) or filename
task.run("project", {quiet = true, kind = "compile_commands", lsp = "clangd", outputdir = outputdir})
end
- opt.compdbfile = path.absolute(filepath)
+ opt.compdbfile = path.absolute(db_path)
-- get sourcefiles
local sourcefiles = {}
@@ -243,4 +231,3 @@ function main(argv)
end
os.setenvs(oldenvs)
end
-