diff options
author | Ken Martin <ken.martin@kitware.com> | 2004-09-07 14:37:39 (GMT) |
---|---|---|
committer | Ken Martin <ken.martin@kitware.com> | 2004-09-07 14:37:39 (GMT) |
commit | 8a2beddad462eb4fb8baa8569b4c2bb51039a517 (patch) | |
tree | 7c9020a4fea0f24d039a2810aec7b45c89195193 /Source/CTest | |
parent | 05d985c08277350c3a1ca5ea6023ac397cf9bf1b (diff) | |
download | CMake-8a2beddad462eb4fb8baa8569b4c2bb51039a517.zip CMake-8a2beddad462eb4fb8baa8569b4c2bb51039a517.tar.gz CMake-8a2beddad462eb4fb8baa8569b4c2bb51039a517.tar.bz2 |
more cleanup
Diffstat (limited to 'Source/CTest')
-rw-r--r-- | Source/CTest/cmCTestBuildHandler.cxx | 453 | ||||
-rw-r--r-- | Source/CTest/cmCTestBuildHandler.h | 81 |
2 files changed, 534 insertions, 0 deletions
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx new file mode 100644 index 0000000..38d19ad --- /dev/null +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -0,0 +1,453 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "cmCTestBuildHandler.h" + +#include "cmCTest.h" +#include "cmake.h" +#include "cmMakefile.h" +#include "cmLocalGenerator.h" +#include "cmGlobalGenerator.h" + +//#include <cmsys/RegularExpression.hxx> +#include <cmsys/Process.h> + +// used for sleep +#ifdef _WIN32 +#include "windows.h" +#endif + +#include <stdlib.h> +#include <time.h> +#include <math.h> +#include <float.h> + + +//---------------------------------------------------------------------- +cmCTestBuildHandler::cmCTestBuildHandler() +{ + m_Verbose = false; + m_CTest = 0; +} + +static const char* cmCTestErrorMatches[] = { + "^[Bb]us [Ee]rror", + "^[Ss]egmentation [Vv]iolation", + "^[Ss]egmentation [Ff]ault", + "([^ :]+):([0-9]+): ([^ \\t])", + "([^:]+): error[ \\t]*[0-9]+[ \\t]*:", + "^Error ([0-9]+):", + "^Fatal", + "^Error: ", + "^Error ", + "[0-9] ERROR: ", + "^\"[^\"]+\", line [0-9]+: [^Ww]", + "^cc[^C]*CC: ERROR File = ([^,]+), Line = ([0-9]+)", + "^ld([^:])*:([ \\t])*ERROR([^:])*:", + "^ild:([ \\t])*\\(undefined symbol\\)", + "([^ :]+) : (error|fatal error|catastrophic error)", + "([^:]+): (Error:|error|undefined reference|multiply defined)", + "([^:]+)\\(([^\\)]+)\\) : (error|fatal error|catastrophic error)", + "^fatal error C[0-9]+:", + ": syntax error ", + "^collect2: ld returned 1 exit status", + "Unsatisfied symbols:", + "^Unresolved:", + "Undefined symbols:", + "^Undefined[ \\t]+first referenced", + "^CMake Error:", + ":[ \\t]cannot find", + ":[ \\t]can't find", + ": \\*\\*\\* No rule to make target \\`.*\\'. Stop", + ": Invalid loader fixup for symbol", + ": internal link edit command failed", + ": Unrecognized option \\`.*\\'", + "\", line [0-9]+\\.[0-9]+: [0-9]+-[0-9]+ \\([^W]\\)", + "ld: 0706-006 Cannot find or open library file: -l ", + "ild: \\(argument error\\) can't find library argument ::", + "^could not be found and will not be loaded.", + "s:616 string too big", + "make: Fatal error: ", + "ld: 0711-993 Error occurred while writing to the output file:", + "make: \\*\\*\\*.*Error", + 0 +}; + +static const char* cmCTestErrorExceptions[] = { + "instantiated from ", + "candidates are:", + ": warning", + "makefile:", + "Makefile:", + ":[ \\t]+Where:", + "([^ :]+):([0-9]+): Warning", + 0 +}; + +static const char* cmCTestWarningMatches[] = { + "([^ :]+):([0-9]+): warning:", + "^cc[^C]*CC: WARNING File = ([^,]+), Line = ([0-9]+)", + "^ld([^:])*:([ \\t])*WARNING([^:])*:", + "([^:]+): warning ([0-9]+):", + "^\"[^\"]+\", line [0-9]+: [Ww]arning", + "([^:]+): warning[ \\t]*[0-9]+[ \\t]*:", + "^Warning ([0-9]+):", + "^Warning ", + "WARNING: ", + "([^ :]+) : warning", + "([^:]+): warning", + "\", line [0-9]+\\.[0-9]+: [0-9]+-[0-9]+ \\(W\\)", + "^cxx: Warning:", + ".*file: .* has no symbols", + "([^ :]+):([0-9]+): Warning", + 0 +}; + +static const char* cmCTestWarningExceptions[] = { + "/usr/openwin/include/X11/Xlib\\.h:[0-9]+: warning: ANSI C\\+\\+ forbids declaration", + "/usr/openwin/include/X11/Xutil\\.h:[0-9]+: warning: ANSI C\\+\\+ forbids declaration", + "/usr/openwin/include/X11/XResource\\.h:[0-9]+: warning: ANSI C\\+\\+ forbids declaration", + "WARNING 84 :", + "WARNING 47 :", + "makefile:", + "Makefile:", + "warning: Clock skew detected. Your build may be incomplete.", + "/usr/openwin/include/GL/[^:]+:", + "bind_at_load", + "XrmQGetResource", + "IceFlush", + "warning LNK4089: all references to [^ \\t]+ discarded by .OPT:REF", + "ld32: WARNING 85: definition of dataKey in", + "cc: warning 422: Unknown option \"\\+b", + "_with_warning_C", + 0 +}; + + +//---------------------------------------------------------------------- +void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile *mf) +{ + cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_ERROR_MATCH", + m_CustomErrorMatches); + cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_ERROR_EXCEPTION", + m_CustomErrorExceptions); + cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_WARNING_MATCH", + m_CustomWarningMatches); + cmCTest::PopulateCustomVector(mf, "CTEST_CUSTOM_WARNING_EXCEPTION", + m_CustomWarningExceptions); +} + +//---------------------------------------------------------------------- +//clearly it would be nice if this were broken up into a few smaller +//functions and commented... +int cmCTestBuildHandler::BuildDirectory(cmCTest *ctest_inst) +{ + m_CTest = ctest_inst; + + std::cout << "Build project" << std::endl; + std::string makeCommand = m_CTest->GetDartConfiguration("MakeCommand"); + if ( makeCommand.size() == 0 ) + { + std::cerr << "Cannot find MakeCommand key in the DartConfiguration.tcl" << std::endl; + return 1; + } + std::string buildDirectory = m_CTest->GetDartConfiguration("BuildDirectory"); + if ( buildDirectory.size() == 0 ) + { + std::cerr << "Cannot find BuildDirectory key in the DartConfiguration.tcl" << std::endl; + return 1; + } + + std::ofstream ofs; + double elapsed_time_start = cmSystemTools::GetTime(); + if ( !m_CTest->OpenOutputFile("Temporary", "LastBuild.log", ofs) ) + { + std::cerr << "Cannot create LastBuild.log file" << std::endl; + } + m_StartBuild = m_CTest->CurrentTime(); + std::string output; + int retVal = 0; + int res = cmsysProcess_State_Exited; + if ( !m_CTest->GetShowOnly() ) + { + res = m_CTest->RunMakeCommand(makeCommand.c_str(), &output, + &retVal, buildDirectory.c_str(), + m_Verbose, 0, ofs); + } + else + { + std::cout << "Build with command: " << makeCommand << std::endl; + } + m_EndBuild = m_CTest->CurrentTime(); + double elapsed_build_time = cmSystemTools::GetTime() - elapsed_time_start; + if (res != cmsysProcess_State_Exited || retVal ) + { + std::cerr << "Error(s) when building project" << std::endl; + } + if ( ofs ) + { + ofs.close(); + } + + std::vector<cmStdString>::size_type cc; + if ( m_CTest->GetDartConfiguration("SourceDirectory").size() > 20 || + m_CTest->GetDartConfiguration("BuildDirectory").size() > 20 ) + { + std::string srcdir = m_CTest->GetDartConfiguration("SourceDirectory") + "/"; + std::string bindir = m_CTest->GetDartConfiguration("BuildDirectory") + "/"; + std::string srcdirrep; + std::string bindirrep; + for ( cc = srcdir.size()-2; cc > 0; cc -- ) + { + if ( srcdir[cc] == '/' ) + { + srcdirrep = srcdir.c_str() + cc; + srcdirrep = "/..." + srcdirrep; + srcdir = srcdir.substr(0, cc+1); + break; + } + } + for ( cc = bindir.size()-2; cc > 0; cc -- ) + { + if ( bindir[cc] == '/' ) + { + bindirrep = bindir.c_str() + cc; + bindirrep = "/..." + bindirrep; + bindir = bindir.substr(0, cc+1); + break; + } + } + + cmSystemTools::ReplaceString(output, srcdir.c_str(), "/.../"); //srcdirrep.c_str()); + cmSystemTools::ReplaceString(output, bindir.c_str(), "/.../"); //bindirrep.c_str()); + } + + // Parsing of output for errors and warnings. + + std::vector<cmStdString> lines; + cmSystemTools::Split(output.c_str(), lines); + + + // Lines are marked: + // 0 - nothing + // 1 - error + // > 1 - warning + std::vector<int> markedLines(lines.size(), 0); + + // Errors + for ( cc = 0; cmCTestErrorMatches[cc]; cc ++ ) + { + m_CustomErrorMatches.push_back(cmCTestErrorMatches[cc]); + } + for ( cc = 0; cmCTestErrorExceptions[cc]; cc ++ ) + { + m_CustomErrorExceptions.push_back(cmCTestErrorExceptions[cc]); + } + for ( cc = 0; cmCTestWarningMatches[cc]; cc ++ ) + { + m_CustomWarningMatches.push_back(cmCTestWarningMatches[cc]); + } + for ( cc = 0; cmCTestWarningExceptions[cc]; cc ++ ) + { + m_CustomWarningExceptions.push_back(cmCTestWarningExceptions[cc]); + } + + for ( cc = 0; cc < m_CustomErrorMatches.size(); cc ++ ) + { + cmsys::RegularExpression re(m_CustomErrorMatches[cc].c_str()); + std::vector<cmStdString>::size_type kk; + for ( kk = 0; kk < lines.size(); kk ++ ) + { + if ( re.find(lines[kk]) ) + { + markedLines[kk] = 1; + } + } + } + // Warnings + for ( cc = 0; cc < m_CustomWarningMatches.size(); cc ++ ) + { + cmsys::RegularExpression re(m_CustomWarningMatches[cc].c_str()); + std::vector<cmStdString>::size_type kk; + for ( kk = 0; kk < lines.size(); kk ++ ) + { + if ( re.find(lines[kk]) ) + { + markedLines[kk] += 2; + } + } + } + // Errors exceptions + for ( cc = 0; cc < m_CustomErrorExceptions.size(); cc ++ ) + { + cmsys::RegularExpression re(m_CustomErrorExceptions[cc].c_str()); + std::vector<int>::size_type kk; + for ( kk =0; kk < markedLines.size(); kk ++ ) + { + if ( markedLines[kk] == 1 ) + { + if ( re.find(lines[kk]) ) + { + markedLines[kk] = 0; + } + } + } + } + // Warning exceptions + for ( cc = 0; cc < m_CustomWarningExceptions.size(); cc ++ ) + { + cmsys::RegularExpression re(m_CustomWarningExceptions[cc].c_str()); + std::vector<int>::size_type kk; + for ( kk =0; kk < markedLines.size(); kk ++ ) + { + if ( markedLines[kk] > 1 ) + { + if ( re.find(lines[kk]) ) + { + markedLines[kk] = 0; + } + } + } + } + std::vector<cmCTestBuildErrorWarning> errorsWarnings; + + int errors = 0; + int warnings = 0; + + std::vector<int>::size_type kk; + cmCTestBuildErrorWarning errorwarning; + for ( kk =0; kk < markedLines.size(); kk ++ ) + { + errorwarning.m_LineNumber = -1; + bool found = false; + if ( markedLines[kk] == 1 ) + { + //std::cout << "Error: " << lines[kk] << std::endl; + errorwarning.m_Error = true; + found = true; + } + else if ( markedLines[kk] > 1 ) + { + //std::cout << "Warning: " << lines[kk] << std::endl; + errorwarning.m_Error = false; + found = true; + } + if ( found ) + { + errorwarning.m_LogLine = static_cast<int>(kk+1); + errorwarning.m_Text = lines[kk]; + errorwarning.m_PreContext = ""; + errorwarning.m_PostContext = ""; + std::vector<int>::size_type jj; + std::vector<int>::size_type ll = 0; + if ( kk > 6 ) + { + ll = kk - 6; + } + for ( jj = kk-1; + jj > 0 && jj > ll && markedLines[jj] != markedLines[kk]; + jj -- ); + while ( markedLines[jj] == markedLines[kk] && jj < kk ) + { + jj ++; + } + for (; jj < kk; jj ++ ) + { + errorwarning.m_PreContext += lines[jj] + "\n"; + } + for ( jj = kk+1; + jj < lines.size() && jj < kk + 7 && markedLines[jj] != markedLines[kk]; + jj ++ ) + { + errorwarning.m_PostContext += lines[jj] + "\n"; + } + errorsWarnings.push_back(errorwarning); + if ( errorwarning.m_Error ) + { + errors ++; + } + else + { + warnings ++; + } + } + } + + std::cout << " " << errors << " Compiler errors" << std::endl; + std::cout << " " << warnings << " Compiler warnings" << std::endl; + + if( !m_CTest->OpenOutputFile(m_CTest->GetCurrentTag(), "Build.xml", ofs) ) + { + std::cerr << "Cannot create build XML file" << std::endl; + return 1; + } + this->GenerateDartBuildOutput(ofs, errorsWarnings, elapsed_build_time); + return 0; +} + + +void cmCTestBuildHandler::GenerateDartBuildOutput( + std::ostream& os, + std::vector<cmCTestBuildErrorWarning> ew, + double elapsed_build_time) +{ + m_CTest->StartXML(os); + os << "<Build>\n" + << "\t<StartDateTime>" << m_StartBuild << "</StartDateTime>\n" + << "<BuildCommand>" + << m_CTest->MakeXMLSafe(m_CTest->GetDartConfiguration("MakeCommand")) + << "</BuildCommand>" << std::endl; + + std::vector<cmCTestBuildErrorWarning>::iterator it; + for ( it = ew.begin(); it != ew.end(); it++ ) + { + cmCTestBuildErrorWarning *cm = &(*it); + os << "\t<" << (cm->m_Error ? "Error" : "Warning") << ">\n" + << "\t\t<BuildLogLine>" << cm->m_LogLine << "</BuildLogLine>\n" + << "\t\t<Text>" << m_CTest->MakeXMLSafe(cm->m_Text) + << "\n</Text>" << std::endl; + if ( cm->m_SourceFile.size() > 0 ) + { + os << "\t\t<SourceFile>" << cm->m_SourceFile << "</SourceFile>" + << std::endl; + } + if ( cm->m_SourceFileTail.size() > 0 ) + { + os << "\t\t<SourceFileTail>" << cm->m_SourceFileTail + << "</SourceFileTail>" << std::endl; + } + if ( cm->m_LineNumber >= 0 ) + { + os << "\t\t<SourceLineNumber>" << cm->m_LineNumber + << "</SourceLineNumber>" << std::endl; + } + os << "\t\t<PreContext>" << m_CTest->MakeXMLSafe(cm->m_PreContext) + << "</PreContext>\n" + << "\t\t<PostContext>" << m_CTest->MakeXMLSafe(cm->m_PostContext) + << "</PostContext>\n" + << "\t\t<RepeatCount>0</RepeatCount>\n" + << "</" << (cm->m_Error ? "Error" : "Warning") << ">\n\n" + << std::endl; + } + os << "\t<Log Encoding=\"base64\" Compression=\"/bin/gzip\">\n\t</Log>\n" + << "\t<EndDateTime>" << m_EndBuild << "</EndDateTime>\n" + << "<ElapsedMinutes>" << static_cast<int>(elapsed_build_time/6)/10.0 + << "</ElapsedMinutes>" + << "</Build>" << std::endl; + m_CTest->EndXML(os); +} + diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h new file mode 100644 index 0000000..ec4c14f --- /dev/null +++ b/Source/CTest/cmCTestBuildHandler.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef cmCTestBuildHandler_h +#define cmCTestBuildHandler_h + + +#include "cmStandardIncludes.h" +#include "cmListFileCache.h" + +class cmCTest; +class cmMakefile; + +/** \class cmCTestBuildHandler + * \brief A class that handles ctest -S invocations + * + */ +class cmCTestBuildHandler +{ +public: + + /* + * The main entry point for this class + */ + int BuildDirectory(cmCTest *); + + /* + * If verbose then more informaiton is printed out + */ + void SetVerbose(bool val) { m_Verbose = val; } + + cmCTestBuildHandler(); + + void PopulateCustomVectors(cmMakefile *mf); + +private: + struct cmCTestBuildErrorWarning + { + bool m_Error; + int m_LogLine; + std::string m_Text; + std::string m_SourceFile; + std::string m_SourceFileTail; + int m_LineNumber; + std::string m_PreContext; + std::string m_PostContext; + }; + + // generate the XML output + void GenerateDartBuildOutput(std::ostream& os, + std::vector<cmCTestBuildErrorWarning>, + double elapsed_time); + + + bool m_Verbose; + cmCTest *m_CTest; + + std::string m_StartBuild; + std::string m_EndBuild; + + std::vector<cmStdString> m_CustomErrorMatches; + std::vector<cmStdString> m_CustomErrorExceptions; + std::vector<cmStdString> m_CustomWarningMatches; + std::vector<cmStdString> m_CustomWarningExceptions; +}; + +#endif |