[Cmake-commits] CMake branch, next, updated. v3.0.0-rc1-1004-gfb049c8

Brad King brad.king at kitware.com
Thu Mar 13 16:37:46 EDT 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  fb049c818beeb339cf01c796449c3837021dfca0 (commit)
       via  9840320dff7d6bc0fc64d06271a639303ea53ce7 (commit)
      from  e58ca2139b9b6c922bdac72e3c7e0d44e2623d7c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fb049c818beeb339cf01c796449c3837021dfca0
commit fb049c818beeb339cf01c796449c3837021dfca0
Merge: e58ca21 9840320
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Mar 13 16:37:45 2014 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Thu Mar 13 16:37:45 2014 -0400

    Merge topic 'ctest-intel-coverage' into next
    
    9840320d CTest: Add support for Intel coverage files


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9840320dff7d6bc0fc64d06271a639303ea53ce7
commit 9840320dff7d6bc0fc64d06271a639303ea53ce7
Author:     Volkan Gezer <volkangezer at gmail.com>
AuthorDate: Thu Feb 27 14:37:52 2014 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Mar 13 16:18:10 2014 -0400

    CTest: Add support for Intel coverage files
    
    By default, Intel compiler coverage tools generate HTML files as
    reports, but the option -txtlcov can be given to codecov to output a
    coverage file with LCov format.
    
    To use Intel coverage:
    
    * build the project with coverage flags
    * run the application
    * run profmerge
    * run codecov
    
    The output file will be "build_dir/CodeCoverage/SRCFILEDIR.LCOV".
    
    Ask users to compile with -prof-dir${BUILD_DIR} instead of searching
    the entire build tree recursively to find coverage files.

diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index f0b1124..cb6e56e 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -383,6 +383,12 @@ int cmCTestCoverageHandler::ProcessHandler()
     {
     return error;
     }
+  file_count += this->HandleLCovCoverage(&cont);
+  error = cont.Error;
+  if ( file_count < 0 )
+    {
+    return error;
+    }
   file_count += this->HandleTracePyCoverage(&cont);
   error = cont.Error;
   if ( file_count < 0 )
@@ -880,6 +886,13 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
   std::string gcovExtraFlags
     = this->CTest->GetCTestConfiguration("CoverageExtraFlags");
 
+  // Immediately skip to next coverage option since codecov is only for Intel
+  // compiler
+  if ( gcovCommand == "codecov" )
+    {
+    return 0;
+    }
+
   // Style 1
   std::string st1gcovOutputRex1
     = "[0-9]+\\.[0-9]+% of [0-9]+ (source |)lines executed in file (.*)$";
@@ -1296,6 +1309,270 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
   return file_count;
 }
 
+//----------------------------------------------------------------------
+int cmCTestCoverageHandler::HandleLCovCoverage(
+  cmCTestCoverageHandlerContainer* cont)
+{
+  std::string lcovCommand
+    = this->CTest->GetCTestConfiguration("CoverageCommand");
+  std::string lcovExtraFlags
+    = this->CTest->GetCTestConfiguration("CoverageExtraFlags");
+  if ( lcovCommand != "codecov" )
+    {
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+               " Not a valid Intel Coverage command."
+               << std::endl);
+    return 0;
+    }
+  // There is only percentage completed output from LCOV
+  std::string st2lcovOutputRex3 = "[0-9]+%";
+  cmsys::RegularExpression st2re3(st2lcovOutputRex3.c_str());
+
+  cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+    " This is coverage command: " << lcovCommand
+    << std::endl);
+
+  cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+    " These are coverage command flags: " << lcovExtraFlags
+    << std::endl);
+
+  std::vector<std::string> files;
+  this->FindLCovFiles(files);
+  std::vector<std::string>::iterator it;
+
+  if ( files.size() == 0 )
+    {
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+      " Cannot find any LCov coverage files."
+      << std::endl);
+    // No coverage files is a valid thing, so the exit code is 0
+    return 0;
+    }
+  std::string testingDir = this->CTest->GetBinaryDir();
+  std::string tempDir = testingDir;
+  std::string currentDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+
+  std::set<std::string> missingFiles;
+
+  std::string actualSourceFile = "";
+  cmCTestLog(this->CTest, HANDLER_OUTPUT,
+    "   Processing coverage (each . represents one file):" << std::endl);
+  cmCTestLog(this->CTest, HANDLER_OUTPUT, "    ");
+  int file_count = 0;
+
+  // make sure output from lcov is in English!
+  cmCTestCoverageHandlerLocale locale_C;
+  static_cast<void>(locale_C);
+
+  // In intel compiler we have to call codecov only once in each executable
+  // directory. It collects all *.dyn files to generate .dpi file.
+  for ( it = files.begin(); it != files.end(); ++ it )
+    {
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "." << std::flush);
+    std::string fileDir = cmSystemTools::GetFilenamePath(it->c_str());
+    cmSystemTools::ChangeDirectory(fileDir.c_str());
+    std::string command = "\"" + lcovCommand + "\" " +
+      lcovExtraFlags + " ";
+
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Current coverage dir: "
+               << fileDir.c_str() << std::endl);
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, command.c_str()
+               << std::endl);
+
+    std::string output = "";
+    std::string errors = "";
+    int retVal = 0;
+    *cont->OFS << "* Run coverage for: " << fileDir.c_str() << std::endl;
+    *cont->OFS << "  Command: " << command.c_str() << std::endl;
+    int res = this->CTest->RunCommand(command.c_str(), &output, &errors,
+                &retVal, fileDir.c_str(), 0 /*this->TimeOut*/);
+
+    *cont->OFS << "  Output: " << output.c_str() << std::endl;
+    *cont->OFS << "  Errors: " << errors.c_str() << std::endl;
+    if ( ! res )
+      {
+      cmCTestLog(this->CTest, ERROR_MESSAGE,
+        "Problem running coverage on file: " << it->c_str() << std::endl);
+      cmCTestLog(this->CTest, ERROR_MESSAGE,
+        "Command produced error: " << errors << std::endl);
+      cont->Error ++;
+      continue;
+      }
+    if ( retVal != 0 )
+      {
+      cmCTestLog(this->CTest, ERROR_MESSAGE, "Coverage command returned: "
+        << retVal << " while processing: " << it->c_str() << std::endl);
+      cmCTestLog(this->CTest, ERROR_MESSAGE,
+        "Command produced error: " << cont->Error << std::endl);
+      }
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+      "--------------------------------------------------------------"
+      << std::endl
+      << output << std::endl
+      << "--------------------------------------------------------------"
+      << std::endl);
+
+    std::vector<std::string> lines;
+    std::vector<std::string>::iterator line;
+
+    cmSystemTools::Split(output.c_str(), lines);
+
+    for ( line = lines.begin(); line != lines.end(); ++line)
+      {
+      std::string sourceFile;
+      std::string lcovFile;
+
+      if ( line->size() == 0 )
+        {
+        // Ignore empty line
+        }
+      // Look for LCOV files in binary directory
+      // Intel Compiler creates a CodeCoverage dir for each subfolder and
+      // each subfolder has LCOV files
+      cmsys::Glob gl;
+      gl.RecurseOn();
+      gl.RecurseThroughSymlinksOff();
+      std::string dir;
+      std::vector<std::string> lcovFiles;
+      dir = this->CTest->GetBinaryDir();
+      std::string daGlob;
+      daGlob = dir;
+      daGlob += "/*.LCOV";
+      cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+                 "   looking for LCOV files in: " << daGlob << std::endl);
+      gl.FindFiles(daGlob);
+      // Keep a list of all LCOV files
+      lcovFiles.insert(lcovFiles.end(), gl.GetFiles().begin(),
+                       gl.GetFiles().end());
+
+      for(std::vector<std::string>::iterator a = lcovFiles.begin();
+          a != lcovFiles.end(); ++a)
+        {
+        lcovFile = *a;
+        cmsys::ifstream srcead(lcovFile.c_str());
+        if ( ! srcead )
+          {
+          cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open file: "
+                     << lcovFile << std::endl);
+          }
+        std::string srcname;
+
+        int success = cmSystemTools::GetLineFromStream(srcead, srcname);
+        if ( !success )
+          {
+          cmCTestLog(this->CTest, ERROR_MESSAGE,
+                     "Error while parsing lcov file '" << lcovFile << "':"
+                     << " No source file name found!" << std::endl);
+          return 0;
+          }
+        srcname = srcname.substr(18);
+        // We can directly read found LCOV files to determine the source
+        // files
+        sourceFile = srcname;
+        actualSourceFile = srcname;
+
+        for(std::vector<std::string>::iterator t = lcovFiles.begin();
+            t != lcovFiles.end(); ++t)
+          {
+          cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Found LCOV File: "
+                     << *t << std::endl);
+          }
+        cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "SourceFile: "
+                   << sourceFile << std::endl);
+        cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "lCovFile: "
+                   << lcovFile << std::endl);
+
+        // If we have some LCOV files to process
+        if ( !lcovFile.empty() && !actualSourceFile.empty() )
+          {
+          cmCTestCoverageHandlerContainer::SingleFileCoverageVector& vec
+            = cont->TotalCoverage[actualSourceFile];
+
+          cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "   in lcovFile: "
+                     << lcovFile << std::endl);
+
+          cmsys::ifstream ifile(lcovFile.c_str());
+          if ( ! ifile )
+            {
+            cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open file: "
+                       << lcovFile << std::endl);
+            }
+          else
+            {
+            long cnt = -1;
+            std::string nl;
+
+            // Skip the first line
+            cmSystemTools::GetLineFromStream(ifile, nl);
+            cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+                       "File is ready, start reading." << std::endl);
+            while ( cmSystemTools::GetLineFromStream(ifile, nl) )
+              {
+              cnt ++;
+
+              // Skip empty lines
+              if ( !nl.size() )
+                {
+                continue;
+                }
+
+              // Skip unused lines
+              if ( nl.size() < 12 )
+                {
+                continue;
+                }
+
+              // Read the coverage count from the beginning of the lcov
+              // output line
+              std::string prefix = nl.substr(0, 17);
+              int cov = atoi(prefix.c_str());
+
+              // Read the line number starting at the 17th character of the
+              // lcov output line
+              std::string lineNumber = nl.substr(17, 7);
+
+              int lineIdx = atoi(lineNumber.c_str())-1;
+              if ( lineIdx >= 0 )
+                {
+                while ( vec.size() <= static_cast<size_t>(lineIdx) )
+                  {
+                  vec.push_back(-1);
+                  }
+
+                // Initially all entries are -1 (not used). If we get coverage
+                // information, increment it to 0 first.
+                if ( vec[lineIdx] < 0 )
+                  {
+                  if ( cov > 0 || prefix.find("#") != prefix.npos )
+                    {
+                    vec[lineIdx] = 0;
+                    }
+                  }
+
+                vec[lineIdx] += cov;
+                }
+              }
+            }
+
+          actualSourceFile = "";
+          }
+        }
+      }
+
+    file_count++;
+
+    if ( file_count % 50 == 0 )
+      {
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, " processed: " << file_count
+                 << " out of " << files.size() << std::endl);
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "    ");
+      }
+    }
+
+  cmSystemTools::ChangeDirectory(currentDirectory.c_str());
+  return file_count;
+}
+
 //----------------------------------------------------------------------------
 void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
 {
@@ -1327,6 +1604,34 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
     }
 }
 
+//----------------------------------------------------------------------------
+void cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
+{
+  cmsys::Glob gl;
+  gl.RecurseOff(); // No need of recurse if -prof_dir${BUILD_DIR} flag is
+                   // used while compiling.
+  gl.RecurseThroughSymlinksOff();
+  std::string prevBinaryDir;
+  cmSystemTools::ChangeDirectory(
+    this->CTest->GetCTestConfiguration("BuildDirectory").c_str());
+
+  // Run profmerge to merge all *.dyn files into dpi files
+  cmSystemTools::RunSingleCommand("profmerge");
+
+  prevBinaryDir = cmSystemTools::GetCurrentWorkingDirectory().c_str();
+
+  // DPI file should appear in build directory
+  std::string daGlob;
+  daGlob = prevBinaryDir;
+  daGlob += "/*.dpi";
+  cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+             "   looking for dpi files in: " << daGlob << std::endl);
+  gl.FindFiles(daGlob);
+  files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
+  cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+             "Now searching in: " << daGlob << std::endl);
+}
+
 //----------------------------------------------------------------------
 int cmCTestCoverageHandler::HandleTracePyCoverage(
   cmCTestCoverageHandlerContainer* cont)
diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h
index 6a8f55d..0a0fe81 100644
--- a/Source/CTest/cmCTestCoverageHandler.h
+++ b/Source/CTest/cmCTestCoverageHandler.h
@@ -68,6 +68,10 @@ private:
   int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont);
   void FindGCovFiles(std::vector<std::string>& files);
 
+  //! Handle coverage using Intel's LCov
+  int HandleLCovCoverage(cmCTestCoverageHandlerContainer* cont);
+  void FindLCovFiles(std::vector<std::string>& files);
+
   //! Handle coverage using xdebug php coverage
   int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont);
 

-----------------------------------------------------------------------

Summary of changes:
 Source/CTest/cmCTestCoverageHandler.cxx |  305 +++++++++++++++++++++++++++++++
 Source/CTest/cmCTestCoverageHandler.h   |    4 +
 2 files changed, 309 insertions(+)


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list