Skip to content

Code coverage support for Rust `no_std` and embedded programs

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

daedaleanai/minicov

 
 

Repository files navigation

minicov

Crates.io Documentation

This crate provides code coverage support for no_std and embedded programs.

This is done through a modified version of the LLVM profiling runtime (normally part of compiler-rt) from which all dependencies on libc have been removed.

All types of instrumentation using the LLVM profiling runtime are supported:

  • Rust code coverage with -Zinstrument-coverage.
  • Rust profile-guided optimization with -Cprofile-generate.
  • Clang code coverage with -fprofile-instr-generate -fcoverage-mapping.
  • Clang profile-guided optimization with -fprofile-instr-generate.
  • Clang LLVM IR profile-guided optimization with -fprofile-generate.

Note that to profile both C and Rust code at the same time you must use Clang with the same LLVM version as the LLVM used by rustc.

Usage

Note: This crate requires a recent nightly compiler.

  1. Ensure that the following environment variables are set up:
export RUSTFLAGS="-Zinstrument-coverage -Zno-profiler-runtime"

Note that these flags also apply to build-dependencies and proc macros by default. This can be worked around by explicitly specifying a target when invoking cargo:

# Applies RUSTFLAGS to everything
cargo build

# Doesn't apply RUSTFLAGS to build dependencies and proc macros
cargo build --target x86_64-unknown-linux-gnu
  1. Add the minicov crate as a dependency to your program:
[dependencies]
minicov = "0.2"
  1. Before your program exits, call minicov::capture_coverage (which returns a Vec<u8>) and dump its contents to a file with the .profraw extension:
fn main() {
    // ...

    let coverage = minicov::capture_coverage();
    std::fs::write("output.profraw", coverage).unwrap();
}

If your program doesn't have the default alloc feature enabled you can use minicov::get_coverage_data_size, to get the size required for the coverage data and minicov::capture_coverage_to_buffer to serialize the coverage data:

fn main() {
    // ...

    // with COVERAGE_DATA_SIZE as a const usize
    let mut buffer: [u8; COVERAGE_DATA_SIZE] = [0; COVERAGE_DATA_SIZE];
    
    let actual_size = minicov::get_coverage_data_size();
    assert!(actual_size <= COVERAGE_DATA_SIZE, "Not enough space reserved for coverage daa");
    minicov::capture_coverage_to_buffer(&mut buffer[0..actual_size]);
    
    // Transfer coverage data somewhere else
}

If your program is running on a different system than your build system, then you will need to transfer this file back to your build system.

  1. Use a tool such as grcov or llvm-cov to generate a human-readable coverage report:
grcov output.profraw -b ./target/debug/my_program -t html -o cov_report

License

Licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Code coverage support for Rust `no_std` and embedded programs

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 59.2%
  • C++ 32.8%
  • Rust 7.5%
  • Go 0.5%