Move TraceDependencies to cmGeneratorTarget.
This commit is contained in:
parent
fa03777626
commit
07f5788385
|
@ -19,6 +19,8 @@
|
|||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorExpressionDAGChecker.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t)
|
||||
{
|
||||
|
@ -45,6 +47,18 @@ const char *cmGeneratorTarget::GetProperty(const char *prop)
|
|||
return this->Target->GetProperty(prop);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::vector<cmSourceFile*> const*
|
||||
cmGeneratorTarget::GetSourceDepends(cmSourceFile* sf)
|
||||
{
|
||||
SourceEntriesType::iterator i = this->SourceEntries.find(sf);
|
||||
if(i != this->SourceEntries.end())
|
||||
{
|
||||
return &i->second.Depends;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir,
|
||||
const char *config)
|
||||
|
@ -269,6 +283,285 @@ void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs)
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class cmTargetTraceDependencies
|
||||
{
|
||||
public:
|
||||
cmTargetTraceDependencies(cmGeneratorTarget* target);
|
||||
void Trace();
|
||||
private:
|
||||
cmTarget* Target;
|
||||
cmGeneratorTarget* GeneratorTarget;
|
||||
cmMakefile* Makefile;
|
||||
cmGlobalGenerator* GlobalGenerator;
|
||||
typedef cmGeneratorTarget::SourceEntry SourceEntry;
|
||||
SourceEntry* CurrentEntry;
|
||||
std::queue<cmSourceFile*> SourceQueue;
|
||||
std::set<cmSourceFile*> SourcesQueued;
|
||||
typedef std::map<cmStdString, cmSourceFile*> NameMapType;
|
||||
NameMapType NameMap;
|
||||
|
||||
void QueueSource(cmSourceFile* sf);
|
||||
void FollowName(std::string const& name);
|
||||
void FollowNames(std::vector<std::string> const& names);
|
||||
bool IsUtility(std::string const& dep);
|
||||
void CheckCustomCommand(cmCustomCommand const& cc);
|
||||
void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmTargetTraceDependencies
|
||||
::cmTargetTraceDependencies(cmGeneratorTarget* target):
|
||||
Target(target->Target), GeneratorTarget(target)
|
||||
{
|
||||
// Convenience.
|
||||
this->Makefile = this->Target->GetMakefile();
|
||||
this->GlobalGenerator =
|
||||
this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
|
||||
this->CurrentEntry = 0;
|
||||
|
||||
// Queue all the source files already specified for the target.
|
||||
std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
|
||||
for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
|
||||
si != sources.end(); ++si)
|
||||
{
|
||||
this->QueueSource(*si);
|
||||
}
|
||||
|
||||
// Queue pre-build, pre-link, and post-build rule dependencies.
|
||||
this->CheckCustomCommands(this->Target->GetPreBuildCommands());
|
||||
this->CheckCustomCommands(this->Target->GetPreLinkCommands());
|
||||
this->CheckCustomCommands(this->Target->GetPostBuildCommands());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTargetTraceDependencies::Trace()
|
||||
{
|
||||
// Process one dependency at a time until the queue is empty.
|
||||
while(!this->SourceQueue.empty())
|
||||
{
|
||||
// Get the next source from the queue.
|
||||
cmSourceFile* sf = this->SourceQueue.front();
|
||||
this->SourceQueue.pop();
|
||||
this->CurrentEntry = &this->GeneratorTarget->SourceEntries[sf];
|
||||
|
||||
// Queue dependencies added explicitly by the user.
|
||||
if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS"))
|
||||
{
|
||||
std::vector<std::string> objDeps;
|
||||
cmSystemTools::ExpandListArgument(additionalDeps, objDeps);
|
||||
this->FollowNames(objDeps);
|
||||
}
|
||||
|
||||
// Queue the source needed to generate this file, if any.
|
||||
this->FollowName(sf->GetFullPath());
|
||||
|
||||
// Queue dependencies added programatically by commands.
|
||||
this->FollowNames(sf->GetDepends());
|
||||
|
||||
// Queue custom command dependencies.
|
||||
if(cmCustomCommand const* cc = sf->GetCustomCommand())
|
||||
{
|
||||
this->CheckCustomCommand(*cc);
|
||||
}
|
||||
}
|
||||
this->CurrentEntry = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
|
||||
{
|
||||
if(this->SourcesQueued.insert(sf).second)
|
||||
{
|
||||
this->SourceQueue.push(sf);
|
||||
|
||||
// Make sure this file is in the target.
|
||||
this->Target->AddSourceFile(sf);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTargetTraceDependencies::FollowName(std::string const& name)
|
||||
{
|
||||
NameMapType::iterator i = this->NameMap.find(name);
|
||||
if(i == this->NameMap.end())
|
||||
{
|
||||
// Check if we know how to generate this file.
|
||||
cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name.c_str());
|
||||
NameMapType::value_type entry(name, sf);
|
||||
i = this->NameMap.insert(entry).first;
|
||||
}
|
||||
if(cmSourceFile* sf = i->second)
|
||||
{
|
||||
// Record the dependency we just followed.
|
||||
if(this->CurrentEntry)
|
||||
{
|
||||
this->CurrentEntry->Depends.push_back(sf);
|
||||
}
|
||||
|
||||
this->QueueSource(sf);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmTargetTraceDependencies::FollowNames(std::vector<std::string> const& names)
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator i = names.begin();
|
||||
i != names.end(); ++i)
|
||||
{
|
||||
this->FollowName(*i);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
|
||||
{
|
||||
// Dependencies on targets (utilities) are supposed to be named by
|
||||
// just the target name. However for compatibility we support
|
||||
// naming the output file generated by the target (assuming there is
|
||||
// no output-name property which old code would not have set). In
|
||||
// that case the target name will be the file basename of the
|
||||
// dependency.
|
||||
std::string util = cmSystemTools::GetFilenameName(dep);
|
||||
if(cmSystemTools::GetFilenameLastExtension(util) == ".exe")
|
||||
{
|
||||
util = cmSystemTools::GetFilenameWithoutLastExtension(util);
|
||||
}
|
||||
|
||||
// Check for a target with this name.
|
||||
if(cmTarget* t = this->Makefile->FindTargetToUse(util.c_str()))
|
||||
{
|
||||
// If we find the target and the dep was given as a full path,
|
||||
// then make sure it was not a full path to something else, and
|
||||
// the fact that the name matched a target was just a coincidence.
|
||||
if(cmSystemTools::FileIsFullPath(dep.c_str()))
|
||||
{
|
||||
if(t->GetType() >= cmTarget::EXECUTABLE &&
|
||||
t->GetType() <= cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
// This is really only for compatibility so we do not need to
|
||||
// worry about configuration names and output names.
|
||||
std::string tLocation = t->GetLocation(0);
|
||||
tLocation = cmSystemTools::GetFilenamePath(tLocation);
|
||||
std::string depLocation = cmSystemTools::GetFilenamePath(dep);
|
||||
depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str());
|
||||
tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
|
||||
if(depLocation == tLocation)
|
||||
{
|
||||
this->Target->AddUtility(util.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The original name of the dependency was not a full path. It
|
||||
// must name a target, so add the target-level dependency.
|
||||
this->Target->AddUtility(util.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// The dependency does not name a target built in this project.
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmTargetTraceDependencies
|
||||
::CheckCustomCommand(cmCustomCommand const& cc)
|
||||
{
|
||||
// Transform command names that reference targets built in this
|
||||
// project to corresponding target-level dependencies.
|
||||
cmGeneratorExpression ge(cc.GetBacktrace());
|
||||
|
||||
// Add target-level dependencies referenced by generator expressions.
|
||||
std::set<cmTarget*> targets;
|
||||
|
||||
for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
|
||||
cit != cc.GetCommandLines().end(); ++cit)
|
||||
{
|
||||
std::string const& command = *cit->begin();
|
||||
// Check for a target with this name.
|
||||
if(cmTarget* t = this->Makefile->FindTargetToUse(command.c_str()))
|
||||
{
|
||||
if(t->GetType() == cmTarget::EXECUTABLE)
|
||||
{
|
||||
// The command refers to an executable target built in
|
||||
// this project. Add the target-level dependency to make
|
||||
// sure the executable is up to date before this custom
|
||||
// command possibly runs.
|
||||
this->Target->AddUtility(command.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check for target references in generator expressions.
|
||||
for(cmCustomCommandLine::const_iterator cli = cit->begin();
|
||||
cli != cit->end(); ++cli)
|
||||
{
|
||||
const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
|
||||
= ge.Parse(*cli);
|
||||
cge->Evaluate(this->Makefile, 0, true);
|
||||
std::set<cmTarget*> geTargets = cge->GetTargets();
|
||||
for(std::set<cmTarget*>::const_iterator it = geTargets.begin();
|
||||
it != geTargets.end(); ++it)
|
||||
{
|
||||
targets.insert(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(std::set<cmTarget*>::iterator ti = targets.begin();
|
||||
ti != targets.end(); ++ti)
|
||||
{
|
||||
this->Target->AddUtility((*ti)->GetName());
|
||||
}
|
||||
|
||||
// Queue the custom command dependencies.
|
||||
std::vector<std::string> const& depends = cc.GetDepends();
|
||||
for(std::vector<std::string>::const_iterator di = depends.begin();
|
||||
di != depends.end(); ++di)
|
||||
{
|
||||
std::string const& dep = *di;
|
||||
if(!this->IsUtility(dep))
|
||||
{
|
||||
// The dependency does not name a target and may be a file we
|
||||
// know how to generate. Queue it.
|
||||
this->FollowName(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmTargetTraceDependencies
|
||||
::CheckCustomCommands(const std::vector<cmCustomCommand>& commands)
|
||||
{
|
||||
for(std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
|
||||
cli != commands.end(); ++cli)
|
||||
{
|
||||
this->CheckCustomCommand(*cli);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmGeneratorTarget::TraceDependencies()
|
||||
{
|
||||
// CMake-generated targets have no dependencies to trace. Normally tracing
|
||||
// would find nothing anyway, but when building CMake itself the "install"
|
||||
// target command ends up referencing the "cmake" target but we do not
|
||||
// really want the dependency because "install" depend on "all" anyway.
|
||||
if(this->GetType() == cmTarget::GLOBAL_TARGET)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Use a helper object to trace the dependencies.
|
||||
cmTargetTraceDependencies tracer(this);
|
||||
tracer.Trace();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmGeneratorTarget::GetAppleArchs(const char* config,
|
||||
std::vector<std::string>& archVec)
|
||||
|
|
|
@ -77,9 +77,22 @@ public:
|
|||
/** Add the target output files to the global generator manifest. */
|
||||
void GenerateTargetManifest(const char* config);
|
||||
|
||||
/**
|
||||
* Trace through the source files in this target and add al source files
|
||||
* that they depend on, used by all generators
|
||||
*/
|
||||
void TraceDependencies();
|
||||
|
||||
void ClassifySources();
|
||||
void LookupObjectLibraries();
|
||||
|
||||
/** Get sources that must be built before the given source. */
|
||||
std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile* sf);
|
||||
|
||||
struct SourceEntry { std::vector<cmSourceFile*> Depends; };
|
||||
typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
|
||||
SourceEntriesType SourceEntries;
|
||||
|
||||
private:
|
||||
std::map<std::string, std::vector<std::string> > SystemIncludesCache;
|
||||
|
||||
|
|
|
@ -257,10 +257,11 @@ void cmLocalGenerator::ConfigureFinalPass()
|
|||
void cmLocalGenerator::TraceDependencies()
|
||||
{
|
||||
// Generate the rule files for each target.
|
||||
cmTargets& targets = this->Makefile->GetTargets();
|
||||
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
|
||||
cmGeneratorTargetsType targets = this->Makefile->GetGeneratorTargets();
|
||||
for(cmGeneratorTargetsType::iterator t = targets.begin();
|
||||
t != targets.end(); ++t)
|
||||
{
|
||||
t->second.TraceDependencies();
|
||||
t->second->TraceDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <cmsys/RegularExpression.hxx>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <queue>
|
||||
#include <stdlib.h> // required for atof
|
||||
#include <assert.h>
|
||||
|
||||
|
@ -84,12 +83,9 @@ public:
|
|||
{
|
||||
this->SourceFileFlagsConstructed = false;
|
||||
}
|
||||
cmTargetInternals(cmTargetInternals const& r)
|
||||
cmTargetInternals(cmTargetInternals const&)
|
||||
{
|
||||
this->SourceFileFlagsConstructed = false;
|
||||
// Only some of these entries are part of the object state.
|
||||
// Others not copied here are result caches.
|
||||
this->SourceEntries = r.SourceEntries;
|
||||
}
|
||||
~cmTargetInternals();
|
||||
typedef cmTarget::SourceFileFlags SourceFileFlags;
|
||||
|
@ -125,10 +121,6 @@ public:
|
|||
LinkClosureMapType;
|
||||
LinkClosureMapType LinkClosureMap;
|
||||
|
||||
struct SourceEntry { std::vector<cmSourceFile*> Depends; };
|
||||
typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
|
||||
SourceEntriesType SourceEntries;
|
||||
|
||||
struct TargetPropertyEntry {
|
||||
TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
|
||||
const std::string &targetName = std::string())
|
||||
|
@ -488,285 +480,6 @@ bool cmTarget::IsBundleOnApple()
|
|||
this->IsCFBundleOnApple();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class cmTargetTraceDependencies
|
||||
{
|
||||
public:
|
||||
cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal);
|
||||
void Trace();
|
||||
private:
|
||||
cmTarget* Target;
|
||||
cmTargetInternals* Internal;
|
||||
cmMakefile* Makefile;
|
||||
cmGlobalGenerator* GlobalGenerator;
|
||||
typedef cmTargetInternals::SourceEntry SourceEntry;
|
||||
SourceEntry* CurrentEntry;
|
||||
std::queue<cmSourceFile*> SourceQueue;
|
||||
std::set<cmSourceFile*> SourcesQueued;
|
||||
typedef std::map<cmStdString, cmSourceFile*> NameMapType;
|
||||
NameMapType NameMap;
|
||||
|
||||
void QueueSource(cmSourceFile* sf);
|
||||
void FollowName(std::string const& name);
|
||||
void FollowNames(std::vector<std::string> const& names);
|
||||
bool IsUtility(std::string const& dep);
|
||||
void CheckCustomCommand(cmCustomCommand const& cc);
|
||||
void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmTargetTraceDependencies
|
||||
::cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal):
|
||||
Target(target), Internal(internal)
|
||||
{
|
||||
// Convenience.
|
||||
this->Makefile = this->Target->GetMakefile();
|
||||
this->GlobalGenerator =
|
||||
this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
|
||||
this->CurrentEntry = 0;
|
||||
|
||||
// Queue all the source files already specified for the target.
|
||||
std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
|
||||
for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
|
||||
si != sources.end(); ++si)
|
||||
{
|
||||
this->QueueSource(*si);
|
||||
}
|
||||
|
||||
// Queue pre-build, pre-link, and post-build rule dependencies.
|
||||
this->CheckCustomCommands(this->Target->GetPreBuildCommands());
|
||||
this->CheckCustomCommands(this->Target->GetPreLinkCommands());
|
||||
this->CheckCustomCommands(this->Target->GetPostBuildCommands());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTargetTraceDependencies::Trace()
|
||||
{
|
||||
// Process one dependency at a time until the queue is empty.
|
||||
while(!this->SourceQueue.empty())
|
||||
{
|
||||
// Get the next source from the queue.
|
||||
cmSourceFile* sf = this->SourceQueue.front();
|
||||
this->SourceQueue.pop();
|
||||
this->CurrentEntry = &this->Internal->SourceEntries[sf];
|
||||
|
||||
// Queue dependencies added explicitly by the user.
|
||||
if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS"))
|
||||
{
|
||||
std::vector<std::string> objDeps;
|
||||
cmSystemTools::ExpandListArgument(additionalDeps, objDeps);
|
||||
this->FollowNames(objDeps);
|
||||
}
|
||||
|
||||
// Queue the source needed to generate this file, if any.
|
||||
this->FollowName(sf->GetFullPath());
|
||||
|
||||
// Queue dependencies added programatically by commands.
|
||||
this->FollowNames(sf->GetDepends());
|
||||
|
||||
// Queue custom command dependencies.
|
||||
if(cmCustomCommand const* cc = sf->GetCustomCommand())
|
||||
{
|
||||
this->CheckCustomCommand(*cc);
|
||||
}
|
||||
}
|
||||
this->CurrentEntry = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
|
||||
{
|
||||
if(this->SourcesQueued.insert(sf).second)
|
||||
{
|
||||
this->SourceQueue.push(sf);
|
||||
|
||||
// Make sure this file is in the target.
|
||||
this->Target->AddSourceFile(sf);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTargetTraceDependencies::FollowName(std::string const& name)
|
||||
{
|
||||
NameMapType::iterator i = this->NameMap.find(name);
|
||||
if(i == this->NameMap.end())
|
||||
{
|
||||
// Check if we know how to generate this file.
|
||||
cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name.c_str());
|
||||
NameMapType::value_type entry(name, sf);
|
||||
i = this->NameMap.insert(entry).first;
|
||||
}
|
||||
if(cmSourceFile* sf = i->second)
|
||||
{
|
||||
// Record the dependency we just followed.
|
||||
if(this->CurrentEntry)
|
||||
{
|
||||
this->CurrentEntry->Depends.push_back(sf);
|
||||
}
|
||||
|
||||
this->QueueSource(sf);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmTargetTraceDependencies::FollowNames(std::vector<std::string> const& names)
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator i = names.begin();
|
||||
i != names.end(); ++i)
|
||||
{
|
||||
this->FollowName(*i);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
|
||||
{
|
||||
// Dependencies on targets (utilities) are supposed to be named by
|
||||
// just the target name. However for compatibility we support
|
||||
// naming the output file generated by the target (assuming there is
|
||||
// no output-name property which old code would not have set). In
|
||||
// that case the target name will be the file basename of the
|
||||
// dependency.
|
||||
std::string util = cmSystemTools::GetFilenameName(dep);
|
||||
if(cmSystemTools::GetFilenameLastExtension(util) == ".exe")
|
||||
{
|
||||
util = cmSystemTools::GetFilenameWithoutLastExtension(util);
|
||||
}
|
||||
|
||||
// Check for a target with this name.
|
||||
if(cmTarget* t = this->Makefile->FindTargetToUse(util.c_str()))
|
||||
{
|
||||
// If we find the target and the dep was given as a full path,
|
||||
// then make sure it was not a full path to something else, and
|
||||
// the fact that the name matched a target was just a coincidence.
|
||||
if(cmSystemTools::FileIsFullPath(dep.c_str()))
|
||||
{
|
||||
if(t->GetType() >= cmTarget::EXECUTABLE &&
|
||||
t->GetType() <= cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
// This is really only for compatibility so we do not need to
|
||||
// worry about configuration names and output names.
|
||||
std::string tLocation = t->GetLocation(0);
|
||||
tLocation = cmSystemTools::GetFilenamePath(tLocation);
|
||||
std::string depLocation = cmSystemTools::GetFilenamePath(dep);
|
||||
depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str());
|
||||
tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
|
||||
if(depLocation == tLocation)
|
||||
{
|
||||
this->Target->AddUtility(util.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The original name of the dependency was not a full path. It
|
||||
// must name a target, so add the target-level dependency.
|
||||
this->Target->AddUtility(util.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// The dependency does not name a target built in this project.
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmTargetTraceDependencies
|
||||
::CheckCustomCommand(cmCustomCommand const& cc)
|
||||
{
|
||||
// Transform command names that reference targets built in this
|
||||
// project to corresponding target-level dependencies.
|
||||
cmGeneratorExpression ge(cc.GetBacktrace());
|
||||
|
||||
// Add target-level dependencies referenced by generator expressions.
|
||||
std::set<cmTarget*> targets;
|
||||
|
||||
for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
|
||||
cit != cc.GetCommandLines().end(); ++cit)
|
||||
{
|
||||
std::string const& command = *cit->begin();
|
||||
// Check for a target with this name.
|
||||
if(cmTarget* t = this->Makefile->FindTargetToUse(command.c_str()))
|
||||
{
|
||||
if(t->GetType() == cmTarget::EXECUTABLE)
|
||||
{
|
||||
// The command refers to an executable target built in
|
||||
// this project. Add the target-level dependency to make
|
||||
// sure the executable is up to date before this custom
|
||||
// command possibly runs.
|
||||
this->Target->AddUtility(command.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check for target references in generator expressions.
|
||||
for(cmCustomCommandLine::const_iterator cli = cit->begin();
|
||||
cli != cit->end(); ++cli)
|
||||
{
|
||||
const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
|
||||
= ge.Parse(*cli);
|
||||
cge->Evaluate(this->Makefile, 0, true);
|
||||
std::set<cmTarget*> geTargets = cge->GetTargets();
|
||||
for(std::set<cmTarget*>::const_iterator it = geTargets.begin();
|
||||
it != geTargets.end(); ++it)
|
||||
{
|
||||
targets.insert(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(std::set<cmTarget*>::iterator ti = targets.begin();
|
||||
ti != targets.end(); ++ti)
|
||||
{
|
||||
this->Target->AddUtility((*ti)->GetName());
|
||||
}
|
||||
|
||||
// Queue the custom command dependencies.
|
||||
std::vector<std::string> const& depends = cc.GetDepends();
|
||||
for(std::vector<std::string>::const_iterator di = depends.begin();
|
||||
di != depends.end(); ++di)
|
||||
{
|
||||
std::string const& dep = *di;
|
||||
if(!this->IsUtility(dep))
|
||||
{
|
||||
// The dependency does not name a target and may be a file we
|
||||
// know how to generate. Queue it.
|
||||
this->FollowName(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmTargetTraceDependencies
|
||||
::CheckCustomCommands(const std::vector<cmCustomCommand>& commands)
|
||||
{
|
||||
for(std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
|
||||
cli != commands.end(); ++cli)
|
||||
{
|
||||
this->CheckCustomCommand(*cli);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::TraceDependencies()
|
||||
{
|
||||
// CMake-generated targets have no dependencies to trace. Normally tracing
|
||||
// would find nothing anyway, but when building CMake itself the "install"
|
||||
// target command ends up referencing the "cmake" target but we do not
|
||||
// really want the dependency because "install" depend on "all" anyway.
|
||||
if(this->GetType() == cmTarget::GLOBAL_TARGET)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Use a helper object to trace the dependencies.
|
||||
cmTargetTraceDependencies tracer(this, this->Internal.Get());
|
||||
tracer.Trace();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmTarget::FindSourceFiles()
|
||||
{
|
||||
|
@ -798,28 +511,13 @@ std::vector<cmSourceFile*> const& cmTarget::GetSourceFiles()
|
|||
//----------------------------------------------------------------------------
|
||||
void cmTarget::AddSourceFile(cmSourceFile* sf)
|
||||
{
|
||||
typedef cmTargetInternals::SourceEntriesType SourceEntriesType;
|
||||
if (std::find(this->SourceFiles.begin(), this->SourceFiles.end(), sf)
|
||||
== this->SourceFiles.end())
|
||||
{
|
||||
typedef cmTargetInternals::SourceEntry SourceEntry;
|
||||
this->SourceFiles.push_back(sf);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::vector<cmSourceFile*> const*
|
||||
cmTarget::GetSourceDepends(cmSourceFile* sf)
|
||||
{
|
||||
typedef cmTargetInternals::SourceEntriesType SourceEntriesType;
|
||||
SourceEntriesType::iterator i = this->Internal->SourceEntries.find(sf);
|
||||
if(i != this->Internal->SourceEntries.end())
|
||||
{
|
||||
return &i->second.Depends;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::AddSources(std::vector<std::string> const& srcs)
|
||||
{
|
||||
|
|
|
@ -34,6 +34,8 @@ class cmGlobalGenerator;
|
|||
class cmComputeLinkInformation;
|
||||
class cmListFileBacktrace;
|
||||
class cmTarget;
|
||||
class cmGeneratorTarget;
|
||||
class cmTargetTraceDependencies;
|
||||
|
||||
struct cmTargetLinkInformationMap:
|
||||
public std::map<std::pair<cmTarget*, std::string>, cmComputeLinkInformation*>
|
||||
|
@ -128,9 +130,6 @@ public:
|
|||
return this->ObjectLibraries;
|
||||
}
|
||||
|
||||
/** Get sources that must be built before the given source. */
|
||||
std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile* sf);
|
||||
|
||||
/**
|
||||
* Flags for a given source file as used in this target. Typically assigned
|
||||
* via SET_TARGET_PROPERTIES when the property is a list of source files.
|
||||
|
@ -346,12 +345,6 @@ public:
|
|||
is returned if the property is not set or cannot be parsed. */
|
||||
void GetTargetVersion(bool soversion, int& major, int& minor, int& patch);
|
||||
|
||||
/**
|
||||
* Trace through the source files in this target and add al source files
|
||||
* that they depend on, used by all generators
|
||||
*/
|
||||
void TraceDependencies();
|
||||
|
||||
/**
|
||||
* Make sure the full path to all source files is known.
|
||||
*/
|
||||
|
@ -732,6 +725,8 @@ private:
|
|||
|
||||
// Internal representation details.
|
||||
friend class cmTargetInternals;
|
||||
friend class cmGeneratorTarget;
|
||||
friend class cmTargetTraceDependencies;
|
||||
cmTargetInternalPointer Internal;
|
||||
|
||||
void ConstructSourceFileFlags();
|
||||
|
|
|
@ -562,7 +562,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommand(cmSourceFile* sf)
|
|||
if(this->SourcesVisited.insert(sf).second)
|
||||
{
|
||||
if(std::vector<cmSourceFile*> const* depends =
|
||||
this->Target->GetSourceDepends(sf))
|
||||
this->GeneratorTarget->GetSourceDepends(sf))
|
||||
{
|
||||
for(std::vector<cmSourceFile*>::const_iterator di = depends->begin();
|
||||
di != depends->end(); ++di)
|
||||
|
@ -1049,7 +1049,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
|
|||
si = this->GeneratorTarget->ExternalObjects.begin();
|
||||
si != this->GeneratorTarget->ExternalObjects.end(); ++si)
|
||||
{
|
||||
std::vector<cmSourceFile*> const* d=this->Target->GetSourceDepends(*si);
|
||||
std::vector<cmSourceFile*> const* d =
|
||||
this->GeneratorTarget->GetSourceDepends(*si);
|
||||
this->WriteSource((d && !d->empty())? "None":"Object", *si);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue