summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKen Martin <ken.martin@kitware.com>2006-04-04 17:04:28 (GMT)
committerKen Martin <ken.martin@kitware.com>2006-04-04 17:04:28 (GMT)
commitd81ebf0c23307162dfc5c4a3c978ad9360bee354 (patch)
tree615b1ec7ff9d411e5d9cffa5c90d3f40641fd446
parentb45f4a5d450c4fd56fd564fe67be00c7aeb4b59a (diff)
downloadCMake-d81ebf0c23307162dfc5c4a3c978ad9360bee354.zip
CMake-d81ebf0c23307162dfc5c4a3c978ad9360bee354.tar.gz
CMake-d81ebf0c23307162dfc5c4a3c978ad9360bee354.tar.bz2
ENH: added support for -SP scripts in new processes
-rw-r--r--Source/CTest/cmCTestRunScriptCommand.cxx12
-rw-r--r--Source/CTest/cmCTestRunScriptCommand.h5
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx101
-rw-r--r--Source/CTest/cmCTestScriptHandler.h11
-rw-r--r--Source/cmCTest.cxx36
-rw-r--r--Source/cmCTest.h6
-rw-r--r--Source/cmForEachCommand.cxx2
-rw-r--r--Source/cmSystemTools.cxx104
-rw-r--r--Source/cmSystemTools.h9
-rw-r--r--Source/cmakexbuild.cxx106
-rw-r--r--Source/ctest.cxx6
11 files changed, 268 insertions, 130 deletions
diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx
index 5df84bb..abb2e48 100644
--- a/Source/CTest/cmCTestRunScriptCommand.cxx
+++ b/Source/CTest/cmCTestRunScriptCommand.cxx
@@ -27,11 +27,17 @@ bool cmCTestRunScriptCommand::InitialPass(
return true;
}
+ bool np = false;
+ unsigned int i = 0;
+ if (args[i] == "NEW_PROCESS")
+ {
+ np = true;
+ i++;
+ }
// run each script
- unsigned int i;
- for (i = 0; i < args.size(); ++i)
+ for (; i < args.size(); ++i)
{
- cmCTestScriptHandler::RunScript(this->CTest, args[i].c_str());
+ cmCTestScriptHandler::RunScript(this->CTest, args[i].c_str(), !np);
}
return true;
}
diff --git a/Source/CTest/cmCTestRunScriptCommand.h b/Source/CTest/cmCTestRunScriptCommand.h
index 1ca022e..949cb77 100644
--- a/Source/CTest/cmCTestRunScriptCommand.h
+++ b/Source/CTest/cmCTestRunScriptCommand.h
@@ -67,11 +67,12 @@ public:
virtual const char* GetFullDocumentation()
{
return
- " CTEST_RUN_SCRIPT(script_file_name script_file_name1 \n"
+ " CTEST_RUN_SCRIPT([NEW_PROCESS] script_file_name script_file_name1 \n"
" script_file_name2 ...)\n"
"Runs a script or scripts much like if it was run from ctest -S. "
"If no argument is provided then the current script is run using "
- "the current settings of the variables.";
+ "the current settings of the variables. If NEW_PROCESS is specified "
+ "then each script will be run in a seperate process.";
}
cmTypeMacro(cmCTestRunScriptCommand, cmCTestCommand);
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 887d8ad..9350334 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -167,9 +167,10 @@ cmCTestScriptHandler::~cmCTestScriptHandler()
//----------------------------------------------------------------------
// just adds an argument to the vector
-void cmCTestScriptHandler::AddConfigurationScript(const char *script)
+void cmCTestScriptHandler::AddConfigurationScript(const char *script, bool pscope)
{
this->ConfigurationScripts.push_back(script);
+ this->ScriptProcessScope.push_back(pscope);
}
@@ -179,14 +180,12 @@ void cmCTestScriptHandler::AddConfigurationScript(const char *script)
int cmCTestScriptHandler::ProcessHandler()
{
int res = 0;
- std::vector<cmStdString>::iterator it;
- for ( it = this->ConfigurationScripts.begin();
- it != this->ConfigurationScripts.end();
- it ++ )
+ for (size_t i=0; i < this->ConfigurationScripts.size(); ++i)
{
// for each script run it
- res += this->RunConfigurationScript(
- cmSystemTools::CollapseFullPath(it->c_str()));
+ res += this->RunConfigurationScript
+ (cmSystemTools::CollapseFullPath(this->ConfigurationScripts[i].c_str()),
+ this->ScriptProcessScope[i]);
}
if ( res )
{
@@ -218,8 +217,73 @@ void cmCTestScriptHandler::AddCTestCommand(cmCTestCommand* command)
this->CMake->AddCommand(newCom);
}
+int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
+{
+ // execute the script passing in the arguments to the script as well as the
+ // arguments from this invocation of cmake
+ std::vector<const char*> argv;
+ argv.push_back(this->CTest->GetCTestExecutable());
+ argv.push_back("-SR");
+ argv.push_back(total_script_arg.c_str());
+
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Executable for CTest is: " <<
+ this->CTest->GetCTestExecutable() << "\n");
+
+ // now pass through all the other arguments
+ std::vector<cmStdString> &initArgs =
+ this->CTest->GetInitialCommandLineArguments();
+ for(size_t i=1; i < initArgs.size(); ++i)
+ {
+ argv.push_back(initArgs[i].c_str());
+ }
+ argv.push_back(0);
+
+ // Now create process object
+ cmsysProcess* cp = cmsysProcess_New();
+ cmsysProcess_SetCommand(cp, &*argv.begin());
+ //cmsysProcess_SetWorkingDirectory(cp, dir);
+ cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
+ //cmsysProcess_SetTimeout(cp, timeout);
+ cmsysProcess_Execute(cp);
+
+ std::vector<char> out;
+ std::vector<char> err;
+ std::string line;
+ int pipe = cmSystemTools::WaitForLine(cp, line, 100.0, out, err);
+ while(pipe != cmsysProcess_Pipe_None)
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Output: " << line << "\n");
+ if(pipe == cmsysProcess_Pipe_STDERR)
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, line << "\n");
+ }
+ else if(pipe == cmsysProcess_Pipe_STDOUT)
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, line << "\n");
+ }
+ pipe = cmSystemTools::WaitForLine(cp, line, 100, out, err);
+ }
+
+ // Properly handle output of the build command
+ cmsysProcess_WaitForExit(cp, 0);
+ int result = cmsysProcess_GetState(cp);
+
+ int retVal = 0;
+ if(result == cmsysProcess_State_Exited)
+ {
+ retVal = cmsysProcess_GetExitValue(cp);
+ }
+ else
+ {
+ abort();
+ }
+ return retVal;
+}
+
+
//----------------------------------------------------------------------
-// this sets up some variables for thew script to use, creates the required
+// this sets up some variables for the script to use, creates the required
// cmake instance and generators, and then reads in the script
int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
{
@@ -426,8 +490,8 @@ void cmCTestScriptHandler::SleepInSeconds(unsigned int secondsToWait)
//----------------------------------------------------------------------
// run a specific script
-int cmCTestScriptHandler::RunConfigurationScript(
- const std::string& total_script_arg)
+int cmCTestScriptHandler::RunConfigurationScript
+(const std::string& total_script_arg, bool pscope)
{
int result;
@@ -435,7 +499,18 @@ int cmCTestScriptHandler::RunConfigurationScript(
cmSystemTools::GetTime();
// read in the script
- result = this->ReadInScript(total_script_arg);
+ if (pscope)
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Reading Script: " << total_script_arg << std::endl);
+ result = this->ReadInScript(total_script_arg);
+ }
+ else
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "Executing Script: " << total_script_arg << std::endl);
+ result = this->ExecuteScript(total_script_arg);
+ }
if (result)
{
return result;
@@ -847,11 +922,11 @@ void cmCTestScriptHandler::RestoreBackupDirectories()
}
}
-bool cmCTestScriptHandler::RunScript(cmCTest* ctest, const char *sname)
+bool cmCTestScriptHandler::RunScript(cmCTest* ctest, const char *sname, bool InProcess)
{
cmCTestScriptHandler* sh = new cmCTestScriptHandler();
sh->SetCTestInstance(ctest);
- sh->AddConfigurationScript(sname);
+ sh->AddConfigurationScript(sname,InProcess);
sh->ProcessHandler();
delete sh;
return true;
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index 344192b..e354005 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -69,9 +69,9 @@ public:
cmTypeMacro(cmCTestScriptHandler, cmCTestGenericHandler);
/**
- * Add a script to run
+ * Add a script to run, and if is should run in the current process
*/
- void AddConfigurationScript(const char *);
+ void AddConfigurationScript(const char *, bool pscope);
/**
* Run a dashboard using a specified confiuration script
@@ -81,7 +81,7 @@ public:
/*
* Run a script
*/
- static bool RunScript(cmCTest* ctest, const char *script);
+ static bool RunScript(cmCTest* ctest, const char *script, bool InProcess);
int RunCurrentScript();
/*
@@ -99,9 +99,11 @@ public:
~cmCTestScriptHandler();
void Initialize();
+
private:
// reads in a script
int ReadInScript(const std::string& total_script_arg);
+ int ExecuteScript(const std::string& total_script_arg);
// extract vars from the script to set ivars
int ExtractVariables();
@@ -116,13 +118,14 @@ private:
int BackupDirectories();
void RestoreBackupDirectories();
- int RunConfigurationScript(const std::string& script);
+ int RunConfigurationScript(const std::string& script, bool pscope);
int RunConfigurationDashboard();
// Add ctest command
void AddCTestCommand(cmCTestCommand* command);
std::vector<cmStdString> ConfigurationScripts;
+ std::vector<bool> ScriptProcessScope;
bool Backup;
bool EmptyBinDir;
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index f84430c..c5ad1f4 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -1302,6 +1302,13 @@ int cmCTest::Run(std::vector<std::string>const& args, std::string* output)
const char* ctestExec = "ctest";
bool cmakeAndTest = false;
bool performSomeTest = true;
+ bool SRArgumentSpecified = false;
+
+ // copy the command line
+ for(size_t i=0; i < args.size(); ++i)
+ {
+ this->InitialCommandLineArguments.push_back(args[i]);
+ }
for(size_t i=1; i < args.size(); ++i)
{
std::string arg = args[i];
@@ -1347,13 +1354,40 @@ int cmCTest::Run(std::vector<std::string>const& args, std::string* output)
this->ShowOnly = true;
}
+ if(this->CheckArgument(arg, "-SP", "--script-new-process") && i < args.size() - 1 )
+ {
+ this->RunConfigurationScript = true;
+ i++;
+ cmCTestScriptHandler* ch
+ = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ // -SR is an internal argument, -SP should be ignored when it is passed
+ if (!SRArgumentSpecified)
+ {
+ ch->AddConfigurationScript(args[i].c_str(),false);
+ }
+ }
+
+ if(this->CheckArgument(arg, "-SR", "--script-run") && i < args.size() - 1 )
+ {
+ SRArgumentSpecified = true;
+ this->RunConfigurationScript = true;
+ i++;
+ cmCTestScriptHandler* ch
+ = static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+ ch->AddConfigurationScript(args[i].c_str(),true);
+ }
+
if(this->CheckArgument(arg, "-S", "--script") && i < args.size() - 1 )
{
this->RunConfigurationScript = true;
i++;
cmCTestScriptHandler* ch
= static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
- ch->AddConfigurationScript(args[i].c_str());
+ // -SR is an internal argument, -S should be ignored when it is passed
+ if (!SRArgumentSpecified)
+ {
+ ch->AddConfigurationScript(args[i].c_str(),true);
+ }
}
if(this->CheckArgument(arg, "-O", "--output-log") && i < args.size() - 1 )
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index f94cb1f..37e05e9 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -293,6 +293,9 @@ public:
//! Read the custom configuration files and apply them to the current ctest
int ReadCustomConfigurationFileTree(const char* dir);
+ std::vector<cmStdString> &GetInitialCommandLineArguments()
+ { return this->InitialCommandLineArguments; };
+
private:
std::string ConfigType;
bool Verbose;
@@ -383,7 +386,8 @@ private:
int DartVersion;
std::set<cmStdString> SubmitFiles;
-
+ std::vector<cmStdString> InitialCommandLineArguments;
+
int SubmitIndex;
cmGeneratedFileStream* OutputLogFile;
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index c9b39dc..e2dce93c 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -42,7 +42,7 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf)
this->Executing = true;
std::vector<std::string>::const_iterator j = this->Args.begin();
++j;
-
+
std::string tmps;
cmListFileArgument arg;
for( ; j != this->Args.end(); ++j)
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 29fcd92..e25ce13 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -21,7 +21,6 @@
#include <cmsys/RegularExpression.hxx>
#include <cmsys/Directory.hxx>
-#include <cmsys/Process.h>
// support for realpath call
#ifndef _WIN32
@@ -1671,3 +1670,106 @@ bool cmSystemTools::ListTar(const char* outFileName,
return false;
#endif
}
+
+int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
+ double timeout,
+ std::vector<char>& out,
+ std::vector<char>& err)
+{
+ line = "";
+ std::vector<char>::iterator outiter = out.begin();
+ std::vector<char>::iterator erriter = err.begin();
+ while(1)
+ {
+ // Check for a newline in stdout.
+ for(;outiter != out.end(); ++outiter)
+ {
+ if((*outiter == '\r') && ((outiter+1) == out.end()))
+ {
+ break;
+ }
+ else if(*outiter == '\n' || *outiter == '\0')
+ {
+ int length = outiter-out.begin();
+ if(length > 1 && *(outiter-1) == '\r')
+ {
+ --length;
+ }
+ if(length > 0)
+ {
+ line.append(&out[0], length);
+ }
+ out.erase(out.begin(), outiter+1);
+ return cmsysProcess_Pipe_STDOUT;
+ }
+ }
+
+ // Check for a newline in stderr.
+ for(;erriter != err.end(); ++erriter)
+ {
+ if((*erriter == '\r') && ((erriter+1) == err.end()))
+ {
+ break;
+ }
+ else if(*erriter == '\n' || *erriter == '\0')
+ {
+ int length = erriter-err.begin();
+ if(length > 1 && *(erriter-1) == '\r')
+ {
+ --length;
+ }
+ if(length > 0)
+ {
+ line.append(&err[0], length);
+ }
+ err.erase(err.begin(), erriter+1);
+ return cmsysProcess_Pipe_STDERR;
+ }
+ }
+
+ // No newlines found. Wait for more data from the process.
+ int length;
+ char* data;
+ int pipe = cmsysProcess_WaitForData(process, &data, &length, &timeout);
+ if(pipe == cmsysProcess_Pipe_Timeout)
+ {
+ // Timeout has been exceeded.
+ return pipe;
+ }
+ else if(pipe == cmsysProcess_Pipe_STDOUT)
+ {
+ // Append to the stdout buffer.
+ std::vector<char>::size_type size = out.size();
+ out.insert(out.end(), data, data+length);
+ outiter = out.begin()+size;
+ }
+ else if(pipe == cmsysProcess_Pipe_STDERR)
+ {
+ // Append to the stderr buffer.
+ std::vector<char>::size_type size = err.size();
+ err.insert(err.end(), data, data+length);
+ erriter = err.begin()+size;
+ }
+ else if(pipe == cmsysProcess_Pipe_None)
+ {
+ // Both stdout and stderr pipes have broken. Return leftover data.
+ if(!out.empty())
+ {
+ line.append(&out[0], outiter-out.begin());
+ out.erase(out.begin(), out.end());
+ return cmsysProcess_Pipe_STDOUT;
+ }
+ else if(!err.empty())
+ {
+ line.append(&err[0], erriter-err.begin());
+ err.erase(err.begin(), err.end());
+ return cmsysProcess_Pipe_STDERR;
+ }
+ else
+ {
+ return cmsysProcess_Pipe_None;
+ }
+ }
+ }
+}
+
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 0973a07..9b3fa68 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -20,6 +20,9 @@
#include "cmStandardIncludes.h"
#include <cmsys/SystemTools.hxx>
+#include <cmsys/Process.h>
+
+
/** \class cmSystemTools
* \brief A collection of useful functions for CMake.
@@ -257,6 +260,12 @@ public:
*/
static void ReportLastSystemError(const char* m);
+ /** a general output handler for cmsysProcess */
+ static int WaitForLine(cmsysProcess* process, std::string& line,
+ double timeout,
+ std::vector<char>& out,
+ std::vector<char>& err);
+
/** Split a string on its newlines into multiple lines. Returns
false only if the last line stored had no newline. */
static bool Split(const char* s, std::vector<cmStdString>& l);
diff --git a/Source/cmakexbuild.cxx b/Source/cmakexbuild.cxx
index 6bf4da4..5f673fb 100644
--- a/Source/cmakexbuild.cxx
+++ b/Source/cmakexbuild.cxx
@@ -8,108 +8,6 @@
// error, and re-runs xcodebuild until that error does
// not show up.
-int WaitForLine(cmsysProcess* process, std::string& line,
- double timeout,
- std::vector<char>& out,
- std::vector<char>& err)
-{
- line = "";
- std::vector<char>::iterator outiter = out.begin();
- std::vector<char>::iterator erriter = err.begin();
- while(1)
- {
- // Check for a newline in stdout.
- for(;outiter != out.end(); ++outiter)
- {
- if((*outiter == '\r') && ((outiter+1) == out.end()))
- {
- break;
- }
- else if(*outiter == '\n' || *outiter == '\0')
- {
- int length = outiter-out.begin();
- if(length > 1 && *(outiter-1) == '\r')
- {
- --length;
- }
- if(length > 0)
- {
- line.append(&out[0], length);
- }
- out.erase(out.begin(), outiter+1);
- return cmsysProcess_Pipe_STDOUT;
- }
- }
-
- // Check for a newline in stderr.
- for(;erriter != err.end(); ++erriter)
- {
- if((*erriter == '\r') && ((erriter+1) == err.end()))
- {
- break;
- }
- else if(*erriter == '\n' || *erriter == '\0')
- {
- int length = erriter-err.begin();
- if(length > 1 && *(erriter-1) == '\r')
- {
- --length;
- }
- if(length > 0)
- {
- line.append(&err[0], length);
- }
- err.erase(err.begin(), erriter+1);
- return cmsysProcess_Pipe_STDERR;
- }
- }
-
- // No newlines found. Wait for more data from the process.
- int length;
- char* data;
- int pipe = cmsysProcess_WaitForData(process, &data, &length, &timeout);
- if(pipe == cmsysProcess_Pipe_Timeout)
- {
- // Timeout has been exceeded.
- return pipe;
- }
- else if(pipe == cmsysProcess_Pipe_STDOUT)
- {
- // Append to the stdout buffer.
- std::vector<char>::size_type size = out.size();
- out.insert(out.end(), data, data+length);
- outiter = out.begin()+size;
- }
- else if(pipe == cmsysProcess_Pipe_STDERR)
- {
- // Append to the stderr buffer.
- std::vector<char>::size_type size = err.size();
- err.insert(err.end(), data, data+length);
- erriter = err.begin()+size;
- }
- else if(pipe == cmsysProcess_Pipe_None)
- {
- // Both stdout and stderr pipes have broken. Return leftover data.
- if(!out.empty())
- {
- line.append(&out[0], outiter-out.begin());
- out.erase(out.begin(), out.end());
- return cmsysProcess_Pipe_STDOUT;
- }
- else if(!err.empty())
- {
- line.append(&err[0], erriter-err.begin());
- err.erase(err.begin(), err.end());
- return cmsysProcess_Pipe_STDERR;
- }
- else
- {
- return cmsysProcess_Pipe_None;
- }
- }
- }
-}
-
int RunXCode(std::vector<const char*>& argv, bool& hitbug)
{
hitbug = false;
@@ -120,7 +18,7 @@ int RunXCode(std::vector<const char*>& argv, bool& hitbug)
std::vector<char> out;
std::vector<char> err;
std::string line;
- int pipe =WaitForLine(cp, line, 100.0, out, err);
+ int pipe = cmSystemTools::WaitForLine(cp, line, 100.0, out, err);
while(pipe != cmsysProcess_Pipe_None)
{
if(line.find("/bin/sh: bad interpreter: Text file busy")
@@ -144,7 +42,7 @@ int RunXCode(std::vector<const char*>& argv, bool& hitbug)
std::cout << line << "\n";
}
}
- pipe =WaitForLine(cp, line, 100, out, err);
+ pipe = cmSystemTools::WaitForLine(cp, line, 100, out, err);
}
cmsysProcess_WaitForExit(cp, 0);
if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 189d1cc..6a8c90c 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -103,6 +103,12 @@ static const cmDocumentationEntry cmDocumentationOptions[] =
"ctest will do what is required to create and run a dashboard. This "
"option basically sets up a dashboard and then runs ctest -D with the "
"appropriate options."},
+ {"-SP <script>, --script-new-process <script>", "Execute a dashboard for a "
+ "configuration",
+ "This option does the same operations as -S but it will do them in a "
+ "seperate process. This is primarily useful in cases where the script "
+ "may modify the environment and you do not want the modified enviroment "
+ "to impact other -S scripts."},
{"-A <file>, --add-notes <file>", "Add a notes file with submission",
"This option tells ctest to include a notes file when submitting "
"dashboard. "},