use anyhow::anyhow;
use anyhow::Result;
use std::path::PathBuf;
use std::process::Command;
pub mod dir;
pub mod llvm;
pub mod report;
pub use minicov::capture_coverage;
pub fn run_command(command: &str, args: &[&str]) -> Result<String> {
let output = Command::new(command).args(args).output()?;
if !output.status.success() {
return Err(anyhow!(
"Command {} failed with status code {}: {}",
command,
output.status.code().unwrap_or(-1),
String::from_utf8(output.stderr)?
));
}
String::from_utf8(output.stdout).map_err(|_| anyhow!("Failed to read command output"))
}
pub fn setup(wasmcov_dir: Option<&PathBuf>) -> Result<String> {
let llvm::VerifyToolingResult {
is_nightly,
llvm_major_version: _,
} = llvm::verify_tooling().expect("Failed to verify tooling");
let mut env_string = dir::set_wasmcov_dir(wasmcov_dir)?;
if !is_nightly {
env_string.push_str("; export RUSTC_BOOTSTRAP=1");
std::env::set_var("RUSTC_BOOTSTRAP", "1");
}
let mut rustflags = String::from(
"-Cinstrument-coverage -Zno-profiler-runtime -Zlocation-detail=none --emit=llvm-ir",
);
rustflags.push_str(" -Clto=no");
std::env::set_var("RUSTFLAGS", rustflags);
env_string.push_str(&format!(
"; export RUSTFLAGS=\"{}\"",
std::env::var("RUSTFLAGS").unwrap()
));
Ok(env_string)
}
pub fn finalize() {
dir::extract_compiled_artefacts().expect("Failed to extract compiled artefacts");
let (_, llvm_major_version) =
llvm::check_rustc_version().expect("Failed to check rustc version");
report::modify_ll_files().expect("Failed to modify LL files");
report::generate_object_file(&llvm_major_version).expect("Failed to generate object file");
report::merge_profraw_to_profdata(&llvm_major_version)
.expect("Failed to merge profraw to profdata");
let output_dir = dir::get_output_dir().expect("Failed to get output directory");
let object_files = glob::glob(output_dir.join("*.o").to_str().unwrap())
.expect("Failed to get object files")
.collect::<Vec<_>>();
if object_files.len() > 1 {
panic!("More than one object file found in the output directory. We don't know which one to use.");
}
if object_files.is_empty() {
panic!("No object file found in the output directory.");
}
let object_file: &std::path::PathBuf = object_files[0].as_ref().unwrap();
report::generate_coverage_report(object_file, &llvm_major_version)
.expect("Failed to generate report");
}
pub fn post_build() -> Vec<PathBuf> {
let target_dir = dir::get_target_dir().expect("Failed to get target directory");
let wasm_files = glob::glob(target_dir.join("**/deps/*.wasm").to_str().unwrap())
.expect("Failed to get wasm files")
.collect::<Vec<_>>();
println!("Found {} wasm compiles", wasm_files.len());
let wasm_files = wasm_files
.into_iter()
.map(|x| x.unwrap())
.collect::<Vec<PathBuf>>();
for wasm_file in &wasm_files {
println!("{}", wasm_file.display());
}
wasm_files
}
#[cfg(feature = "near")]
pub mod near;