diff options
author | MyungJoo Ham <myungjoo.ham@samsung.com> | 2017-10-11 15:16:57 +0900 |
---|---|---|
committer | MyungJoo Ham <myungjoo.ham@samsung.com> | 2017-10-11 15:16:57 +0900 |
commit | 915c76ded744c0f5f151402b9fa69f3fd8452573 (patch) | |
tree | ca6a387466543248890f346847acaa8343989b22 /Source/cmExecProgramCommand.cxx | |
parent | 317dbdb79761ef65e45c7358cfc7571c6afa54ad (diff) | |
download | cmake-915c76ded744c0f5f151402b9fa69f3fd8452573.tar.gz cmake-915c76ded744c0f5f151402b9fa69f3fd8452573.tar.bz2 cmake-915c76ded744c0f5f151402b9fa69f3fd8452573.zip |
Imported Upstream version 3.9.4upstream/3.9.4
Diffstat (limited to 'Source/cmExecProgramCommand.cxx')
-rw-r--r-- | Source/cmExecProgramCommand.cxx | 301 |
1 files changed, 221 insertions, 80 deletions
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index 9fdb1e896..fcc3c45c6 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -1,26 +1,24 @@ -/*============================================================================ - CMake - Cross Platform Makefile Generator - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmExecProgramCommand.h" - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. +#include "cmsys/Process.h" +#include <stdio.h> - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include "cmExecProgramCommand.h" +#include "cmMakefile.h" +#include "cmProcessOutput.h" #include "cmSystemTools.h" +class cmExecutionStatus; + // cmExecProgramCommand -bool cmExecProgramCommand -::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) +bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args, + cmExecutionStatus&) { - if(args.size() < 1 ) - { + if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; - } + } std::string arguments; bool doingargs = false; int count = 0; @@ -28,118 +26,261 @@ bool cmExecProgramCommand bool haveoutput_variable = false; std::string return_variable; bool havereturn_variable = false; - for(size_t i=0; i < args.size(); ++i) - { - if(args[i] == "OUTPUT_VARIABLE") - { + for (size_t i = 0; i < args.size(); ++i) { + if (args[i] == "OUTPUT_VARIABLE") { count++; doingargs = false; havereturn_variable = false; haveoutput_variable = true; - } - else if ( haveoutput_variable ) - { - if ( output_variable.size() > 0 ) - { + } else if (haveoutput_variable) { + if (!output_variable.empty()) { this->SetError("called with incorrect number of arguments"); return false; - } + } output_variable = args[i]; haveoutput_variable = false; - count ++; - } - else if(args[i] == "RETURN_VALUE") - { + count++; + } else if (args[i] == "RETURN_VALUE") { count++; doingargs = false; haveoutput_variable = false; havereturn_variable = true; - } - else if ( havereturn_variable ) - { - if ( return_variable.size() > 0 ) - { + } else if (havereturn_variable) { + if (!return_variable.empty()) { this->SetError("called with incorrect number of arguments"); return false; - } + } return_variable = args[i]; havereturn_variable = false; - count ++; - } - else if(args[i] == "ARGS") - { + count++; + } else if (args[i] == "ARGS") { count++; havereturn_variable = false; haveoutput_variable = false; doingargs = true; - } - else if(doingargs) - { + } else if (doingargs) { arguments += args[i]; arguments += " "; count++; - } } + } std::string command; - if(arguments.size()) - { + if (!arguments.empty()) { command = cmSystemTools::ConvertToRunCommandPath(args[0].c_str()); command += " "; command += arguments; - } - else - { + } else { command = args[0]; - } + } bool verbose = true; - if(output_variable.size() > 0) - { + if (!output_variable.empty()) { verbose = false; - } + } int retVal = 0; std::string output; bool result = true; - if(args.size() - count == 2) - { + if (args.size() - count == 2) { cmSystemTools::MakeDirectory(args[1].c_str()); - result = cmSystemTools::RunCommand(command.c_str(), output, retVal, - args[1].c_str(), verbose); - } - else - { - result = cmSystemTools::RunCommand(command.c_str(), output, - retVal, 0, verbose); - } - if(!result) - { + result = cmExecProgramCommand::RunCommand(command.c_str(), output, retVal, + args[1].c_str(), verbose); + } else { + result = cmExecProgramCommand::RunCommand(command.c_str(), output, retVal, + CM_NULLPTR, verbose); + } + if (!result) { retVal = -1; - } + } - if ( output_variable.size() > 0 ) - { + if (!output_variable.empty()) { std::string::size_type first = output.find_first_not_of(" \n\t\r"); std::string::size_type last = output.find_last_not_of(" \n\t\r"); - if(first == std::string::npos) - { + if (first == std::string::npos) { first = 0; + } + if (last == std::string::npos) { + last = output.size() - 1; + } + + std::string coutput = std::string(output, first, last - first + 1); + this->Makefile->AddDefinition(output_variable, coutput.c_str()); + } + + if (!return_variable.empty()) { + char buffer[100]; + sprintf(buffer, "%d", retVal); + this->Makefile->AddDefinition(return_variable, buffer); + } + + return true; +} + +bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, + int& retVal, const char* dir, + bool verbose, Encoding encoding) +{ + if (cmSystemTools::GetRunCommandOutput()) { + verbose = false; + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + // if the command does not start with a quote, then + // try to find the program, and if the program can not be + // found use system to run the command as it must be a built in + // shell command like echo or dir + int count = 0; + std::string shortCmd; + if (command[0] == '\"') { + // count the number of quotes + for (const char* s = command; *s != 0; ++s) { + if (*s == '\"') { + count++; + if (count > 2) { + break; + } } - if(last == std::string::npos) - { - last = output.size()-1; + } + // if there are more than two double quotes use + // GetShortPathName, the cmd.exe program in windows which + // is used by system fails to execute if there are more than + // one set of quotes in the arguments + if (count > 2) { + cmsys::RegularExpression quoted("^\"([^\"]*)\"[ \t](.*)"); + if (quoted.find(command)) { + std::string cmd = quoted.match(1); + std::string args = quoted.match(2); + if (!cmSystemTools::FileExists(cmd.c_str())) { + shortCmd = cmd; + } else if (!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd)) { + cmSystemTools::Error("GetShortPath failed for ", cmd.c_str()); + return false; + } + shortCmd += " "; + shortCmd += args; + + command = shortCmd.c_str(); + } else { + cmSystemTools::Error("Could not parse command line with quotes ", + command); } + } + } +#endif - std::string coutput = std::string(output, first, last-first+1); - this->Makefile->AddDefinition(output_variable.c_str(), coutput.c_str()); + // Allocate a process instance. + cmsysProcess* cp = cmsysProcess_New(); + if (!cp) { + cmSystemTools::Error("Error allocating process instance."); + return false; + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + if (dir) { + cmsysProcess_SetWorkingDirectory(cp, dir); + } + if (cmSystemTools::GetRunCommandHideConsole()) { + cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); + } + cmsysProcess_SetOption(cp, cmsysProcess_Option_Verbatim, 1); + const char* cmd[] = { command, 0 }; + cmsysProcess_SetCommand(cp, cmd); +#else + std::string commandInDir; + if (dir) { + commandInDir = "cd \""; + commandInDir += dir; + commandInDir += "\" && "; + commandInDir += command; + } else { + commandInDir = command; + } +#ifndef __VMS + commandInDir += " 2>&1"; +#endif + command = commandInDir.c_str(); + if (verbose) { + cmSystemTools::Stdout("running "); + cmSystemTools::Stdout(command); + cmSystemTools::Stdout("\n"); + } + fflush(stdout); + fflush(stderr); + const char* cmd[] = { "/bin/sh", "-c", command, CM_NULLPTR }; + cmsysProcess_SetCommand(cp, cmd); +#endif + + cmsysProcess_Execute(cp); + + // Read the process output. + int length; + char* data; + int p; + cmProcessOutput processOutput(encoding); + std::string strdata; + while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { + if (p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) { + if (verbose) { + processOutput.DecodeText(data, length, strdata); + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + } + output.append(data, length); } + } - if ( return_variable.size() > 0 ) - { - char buffer[100]; - sprintf(buffer, "%d", retVal); - this->Makefile->AddDefinition(return_variable.c_str(), buffer); + if (verbose) { + processOutput.DecodeText(std::string(), strdata); + if (!strdata.empty()) { + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); } + } + + // All output has been read. Wait for the process to exit. + cmsysProcess_WaitForExit(cp, CM_NULLPTR); + processOutput.DecodeText(output, output); + + // Check the result of running the process. + std::string msg; + switch (cmsysProcess_GetState(cp)) { + case cmsysProcess_State_Exited: + retVal = cmsysProcess_GetExitValue(cp); + break; + case cmsysProcess_State_Exception: + retVal = -1; + msg += "\nProcess terminated due to: "; + msg += cmsysProcess_GetExceptionString(cp); + break; + case cmsysProcess_State_Error: + retVal = -1; + msg += "\nProcess failed because: "; + msg += cmsysProcess_GetErrorString(cp); + break; + case cmsysProcess_State_Expired: + retVal = -1; + msg += "\nProcess terminated due to timeout."; + break; + } + if (!msg.empty()) { +#if defined(_WIN32) && !defined(__CYGWIN__) + // Old Windows process execution printed this info. + msg += "\n\nfor command: "; + msg += command; + if (dir) { + msg += "\nin dir: "; + msg += dir; + } + msg += "\n"; + if (verbose) { + cmSystemTools::Stdout(msg.c_str()); + } + output += msg; +#else + // Old UNIX process execution only put message in output. + output += msg; +#endif + } + + // Delete the process instance. + cmsysProcess_Delete(cp); return true; } - |