From 2521ddbc6f7726f52f951b628c85ef65accba9e1 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 6 Feb 2022 19:50:58 +0900 Subject: [PATCH] Update to stabilized `-C instrument-coverage` --- CHANGELOG.md | 6 ++++++ Cargo.toml | 2 +- README.md | 16 ++++++---------- src/cargo.rs | 42 +++++++++++++++++++++++++++++++++++++----- src/clean.rs | 2 +- src/cli.rs | 2 +- src/config.rs | 5 +++-- src/context.rs | 4 ++-- src/main.rs | 41 +++++++++++++++++++++++++---------------- tests/long-help.txt | 2 +- tests/short-help.txt | 2 +- 11 files changed, 84 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eff9525..3179a540 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com ## [Unreleased] +- Update to stabilized `-C instrument-coverage`. ([#130](https://github.com/taiki-e/cargo-llvm-cov/pull/130)) + + Support for `-Z instrument-coverage` in the old nightly will also be kept for compatibility. + + **Compatibility Note:** In 0.1, if `-C instrument-coverage` or `-Z instrument-coverage` is not available in the default toolchain, running `cargo llvm-cov` will find and use nightly. This behavior will be changed in 0.2 to always select the default toolchain. If you are likely to be affected by the change in 0.2, cargo-llvm-cov will emit a warning. + ## [0.1.16] - 2022-01-21 - Alleviate an issue where "File name or extension is too long" error occurs in Windows. ([#126](https://github.com/taiki-e/cargo-llvm-cov/pull/126), thanks @aganders3) diff --git a/Cargo.toml b/Cargo.toml index 0b36add2..b74733e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ keywords = ["cargo", "coverage", "subcommand", "testing"] categories = ["command-line-utilities", "development-tools", "development-tools::cargo-plugins", "development-tools::testing"] exclude = ["/.*", "/tools"] description = """ -Cargo subcommand to easily use LLVM source-based code coverage (-Z instrument-coverage). +Cargo subcommand to easily use LLVM source-based code coverage (-C instrument-coverage). """ [package.metadata.docs.rs] diff --git a/README.md b/README.md index 1262332a..70fef34a 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,12 @@ Cargo subcommand to easily use LLVM source-based code coverage. -This is a wrapper around rustc [`-Z instrument-coverage`][instrument-coverage] and provides: +This is a wrapper around rustc [`-C instrument-coverage`][instrument-coverage] and provides: - Generate very precise coverage data. (line coverage and region coverage) - Support both `cargo test` and `cargo run`. - Support for proc-macro, including coverage of UI tests. -- Support for doc tests. (this is currently optional, see [#2] for more) +- Support for doc tests. (this is currently optional and requires nightly, see [#2] for more) - Command-line interface compatible with cargo. **Table of Contents:** @@ -34,7 +34,7 @@ This is a wrapper around rustc [`-Z instrument-coverage`][instrument-coverage] a ```console $ cargo llvm-cov --help cargo-llvm-cov -Cargo subcommand to easily use LLVM source-based code coverage (-Z instrument-coverage). +Cargo subcommand to easily use LLVM source-based code coverage (-C instrument-coverage). Use -h for short descriptions and --help for more details. @@ -382,11 +382,7 @@ rustup component add llvm-tools-preview --toolchain nightly cargo install cargo-llvm-cov ``` -cargo-llvm-cov relies on unstable compiler flags so it requires a nightly -toolchain to be installed, though does not require nightly to be the default -toolchain or the one with which cargo-llvm-cov itself is executed. If the -default toolchain is one other than nightly, running `cargo llvm-cov` will find -and use nightly. +If `-C instrument-coverage` or `-Z instrument-coverage` is not available in the default toolchain, running `cargo llvm-cov` will find and use nightly. This behavior will be changed in 0.2 to always select the default toolchain. Currently, installing cargo-llvm-cov requires rustc 1.54+. @@ -409,7 +405,7 @@ This makes the installation faster and may avoid the impact of [problems caused ### Via Homebrew -You can install cargo-llvm-cov using [Homebrew tap on macOS and Linux](https://github.com/taiki-e/homebrew-tap/blob/main/Formula/cargo-llvm-cov.rb): +You can install cargo-llvm-cov using [Homebrew tap on macOS and Linux](https://github.com/taiki-e/homebrew-tap/blob/HEAD/Formula/cargo-llvm-cov.rb): ```sh brew install taiki-e/tap/cargo-llvm-cov @@ -446,7 +442,7 @@ See also [the code-coverage-related issues reported in rust-lang/rust](https://g [cargo-hack]: https://github.com/taiki-e/cargo-hack [cargo-minimal-versions]: https://github.com/taiki-e/cargo-minimal-versions [codecov]: https://codecov.io -[instrument-coverage]: https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/instrument-coverage.html +[instrument-coverage]: https://doc.rust-lang.org/nightly/rustc/instrument-coverage.html [rust-lang/rust#79417]: https://github.com/rust-lang/rust/issues/79417 [rust-lang/rust#79649]: https://github.com/rust-lang/rust/issues/79649 [rust-lang/rust#84605]: https://github.com/rust-lang/rust/issues/84605 diff --git a/src/cargo.rs b/src/cargo.rs index 4d2625f0..6ad379b0 100644 --- a/src/cargo.rs +++ b/src/cargo.rs @@ -27,24 +27,53 @@ pub(crate) struct Workspace { cargo: PathBuf, rustc: PathBuf, - pub(crate) nightly: bool, + /// Whether use `cargo +nightly`. + pub(crate) force_nightly: bool, + /// Whether `-C instrument-coverage` is available. + pub(crate) stable_coverage: bool, } impl Workspace { pub(crate) fn new( options: &ManifestOptions, target: Option<&str>, + doctests: bool, show_env: bool, ) -> Result { let cargo = env::var_os("CARGO").unwrap_or_else(|| "cargo".into()); let rustc = rustc_path(&cargo); let (nightly, ref host) = rustc_version(&rustc)?; + let stable_coverage; + let force_nightly; + if (nightly || !doctests) + && cmd!(&rustc, "-C", "help").read()?.contains("instrument-coverage") + { + stable_coverage = true; + force_nightly = false; + } else if nightly { + stable_coverage = false; + force_nightly = false; + } else if cmd!("rustc", "+nightly", "-C", "help").read()?.contains("instrument-coverage") { + stable_coverage = true; + force_nightly = true; + } else { + stable_coverage = false; + force_nightly = true; + } + if force_nightly && doctests { + warn!( + "cargo-llvm-cov will be changed to always select default toolchain in the future \ + major version, but --doctests requires nightly toolchain; \ + consider using `cargo +nightly llvm-cov`" + ) + } + // Metadata and config let current_manifest = package_root(&cargo, options.manifest_path.as_deref())?; let metadata = metadata(&cargo, ¤t_manifest, options)?; let config = Config::new( - if nightly { cmd!(&cargo) } else { cmd!("cargo", "+nightly") }, + if force_nightly { cmd!("cargo", "+nightly") } else { cmd!(&cargo) }, &metadata.workspace_root, target, Some(host), @@ -76,12 +105,14 @@ impl Workspace { profdata_file, cargo: cargo.into(), rustc, - nightly, + force_nightly, + stable_coverage, }) } pub(crate) fn cargo(&self, verbose: u8) -> ProcessBuilder { - let mut cmd = if self.nightly { cmd!(&self.cargo) } else { cmd!("cargo", "+nightly") }; + let mut cmd = + if self.force_nightly { cmd!("cargo", "+nightly") } else { cmd!(&self.cargo) }; cmd.dir(&self.metadata.workspace_root); // cargo displays env vars only with -vv. if verbose > 1 { @@ -91,7 +122,8 @@ impl Workspace { } pub(crate) fn rustc(&self) -> ProcessBuilder { - let mut cmd = if self.nightly { cmd!(&self.rustc) } else { cmd!("rustc", "+nightly") }; + let mut cmd = + if self.force_nightly { cmd!("rustc", "+nightly") } else { cmd!(&self.rustc) }; cmd.dir(&self.metadata.workspace_root); cmd } diff --git a/src/clean.rs b/src/clean.rs index fb84d0eb..a8ca8cc1 100644 --- a/src/clean.rs +++ b/src/clean.rs @@ -17,7 +17,7 @@ use crate::{ }; pub(crate) fn run(mut options: CleanOptions) -> Result<()> { - let ws = Workspace::new(&options.manifest, None, false)?; + let ws = Workspace::new(&options.manifest, None, false, false)?; ws.config.merge_to_args(&mut None, &mut options.verbose, &mut options.color); term::set_coloring(&mut options.color); diff --git a/src/cli.rs b/src/cli.rs index f58bf6bc..4362a857 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -6,7 +6,7 @@ use clap::{AppSettings, ArgSettings, Parser}; use crate::{process::ProcessBuilder, term::Coloring}; const ABOUT: &str = - "Cargo subcommand to easily use LLVM source-based code coverage (-Z instrument-coverage). + "Cargo subcommand to easily use LLVM source-based code coverage (-C instrument-coverage). Use -h for short descriptions and --help for more details."; diff --git a/src/config.rs b/src/config.rs index 363c0b6e..1433b86d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -36,8 +36,9 @@ impl Config { // https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#cargo-config // https://github.com/rust-lang/cargo/issues/9301 cargo - .args(["-Z", "unstable-options", "config", "get", "--format", "json"]) - .dir(workspace_root); + .args(&["-Z", "unstable-options", "config", "get", "--format", "json"]) + .dir(workspace_root) + .env("RUSTC_BOOTSTRAP", "1"); let mut config = match cargo.read() { Ok(s) => serde_json::from_str(&s) .with_context(|| format!("failed to parse output from {}", cargo))?, diff --git a/src/context.rs b/src/context.rs index 8c4a2703..8634dc28 100644 --- a/src/context.rs +++ b/src/context.rs @@ -50,7 +50,7 @@ impl Context { no_run: bool, show_env: bool, ) -> Result { - let ws = Workspace::new(&manifest, build.target.as_deref(), show_env)?; + let ws = Workspace::new(&manifest, build.target.as_deref(), doctests, show_env)?; ws.config.merge_to_args(&mut build.target, &mut build.verbose, &mut build.color); term::set_coloring(&mut build.color); term::verbose::set(build.verbose != 0); @@ -95,7 +95,7 @@ impl Context { if !llvm_cov.exists() || !llvm_profdata.exists() { bail!( "failed to find llvm-tools-preview, please install llvm-tools-preview with `rustup component add llvm-tools-preview{}`", - if ws.nightly { "" } else { " --toolchain nightly" } + if ws.force_nightly { " --toolchain nightly" } else { "" } ); } diff --git a/src/main.rs b/src/main.rs index e638ebbd..c5a4da92 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ #![warn(clippy::default_trait_access, clippy::wildcard_imports)] // Refs: -// - https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/instrument-coverage.html +// - https://doc.rust-lang.org/nightly/rustc/instrument-coverage.html // - https://llvm.org/docs/CommandGuide/llvm-profdata.html // - https://llvm.org/docs/CommandGuide/llvm-cov.html @@ -196,17 +196,22 @@ fn set_env(cx: &Context, target: &mut impl EnvTarget) { let llvm_profile_file = cx.ws.target_dir.join(format!("{}-%m.profraw", cx.ws.name)); let rustflags = &mut cx.ws.config.rustflags().unwrap_or_default(); - rustflags.push_str(" -Z instrument-coverage"); + if cx.ws.stable_coverage { + rustflags.push_str(" -C instrument-coverage"); + } else { + // TODO: drop support for `-Z instrument-coverage` in 0.2. + rustflags.push_str(" -Z instrument-coverage"); + if cfg!(windows) { + // `-C codegen-units=1` is needed to work around link error on windows + // https://github.com/rust-lang/rust/issues/85461 + // https://github.com/microsoft/windows-rs/issues/1006#issuecomment-887789950 + // This has been fixed in https://github.com/rust-lang/rust/pull/91470, + // but old nightly compilers still need this. + rustflags.push_str(" -C codegen-units=1"); + } + } // --remap-path-prefix is needed because sometimes macros are displayed with absolute path rustflags.push_str(&format!(" --remap-path-prefix {}/=", cx.ws.metadata.workspace_root)); - if cfg!(windows) { - // `-C codegen-units=1` is needed to work around link error on windows - // https://github.com/rust-lang/rust/issues/85461 - // https://github.com/microsoft/windows-rs/issues/1006#issuecomment-887789950 - // This has been fixed in https://github.com/rust-lang/rust/pull/91470, - // but old nightly compilers still need this. - rustflags.push_str(" -C codegen-units=1"); - } if !cx.cov.no_cfg_coverage { rustflags.push_str(" --cfg coverage"); } @@ -217,14 +222,18 @@ fn set_env(cx: &Context, target: &mut impl EnvTarget) { rustflags.push_str(" --cfg trybuild_no_target"); } - // https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/instrument-coverage.html#including-doc-tests + // https://doc.rust-lang.org/nightly/rustc/instrument-coverage.html#including-doc-tests let rustdocflags = &mut cx.ws.config.rustdocflags(); if cx.doctests { let rustdocflags = rustdocflags.get_or_insert_with(String::new); - rustdocflags.push_str(&format!( - " -Z instrument-coverage -Z unstable-options --persist-doctests {}", - cx.ws.doctests_dir - )); + if cx.ws.stable_coverage { + rustdocflags.push_str(" -C instrument-coverage"); + } else { + // TODO: drop support for `-Z instrument-coverage` in 0.2. + rustdocflags.push_str(" -Z instrument-coverage"); + } + rustdocflags + .push_str(&format!(" -Z unstable-options --persist-doctests {}", cx.ws.doctests_dir)); if cfg!(windows) { rustdocflags.push_str(" -C codegen-units=1"); } @@ -360,7 +369,7 @@ fn object_files(cx: &Context) -> Result> { // To support testing binary crate like tests that use the CARGO_BIN_EXE // environment variable, pass all compiled executables. // This is not the ideal way, but the way unstable book says it is cannot support them. - // https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/instrument-coverage.html#tips-for-listing-the-binaries-automatically + // https://doc.rust-lang.org/nightly/rustc/instrument-coverage.html#tips-for-listing-the-binaries-automatically let mut target_dir = cx.ws.target_dir.clone(); // https://doc.rust-lang.org/nightly/cargo/guide/build-cache.html if let Some(target) = &cx.build.target { diff --git a/tests/long-help.txt b/tests/long-help.txt index 15ee4ee0..8ce7673d 100644 --- a/tests/long-help.txt +++ b/tests/long-help.txt @@ -1,5 +1,5 @@ cargo-llvm-cov -Cargo subcommand to easily use LLVM source-based code coverage (-Z instrument-coverage). +Cargo subcommand to easily use LLVM source-based code coverage (-C instrument-coverage). Use -h for short descriptions and --help for more details. diff --git a/tests/short-help.txt b/tests/short-help.txt index ea5dc864..6ff3b95b 100644 --- a/tests/short-help.txt +++ b/tests/short-help.txt @@ -1,5 +1,5 @@ cargo-llvm-cov -Cargo subcommand to easily use LLVM source-based code coverage (-Z instrument-coverage). +Cargo subcommand to easily use LLVM source-based code coverage (-C instrument-coverage). Use -h for short descriptions and --help for more details.