mirror of
https://github.com/reactos/CMake.git
synced 2024-12-03 00:57:25 +00:00
21c573f682
Use the clang RemoveCStrCalls tool to automatically migrate the code. This was only run on linux, so does not have any positive or negative effect on other platforms.
334 lines
8.3 KiB
C++
334 lines
8.3 KiB
C++
/*============================================================================
|
|
CMake - Cross Platform Makefile Generator
|
|
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
|
|
Distributed under the OSI-approved BSD License (the "License");
|
|
see accompanying file Copyright.txt for details.
|
|
|
|
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 "cmSystemTools.h"
|
|
|
|
#include <cmsys/Process.h>
|
|
|
|
// cmExecProgramCommand
|
|
bool cmExecProgramCommand
|
|
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
|
|
{
|
|
if(args.size() < 1 )
|
|
{
|
|
this->SetError("called with incorrect number of arguments");
|
|
return false;
|
|
}
|
|
std::string arguments;
|
|
bool doingargs = false;
|
|
int count = 0;
|
|
std::string output_variable;
|
|
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")
|
|
{
|
|
count++;
|
|
doingargs = false;
|
|
havereturn_variable = false;
|
|
haveoutput_variable = true;
|
|
}
|
|
else if ( haveoutput_variable )
|
|
{
|
|
if ( output_variable.size() > 0 )
|
|
{
|
|
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++;
|
|
doingargs = false;
|
|
haveoutput_variable = false;
|
|
havereturn_variable = true;
|
|
}
|
|
else if ( havereturn_variable )
|
|
{
|
|
if ( return_variable.size() > 0 )
|
|
{
|
|
this->SetError("called with incorrect number of arguments");
|
|
return false;
|
|
}
|
|
return_variable = args[i];
|
|
havereturn_variable = false;
|
|
count ++;
|
|
}
|
|
else if(args[i] == "ARGS")
|
|
{
|
|
count++;
|
|
havereturn_variable = false;
|
|
haveoutput_variable = false;
|
|
doingargs = true;
|
|
}
|
|
else if(doingargs)
|
|
{
|
|
arguments += args[i];
|
|
arguments += " ";
|
|
count++;
|
|
}
|
|
}
|
|
|
|
std::string command;
|
|
if(arguments.size())
|
|
{
|
|
command = cmSystemTools::ConvertToRunCommandPath(args[0].c_str());
|
|
command += " ";
|
|
command += arguments;
|
|
}
|
|
else
|
|
{
|
|
command = args[0];
|
|
}
|
|
bool verbose = true;
|
|
if(output_variable.size() > 0)
|
|
{
|
|
verbose = false;
|
|
}
|
|
int retVal = 0;
|
|
std::string output;
|
|
bool result = true;
|
|
if(args.size() - count == 2)
|
|
{
|
|
cmSystemTools::MakeDirectory(args[1].c_str());
|
|
result = cmExecProgramCommand::RunCommand(command.c_str(), output, retVal,
|
|
args[1].c_str(), verbose);
|
|
}
|
|
else
|
|
{
|
|
result = cmExecProgramCommand::RunCommand(command.c_str(), output,
|
|
retVal, 0, verbose);
|
|
}
|
|
if(!result)
|
|
{
|
|
retVal = -1;
|
|
}
|
|
|
|
if ( output_variable.size() > 0 )
|
|
{
|
|
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)
|
|
{
|
|
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.size() > 0 )
|
|
{
|
|
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)
|
|
{
|
|
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 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
|
|
|
|
// 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, 0};
|
|
cmsysProcess_SetCommand(cp, cmd);
|
|
#endif
|
|
|
|
cmsysProcess_Execute(cp);
|
|
|
|
// Read the process output.
|
|
int length;
|
|
char* data;
|
|
int p;
|
|
while((p = cmsysProcess_WaitForData(cp, &data, &length, 0), p))
|
|
{
|
|
if(p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR)
|
|
{
|
|
if(verbose)
|
|
{
|
|
cmSystemTools::Stdout(data, length);
|
|
}
|
|
output.append(data, length);
|
|
}
|
|
}
|
|
|
|
// All output has been read. Wait for the process to exit.
|
|
cmsysProcess_WaitForExit(cp, 0);
|
|
|
|
// 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;
|
|
}
|