llvm-project
198 строк · 5.5 Кб
1#!/usr/bin/env python
2
3from __future__ import print_function
4
5"""Prepare a code coverage artifact.
6
7- Collate raw profiles into one indexed profile.
8- Generate html reports for the given binaries.
9
10Caution: The positional arguments to this script must be specified before any
11optional arguments, such as --restrict.
12"""
13
14import argparse
15import glob
16import os
17import subprocess
18import sys
19
20
21def merge_raw_profiles(host_llvm_profdata, profile_data_dir, preserve_profiles):
22print(":: Merging raw profiles...", end="")
23sys.stdout.flush()
24raw_profiles = glob.glob(os.path.join(profile_data_dir, "*.profraw"))
25manifest_path = os.path.join(profile_data_dir, "profiles.manifest")
26profdata_path = os.path.join(profile_data_dir, "Coverage.profdata")
27with open(manifest_path, "w") as manifest:
28manifest.write("\n".join(raw_profiles))
29subprocess.check_call(
30[
31host_llvm_profdata,
32"merge",
33"-sparse",
34"-f",
35manifest_path,
36"-o",
37profdata_path,
38]
39)
40if not preserve_profiles:
41for raw_profile in raw_profiles:
42os.remove(raw_profile)
43os.remove(manifest_path)
44print("Done!")
45return profdata_path
46
47
48def prepare_html_report(
49host_llvm_cov, profile, report_dir, binaries, restricted_dirs, compilation_dir
50):
51print(":: Preparing html report for {0}...".format(binaries), end="")
52sys.stdout.flush()
53objects = []
54for i, binary in enumerate(binaries):
55if i == 0:
56objects.append(binary)
57else:
58objects.extend(("-object", binary))
59invocation = (
60[host_llvm_cov, "show"]
61+ objects
62+ [
63"-format",
64"html",
65"-instr-profile",
66profile,
67"-o",
68report_dir,
69"-show-line-counts-or-regions",
70"-show-directory-coverage",
71"-Xdemangler",
72"c++filt",
73"-Xdemangler",
74"-n",
75]
76+ restricted_dirs
77)
78if compilation_dir:
79invocation += ["-compilation-dir=" + compilation_dir]
80subprocess.check_call(invocation)
81with open(os.path.join(report_dir, "summary.txt"), "wb") as Summary:
82subprocess.check_call(
83[host_llvm_cov, "report"]
84+ objects
85+ ["-instr-profile", profile]
86+ restricted_dirs,
87stdout=Summary,
88)
89print("Done!")
90
91
92def prepare_html_reports(
93host_llvm_cov,
94profdata_path,
95report_dir,
96binaries,
97unified_report,
98restricted_dirs,
99compilation_dir,
100):
101if unified_report:
102prepare_html_report(
103host_llvm_cov,
104profdata_path,
105report_dir,
106binaries,
107restricted_dirs,
108compilation_dir,
109)
110else:
111for binary in binaries:
112binary_report_dir = os.path.join(report_dir, os.path.basename(binary))
113prepare_html_report(
114host_llvm_cov,
115profdata_path,
116binary_report_dir,
117[binary],
118restricted_dirs,
119compilation_dir,
120)
121
122
123if __name__ == "__main__":
124parser = argparse.ArgumentParser(description=__doc__)
125parser.add_argument("host_llvm_profdata", help="Path to llvm-profdata")
126parser.add_argument("host_llvm_cov", help="Path to llvm-cov")
127parser.add_argument(
128"profile_data_dir", help="Path to the directory containing the raw profiles"
129)
130parser.add_argument(
131"report_dir", help="Path to the output directory for html reports"
132)
133parser.add_argument(
134"binaries",
135metavar="B",
136type=str,
137nargs="*",
138help="Path to an instrumented binary",
139)
140parser.add_argument(
141"--only-merge",
142action="store_true",
143help="Only merge raw profiles together, skip report " "generation",
144)
145parser.add_argument(
146"--preserve-profiles", help="Do not delete raw profiles", action="store_true"
147)
148parser.add_argument(
149"--use-existing-profdata", help="Specify an existing indexed profile to use"
150)
151parser.add_argument(
152"--unified-report",
153action="store_true",
154help="Emit a unified report for all binaries",
155)
156parser.add_argument(
157"--restrict",
158metavar="R",
159type=str,
160nargs="*",
161default=[],
162help="Restrict the reporting to the given source paths"
163" (must be specified after all other positional arguments)",
164)
165parser.add_argument(
166"-C",
167"--compilation-dir",
168type=str,
169default="",
170help="The compilation directory of the binary",
171)
172args = parser.parse_args()
173
174if args.use_existing_profdata and args.only_merge:
175print("--use-existing-profdata and --only-merge are incompatible")
176exit(1)
177
178if args.use_existing_profdata:
179profdata_path = args.use_existing_profdata
180else:
181profdata_path = merge_raw_profiles(
182args.host_llvm_profdata, args.profile_data_dir, args.preserve_profiles
183)
184
185if not len(args.binaries):
186print("No binaries specified, no work to do!")
187exit(1)
188
189if not args.only_merge:
190prepare_html_reports(
191args.host_llvm_cov,
192profdata_path,
193args.report_dir,
194args.binaries,
195args.unified_report,
196args.restrict,
197args.compilation_dir,
198)
199