c4af46b444
While tracing dependencies of a target, cmTargetTraceDependencies follows sources by full path to determine if the source is to be produced by a custom command. Commit 4959f341 (cmSourceFileLocation: Collapse full path for directory comparisons., 2014-03-27) changed the storage of target sources to be in the form of a normalized path instead of an unnormalized path. The path is followed by looking it up in a mapping via cmMakefile::GetSourceFileWithOutput to acquire an appropriate cmSourceFile. The mapping is populated with the OUTPUT components of add_custom_command invocations, however it is populated with unnormalized paths. This means that the tracing logic does not find appropriate cmSourceFiles, and does not generate appropriate build rules for the generated sources. Normalize the paths in the OUTPUT components of add_custom_command to resolve this. The paths in the DEPENDS component of add_custom_command are also not normalized, leading to the same problem again. Normalize the depends paths after generator evaluation and expansion.
122 lines
4.3 KiB
C++
122 lines
4.3 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 "cmLocalGenerator.h"
|
|
#include "cmGeneratorExpression.h"
|
|
|
|
//----------------------------------------------------------------------------
|
|
cmCustomCommandGenerator::cmCustomCommandGenerator(
|
|
cmCustomCommand const& cc, const std::string& config, cmMakefile* mf):
|
|
CC(cc), Config(config), Makefile(mf), LG(mf->GetLocalGenerator()),
|
|
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);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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 += this->LG->EscapeForShellOldStyle(arg);
|
|
}
|
|
else
|
|
{
|
|
cmd += this->LG->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::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;
|
|
}
|