CMake/Source/cmCustomCommandGenerator.cxx
Stephen Kelly fc1c7cf85d Genex: Store a backtrace, not a pointer to one.
The storage of a pointer means that the ownership and lifetime are
externally determined, which is harder to reason about. It also imposes
API constraints, requiring APIs to return references to backtraces.

This pointer storage was introduced in commit v3.1.0-rc1~425^2~3 (genex:
remove the need for backtraces, 2014-05-23).  As backtraces are now cheap
to copy around, just do that instead.
2015-07-17 22:14:37 +02:00

158 lines
5.1 KiB
C++

/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2010 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 "cmCustomCommandGenerator.h"
#include "cmMakefile.h"
#include "cmCustomCommand.h"
#include "cmOutputConverter.h"
#include "cmGeneratorExpression.h"
//----------------------------------------------------------------------------
cmCustomCommandGenerator::cmCustomCommandGenerator(
cmCustomCommand const& cc, const std::string& config, cmMakefile* mf):
CC(cc), Config(config), Makefile(mf),
OldStyle(cc.GetEscapeOldStyle()), MakeVars(cc.GetEscapeAllowMakeVars()),
GE(new cmGeneratorExpression(cc.GetBacktrace())), DependsDone(false)
{
}
//----------------------------------------------------------------------------
cmCustomCommandGenerator::~cmCustomCommandGenerator()
{
delete this->GE;
}
//----------------------------------------------------------------------------
unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
{
return static_cast<unsigned int>(this->CC.GetCommandLines().size());
}
//----------------------------------------------------------------------------
std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
{
std::string const& argv0 = this->CC.GetCommandLines()[c][0];
cmTarget* target = this->Makefile->FindTargetToUse(argv0);
if(target && target->GetType() == cmTarget::EXECUTABLE &&
(target->IsImported() || !this->Makefile->IsOn("CMAKE_CROSSCOMPILING")))
{
return target->GetLocation(this->Config);
}
return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config);
}
//----------------------------------------------------------------------------
std::string escapeForShellOldStyle(const std::string& str)
{
std::string result;
#if defined(_WIN32) && !defined(__CYGWIN__)
// if there are spaces
std::string temp = str;
if (temp.find(" ") != std::string::npos &&
temp.find("\"")==std::string::npos)
{
result = "\"";
result += str;
result += "\"";
return result;
}
return str;
#else
for(const char* ch = str.c_str(); *ch != '\0'; ++ch)
{
if(*ch == ' ')
{
result += '\\';
}
result += *ch;
}
return result;
#endif
}
//----------------------------------------------------------------------------
void
cmCustomCommandGenerator
::AppendArguments(unsigned int c, std::string& cmd) const
{
cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c];
for(unsigned int j=1;j < commandLine.size(); ++j)
{
std::string arg = this->GE->Parse(commandLine[j])->Evaluate(this->Makefile,
this->Config);
cmd += " ";
if(this->OldStyle)
{
cmd += escapeForShellOldStyle(arg);
}
else
{
cmOutputConverter converter(this->Makefile->GetStateSnapshot());
cmd += converter.EscapeForShell(arg, this->MakeVars);
}
}
}
//----------------------------------------------------------------------------
const char* cmCustomCommandGenerator::GetComment() const
{
return this->CC.GetComment();
}
//----------------------------------------------------------------------------
std::string cmCustomCommandGenerator::GetWorkingDirectory() const
{
return this->CC.GetWorkingDirectory();
}
//----------------------------------------------------------------------------
std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
{
return this->CC.GetOutputs();
}
//----------------------------------------------------------------------------
std::vector<std::string> const& cmCustomCommandGenerator::GetByproducts() const
{
return this->CC.GetByproducts();
}
//----------------------------------------------------------------------------
std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const
{
if (!this->DependsDone)
{
this->DependsDone = true;
std::vector<std::string> depends = this->CC.GetDepends();
for(std::vector<std::string>::const_iterator
i = depends.begin();
i != depends.end(); ++i)
{
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
= this->GE->Parse(*i);
std::vector<std::string> result;
cmSystemTools::ExpandListArgument(
cge->Evaluate(this->Makefile, this->Config), result);
for (std::vector<std::string>::iterator it = result.begin();
it != result.end(); ++it)
{
if (cmSystemTools::FileIsFullPath(it->c_str()))
{
*it = cmSystemTools::CollapseFullPath(*it);
}
}
this->Depends.insert(this->Depends.end(), result.begin(), result.end());
}
}
return this->Depends;
}