llvm.org GIT mirror llvm / b979c03
[llvm-cov] Add an -output-dir option for the show sub-command Passing -output-dir path/to/dir to llvm-cov show creates path/to/dir if it doesn't already exist, and prints reports into that directory. In function view mode, all views are written into path/to/dir/functions.$EXTENSION. In file view mode, all views are written into path/to/dir/coverage/$PATH.$EXTENSION. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273971 91177308-0d34-0410-b5e6-96231b3b80d8 Vedant Kumar 3 years ago
8 changed file(s) with 130 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
239239
240240 Use the specified output format. The supported formats are: "text".
241241
242 .. option:: -output-dir=PATH
243
244 Specify a directory to write coverage reports into. If the directory does not
245 exist, it is created. When used in function view mode (i.e when -name or
246 -name-regex are used to select specific functions), the report is written to
247 PATH/functions.EXTENSION. When used in file view mode, a report for each file
248 is written to PATH/REL_PATH_TO_FILE.EXTENSION.
249
242250 .. option:: -line-coverage-gt=
243251
244252 Show code coverage only for functions with line coverage greater than the
2727
2828 // RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck -check-prefixes=CHECK,WHOLE-FILE %s
2929 // RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -filename-equivalence -name=main %s | FileCheck -check-prefixes=CHECK,FILTER %s
30
31 // Test -output-dir.
32 // RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir -instr-profile %t.profdata -filename-equivalence %s
33 // RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir -instr-profile %t.profdata -filename-equivalence -name=main %s
34 // RUN: FileCheck -check-prefixes=CHECK,WHOLE-FILE -input-file %t.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %s
35 // RUN: FileCheck -check-prefixes=CHECK,FILTER -input-file %t.dir/functions.txt %s
405405 clEnumValEnd),
406406 cl::init(CoverageViewOptions::OutputFormat::Text));
407407
408 cl::opt ShowOutputDirectory(
409 "output-dir", cl::init(""),
410 cl::desc("Directory in which coverage information is written out"));
411 cl::alias ShowOutputDirectoryA("o", cl::desc("Alias for --output-dir"),
412 cl::aliasopt(ShowOutputDirectory));
413
408414 auto Err = commandLineParser(argc, argv);
409415 if (Err)
410416 return Err;
417423 ViewOpts.ShowExpandedRegions = ShowExpansions;
418424 ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
419425 ViewOpts.ShowFormat = ShowFormat;
426 ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
427
428 if (ViewOpts.ShowOutputDirectory != "") {
429 if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) {
430 error("Could not create output directory!", E.message());
431 return 1;
432 }
433 }
420434
421435 auto Coverage = load();
422436 if (!Coverage)
435449 << "\n";
436450 continue;
437451 }
438 mainView->print(outs(), /*WholeFile=*/false, /*ShowSourceName=*/true);
439 outs() << "\n";
452
453 auto OSOrErr =
454 mainView->createOutputFile("functions", /*InToplevel=*/true);
455 if (Error E = OSOrErr.takeError()) {
456 handleAllErrors(OSOrErr.takeError(),
457 [&](const ErrorInfoBase &EI) { error(EI.message()); });
458 return 1;
459 }
460 std::unique_ptr OS = std::move(OSOrErr.get());
461 mainView->print(*OS.get(), /*WholeFile=*/false, /*ShowSourceName=*/true);
462 mainView->closeOutputFile(std::move(OS));
440463 }
441464 return 0;
442465 }
458481 continue;
459482 }
460483
461 mainView->print(outs(), /*Wholefile=*/true,
484 auto OSOrErr = mainView->createOutputFile(SourceFile, /*InToplevel=*/false);
485 if (Error E = OSOrErr.takeError()) {
486 handleAllErrors(OSOrErr.takeError(),
487 [&](const ErrorInfoBase &EI) { error(EI.message()); });
488 return 1;
489 }
490 std::unique_ptr OS = std::move(OSOrErr.get());
491 mainView->print(*OS.get(), /*Wholefile=*/true,
462492 /*ShowSourceName=*/ShowFilenames);
463 if (SourceFiles.size() > 1)
464 outs() << "\n";
493 mainView->closeOutputFile(std::move(OS));
465494 }
466495
467496 return 0;
2929 bool ShowFunctionInstantiations;
3030 bool ShowFullFilenames;
3131 OutputFormat ShowFormat;
32 std::string ShowOutputDirectory;
3233
3334 /// \brief Change the output's stream color if the colors are enabled.
3435 ColoredRawOstream colored_ostream(raw_ostream &OS,
1414 #include "SourceCoverageViewText.h"
1515 #include "llvm/ADT/SmallString.h"
1616 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/Support/FileSystem.h"
1718 #include "llvm/Support/LineIterator.h"
19 #include "llvm/Support/Path.h"
1820
1921 using namespace llvm;
2022
3133 }
3234 Result.push_back(" kMGTPEZY"[(Len - 1) / 3]);
3335 return Result;
36 }
37
38 /// \brief Create a file at ``Dir/ToplevelDir/@Path.Extension``. If
39 /// \p ToplevelDir is empty, its path component is skipped.
40 static Expected>
41 createFileInDirectory(StringRef Dir, StringRef ToplevelDir, StringRef Path,
42 StringRef Extension) {
43 assert(Extension.size() && "The file extension may not be empty");
44
45 SmallString<256> FullPath(Dir);
46 if (!ToplevelDir.empty())
47 sys::path::append(FullPath, ToplevelDir);
48
49 auto PathBaseDir = sys::path::relative_path(sys::path::parent_path(Path));
50 sys::path::append(FullPath, PathBaseDir);
51
52 if (auto E = sys::fs::create_directories(FullPath))
53 return errorCodeToError(E);
54
55 auto PathFilename = (sys::path::filename(Path) + "." + Extension).str();
56 sys::path::append(FullPath, PathFilename);
57
58 std::error_code E;
59 auto OS = llvm::make_unique(FullPath, E, sys::fs::F_RW);
60 if (E)
61 return errorCodeToError(E);
62 return std::move(OS);
63 }
64
65 Expected>
66 SourceCoverageView::createOutputStream(const CoverageViewOptions &Opts,
67 StringRef Path, StringRef Extension,
68 bool InToplevel) {
69 if (Opts.ShowOutputDirectory == "") {
70 std::error_code E;
71 auto OS = llvm::make_unique("-", E, sys::fs::F_None);
72 if (E)
73 return errorCodeToError(E);
74 return std::move(OS);
75 }
76
77 return createFileInDirectory(Opts.ShowOutputDirectory,
78 InToplevel ? "" : "coverage", Path, Extension);
3479 }
3580
3681 void SourceCoverageView::addExpansion(
100100 ///
101101 /// A source coverage view and its nested sub-views form a file-oriented
102102 /// representation of code coverage data. This view can be printed out by a
103 /// renderer which implements the Rendering Interface.
103 /// renderer which implements both the File Creation and Rendering interfaces.
104104 class SourceCoverageView {
105105 /// A function or file name.
106106 StringRef SourceName;
120120 /// A container for all instantiations (e.g template functions) in the source
121121 /// on display.
122122 std::vector InstantiationSubViews;
123
124 public:
125 /// @name File Creation Interface
126 /// @{
127
128 /// \brief Create a file to print a coverage view into.
129 virtual Expected>
130 createOutputFile(StringRef Path, bool InToplevel) = 0;
131
132 /// \brief Close a file which has been used to print a coverage view.
133 virtual void closeOutputFile(std::unique_ptr OS) = 0;
134
135 /// @}
123136
124137 protected:
125138 struct LineRef {
182195 /// digits.
183196 static std::string formatCount(uint64_t N);
184197
198 /// \brief If directory output is enabled, create a file with \p Path as the
199 /// suffix. Otherwise, return stdout.
200 static Expected>
201 createOutputStream(const CoverageViewOptions &Opts, StringRef Path,
202 StringRef Extension, bool InToplevel);
203
185204 SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
186205 const CoverageViewOptions &Options,
187206 coverage::CoverageData &&CoverageInfo)
3535 }
3636
3737 } // anonymous namespace
38
39 Expected>
40 SourceCoverageViewText::createOutputFile(StringRef Path, bool InToplevel) {
41 return createOutputStream(getOptions(), Path, "txt", InToplevel);
42 }
43
44 void SourceCoverageViewText::closeOutputFile(std::unique_ptr OS) {
45 OS.get()->operator<<('\n');
46 }
3847
3948 void SourceCoverageViewText::renderSourceName(raw_ostream &OS) {
4049 getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName()
1919
2020 /// \brief A code coverage view which supports text-based rendering.
2121 class SourceCoverageViewText : public SourceCoverageView {
22 public:
23 Expected>
24 createOutputFile(StringRef Path, bool InToplevel) override;
25
26 void closeOutputFile(std::unique_ptr OS) override;
27
28 private:
2229 void renderSourceName(raw_ostream &OS) override;
2330
2431 void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;