From 4096066723ec7dd6f450e1c8da13616c0ca2f124 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 28 Jul 2011 10:28:52 -0400 Subject: [PATCH 1/4] RunSingleCommand: Fix indentation --- Source/cmSystemTools.cxx | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 5fe47d728..526ae3de8 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -607,30 +607,30 @@ bool cmSystemTools::RunSingleCommand(std::vectorconst& command, int length; if ( output || verbose ) { - while(cmsysProcess_WaitForData(cp, &data, &length, 0)) - { - if(output || verbose) + while(cmsysProcess_WaitForData(cp, &data, &length, 0)) { - // Translate NULL characters in the output into valid text. - // Visual Studio 7 puts these characters in the output of its - // build process. - for(int i=0; i < length; ++i) + if(output || verbose) { - if(data[i] == '\0') + // Translate NULL characters in the output into valid text. + // Visual Studio 7 puts these characters in the output of its + // build process. + for(int i=0; i < length; ++i) { - data[i] = ' '; + if(data[i] == '\0') + { + data[i] = ' '; + } } } + if ( output ) + { + tempOutput.insert(tempOutput.end(), data, data+length); + } + if(verbose) + { + cmSystemTools::Stdout(data, length); + } } - if ( output ) - { - tempOutput.insert(tempOutput.end(), data, data+length); - } - if(verbose) - { - cmSystemTools::Stdout(data, length); - } - } } cmsysProcess_WaitForExit(cp, 0); From 856a9e499f299a33cb4f763bf36a75524a03e4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bj=C3=B6rk?= Date: Tue, 26 Jul 2011 09:26:18 +0200 Subject: [PATCH 2/4] RunSingleCommand: Replace verbose boolean with enum No behaviour change, this prepares for adding a flag to skip the merging of output streams. --- Source/CPack/cmCPackGenerator.cxx | 2 +- Source/CPack/cmCPackGenerator.h | 7 +++++-- Source/CPack/cmCPackNSISGenerator.cxx | 3 ++- Source/CTest/cmCTestGenericHandler.cxx | 2 +- Source/CTest/cmCTestGenericHandler.h | 7 +++++-- Source/CTest/cmCTestTestHandler.cxx | 3 ++- Source/cmGlobalGenerator.cxx | 6 +++--- Source/cmGlobalGenerator.h | 5 +++-- Source/cmSiteNameCommand.cxx | 2 +- Source/cmSystemTools.cxx | 24 +++++++++++++----------- Source/cmSystemTools.h | 18 ++++++++++++------ Source/cmTryRunCommand.cxx | 2 +- Source/cmake.cxx | 7 ++++--- 13 files changed, 53 insertions(+), 35 deletions(-) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 7e5b26d62..0e4acd556 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -33,7 +33,7 @@ //---------------------------------------------------------------------- cmCPackGenerator::cmCPackGenerator() { - this->GeneratorVerbose = false; + this->GeneratorVerbose = cmSystemTools::OUTPUT_NONE; this->MakefileMap = 0; this->Logger = 0; this->componentPackageMethod = ONE_PACKAGE_PER_GROUP; diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 05d95b874..52def9da7 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -14,6 +14,7 @@ #define cmCPackGenerator_h #include "cmObject.h" +#include "cmSystemTools.h" #include #include @@ -57,7 +58,9 @@ public: /** * If verbose then more information is printed out */ - void SetVerbose(bool val) { this->GeneratorVerbose = val; } + void SetVerbose(bool val) + { this->GeneratorVerbose = val ? + cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE; } /** * Do the actual whole package processing. @@ -194,7 +197,7 @@ protected: virtual cmCPackComponentGroup* GetComponentGroup(const char *projectName, const char* name); - bool GeneratorVerbose; + cmSystemTools::OutputOption GeneratorVerbose; std::string Name; std::string InstallPath; diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index e5fe5759b..a1f4f2e4a 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -786,7 +786,8 @@ CreateComponentDescription(cmCPackComponent *component, std::string output; int retVal = -1; int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &retVal, - dirName.c_str(), false, 0); + dirName.c_str(), + cmSystemTools::OUTPUT_NONE, 0); if ( !res || retVal ) { std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 8c3c22acf..fd75e45e8 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -18,7 +18,7 @@ //---------------------------------------------------------------------- cmCTestGenericHandler::cmCTestGenericHandler() { - this->HandlerVerbose = false; + this->HandlerVerbose = cmSystemTools::OUTPUT_NONE; this->CTest = 0; this->SubmitIndex = 0; this->AppendXML = false; diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index 739314521..18189ec2b 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -16,6 +16,7 @@ #include "cmObject.h" #include "cmCTest.h" +#include "cmSystemTools.h" //OutputOption class cmMakefile; class cmCTestCommand; @@ -31,7 +32,9 @@ public: /** * If verbose then more informaiton is printed out */ - void SetVerbose(bool val) { this->HandlerVerbose = val; } + void SetVerbose(bool val) + { this->HandlerVerbose = val ? + cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE; } /** * Populate internals from CTest custom scripts @@ -91,7 +94,7 @@ protected: bool StartLogFile(const char* name, cmGeneratedFileStream& xofs); bool AppendXML; - bool HandlerVerbose; + cmSystemTools::OutputOption HandlerVerbose; cmCTest *CTest; t_StringToString Options; t_StringToString PersistentOptions; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index e3b81df88..b824e4708 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1301,7 +1301,8 @@ int cmCTestTestHandler::ExecuteCommands(std::vector& vec) int retVal = 0; cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << *it << std::endl); - if ( !cmSystemTools::RunSingleCommand(it->c_str(), 0, &retVal, 0, true + if ( !cmSystemTools::RunSingleCommand(it->c_str(), 0, &retVal, 0, + cmSystemTools::OUTPUT_MERGE /*this->Verbose*/) || retVal != 0 ) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Problem running command: " diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 6c8938e5d..2eae01e68 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1136,7 +1136,7 @@ int cmGlobalGenerator::Build( const char *config, bool clean, bool fast, double timeout, - bool verbose, + cmSystemTools::OutputOption outputflag, const char* extraOptions, std::vector const& nativeOptions) { @@ -1176,7 +1176,7 @@ int cmGlobalGenerator::Build( } if (!cmSystemTools::RunSingleCommand(cleanCommand.c_str(), outputPtr, - &retVal, 0, verbose, timeout)) + &retVal, 0, outputflag, timeout)) { cmSystemTools::SetRunCommandHideConsole(hideconsole); cmSystemTools::Error("Generator: execution of make clean failed."); @@ -1217,7 +1217,7 @@ int cmGlobalGenerator::Build( } if (!cmSystemTools::RunSingleCommand(command, outputPtr, - &retVal, 0, verbose, timeout)) + &retVal, 0, outputflag, timeout)) { cmSystemTools::SetRunCommandHideConsole(hideconsole); cmSystemTools::Error diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 5268731f7..b7b1bff82 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -17,7 +17,7 @@ #include "cmTarget.h" // For cmTargets #include "cmTargetDepend.h" // For cmTargetDependSet - +#include "cmSystemTools.h" // for cmSystemTools::OutputOption class cmake; class cmMakefile; class cmLocalGenerator; @@ -102,7 +102,8 @@ public: std::string *output, const char *makeProgram, const char *config, bool clean, bool fast, - double timeout, bool verbose=false, + double timeout, + cmSystemTools::OutputOption outputflag=cmSystemTools::OUTPUT_NONE, const char* extraOptions = 0, std::vector const& nativeOptions = std::vector()); diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index 7b80c5c4c..04e357ca8 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -63,7 +63,7 @@ bool cmSiteNameCommand { std::string host; cmSystemTools::RunSingleCommand(hostname_cmd.c_str(), - &host, 0, 0, false); + &host, 0, 0, cmSystemTools::OUTPUT_NONE); // got the hostname if (host.length()) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 526ae3de8..ba620d117 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -577,7 +577,7 @@ std::vector cmSystemTools::ParseArguments(const char* command) bool cmSystemTools::RunSingleCommand(std::vectorconst& command, std::string* output , int* retVal , const char* dir , - bool verbose , + OutputOption outputflag , double timeout ) { std::vector argv; @@ -599,17 +599,19 @@ bool cmSystemTools::RunSingleCommand(std::vectorconst& command, { cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); } + cmsysProcess_SetTimeout(cp, timeout); cmsysProcess_Execute(cp); std::vector tempOutput; char* data; int length; - if ( output || verbose ) + int pipe; + if ( output || outputflag != OUTPUT_NONE ) { - while(cmsysProcess_WaitForData(cp, &data, &length, 0)) + while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0))) { - if(output || verbose) + if(output || outputflag != OUTPUT_NONE) { // Translate NULL characters in the output into valid text. // Visual Studio 7 puts these characters in the output of its @@ -626,7 +628,7 @@ bool cmSystemTools::RunSingleCommand(std::vectorconst& command, { tempOutput.insert(tempOutput.end(), data, data+length); } - if(verbose) + if(outputflag != OUTPUT_NONE) { cmSystemTools::Stdout(data, length); } @@ -657,7 +659,7 @@ bool cmSystemTools::RunSingleCommand(std::vectorconst& command, else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) { const char* exception_str = cmsysProcess_GetExceptionString(cp); - if ( verbose ) + if ( outputflag != OUTPUT_NONE ) { std::cerr << exception_str << std::endl; } @@ -670,7 +672,7 @@ bool cmSystemTools::RunSingleCommand(std::vectorconst& command, else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error) { const char* error_str = cmsysProcess_GetErrorString(cp); - if ( verbose ) + if ( outputflag != OUTPUT_NONE ) { std::cerr << error_str << std::endl; } @@ -683,7 +685,7 @@ bool cmSystemTools::RunSingleCommand(std::vectorconst& command, else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) { const char* error_str = "Process terminated due to timeout\n"; - if ( verbose ) + if ( outputflag != OUTPUT_NONE ) { std::cerr << error_str << std::endl; } @@ -703,12 +705,12 @@ bool cmSystemTools::RunSingleCommand( std::string* output, int *retVal, const char* dir, - bool verbose, + OutputOption outputflag, double timeout) { if(s_DisableRunCommandOutput) { - verbose = false; + outputflag = OUTPUT_NONE; } std::vector args = cmSystemTools::ParseArguments(command); @@ -718,7 +720,7 @@ bool cmSystemTools::RunSingleCommand( return false; } return cmSystemTools::RunSingleCommand(args, output,retVal, - dir, verbose, timeout); + dir, outputflag, timeout); } bool cmSystemTools::RunCommand(const char* command, std::string& output, diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index f434390f8..bf513ad4b 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -191,11 +191,12 @@ public: int &retVal, const char* directory = 0, bool verbose = true, int timeout = 0); /** - * Run a single executable command and put the stdout and stderr - * in output. + * Run a single executable command * - * If verbose is false, no user-viewable output from the program - * being run will be generated. + * Output is controlled with outputflag. If outputflag is OUTPUT_NONE, no + * user-viewable output from the program being run will be generated. + * OUTPUT_MERGE is the legacy behaviour where stdout and stderr are merged + * into stdout. * * If timeout is specified, the command will be terminated after * timeout expires. Timeout is specified in seconds. @@ -210,9 +211,14 @@ public: * it into this function or it will not work. The command must be correctly * escaped for this to with spaces. */ + enum OutputOption + { + OUTPUT_NONE = 0, + OUTPUT_MERGE + }; static bool RunSingleCommand(const char* command, std::string* output = 0, int* retVal = 0, const char* dir = 0, - bool verbose = true, + OutputOption outputflag = OUTPUT_MERGE, double timeout = 0.0); /** * In this version of RunSingleCommand, command[0] should be @@ -222,7 +228,7 @@ public: static bool RunSingleCommand(std::vector const& command, std::string* output = 0, int* retVal = 0, const char* dir = 0, - bool verbose = true, + OutputOption outputflag = OUTPUT_MERGE, double timeout = 0.0); /** diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 4d31a1499..c9c4ed538 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -194,7 +194,7 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs, int timeout = 0; bool worked = cmSystemTools::RunSingleCommand(finalCommand.c_str(), out, &retVal, - 0, false, timeout); + 0, cmSystemTools::OUTPUT_NONE, timeout); // set the run var char retChar[1000]; if (worked) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 45927cb04..3473d9173 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1297,7 +1297,7 @@ int cmake::ExecuteCMakeCommand(std::vector& args) int retval = 0; int timeout = 0; if ( cmSystemTools::RunSingleCommand(command.c_str(), 0, &retval, - directory.c_str(), true, timeout) ) + directory.c_str(), cmSystemTools::OUTPUT_MERGE, timeout) ) { return retval; } @@ -3978,7 +3978,7 @@ bool cmake::RunCommand(const char* comment, // use rc command to create .res file cmSystemTools::RunSingleCommand(command, &output, - &retCode, 0, false); + &retCode, 0, cmSystemTools::OUTPUT_NONE); // always print the output of the command, unless // it is the dumb rc command banner, but if the command // returned an error code then print the output anyway as @@ -4338,7 +4338,8 @@ int cmake::Build(const std::string& dir, projName.c_str(), target.c_str(), &output, makeProgram.c_str(), - config.c_str(), clean, false, 0, true, + config.c_str(), clean, false, 0, + cmSystemTools::OUTPUT_MERGE, 0, nativeOptions); } From 642f10066a5c9b33e8736b9ca013a44023c21b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Bj=C3=B6rk?= Date: Tue, 26 Jul 2011 09:36:40 +0200 Subject: [PATCH 3/4] RunSingleCommand: Add a OUTPUT_NORMAL flag. OUTPUT_NORMAL does no processing of the output streams, it just passes them through the same streams as they were received on. --- Source/cmSystemTools.cxx | 22 +++++++++++++++++++++- Source/cmSystemTools.h | 9 +++++++-- Source/cmake.cxx | 6 +++--- Source/cmake.h | 3 ++- Source/cmakemain.cxx | 8 +++++++- 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index ba620d117..197161005 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -247,6 +247,12 @@ void cmSystemTools::Stdout(const char* s) } } +void cmSystemTools::Stderr(const char* s, int length) +{ + std::cerr.write(s, length); + std::cerr.flush(); +} + void cmSystemTools::Stdout(const char* s, int length) { if(s_StdoutCallback) @@ -630,7 +636,21 @@ bool cmSystemTools::RunSingleCommand(std::vectorconst& command, } if(outputflag != OUTPUT_NONE) { - cmSystemTools::Stdout(data, length); + if(outputflag == OUTPUT_MERGE) + { + cmSystemTools::Stdout(data, length); + } + else + { + if(pipe == cmsysProcess_Pipe_STDERR) + { + cmSystemTools::Stderr(data, length); + } + else if(pipe == cmsysProcess_Pipe_STDOUT) + { + cmSystemTools::Stdout(data, length); + } + } } } } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index bf513ad4b..641c89fae 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -75,6 +75,9 @@ public: typedef void (*StdoutCallback)(const char*, int length, void*); static void SetStdoutCallback(StdoutCallback, void* clientData=0); + ///! Send a string to stderr. Stdout callbacks will not be invoced. + static void Stderr(const char* s, int length); + ///! Return true if there was an error at any point. static bool GetErrorOccuredFlag() { @@ -196,7 +199,8 @@ public: * Output is controlled with outputflag. If outputflag is OUTPUT_NONE, no * user-viewable output from the program being run will be generated. * OUTPUT_MERGE is the legacy behaviour where stdout and stderr are merged - * into stdout. + * into stdout. OUTPUT_NORMAL passes through the output to stdout/stderr as + * it was received. * * If timeout is specified, the command will be terminated after * timeout expires. Timeout is specified in seconds. @@ -214,7 +218,8 @@ public: enum OutputOption { OUTPUT_NONE = 0, - OUTPUT_MERGE + OUTPUT_MERGE, + OUTPUT_NORMAL }; static bool RunSingleCommand(const char* command, std::string* output = 0, int* retVal = 0, const char* dir = 0, diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 3473d9173..137665d8e 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -4296,7 +4296,8 @@ int cmake::Build(const std::string& dir, const std::string& target, const std::string& config, const std::vector& nativeOptions, - bool clean) + bool clean, + cmSystemTools::OutputOption outputflag) { if(!cmSystemTools::FileIsDirectory(dir.c_str())) { @@ -4338,8 +4339,7 @@ int cmake::Build(const std::string& dir, projName.c_str(), target.c_str(), &output, makeProgram.c_str(), - config.c_str(), clean, false, 0, - cmSystemTools::OUTPUT_MERGE, + config.c_str(), clean, false, 0, outputflag, 0, nativeOptions); } diff --git a/Source/cmake.h b/Source/cmake.h index fac86c18e..88847cf3e 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -364,7 +364,8 @@ class cmake const std::string& target, const std::string& config, const std::vector& nativeOptions, - bool clean); + bool clean, + cmSystemTools::OutputOption outputflag); void UnwatchUnusedCli(const char* var); void WatchUnusedCli(const char* var); diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 663ce8f07..1fe9e82d4 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -62,6 +62,7 @@ static const char * cmDocumentationDescription[][3] = " --config = For multi-configuration tools, choose .\n" \ " --clean-first = Build target 'clean' first, then build.\n" \ " (To clean only, use --target 'clean'.)\n" \ + " --use-stderr = Don't merge stdout/stderr.\n" \ " -- = Pass remaining options to the native tool.\n" //---------------------------------------------------------------------------- @@ -568,6 +569,7 @@ static int do_build(int ac, char** av) std::string dir; std::vector nativeOptions; bool clean = false; + cmSystemTools::OutputOption outputflag = cmSystemTools::OUTPUT_MERGE; enum Doing { DoingNone, DoingDir, DoingTarget, DoingConfig, DoingNative}; Doing doing = DoingDir; @@ -590,6 +592,10 @@ static int do_build(int ac, char** av) clean = true; doing = DoingNone; } + else if(strcmp(av[i], "--use-stderr") == 0) + { + outputflag = cmSystemTools::OUTPUT_NORMAL; + } else if(strcmp(av[i], "--") == 0) { doing = DoingNative; @@ -635,6 +641,6 @@ static int do_build(int ac, char** av) } cmake cm; - return cm.Build(dir, target, config, nativeOptions, clean); + return cm.Build(dir, target, config, nativeOptions, clean, outputflag); #endif } From a343bc1c764c87b20edbdf960d870fd4b084ce8a Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 28 Jul 2011 09:04:45 -0400 Subject: [PATCH 4/4] RunSingleCommand: Avoid assignment in condition Several compilers warn about this case even when an extra layer of parenthesis surrounds the assignment. Make the condition explicit. --- Source/cmSystemTools.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 197161005..03364bd2b 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -615,7 +615,7 @@ bool cmSystemTools::RunSingleCommand(std::vectorconst& command, int pipe; if ( output || outputflag != OUTPUT_NONE ) { - while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0))) + while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0)) > 0) { if(output || outputflag != OUTPUT_NONE) {