Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cli: add show-env subcommand #115

Merged
merged 5 commits into from
Jan 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,17 @@ cargo llvm-cov --no-report --features b
cargo llvm-cov --no-run --lcov
```

In combination with the `show-env` subcommand, coverage can also be produced from arbitrary binaries:

```sh
cargo llvm-cov clean --workspace # remove artifacts that may affect the coverage results
source <(cargo llvm-cov show-env --export-prefix)
cargo build # build rust binaries
# commands using binaries in target/debug/*, including `cargo test`
# ...
cargo llvm-cov --no-run --lcov # generate report without tests
```

To exclude specific file patterns from the report, use the `--ignore-filename-regex` option.

```sh
Expand Down
15 changes: 15 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ pub(crate) enum Subcommand {
)]
Run(Box<RunOptions>),

/// Output the environment set by cargo-llvm-cov to build Rust projects.
#[clap(
bin_name = "cargo llvm-cov show-env",
max_term_width = MAX_TERM_WIDTH,
setting = AppSettings::DeriveDisplayOrder,
)]
ShowEnv(ShowEnvOptions),

/// Remove artifacts that cargo-llvm-cov has generated in the past
#[clap(
bin_name = "cargo llvm-cov clean",
Expand Down Expand Up @@ -430,6 +438,13 @@ impl RunOptions {
}
}

#[derive(Debug, Parser)]
pub(crate) struct ShowEnvOptions {
/// Prepend "export " to each line, so that the output is suitable to be sourced by bash.
#[clap(long)]
pub(crate) export_prefix: bool,
}

#[derive(Debug, Parser)]
pub(crate) struct CleanOptions {
/// Remove artifacts that may affect the coverage results of packages in the workspace.
Expand Down
71 changes: 53 additions & 18 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use std::{
use anyhow::{Context as _, Result};
use camino::{Utf8Path, Utf8PathBuf};
use clap::Parser;
use cli::RunOptions;
use cli::{RunOptions, ShowEnvOptions};
use regex::Regex;
use walkdir::WalkDir;

Expand All @@ -57,6 +57,7 @@ fn main() {

fn try_main() -> Result<()> {
let Opts::LlvmCov(mut args) = Opts::parse();
let cx = &context_from_args(&mut args)?;

match args.subcommand {
Some(Subcommand::Demangle) => {
Expand Down Expand Up @@ -92,6 +93,10 @@ fn try_main() -> Result<()> {
}
}

Some(Subcommand::ShowEnv(options)) => {
set_env(cx, &mut ShowEnvWriter { target: std::io::stdout(), options });
}

None => {
term::set_quiet(args.quiet);
if args.doctests {
Expand All @@ -102,18 +107,6 @@ fn try_main() -> Result<()> {
warn!("--doc option is unstable");
}

let cx = &Context::new(
args.build(),
args.manifest(),
args.cov(),
args.workspace,
&args.exclude,
&args.package,
args.quiet,
args.doctests,
args.no_run,
)?;

clean::clean_partial(cx)?;
create_dirs(cx)?;
match (args.no_run, cx.cov.no_report) {
Expand All @@ -134,6 +127,20 @@ fn try_main() -> Result<()> {
Ok(())
}

fn context_from_args(args: &mut Args) -> Result<Context> {
Context::new(
args.build(),
args.manifest(),
args.cov(),
args.workspace,
&args.exclude,
&args.package,
args.quiet,
args.doctests,
args.no_run,
)
}

fn create_dirs(cx: &Context) -> Result<()> {
fs::create_dir_all(&cx.ws.target_dir)?;

Expand All @@ -153,7 +160,35 @@ fn create_dirs(cx: &Context) -> Result<()> {
Ok(())
}

fn set_env(cx: &Context, cmd: &mut ProcessBuilder) {
trait EnvTarget {
fn set(&mut self, key: &str, value: &str);
}

impl EnvTarget for ProcessBuilder {
fn set(&mut self, key: &str, value: &str) {
self.env(key, value);
}
}

struct ShowEnvWriter<W: std::io::Write> {
target: W,
options: ShowEnvOptions,
}

impl<W: std::io::Write> EnvTarget for ShowEnvWriter<W> {
fn set(&mut self, key: &str, value: &str) {
writeln!(
self.target,
r#"{prefix}{key}="{value}""#,
prefix = if self.options.export_prefix { "export " } else { "" },
key = key,
value = value,
)
.expect("failed to write to stdout");
}
}

fn set_env(cx: &Context, target: &mut impl EnvTarget) {
let llvm_profile_file = cx.ws.target_dir.join(format!("{}-%m.profraw", cx.ws.package_name));

let rustflags = &mut cx.ws.config.rustflags().unwrap_or_default();
Expand Down Expand Up @@ -192,12 +227,12 @@ fn set_env(cx: &Context, cmd: &mut ProcessBuilder) {
}
}

cmd.env("RUSTFLAGS", &rustflags);
target.set("RUSTFLAGS", rustflags);
if let Some(rustdocflags) = rustdocflags {
cmd.env("RUSTDOCFLAGS", &rustdocflags);
target.set("RUSTDOCFLAGS", rustdocflags);
}
cmd.env("LLVM_PROFILE_FILE", &*llvm_profile_file);
cmd.env("CARGO_INCREMENTAL", "0");
target.set("LLVM_PROFILE_FILE", llvm_profile_file.as_str());
target.set("CARGO_INCREMENTAL", "0");
}

fn run_test(cx: &Context, args: &Args) -> Result<()> {
Expand Down
2 changes: 2 additions & 0 deletions tests/long-help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ OPTIONS:
SUBCOMMANDS:
run
Run a binary or example and generate coverage report
show-env
Output the environment set by cargo-llvm-cov to build Rust projects
clean
Remove artifacts that cargo-llvm-cov has generated in the past
help
Expand Down
7 changes: 4 additions & 3 deletions tests/short-help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ OPTIONS:
Print version information

SUBCOMMANDS:
run Run a binary or example and generate coverage report
clean Remove artifacts that cargo-llvm-cov has generated in the past
help Print this message or the help of the given subcommand(s)
run Run a binary or example and generate coverage report
show-env Output the environment set by cargo-llvm-cov to build Rust projects
clean Remove artifacts that cargo-llvm-cov has generated in the past
help Print this message or the help of the given subcommand(s)