use crate::cmake;
use crate::preset;
use crate::runner;
use crate::utils;
use anyhow;
use clap;
use log::{debug, warn};
#[derive(clap::Parser, Debug)]
pub struct AnalyzeArgs {
#[command(subcommand)]
pub tool: Option<Tool>,
#[arg(short = 'j', long, default_value_t = utils::num_cpus())]
pub jobs: u32,
#[arg(short = 'k', long)]
pub keep_going: bool,
#[arg(short = 'D', value_name = "VAR=VALUE")]
pub defines: Vec<String>,
#[arg(short, long)]
pub reconfigure: bool,
#[arg(short, long)]
pub fresh: bool,
}
#[derive(clap::Subcommand, Debug)]
pub enum Tool {
ClangTidy,
ClangCheck,
Cppcheck,
ClangFormat,
CmakeFormat,
}
pub fn run(ctx: &runner::Context, args: AnalyzeArgs) -> anyhow::Result<()> {
match args.tool {
Some(Tool::ClangTidy) => run_target(ctx, args, "analyze-clang-tidy"),
Some(Tool::ClangCheck) => run_target(ctx, args, "analyze-clang-check"),
Some(Tool::Cppcheck) => run_target(ctx, args, "analyze-cppcheck"),
Some(Tool::ClangFormat) => run_target(ctx, args, "analyze-clang-format"),
Some(Tool::CmakeFormat) => run_target(ctx, args, "analyze-cmake-format"),
None => run_target(ctx, args, "analyze"),
}
}
pub fn run_target(ctx: &runner::Context, args: AnalyzeArgs, target: &str) -> anyhow::Result<()> {
preset::ensure_project_root(ctx)?;
let preset = preset::resolve(ctx, Some("analyze"))?;
debug!("Begin");
if args.reconfigure || args.fresh {
debug!("Begin reconfigure");
cmake::reconf(ctx, &preset, args.fresh, &args.defines)?;
}
if !ctx.dry_run {
cmake::ensure_libra_feature_enabled(ctx, &preset, "LIBRA_ANALYSIS")?;
match cmake::target_status(target, &preset, ctx)? {
cmake::TargetStatus::Unavailable(reason) => {
anyhow::bail!(
"Analysis target {} does not exist! Reason: {}",
&target,
reason
);
}
cmake::TargetStatus::Available => {}
}
}
let mut cmd = cmake::base_build(&preset);
cmd.args(["--target", target, "--parallel", &args.jobs.to_string()]);
if args.keep_going {
let generator = cmake::generator(&preset).unwrap_or_else(|e| {
warn!("Failed to detect CMake generator: {e}, defaulting to Unix Makefiles");
"Unix Makefiles".to_string()
});
if generator == "Ninja" {
cmd.args(["--", "-k0"]);
} else if generator == "Unix Makefiles" {
cmd.args(["--", "--keep-going"]);
} else {
anyhow::bail!("--keep-going only supported with {{Ninja, Unix Makefiles}} generators");
}
}
ctx.run(&mut cmd)?;
Ok(())
}