|
9 | 9 | //! data files to compute the coverage report. |
10 | 10 | //! |
11 | 11 | //! This script assumes the following environment variables are set: |
12 | | -//! - `COVERAGE_DIR``: Directory containing metadata files needed for coverage collection (e.g. gcda files, profraw). |
| 12 | +//! - `COVERAGE_DIR`: Directory containing metadata files needed for coverage collection (e.g. gcda files, profraw). |
13 | 13 | //! - `COVERAGE_OUTPUT_FILE`: The coverage action output path. |
14 | 14 | //! - `ROOT`: Location from where the code coverage collection was invoked. |
15 | | -//! - `RUNFILES_DIR`: Location of the test's runfiles. |
| 15 | +//! - `RUNFILES_DIR` (optional): Location of the test's runfiles. Not set in split |
| 16 | +//! coverage postprocessing mode (`--experimental_split_coverage_postprocessing`). |
| 17 | +//! - `TEST_BINARY`: Runfiles-relative path to the test binary (used when `RUNFILES_DIR` is absent). |
16 | 18 | //! - `VERBOSE_COVERAGE`: Print debug info from the coverage scripts |
17 | 19 | //! |
18 | 20 | //! The script looks in $COVERAGE_DIR for the Rust metadata coverage files |
@@ -85,31 +87,71 @@ fn find_test_binary(execroot: &Path, runfiles_dir: &Path) -> PathBuf { |
85 | 87 | } |
86 | 88 | } |
87 | 89 |
|
| 90 | +/// Derive the Bazel output configuration bin directory from `COVERAGE_DIR`. |
| 91 | +/// |
| 92 | +/// `COVERAGE_DIR` follows the stable convention `bazel-out/<config>/testlogs/...`. |
| 93 | +/// Extracting the first two path components gives `bazel-out/<config>`, which |
| 94 | +/// combined with `bin` yields the directory containing the test binary. |
| 95 | +fn config_bin_dir(execroot: &Path, coverage_dir: &Path) -> PathBuf { |
| 96 | + let coverage_rel = coverage_dir.strip_prefix(execroot).unwrap_or(coverage_dir); |
| 97 | + let mut components = coverage_rel.components(); |
| 98 | + let bazel_out = components |
| 99 | + .next() |
| 100 | + .expect("COVERAGE_DIR should have at least 2 path components"); |
| 101 | + let config = components |
| 102 | + .next() |
| 103 | + .expect("COVERAGE_DIR should have at least 2 path components"); |
| 104 | + PathBuf::from(bazel_out.as_os_str()) |
| 105 | + .join(config.as_os_str()) |
| 106 | + .join("bin") |
| 107 | +} |
| 108 | + |
88 | 109 | fn main() { |
89 | 110 | let coverage_dir = PathBuf::from(env::var("COVERAGE_DIR").unwrap()); |
90 | 111 | let execroot = PathBuf::from(env::var("ROOT").unwrap()); |
91 | | - let mut runfiles_dir = PathBuf::from(env::var("RUNFILES_DIR").unwrap()); |
92 | 112 |
|
93 | | - if !runfiles_dir.is_absolute() { |
94 | | - runfiles_dir = execroot.join(runfiles_dir); |
95 | | - } |
| 113 | + // RUNFILES_DIR is explicitly removed by Bazel in split coverage |
| 114 | + // postprocessing mode (--experimental_split_coverage_postprocessing). |
| 115 | + let runfiles_dir = env::var("RUNFILES_DIR") |
| 116 | + .map(|d| { |
| 117 | + let p = PathBuf::from(d); |
| 118 | + if p.is_absolute() { |
| 119 | + p |
| 120 | + } else { |
| 121 | + execroot.join(p) |
| 122 | + } |
| 123 | + }) |
| 124 | + .ok(); |
96 | 125 |
|
97 | 126 | debug_log!("ROOT: {}", execroot.display()); |
98 | | - debug_log!("RUNFILES_DIR: {}", runfiles_dir.display()); |
| 127 | + match runfiles_dir { |
| 128 | + Some(ref rd) => debug_log!("RUNFILES_DIR: {}", rd.display()), |
| 129 | + None => debug_log!("RUNFILES_DIR: not set (split coverage postprocessing)"), |
| 130 | + } |
99 | 131 |
|
100 | 132 | let coverage_output_file = coverage_dir.join("coverage.dat"); |
101 | 133 | let profdata_file = coverage_dir.join("coverage.profdata"); |
102 | | - let llvm_cov = find_metadata_file( |
103 | | - &execroot, |
104 | | - &runfiles_dir, |
105 | | - &env::var("RUST_LLVM_COV").unwrap(), |
106 | | - ); |
107 | | - let llvm_profdata = find_metadata_file( |
108 | | - &execroot, |
109 | | - &runfiles_dir, |
110 | | - &env::var("RUST_LLVM_PROFDATA").unwrap(), |
111 | | - ); |
112 | | - let test_binary = find_test_binary(&execroot, &runfiles_dir); |
| 134 | + let llvm_cov_path = env::var("RUST_LLVM_COV").unwrap(); |
| 135 | + let llvm_profdata_path = env::var("RUST_LLVM_PROFDATA").unwrap(); |
| 136 | + let llvm_cov = match runfiles_dir { |
| 137 | + Some(ref rd) => find_metadata_file(&execroot, rd, &llvm_cov_path), |
| 138 | + None => execroot.join(&llvm_cov_path), |
| 139 | + }; |
| 140 | + let llvm_profdata = match runfiles_dir { |
| 141 | + Some(ref rd) => find_metadata_file(&execroot, rd, &llvm_profdata_path), |
| 142 | + None => execroot.join(&llvm_profdata_path), |
| 143 | + }; |
| 144 | + let test_binary = match runfiles_dir { |
| 145 | + Some(ref rd) => find_test_binary(&execroot, rd), |
| 146 | + None => { |
| 147 | + let bin_dir = config_bin_dir(&execroot, &coverage_dir); |
| 148 | + let test_binary = execroot |
| 149 | + .join(bin_dir) |
| 150 | + .join(env::var("TEST_BINARY").unwrap()); |
| 151 | + debug_log!("Resolved TEST_BINARY to: {}", test_binary.display()); |
| 152 | + test_binary |
| 153 | + } |
| 154 | + }; |
113 | 155 | let profraw_files: Vec<PathBuf> = fs::read_dir(coverage_dir) |
114 | 156 | .unwrap() |
115 | 157 | .flatten() |
|
0 commit comments