[llvm] r273985 - Reapply "[llvm-cov] Add an -output-dir option for the show sub-command""

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 27 19:09:40 PDT 2016


Author: vedantk
Date: Mon Jun 27 21:09:39 2016
New Revision: 273985

URL: http://llvm.org/viewvc/llvm-project?rev=273985&view=rev
Log:
Reapply "[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.

Changes since the initial commit:

- Avoid accidentally closing stdout twice.

Modified:
    llvm/trunk/docs/CommandGuide/llvm-cov.rst
    llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp
    llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
    llvm/trunk/tools/llvm-cov/CoverageViewOptions.h
    llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
    llvm/trunk/tools/llvm-cov/SourceCoverageView.h
    llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp
    llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h

Modified: llvm/trunk/docs/CommandGuide/llvm-cov.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-cov.rst?rev=273985&r1=273984&r2=273985&view=diff
==============================================================================
--- llvm/trunk/docs/CommandGuide/llvm-cov.rst (original)
+++ llvm/trunk/docs/CommandGuide/llvm-cov.rst Mon Jun 27 21:09:39 2016
@@ -240,6 +240,14 @@ OPTIONS
 
  Use the specified output format. The supported formats are: "text".
 
+.. option:: -output-dir=PATH
+
+ Specify a directory to write coverage reports into. If the directory does not
+ exist, it is created. When used in function view mode (i.e when -name or
+ -name-regex are used to select specific functions), the report is written to
+ PATH/functions.EXTENSION. When used in file view mode, a report for each file
+ is written to PATH/REL_PATH_TO_FILE.EXTENSION.
+
 .. option:: -line-coverage-gt=<N>
 
  Show code coverage only for functions with line coverage greater than the

Modified: llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp?rev=273985&r1=273984&r2=273985&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp (original)
+++ llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp Mon Jun 27 21:09:39 2016
@@ -28,3 +28,9 @@ int main() {
 
 // RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck -check-prefixes=CHECK,WHOLE-FILE %s
 // RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -filename-equivalence -name=main %s | FileCheck -check-prefixes=CHECK,FILTER %s
+
+// Test -output-dir.
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir -instr-profile %t.profdata -filename-equivalence %s
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir -instr-profile %t.profdata -filename-equivalence -name=main %s
+// RUN: FileCheck -check-prefixes=CHECK,WHOLE-FILE -input-file %t.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %s
+// RUN: FileCheck -check-prefixes=CHECK,FILTER -input-file %t.dir/functions.txt %s

Modified: llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CodeCoverage.cpp?rev=273985&r1=273984&r2=273985&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CodeCoverage.cpp (original)
+++ llvm/trunk/tools/llvm-cov/CodeCoverage.cpp Mon Jun 27 21:09:39 2016
@@ -406,6 +406,12 @@ int CodeCoverageTool::show(int argc, con
                  clEnumValEnd),
       cl::init(CoverageViewOptions::OutputFormat::Text));
 
+  cl::opt<std::string> ShowOutputDirectory(
+      "output-dir", cl::init(""),
+      cl::desc("Directory in which coverage information is written out"));
+  cl::alias ShowOutputDirectoryA("o", cl::desc("Alias for --output-dir"),
+                                 cl::aliasopt(ShowOutputDirectory));
+
   auto Err = commandLineParser(argc, argv);
   if (Err)
     return Err;
@@ -418,6 +424,14 @@ int CodeCoverageTool::show(int argc, con
   ViewOpts.ShowExpandedRegions = ShowExpansions;
   ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
   ViewOpts.ShowFormat = ShowFormat;
+  ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
+
+  if (ViewOpts.ShowOutputDirectory != "") {
+    if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) {
+      error("Could not create output directory!", E.message());
+      return 1;
+    }
+  }
 
   auto Coverage = load();
   if (!Coverage)
@@ -436,8 +450,17 @@ int CodeCoverageTool::show(int argc, con
             << "\n";
         continue;
       }
-      mainView->print(outs(), /*WholeFile=*/false, /*ShowSourceName=*/true);
-      outs() << "\n";
+
+      auto OSOrErr =
+          mainView->createOutputFile("functions", /*InToplevel=*/true);
+      if (Error E = OSOrErr.takeError()) {
+        handleAllErrors(OSOrErr.takeError(),
+                        [&](const ErrorInfoBase &EI) { error(EI.message()); });
+        return 1;
+      }
+      auto OS = std::move(OSOrErr.get());
+      mainView->print(*OS.get(), /*WholeFile=*/false, /*ShowSourceName=*/true);
+      mainView->closeOutputFile(std::move(OS));
     }
     return 0;
   }
@@ -459,10 +482,16 @@ int CodeCoverageTool::show(int argc, con
       continue;
     }
 
-    mainView->print(outs(), /*Wholefile=*/true,
+    auto OSOrErr = mainView->createOutputFile(SourceFile, /*InToplevel=*/false);
+    if (Error E = OSOrErr.takeError()) {
+      handleAllErrors(OSOrErr.takeError(),
+                      [&](const ErrorInfoBase &EI) { error(EI.message()); });
+      return 1;
+    }
+    auto OS = std::move(OSOrErr.get());
+    mainView->print(*OS.get(), /*Wholefile=*/true,
                     /*ShowSourceName=*/ShowFilenames);
-    if (SourceFiles.size() > 1)
-      outs() << "\n";
+    mainView->closeOutputFile(std::move(OS));
   }
 
   return 0;

Modified: llvm/trunk/tools/llvm-cov/CoverageViewOptions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageViewOptions.h?rev=273985&r1=273984&r2=273985&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageViewOptions.h (original)
+++ llvm/trunk/tools/llvm-cov/CoverageViewOptions.h Mon Jun 27 21:09:39 2016
@@ -30,6 +30,7 @@ struct CoverageViewOptions {
   bool ShowFunctionInstantiations;
   bool ShowFullFilenames;
   OutputFormat ShowFormat;
+  std::string ShowOutputDirectory;
 
   /// \brief Change the output's stream color if the colors are enabled.
   ColoredRawOstream colored_ostream(raw_ostream &OS,

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp?rev=273985&r1=273984&r2=273985&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp Mon Jun 27 21:09:39 2016
@@ -15,7 +15,9 @@
 #include "SourceCoverageViewText.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/LineIterator.h"
+#include "llvm/Support/Path.h"
 
 using namespace llvm;
 
@@ -34,6 +36,51 @@ std::string SourceCoverageView::formatCo
   return Result;
 }
 
+void SourceCoverageView::StreamDestructor::operator()(raw_ostream *OS) const {
+  if (OS == &outs())
+    return;
+  delete OS;
+}
+
+/// \brief Create a file at ``Dir/ToplevelDir/@Path.Extension``. If
+/// \p ToplevelDir is empty, its path component is skipped.
+static Expected<SourceCoverageView::OwnedStream>
+createFileInDirectory(StringRef Dir, StringRef ToplevelDir, StringRef Path,
+                      StringRef Extension) {
+  assert(Extension.size() && "The file extension may not be empty");
+
+  SmallString<256> FullPath(Dir);
+  if (!ToplevelDir.empty())
+    sys::path::append(FullPath, ToplevelDir);
+
+  auto PathBaseDir = sys::path::relative_path(sys::path::parent_path(Path));
+  sys::path::append(FullPath, PathBaseDir);
+
+  if (auto E = sys::fs::create_directories(FullPath))
+    return errorCodeToError(E);
+
+  auto PathFilename = (sys::path::filename(Path) + "." + Extension).str();
+  sys::path::append(FullPath, PathFilename);
+
+  std::error_code E;
+  auto OS = SourceCoverageView::OwnedStream(
+      new raw_fd_ostream(FullPath, E, sys::fs::F_RW));
+  if (E)
+    return errorCodeToError(E);
+  return std::move(OS);
+}
+
+Expected<SourceCoverageView::OwnedStream>
+SourceCoverageView::createOutputStream(const CoverageViewOptions &Opts,
+                                       StringRef Path, StringRef Extension,
+                                       bool InToplevel) {
+  if (Opts.ShowOutputDirectory == "")
+    return OwnedStream(&outs());
+
+  return createFileInDirectory(Opts.ShowOutputDirectory,
+                               InToplevel ? "" : "coverage", Path, Extension);
+}
+
 void SourceCoverageView::addExpansion(
     const coverage::CounterMappingRegion &Region,
     std::unique_ptr<SourceCoverageView> View) {

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageView.h?rev=273985&r1=273984&r2=273985&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageView.h (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageView.h Mon Jun 27 21:09:39 2016
@@ -101,7 +101,7 @@ struct LineCoverageStats {
 ///
 /// A source coverage view and its nested sub-views form a file-oriented
 /// representation of code coverage data. This view can be printed out by a
-/// renderer which implements the Rendering Interface.
+/// renderer which implements both the File Creation and Rendering interfaces.
 class SourceCoverageView {
   /// A function or file name.
   StringRef SourceName;
@@ -122,6 +122,25 @@ class SourceCoverageView {
   /// on display.
   std::vector<InstantiationView> InstantiationSubViews;
 
+public:
+  struct StreamDestructor {
+    void operator()(raw_ostream *OS) const;
+  };
+
+  using OwnedStream = std::unique_ptr<raw_ostream, StreamDestructor>;
+
+  /// @name File Creation Interface
+  /// @{
+
+  /// \brief Create a file to print a coverage view into.
+  virtual Expected<OwnedStream> createOutputFile(StringRef Path,
+                                                 bool InToplevel) = 0;
+
+  /// \brief Close a file which has been used to print a coverage view.
+  virtual void closeOutputFile(OwnedStream OS) = 0;
+
+  /// @}
+
 protected:
   struct LineRef {
     StringRef Line;
@@ -183,6 +202,12 @@ protected:
   /// digits.
   static std::string formatCount(uint64_t N);
 
+  /// \brief If directory output is enabled, create a file with \p Path as the
+  /// suffix. Otherwise, return stdout.
+  static Expected<OwnedStream>
+  createOutputStream(const CoverageViewOptions &Opts, StringRef Path,
+                     StringRef Extension, bool InToplevel);
+
   SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
                      const CoverageViewOptions &Options,
                      coverage::CoverageData &&CoverageInfo)

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp?rev=273985&r1=273984&r2=273985&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp Mon Jun 27 21:09:39 2016
@@ -37,6 +37,15 @@ unsigned getDividerWidth(const CoverageV
 
 } // anonymous namespace
 
+Expected<SourceCoverageView::OwnedStream>
+SourceCoverageViewText::createOutputFile(StringRef Path, bool InToplevel) {
+  return createOutputStream(getOptions(), Path, "txt", InToplevel);
+}
+
+void SourceCoverageViewText::closeOutputFile(OwnedStream OS) {
+  OS->operator<<('\n');
+}
+
 void SourceCoverageViewText::renderSourceName(raw_ostream &OS) {
   getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName()
                                                       << ":\n";

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h?rev=273985&r1=273984&r2=273985&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h Mon Jun 27 21:09:39 2016
@@ -20,6 +20,13 @@ namespace llvm {
 
 /// \brief A code coverage view which supports text-based rendering.
 class SourceCoverageViewText : public SourceCoverageView {
+public:
+  Expected<OwnedStream> createOutputFile(StringRef Path,
+                                         bool InToplevel) override;
+
+  void closeOutputFile(OwnedStream OS) override;
+
+private:
   void renderSourceName(raw_ostream &OS) override;
 
   void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;




More information about the llvm-commits mailing list