1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCTestScriptHandler.cxx,v $
6 Date: $Date: 2008/01/23 15:28:01 $
7 Version: $Revision: 1.43 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmCTestScriptHandler.h"
22 #include "cmFunctionBlocker.h"
23 #include "cmMakefile.h"
24 #include "cmLocalGenerator.h"
25 #include "cmGlobalGenerator.h"
26 #include "cmGeneratedFileStream.h"
28 //#include <cmsys/RegularExpression.hxx>
29 #include <cmsys/Process.h>
46 #include "cmCTestBuildCommand.h"
47 #include "cmCTestConfigureCommand.h"
48 #include "cmCTestCoverageCommand.h"
49 #include "cmCTestEmptyBinaryDirectoryCommand.h"
50 #include "cmCTestMemCheckCommand.h"
51 #include "cmCTestReadCustomFilesCommand.h"
52 #include "cmCTestRunScriptCommand.h"
53 #include "cmCTestSleepCommand.h"
54 #include "cmCTestStartCommand.h"
55 #include "cmCTestSubmitCommand.h"
56 #include "cmCTestTestCommand.h"
57 #include "cmCTestUpdateCommand.h"
59 #define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log"
61 // used to keep elapsed time up to date
62 class cmCTestScriptFunctionBlocker
: public cmFunctionBlocker
65 cmCTestScriptFunctionBlocker() {}
66 virtual ~cmCTestScriptFunctionBlocker() {}
67 virtual bool IsFunctionBlocked(const cmListFileFunction
& lff
,
70 //virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf);
71 //virtual void ScopeEnded(cmMakefile &mf);
73 cmCTestScriptHandler
* CTestScriptHandler
;
76 // simply update the time and don't block anything
77 bool cmCTestScriptFunctionBlocker::
78 IsFunctionBlocked(const cmListFileFunction
& , cmMakefile
&,
81 this->CTestScriptHandler
->UpdateElapsedTime();
85 //----------------------------------------------------------------------
86 cmCTestScriptHandler::cmCTestScriptHandler()
89 this->EmptyBinDir
= false;
90 this->EmptyBinDirOnce
= false;
92 this->LocalGenerator
= 0;
94 this->GlobalGenerator
= 0;
96 this->ScriptStartTime
= 0;
98 // the *60 is becuase the settings are in minutes but GetTime is seconds
99 this->MinimumInterval
= 30*60;
100 this->ContinuousDuration
= -1;
103 //----------------------------------------------------------------------
104 void cmCTestScriptHandler::Initialize()
106 this->Superclass::Initialize();
107 this->Backup
= false;
108 this->EmptyBinDir
= false;
109 this->EmptyBinDirOnce
= false;
111 this->SourceDir
= "";
112 this->BinaryDir
= "";
113 this->BackupSourceDir
= "";
114 this->BackupBinaryDir
= "";
115 this->CTestRoot
= "";
116 this->CVSCheckOut
= "";
118 this->UpdateCmd
= "";
120 this->InitCache
= "";
122 this->CMOutFile
= "";
123 this->ExtraUpdates
.clear();
125 this->MinimumInterval
= 20*60;
126 this->ContinuousDuration
= -1;
128 // what time in seconds did this script start running
129 this->ScriptStartTime
= 0;
132 if (this->LocalGenerator
)
134 delete this->LocalGenerator
;
136 this->LocalGenerator
= 0;
137 if (this->GlobalGenerator
)
139 delete this->GlobalGenerator
;
141 this->GlobalGenerator
= 0;
148 //----------------------------------------------------------------------
149 cmCTestScriptHandler::~cmCTestScriptHandler()
151 // local generator owns the makefile
153 if (this->LocalGenerator
)
155 delete this->LocalGenerator
;
157 this->LocalGenerator
= 0;
158 if (this->GlobalGenerator
)
160 delete this->GlobalGenerator
;
162 this->GlobalGenerator
= 0;
170 //----------------------------------------------------------------------
171 // just adds an argument to the vector
172 void cmCTestScriptHandler::AddConfigurationScript(const char *script
,
175 this->ConfigurationScripts
.push_back(script
);
176 this->ScriptProcessScope
.push_back(pscope
);
180 //----------------------------------------------------------------------
181 // the generic entry point for handling scripts, this routine will run all
182 // the scripts provides a -S arguments
183 int cmCTestScriptHandler::ProcessHandler()
186 for (size_t i
=0; i
< this->ConfigurationScripts
.size(); ++i
)
188 // for each script run it
189 res
+= this->RunConfigurationScript
190 (cmSystemTools::CollapseFullPath(this->ConfigurationScripts
[i
].c_str()),
191 this->ScriptProcessScope
[i
]);
200 void cmCTestScriptHandler::UpdateElapsedTime()
202 if (this->LocalGenerator
)
204 // set the current elapsed time
206 int itime
= static_cast<unsigned int>(cmSystemTools::GetTime()
207 - this->ScriptStartTime
);
208 sprintf(timeString
,"%i",itime
);
209 this->LocalGenerator
->GetMakefile()->AddDefinition("CTEST_ELAPSED_TIME",
214 //----------------------------------------------------------------------
215 void cmCTestScriptHandler::AddCTestCommand(cmCTestCommand
* command
)
217 cmCTestCommand
* newCom
= command
;
218 newCom
->CTest
= this->CTest
;
219 newCom
->CTestScriptHandler
= this;
220 this->CMake
->AddCommand(newCom
);
223 int cmCTestScriptHandler::ExecuteScript(const std::string
& total_script_arg
)
225 // execute the script passing in the arguments to the script as well as the
226 // arguments from this invocation of cmake
227 std::vector
<const char*> argv
;
228 argv
.push_back(this->CTest
->GetCTestExecutable());
229 argv
.push_back("-SR");
230 argv
.push_back(total_script_arg
.c_str());
232 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
233 "Executable for CTest is: " <<
234 this->CTest
->GetCTestExecutable() << "\n");
236 // now pass through all the other arguments
237 std::vector
<cmStdString
> &initArgs
=
238 this->CTest
->GetInitialCommandLineArguments();
239 for(size_t i
=1; i
< initArgs
.size(); ++i
)
241 argv
.push_back(initArgs
[i
].c_str());
245 // Now create process object
246 cmsysProcess
* cp
= cmsysProcess_New();
247 cmsysProcess_SetCommand(cp
, &*argv
.begin());
248 //cmsysProcess_SetWorkingDirectory(cp, dir);
249 cmsysProcess_SetOption(cp
, cmsysProcess_Option_HideWindow
, 1);
250 //cmsysProcess_SetTimeout(cp, timeout);
251 cmsysProcess_Execute(cp
);
253 std::vector
<char> out
;
254 std::vector
<char> err
;
256 int pipe
= cmSystemTools::WaitForLine(cp
, line
, 100.0, out
, err
);
257 while(pipe
!= cmsysProcess_Pipe_None
)
259 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Output: "
261 if(pipe
== cmsysProcess_Pipe_STDERR
)
263 cmCTestLog(this->CTest
, ERROR_MESSAGE
, line
<< "\n");
265 else if(pipe
== cmsysProcess_Pipe_STDOUT
)
267 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, line
<< "\n");
269 pipe
= cmSystemTools::WaitForLine(cp
, line
, 100, out
, err
);
272 // Properly handle output of the build command
273 cmsysProcess_WaitForExit(cp
, 0);
274 int result
= cmsysProcess_GetState(cp
);
277 if(result
== cmsysProcess_State_Exited
)
279 retVal
= cmsysProcess_GetExitValue(cp
);
288 void cmCTestScriptHandler::CreateCMake()
290 // create a cmake instance to read the configuration script
294 delete this->GlobalGenerator
;
295 delete this->LocalGenerator
;
297 this->CMake
= new cmake
;
298 this->CMake
->AddCMakePaths();
299 this->GlobalGenerator
= new cmGlobalGenerator
;
300 this->GlobalGenerator
->SetCMakeInstance(this->CMake
);
302 this->LocalGenerator
= this->GlobalGenerator
->CreateLocalGenerator();
303 this->LocalGenerator
->SetGlobalGenerator(this->GlobalGenerator
);
304 this->Makefile
= this->LocalGenerator
->GetMakefile();
306 // remove all cmake commands which are not scriptable, since they can't be
307 // used in ctest scripts
308 this->CMake
->RemoveUnscriptableCommands();
310 // add any ctest specific commands, probably should have common superclass
311 // for ctest commands to clean this up. If a couple more commands are
312 // created with the same format lets do that - ken
313 this->AddCTestCommand(new cmCTestBuildCommand
);
314 this->AddCTestCommand(new cmCTestConfigureCommand
);
315 this->AddCTestCommand(new cmCTestCoverageCommand
);
316 this->AddCTestCommand(new cmCTestEmptyBinaryDirectoryCommand
);
317 this->AddCTestCommand(new cmCTestMemCheckCommand
);
318 this->AddCTestCommand(new cmCTestReadCustomFilesCommand
);
319 this->AddCTestCommand(new cmCTestRunScriptCommand
);
320 this->AddCTestCommand(new cmCTestSleepCommand
);
321 this->AddCTestCommand(new cmCTestStartCommand
);
322 this->AddCTestCommand(new cmCTestSubmitCommand
);
323 this->AddCTestCommand(new cmCTestTestCommand
);
324 this->AddCTestCommand(new cmCTestUpdateCommand
);
327 void cmCTestScriptHandler::GetCommandDocumentation(
328 std::vector
<cmDocumentationEntry
>& v
) const
330 this->CMake
->GetCommandDocumentation(v
);
333 //----------------------------------------------------------------------
334 // this sets up some variables for the script to use, creates the required
335 // cmake instance and generators, and then reads in the script
336 int cmCTestScriptHandler::ReadInScript(const std::string
& total_script_arg
)
338 // if the argument has a , in it then it needs to be broken into the fist
339 // argument (which is the script) and the second argument which will be
340 // passed into the scripts as S_ARG
341 std::string script
= total_script_arg
;
342 std::string script_arg
;
343 if (total_script_arg
.find(",") != std::string::npos
)
345 script
= total_script_arg
.substr(0,total_script_arg
.find(","));
346 script_arg
= total_script_arg
.substr(total_script_arg
.find(",")+1);
349 // make sure the file exists
350 if (!cmSystemTools::FileExists(script
.c_str()))
352 cmSystemTools::Error("Cannot find file: ", script
.c_str());
356 // read in the list file to fill the cache
357 // create a cmake instance to read the configuration script
360 // set a variable with the path to the current script
361 this->Makefile
->AddDefinition("CTEST_SCRIPT_DIRECTORY",
362 cmSystemTools::GetFilenamePath(script
).c_str());
363 this->Makefile
->AddDefinition("CTEST_SCRIPT_NAME",
364 cmSystemTools::GetFilenameName(script
).c_str());
365 this->Makefile
->AddDefinition("CTEST_EXECUTABLE_NAME",
366 this->CTest
->GetCTestExecutable());
367 this->Makefile
->AddDefinition("CMAKE_EXECUTABLE_NAME",
368 this->CTest
->GetCMakeExecutable());
369 this->Makefile
->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", true);
370 this->UpdateElapsedTime();
372 // add the script arg if defined
373 if (script_arg
.size())
375 this->Makefile
->AddDefinition("CTEST_SCRIPT_ARG", script_arg
.c_str());
378 // always add a function blocker to update the elapsed time
379 cmCTestScriptFunctionBlocker
*f
= new cmCTestScriptFunctionBlocker();
380 f
->CTestScriptHandler
= this;
381 this->Makefile
->AddFunctionBlocker(f
);
383 // finally read in the script
384 if (!this->Makefile
->ReadListFile(0, script
.c_str()) ||
385 cmSystemTools::GetErrorOccuredFlag())
394 //----------------------------------------------------------------------
395 // extract variabels from the script to set ivars
396 int cmCTestScriptHandler::ExtractVariables()
398 // Temporary variables
399 const char* minInterval
;
400 const char* contDuration
;
403 = this->Makefile
->GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
405 = this->Makefile
->GetSafeDefinition("CTEST_BINARY_DIRECTORY");
407 // add in translations for src and bin
408 cmSystemTools::AddKeepPath(this->SourceDir
.c_str());
409 cmSystemTools::AddKeepPath(this->BinaryDir
.c_str());
412 = this->Makefile
->GetSafeDefinition("CTEST_COMMAND");
414 = this->Makefile
->GetSafeDefinition("CTEST_CVS_CHECKOUT");
416 = this->Makefile
->GetSafeDefinition("CTEST_DASHBOARD_ROOT");
418 = this->Makefile
->GetSafeDefinition("CTEST_UPDATE_COMMAND");
419 if ( this->UpdateCmd
.empty() )
422 = this->Makefile
->GetSafeDefinition("CTEST_CVS_COMMAND");
425 = this->Makefile
->GetSafeDefinition("CTEST_ENVIRONMENT");
427 = this->Makefile
->GetSafeDefinition("CTEST_INITIAL_CACHE");
429 = this->Makefile
->GetSafeDefinition("CTEST_CMAKE_COMMAND");
431 = this->Makefile
->GetSafeDefinition("CTEST_CMAKE_OUTPUT_FILE_NAME");
434 = this->Makefile
->IsOn("CTEST_BACKUP_AND_RESTORE");
436 = this->Makefile
->IsOn("CTEST_START_WITH_EMPTY_BINARY_DIRECTORY");
437 this->EmptyBinDirOnce
438 = this->Makefile
->IsOn("CTEST_START_WITH_EMPTY_BINARY_DIRECTORY_ONCE");
441 = this->Makefile
->GetDefinition("CTEST_CONTINUOUS_MINIMUM_INTERVAL");
443 = this->Makefile
->GetDefinition("CTEST_CONTINUOUS_DURATION");
447 for (i
= 1; i
< 10; ++i
)
449 sprintf(updateVar
,"CTEST_EXTRA_UPDATES_%i",i
);
450 const char *updateVal
= this->Makefile
->GetDefinition(updateVar
);
453 if ( this->UpdateCmd
.empty() )
455 cmSystemTools::Error(updateVar
,
456 " specified without specifying CTEST_CVS_COMMAND.");
459 this->ExtraUpdates
.push_back(updateVal
);
463 // in order to backup and restore we also must have the cvs root
464 if (this->Backup
&& this->CVSCheckOut
.empty())
466 cmSystemTools::Error(
467 "Backup was requested without specifying CTEST_CVS_CHECKOUT.");
471 // make sure the required info is here
472 if (this->SourceDir
.empty() ||
473 this->BinaryDir
.empty() ||
474 this->CTestCmd
.empty())
476 std::string msg
= "CTEST_SOURCE_DIRECTORY = ";
477 msg
+= (!this->SourceDir
.empty()) ? this->SourceDir
.c_str() : "(Null)";
478 msg
+= "\nCTEST_BINARY_DIRECTORY = ";
479 msg
+= (!this->BinaryDir
.empty()) ? this->BinaryDir
.c_str() : "(Null)";
480 msg
+= "\nCTEST_COMMAND = ";
481 msg
+= (!this->CTestCmd
.empty()) ? this->CTestCmd
.c_str() : "(Null)";
482 cmSystemTools::Error(
483 "Some required settings in the configuration file were missing:\n",
488 // if the dashboard root isn't specified then we can compute it from the
490 if (this->CTestRoot
.empty() )
492 this->CTestRoot
= cmSystemTools::GetFilenamePath(this->SourceDir
).c_str();
495 // the script may override the minimum continuous interval
498 this->MinimumInterval
= 60 * atof(minInterval
);
502 this->ContinuousDuration
= 60.0 * atof(contDuration
);
506 this->UpdateElapsedTime();
511 //----------------------------------------------------------------------
512 void cmCTestScriptHandler::SleepInSeconds(unsigned int secondsToWait
)
515 Sleep(1000*secondsToWait
);
517 sleep(secondsToWait
);
521 //----------------------------------------------------------------------
522 // run a specific script
523 int cmCTestScriptHandler::RunConfigurationScript
524 (const std::string
& total_script_arg
, bool pscope
)
528 this->ScriptStartTime
=
529 cmSystemTools::GetTime();
531 // read in the script
534 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
535 "Reading Script: " << total_script_arg
<< std::endl
);
536 result
= this->ReadInScript(total_script_arg
);
540 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
541 "Executing Script: " << total_script_arg
<< std::endl
);
542 result
= this->ExecuteScript(total_script_arg
);
549 // only run the curent script if we should
550 if (this->Makefile
&& this->Makefile
->IsOn("CTEST_RUN_CURRENT_SCRIPT"))
552 return this->RunCurrentScript();
557 //----------------------------------------------------------------------
558 int cmCTestScriptHandler::RunCurrentScript()
563 this->Makefile
->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", false);
566 cmSystemTools::SetRunCommandHideConsole(true);
568 // extract the vars from the cache and store in ivars
569 result
= this->ExtractVariables();
575 // set any environment variables
576 if (!this->CTestEnv
.empty())
578 std::vector
<std::string
> envArgs
;
579 cmSystemTools::ExpandListArgument(this->CTestEnv
.c_str(),envArgs
);
580 // for each variable/argument do a putenv
581 for (unsigned i
= 0; i
< envArgs
.size(); ++i
)
583 cmSystemTools::PutEnv(envArgs
[i
].c_str());
587 // now that we have done most of the error checking finally run the
588 // dashboard, we may be asked to repeatedly run this dashboard, such as
589 // for a continuous, do we ned to run it more than once?
590 if ( this->ContinuousDuration
>= 0 )
592 this->UpdateElapsedTime();
593 double ending_time
= cmSystemTools::GetTime() + this->ContinuousDuration
;
594 if (this->EmptyBinDirOnce
)
596 this->EmptyBinDir
= true;
600 double interval
= cmSystemTools::GetTime();
601 result
= this->RunConfigurationDashboard();
602 interval
= cmSystemTools::GetTime() - interval
;
603 if (interval
< this->MinimumInterval
)
605 this->SleepInSeconds(
606 static_cast<unsigned int>(this->MinimumInterval
- interval
));
608 if (this->EmptyBinDirOnce
)
610 this->EmptyBinDir
= false;
613 while (cmSystemTools::GetTime() < ending_time
);
615 // otherwise just run it once
618 result
= this->RunConfigurationDashboard();
624 //----------------------------------------------------------------------
625 int cmCTestScriptHandler::CheckOutSourceDir()
632 if (!cmSystemTools::FileExists(this->SourceDir
.c_str()) &&
633 !this->CVSCheckOut
.empty())
635 // we must now checkout the src dir
637 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
638 "Run cvs: " << this->CVSCheckOut
<< std::endl
);
639 res
= cmSystemTools::RunSingleCommand(this->CVSCheckOut
.c_str(), &output
,
640 &retVal
, this->CTestRoot
.c_str(), this->HandlerVerbose
,
641 0 /*this->TimeOut*/);
642 if (!res
|| retVal
!= 0)
644 cmSystemTools::Error("Unable to perform cvs checkout:\n",
652 //----------------------------------------------------------------------
653 int cmCTestScriptHandler::BackupDirectories()
657 // compute the backup names
658 this->BackupSourceDir
= this->SourceDir
;
659 this->BackupSourceDir
+= "_CMakeBackup";
660 this->BackupBinaryDir
= this->BinaryDir
;
661 this->BackupBinaryDir
+= "_CMakeBackup";
663 // backup the binary and src directories if requested
666 // if for some reason those directories exist then first delete them
667 if (cmSystemTools::FileExists(this->BackupSourceDir
.c_str()))
669 cmSystemTools::RemoveADirectory(this->BackupSourceDir
.c_str());
671 if (cmSystemTools::FileExists(this->BackupBinaryDir
.c_str()))
673 cmSystemTools::RemoveADirectory(this->BackupBinaryDir
.c_str());
676 // first rename the src and binary directories
677 rename(this->SourceDir
.c_str(), this->BackupSourceDir
.c_str());
678 rename(this->BinaryDir
.c_str(), this->BackupBinaryDir
.c_str());
680 // we must now checkout the src dir
681 retVal
= this->CheckOutSourceDir();
684 this->RestoreBackupDirectories();
693 //----------------------------------------------------------------------
694 int cmCTestScriptHandler::PerformExtraUpdates()
701 // do an initial cvs update as required
702 command
= this->UpdateCmd
;
703 std::vector
<cmStdString
>::iterator it
;
704 for (it
= this->ExtraUpdates
.begin();
705 it
!= this->ExtraUpdates
.end();
708 std::vector
<std::string
> cvsArgs
;
709 cmSystemTools::ExpandListArgument(it
->c_str(),cvsArgs
);
710 if (cvsArgs
.size() == 2)
712 std::string fullCommand
= command
;
713 fullCommand
+= " update ";
714 fullCommand
+= cvsArgs
[1];
717 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Run Update: "
718 << fullCommand
.c_str() << std::endl
);
719 res
= cmSystemTools::RunSingleCommand(fullCommand
.c_str(), &output
,
720 &retVal
, cvsArgs
[0].c_str(),
721 this->HandlerVerbose
, 0 /*this->TimeOut*/);
722 if (!res
|| retVal
!= 0)
724 cmSystemTools::Error("Unable to perform extra updates:\n",
725 it
->c_str(), "\nWith output:\n",
735 //----------------------------------------------------------------------
736 // run a single dashboard entry
737 int cmCTestScriptHandler::RunConfigurationDashboard()
745 // make sure the src directory is there, if it isn't then we might be able
746 // to check it out from cvs
747 retVal
= this->CheckOutSourceDir();
753 // backup the dirs if requested
754 retVal
= this->BackupDirectories();
760 // clear the binary directory?
761 if (this->EmptyBinDir
)
763 if ( !cmCTestScriptHandler::EmptyBinaryDirectory(
764 this->BinaryDir
.c_str()) )
766 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
767 "Problem removing the binary directory" << std::endl
);
771 // make sure the binary directory exists if it isn't the srcdir
772 if (!cmSystemTools::FileExists(this->BinaryDir
.c_str()) &&
773 this->SourceDir
!= this->BinaryDir
)
775 if (!cmSystemTools::MakeDirectory(this->BinaryDir
.c_str()))
777 cmSystemTools::Error("Unable to create the binary directory:\n",
778 this->BinaryDir
.c_str());
779 this->RestoreBackupDirectories();
784 // if the binary directory and the source directory are the same,
785 // and we are starting with an empty binary directory, then that means
786 // we must check out the source tree
787 if (this->EmptyBinDir
&& this->SourceDir
== this->BinaryDir
)
789 // make sure we have the required info
790 if (this->CVSCheckOut
.empty())
792 cmSystemTools::Error("You have specified the source and binary "
793 "directories to be the same (an in source build). You have also "
794 "specified that the binary directory is to be erased. This means "
795 "that the source will have to be checked out from CVS. But you have "
796 "not specified CTEST_CVS_CHECKOUT");
800 // we must now checkout the src dir
801 retVal
= this->CheckOutSourceDir();
804 this->RestoreBackupDirectories();
809 // backup the dirs if requested
810 retVal
= this->PerformExtraUpdates();
816 // put the initial cache into the bin dir
817 if (!this->InitCache
.empty())
819 std::string cacheFile
= this->BinaryDir
;
820 cacheFile
+= "/CMakeCache.txt";
821 cmGeneratedFileStream
fout(cacheFile
.c_str());
824 this->RestoreBackupDirectories();
828 fout
.write(this->InitCache
.c_str(), this->InitCache
.size());
830 // Make sure the operating system has finished writing the file
831 // before closing it. This will ensure the file is finished before
837 // do an initial cmake to setup the DartConfig file
839 std::string cmakeFailedOuput
;
840 if (!this->CMakeCmd
.empty())
842 command
= this->CMakeCmd
;
844 command
+= this->SourceDir
;
848 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Run cmake command: "
849 << command
.c_str() << std::endl
);
850 res
= cmSystemTools::RunSingleCommand(command
.c_str(), &output
,
851 &retVal
, this->BinaryDir
.c_str(),
852 this->HandlerVerbose
, 0 /*this->TimeOut*/);
854 if ( !this->CMOutFile
.empty() )
856 std::string cmakeOutputFile
= this->CMOutFile
;
857 if ( !cmSystemTools::FileIsFullPath(cmakeOutputFile
.c_str()) )
859 cmakeOutputFile
= this->BinaryDir
+ "/" + cmakeOutputFile
;
862 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
,
863 "Write CMake output to file: " << cmakeOutputFile
.c_str()
865 cmGeneratedFileStream
fout(cmakeOutputFile
.c_str());
868 fout
<< output
.c_str();
872 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
873 "Cannot open CMake output file: "
874 << cmakeOutputFile
.c_str() << " for writing" << std::endl
);
877 if (!res
|| retVal
!= 0)
879 // even if this fails continue to the next step
881 cmakeFailedOuput
= output
;
885 // run ctest, it may be more than one command in here
886 std::vector
<std::string
> ctestCommands
;
887 cmSystemTools::ExpandListArgument(this->CTestCmd
,ctestCommands
);
888 // for each variable/argument do a putenv
889 for (unsigned i
= 0; i
< ctestCommands
.size(); ++i
)
891 command
= ctestCommands
[i
];
894 cmCTestLog(this->CTest
, HANDLER_VERBOSE_OUTPUT
, "Run ctest command: "
895 << command
.c_str() << std::endl
);
896 res
= cmSystemTools::RunSingleCommand(command
.c_str(), &output
,
897 &retVal
, this->BinaryDir
.c_str(), this->HandlerVerbose
,
898 0 /*this->TimeOut*/);
900 // did something critical fail in ctest
901 if (!res
|| cmakeFailed
||
902 retVal
& cmCTest::BUILD_ERRORS
)
904 this->RestoreBackupDirectories();
907 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
908 "Unable to run cmake:" << std::endl
909 << cmakeFailedOuput
.c_str() << std::endl
);
912 cmCTestLog(this->CTest
, ERROR_MESSAGE
,
913 "Unable to run ctest:" << std::endl
914 << output
.c_str() << std::endl
);
923 // if all was succesful, delete the backup dirs to free up disk space
926 cmSystemTools::RemoveADirectory(this->BackupSourceDir
.c_str());
927 cmSystemTools::RemoveADirectory(this->BackupBinaryDir
.c_str());
934 //-------------------------------------------------------------------------
935 void cmCTestScriptHandler::RestoreBackupDirectories()
937 // if we backed up the dirs and the build failed, then restore
938 // the backed up dirs
941 // if for some reason those directories exist then first delete them
942 if (cmSystemTools::FileExists(this->SourceDir
.c_str()))
944 cmSystemTools::RemoveADirectory(this->SourceDir
.c_str());
946 if (cmSystemTools::FileExists(this->BinaryDir
.c_str()))
948 cmSystemTools::RemoveADirectory(this->BinaryDir
.c_str());
950 // rename the src and binary directories
951 rename(this->BackupSourceDir
.c_str(), this->SourceDir
.c_str());
952 rename(this->BackupBinaryDir
.c_str(), this->BinaryDir
.c_str());
956 bool cmCTestScriptHandler::RunScript(cmCTest
* ctest
, const char *sname
,
959 cmCTestScriptHandler
* sh
= new cmCTestScriptHandler();
960 sh
->SetCTestInstance(ctest
);
961 sh
->AddConfigurationScript(sname
,InProcess
);
962 sh
->ProcessHandler();
967 bool cmCTestScriptHandler::EmptyBinaryDirectory(const char *sname
)
969 // try to avoid deleting root
970 if (!sname
|| strlen(sname
) < 2)
975 // try to avoid deleting directories that we shouldn't
976 std::string check
= sname
;
977 check
+= "/CMakeCache.txt";
978 if(cmSystemTools::FileExists(check
.c_str()) &&
979 !cmSystemTools::RemoveADirectory(sname
))
986 //-------------------------------------------------------------------------
987 double cmCTestScriptHandler::GetRemainingTimeAllowed()
994 const char *timelimitS
995 = this->Makefile
->GetDefinition("CTEST_TIME_LIMIT");
1002 double timelimit
= atof(timelimitS
);
1004 return timelimit
- cmSystemTools::GetTime() + this->ScriptStartTime
;