[Cmake-commits] [cmake-commits] king committed cmCTestBuildHandler.cxx 1.70 1.71 cmCTestBuildHandler.h 1.15 1.16
cmake-commits at cmake.org
cmake-commits at cmake.org
Wed Feb 11 15:18:10 EST 2009
Update of /cvsroot/CMake/CMake/Source/CTest
In directory public:/mounts/ram/cvs-serv19955/Source/CTest
Modified Files:
cmCTestBuildHandler.cxx cmCTestBuildHandler.h
Log Message:
ENH: Teach CTest dashboard builds to use launchers
This defines a 'UseLaunchers' CTest configuration option. When enabled,
CTest skips log scraping from the Build step output. Instead it defines
the environment variable CTEST_LAUNCH_LOGS to a log directory during the
build. After the build it looks for error-*.xml and warning-*.xml files
containing fragments for inclusion in Build.xml and submission.
This is useful in conjuction with 'ctest --launch' and the RULE_LAUNCH_*
properties to get reliable, highly-granular build failure reports.
Index: cmCTestBuildHandler.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CTest/cmCTestBuildHandler.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -C 2 -d -r1.15 -r1.16
*** cmCTestBuildHandler.h 4 Feb 2009 19:34:12 -0000 1.15
--- cmCTestBuildHandler.h 11 Feb 2009 20:18:08 -0000 1.16
***************
*** 88,93 ****
--- 88,97 ----
// generate the XML output
void GenerateXMLHeader(std::ostream& os);
+ void GenerateXMLLaunched(std::ostream& os);
void GenerateXMLLogScraped(std::ostream& os);
void GenerateXMLFooter(std::ostream& os, double elapsed_build_time);
+ void GenerateXMLLaunchedFragment(std::ostream& os, const char* fname);
+ bool IsLaunchedErrorFile(const char* fname);
+ bool IsLaunchedWarningFile(const char* fname);
std::string StartBuild;
***************
*** 100,103 ****
--- 104,109 ----
std::vector<cmStdString> CustomWarningMatches;
std::vector<cmStdString> CustomWarningExceptions;
+ std::vector<std::string> ReallyCustomWarningMatches;
+ std::vector<std::string> ReallyCustomWarningExceptions;
std::vector<cmCTestCompileErrorWarningRex> ErrorWarningFileLineRegex;
***************
*** 138,141 ****
--- 144,153 ----
int MaxErrors;
int MaxWarnings;
+
+ bool UseCTestLaunch;
+ std::string CTestLaunchDir;
+ class LaunchHelper;
+ friend class LaunchHelper;
+ class FragmentCompare;
};
Index: cmCTestBuildHandler.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CTest/cmCTestBuildHandler.cxx,v
retrieving revision 1.70
retrieving revision 1.71
diff -C 2 -d -r1.70 -r1.71
*** cmCTestBuildHandler.cxx 5 Feb 2009 21:31:37 -0000 1.70
--- cmCTestBuildHandler.cxx 11 Feb 2009 20:18:08 -0000 1.71
***************
*** 25,31 ****
--- 25,33 ----
#include "cmGeneratedFileStream.h"
#include "cmXMLSafe.h"
+ #include "cmFileTimeComparison.h"
//#include <cmsys/RegularExpression.hxx>
#include <cmsys/Process.h>
+ #include <cmsys/Directory.hxx>
// used for sleep
***************
*** 186,189 ****
--- 188,192 ----
this->LastErrorOrWarning = this->ErrorsAndWarnings.end();
+ this->UseCTestLaunch = false;
}
***************
*** 198,201 ****
--- 201,206 ----
this->CustomWarningMatches.clear();
this->CustomWarningExceptions.clear();
+ this->ReallyCustomWarningMatches.clear();
+ this->ReallyCustomWarningExceptions.clear();
this->ErrorWarningFileLineRegex.clear();
***************
*** 228,231 ****
--- 233,238 ----
this->MaxErrors = 50;
this->MaxWarnings = 50;
+
+ this->UseCTestLaunch = false;
}
***************
*** 247,250 ****
--- 254,271 ----
"CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS",
this->MaxWarnings);
+
+ // Record the user-specified custom warning rules.
+ if(const char* customWarningMatchers =
+ mf->GetDefinition("CTEST_CUSTOM_WARNING_MATCH"))
+ {
+ cmSystemTools::ExpandListArgument(customWarningMatchers,
+ this->ReallyCustomWarningMatches);
+ }
+ if(const char* customWarningExceptions =
+ mf->GetDefinition("CTEST_CUSTOM_WARNING_EXCEPTION"))
+ {
+ cmSystemTools::ExpandListArgument(customWarningExceptions,
+ this->ReallyCustomWarningExceptions);
+ }
}
***************
*** 307,310 ****
--- 328,335 ----
}
+ std::string const& useLaunchers =
+ this->CTest->GetCTestConfiguration("UseLaunchers");
+ this->UseCTestLaunch = cmSystemTools::IsOn(useLaunchers.c_str());
+
// Create a last build log
cmGeneratedFileStream ofs;
***************
*** 468,472 ****
}
this->GenerateXMLHeader(xofs);
! this->GenerateXMLLogScraped(xofs);
this->GenerateXMLFooter(xofs, elapsed_build_time);
--- 493,504 ----
}
this->GenerateXMLHeader(xofs);
! if(this->UseCTestLaunch)
! {
! this->GenerateXMLLaunched(xofs);
! }
! else
! {
! this->GenerateXMLLogScraped(xofs);
! }
this->GenerateXMLFooter(xofs, elapsed_build_time);
***************
*** 498,501 ****
--- 530,597 ----
//----------------------------------------------------------------------------
+ class cmCTestBuildHandler::FragmentCompare
+ {
+ public:
+ FragmentCompare(cmFileTimeComparison* ftc): FTC(ftc) {}
+ bool operator()(std::string const& l, std::string const& r)
+ {
+ // Order files by modification time. If comparison fails, just
+ // use lexicographic order (should not happen in our use case).
+ int result;
+ if(this->FTC->FileTimeCompare(l.c_str(), r.c_str(), &result))
+ {
+ return result < 0;
+ }
+ else
+ {
+ return l < r;
+ }
+ }
+ private:
+ cmFileTimeComparison* FTC;
+ };
+
+ //----------------------------------------------------------------------------
+ void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os)
+ {
+ if(this->CTestLaunchDir.empty())
+ {
+ return;
+ }
+
+ // Sort XML fragments in chronological order.
+ cmFileTimeComparison ftc;
+ FragmentCompare fragmentCompare(&ftc);
+ typedef std::set<cmStdString, FragmentCompare> Fragments;
+ Fragments fragments(fragmentCompare);
+
+ // Identify fragments on disk.
+ cmsys::Directory launchDir;
+ launchDir.Load(this->CTestLaunchDir.c_str());
+ unsigned long n = launchDir.GetNumberOfFiles();
+ for(unsigned long i=0; i < n; ++i)
+ {
+ const char* fname = launchDir.GetFile(i);
+ if(this->IsLaunchedErrorFile(fname))
+ {
+ fragments.insert(this->CTestLaunchDir + "/" + fname);
+ ++this->TotalErrors;
+ }
+ else if(this->IsLaunchedWarningFile(fname))
+ {
+ fragments.insert(this->CTestLaunchDir + "/" + fname);
+ ++this->TotalWarnings;
+ }
+ }
+
+ // Copy the fragments into the final XML file.
+ for(Fragments::const_iterator fi = fragments.begin();
+ fi != fragments.end(); ++fi)
+ {
+ this->GenerateXMLLaunchedFragment(os, fi->c_str());
+ }
+ }
+
+ //----------------------------------------------------------------------------
void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os)
{
***************
*** 613,616 ****
--- 709,740 ----
}
+ //----------------------------------------------------------------------------
+ void cmCTestBuildHandler::GenerateXMLLaunchedFragment(std::ostream& os,
+ const char* fname)
+ {
+ std::ifstream fin(fname, std::ios::in | std::ios::binary);
+ std::string line;
+ while(cmSystemTools::GetLineFromStream(fin, line))
+ {
+ os << line << "\n";
+ }
+ }
+
+ //----------------------------------------------------------------------------
+ bool cmCTestBuildHandler::IsLaunchedErrorFile(const char* fname)
+ {
+ // error-{hash}.xml
+ return (strncmp(fname, "error-", 6) == 0 &&
+ strcmp(fname+strlen(fname)-4, ".xml") == 0);
+ }
+
+ //----------------------------------------------------------------------------
+ bool cmCTestBuildHandler::IsLaunchedWarningFile(const char* fname)
+ {
+ // warning-{hash}.xml
+ return (strncmp(fname, "warning-", 8) == 0 &&
+ strcmp(fname+strlen(fname)-4, ".xml") == 0);
+ }
+
//######################################################################
//######################################################################
***************
*** 618,621 ****
--- 742,841 ----
//######################################################################
+ //----------------------------------------------------------------------------
+ class cmCTestBuildHandler::LaunchHelper
+ {
+ public:
+ LaunchHelper(cmCTestBuildHandler* handler);
+ ~LaunchHelper();
+ private:
+ cmCTestBuildHandler* Handler;
+ cmCTest* CTest;
+
+ void WriteScrapeMatchers();
+ void WriteScrapeMatchers(const char* purpose,
+ std::vector<std::string> const& matchers);
+ };
+
+ //----------------------------------------------------------------------------
+ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler):
+ Handler(handler), CTest(handler->CTest)
+ {
+ std::string tag = this->CTest->GetCurrentTag();
+ if(tag.empty())
+ {
+ // This is not for a dashboard submission, so there is no XML.
+ // Skip enabling the launchers.
+ this->Handler->UseCTestLaunch = false;
+ }
+ else
+ {
+ // Compute a directory in which to store launcher fragments.
+ std::string& launchDir = this->Handler->CTestLaunchDir;
+ launchDir = this->CTest->GetBinaryDir();
+ launchDir += "/Testing/";
+ launchDir += tag;
+ launchDir += "/Build";
+
+ // Clean out any existing launcher fragments.
+ cmSystemTools::RemoveADirectory(launchDir.c_str());
+
+ if(this->Handler->UseCTestLaunch)
+ {
+ // Enable launcher fragments.
+ cmSystemTools::MakeDirectory(launchDir.c_str());
+ this->WriteScrapeMatchers();
+ std::string launchEnv = "CTEST_LAUNCH_LOGS=";
+ launchEnv += launchDir;
+ cmSystemTools::PutEnv(launchEnv.c_str());
+ }
+ }
+
+ // If not using launchers, make sure they passthru.
+ if(!this->Handler->UseCTestLaunch)
+ {
+ cmSystemTools::UnsetEnv("CTEST_LAUNCH_LOGS");
+ }
+ }
+
+ //----------------------------------------------------------------------------
+ cmCTestBuildHandler::LaunchHelper::~LaunchHelper()
+ {
+ if(this->Handler->UseCTestLaunch)
+ {
+ cmSystemTools::UnsetEnv("CTEST_LAUNCH_LOGS");
+ }
+ }
+
+ //----------------------------------------------------------------------------
+ void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers()
+ {
+ this->WriteScrapeMatchers("Warning",
+ this->Handler->ReallyCustomWarningMatches);
+ this->WriteScrapeMatchers("WarningSuppress",
+ this->Handler->ReallyCustomWarningExceptions);
+ }
+
+ //----------------------------------------------------------------------------
+ void
+ cmCTestBuildHandler::LaunchHelper
+ ::WriteScrapeMatchers(const char* purpose,
+ std::vector<std::string> const& matchers)
+ {
+ if(matchers.empty())
+ {
+ return;
+ }
+ std::string fname = this->Handler->CTestLaunchDir;
+ fname += "/Custom";
+ fname += purpose;
+ fname += ".txt";
+ cmGeneratedFileStream fout(fname.c_str());
+ for(std::vector<std::string>::const_iterator mi = matchers.begin();
+ mi != matchers.end(); ++mi)
+ {
+ fout << *mi << "\n";
+ }
+ }
+
//----------------------------------------------------------------------
int cmCTestBuildHandler::RunMakeCommand(const char* command,
***************
*** 646,649 ****
--- 866,873 ----
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl);
+ // Optionally use make rule launchers to record errors and warnings.
+ LaunchHelper launchHelper(this);
+ static_cast<void>(launchHelper);
+
// Now create process object
cmsysProcess* cp = cmsysProcess_New();
***************
*** 663,667 ****
" Each symbol represents " << tick_len << " bytes of output."
<< std::endl
! << " '!' represents an error and '*' a warning." << std::endl
<< " " << std::flush);
--- 887,892 ----
" Each symbol represents " << tick_len << " bytes of output."
<< std::endl
! << (this->UseCTestLaunch? "" :
! " '!' represents an error and '*' a warning.\n")
<< " " << std::flush);
***************
*** 940,943 ****
--- 1165,1174 ----
int cmCTestBuildHandler::ProcessSingleLine(const char* data)
{
+ if(this->UseCTestLaunch)
+ {
+ // No log scraping when using launchers.
+ return b_REGULAR_LINE;
+ }
+
cmCTestLog(this->CTest, DEBUG, "Line: [" << data << "]" << std::endl);
More information about the Cmake-commits
mailing list