use std::path::PathBuf;
use clap::{CommandFactory, FromArgMatches, Parser};
use rllvm::{
compiler_wrapper::{
CompilerKind, CompilerWrapper, CompilerWrapperBuilder, llvm::ClangWrapperBuilder,
},
config::try_rllvm_config,
error::Error,
};
use tracing::Level;
use tracing_subscriber::FmtSubscriber;
#[derive(Parser, Debug)]
#[command(
about = "Execute the wrapped clang compiler",
long_about = None,
author = "Shengtuo Hu <h1994st@gmail.com>",
version,
disable_help_flag = true,
disable_version_flag = true
)]
struct ClangWrapperArgs {
#[arg(long = "rllvm-compiler")]
compiler: Option<PathBuf>,
#[arg(
long = "rllvm-verbose",
num_args = 0..=1,
require_equals = true,
default_missing_value = "1",
default_value = "0"
)]
verbose: u8,
#[arg(long = "rllvm-help", action = clap::ArgAction::Help)]
rllvm_help: Option<bool>,
#[arg(long = "rllvm-version", action = clap::ArgAction::Version)]
rllvm_version: Option<bool>,
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
clang_args: Vec<String>,
}
pub fn rllvm_main(name: &str, compiler_kind: CompilerKind) -> Result<(), Error> {
let bin_name = match compiler_kind {
CompilerKind::Clang => "rllvm-cc",
CompilerKind::ClangXX => "rllvm-cxx",
};
let matches = ClangWrapperArgs::command().name(bin_name).get_matches();
let args = ClangWrapperArgs::from_arg_matches(&matches).unwrap_or_else(|err| err.exit());
let log_level = if args.verbose == 0 {
try_rllvm_config()?.log_level()
} else {
match args.verbose {
1 => Level::WARN,
2 => Level::INFO,
3 => Level::DEBUG,
_ => Level::TRACE,
}
};
FmtSubscriber::builder()
.with_max_level(log_level)
.with_writer(std::io::stderr)
.init();
let mut cc_builder = ClangWrapperBuilder::new()
.name(name)
.compiler_kind(compiler_kind);
if let Some(compiler) = args.compiler {
cc_builder = cc_builder.wrapped_compiler(compiler);
}
let mut cc = cc_builder.build()?;
if let Some(code) = cc.parse_args(&args.clang_args)?.run()? {
std::process::exit(code);
}
Ok(())
}
pub fn main() -> Result<(), Error> {
rllvm_main("rllvm", CompilerKind::Clang)
}