summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx12
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h5
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx7
-rw-r--r--Source/cmTarget.cxx191
-rw-r--r--Source/cmTarget.h12
5 files changed, 185 insertions, 42 deletions
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 07efba9..7f8e694 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -179,6 +179,18 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt)
|| strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
}
+std::string cmGeneratorExpressionDAGChecker::TopTarget() const
+{
+ const cmGeneratorExpressionDAGChecker *top = this;
+ const cmGeneratorExpressionDAGChecker *parent = this->Parent;
+ while (parent)
+ {
+ top = parent;
+ parent = parent->Parent;
+ }
+ return top->Target;
+}
+
enum TransitiveProperty {
#define DEFINE_ENUM_ENTRY(NAME) NAME,
CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(DEFINE_ENUM_ENTRY)
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 6cbbd2a..b3147f7 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -25,7 +25,8 @@
SELECT(F, EvaluatingSystemIncludeDirectories, SYSTEM_INCLUDE_DIRECTORIES) \
SELECT(F, EvaluatingCompileDefinitions, COMPILE_DEFINITIONS) \
SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \
- SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS)
+ SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \
+ SELECT(F, EvaluatingSources, SOURCES)
#define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \
CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH)
@@ -70,6 +71,8 @@ struct cmGeneratorExpressionDAGChecker
void SetTransitivePropertiesOnly()
{ this->TransitivePropertiesOnly = true; }
+ std::string TopTarget() const;
+
private:
Result CheckGraph() const;
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index a392675..59e3aec 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -985,7 +985,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
if (propertyName == "LINKER_LANGUAGE")
{
if (target->LinkLanguagePropagatesToDependents() &&
- dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
+ dagCheckerParent && (dagCheckerParent->EvaluatingLinkLibraries()
+ || dagCheckerParent->EvaluatingSources()))
{
reportError(context, content->GetOriginalExpression(),
"LINKER_LANGUAGE target property can not be used while evaluating "
@@ -1569,7 +1570,9 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
"Target \"" + name + "\" is not an executable or library.");
return std::string();
}
- if (dagChecker && dagChecker->EvaluatingLinkLibraries(name.c_str()))
+ if (dagChecker && (dagChecker->EvaluatingLinkLibraries(name.c_str())
+ || (dagChecker->EvaluatingSources()
+ && name == dagChecker->TopTarget())))
{
::reportError(context, content->GetOriginalExpression(),
"Expressions which require the linker language may not "
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index fbd7315..0b5734d 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -159,10 +159,13 @@ public:
CachedLinkInterfaceCompileOptionsEntries;
mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
CachedLinkInterfaceCompileDefinitionsEntries;
+ mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
+ CachedLinkInterfaceSourcesEntries;
mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
+ mutable std::map<std::string, bool> CacheLinkInterfaceSourcesDone;
};
//----------------------------------------------------------------------------
@@ -198,6 +201,7 @@ cmTargetInternals::~cmTargetInternals()
deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
+ deleteAndClear(this->CachedLinkInterfaceSourcesEntries);
}
//----------------------------------------------------------------------------
@@ -543,44 +547,158 @@ bool cmTarget::IsBundleOnApple() const
}
//----------------------------------------------------------------------------
-void cmTarget::GetSourceFiles(std::vector<std::string> &files,
- const std::string& config) const
+static void processSources(cmTarget const* tgt,
+ const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+ std::vector<std::string> &srcs,
+ std::set<std::string> &uniqueSrcs,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ cmTarget const* head,
+ std::string const& config)
{
- assert(this->GetType() != INTERFACE_LIBRARY);
- for(std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
- si = this->Internal->SourceEntries.begin();
- si != this->Internal->SourceEntries.end(); ++si)
- {
- std::vector<std::string> srcs;
- cmSystemTools::ExpandListArgument((*si)->ge->Evaluate(this->Makefile,
- config,
- false,
- this),
- srcs);
+ cmMakefile *mf = tgt->GetMakefile();
- for(std::vector<std::string>::const_iterator i = srcs.begin();
- i != srcs.end(); ++i)
+ for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
+ it = entries.begin(), end = entries.end(); it != end; ++it)
+ {
+ bool cacheSources = false;
+ std::vector<std::string> entrySources = (*it)->CachedEntries;
+ if(entrySources.empty())
{
- std::string src = *i;
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(src);
- std::string e;
- src = sf->GetFullPath(&e);
- if(src.empty())
+ cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
+ config,
+ false,
+ head ? head : tgt,
+ tgt,
+ dagChecker),
+ entrySources);
+ if (mf->IsGeneratingBuildSystem()
+ && !(*it)->ge->GetHadContextSensitiveCondition())
+ {
+ cacheSources = true;
+ }
+
+ for(std::vector<std::string>::iterator i = entrySources.begin();
+ i != entrySources.end(); ++i)
{
- if(!e.empty())
+ std::string& src = *i;
+
+ cmSourceFile* sf = mf->GetOrCreateSource(src);
+ std::string e;
+ src = sf->GetFullPath(&e);
+ if(src.empty())
{
- cmake* cm = this->Makefile->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, e,
- this->GetBacktrace());
+ if(!e.empty())
+ {
+ cmake* cm = mf->GetCMakeInstance();
+ cm->IssueMessage(cmake::FATAL_ERROR, e,
+ tgt->GetBacktrace());
+ }
+ return;
}
- return;
}
- files.push_back(src);
+ if (cacheSources)
+ {
+ (*it)->CachedEntries = entrySources;
+ }
+ }
+ for(std::vector<std::string>::iterator
+ li = entrySources.begin(); li != entrySources.end(); ++li)
+ {
+ std::string src = *li;
+
+ if(uniqueSrcs.insert(src).second)
+ {
+ srcs.push_back(src);
+ }
}
}
}
//----------------------------------------------------------------------------
+void cmTarget::GetSourceFiles(std::vector<std::string> &files,
+ const std::string& config,
+ cmTarget const* head) const
+{
+ assert(this->GetType() != INTERFACE_LIBRARY);
+
+
+ cmListFileBacktrace lfbt;
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "SOURCES", 0, 0);
+
+ std::set<std::string> uniqueSrcs;
+ processSources(this,
+ this->Internal->SourceEntries,
+ files,
+ uniqueSrcs,
+ &dagChecker,
+ head,
+ config);
+
+ if (!this->Internal->CacheLinkInterfaceSourcesDone[config])
+ {
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->Internal->LinkImplementationPropertyEntries.begin(),
+ end = this->Internal->LinkImplementationPropertyEntries.end();
+ it != end; ++it)
+ {
+ if (!cmGeneratorExpression::IsValidTargetName(it->Value)
+ && cmGeneratorExpression::Find(it->Value) == std::string::npos)
+ {
+ continue;
+ }
+ {
+ cmGeneratorExpression ge(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(it->Value);
+ std::string targetResult = cge->Evaluate(this->Makefile, config,
+ false, this, 0, &dagChecker);
+ if (!this->Makefile->FindTargetToUse(targetResult))
+ {
+ continue;
+ }
+ }
+ std::string sourceGenex = "$<TARGET_PROPERTY:" +
+ it->Value + ",INTERFACE_SOURCES>";
+ if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
+ {
+ // Because it->Value is a generator expression, ensure that it
+ // evaluates to the non-empty string before being used in the
+ // TARGET_PROPERTY expression.
+ sourceGenex = "$<$<BOOL:" + it->Value + ">:" + sourceGenex + ">";
+ }
+ cmGeneratorExpression ge(it->Backtrace);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
+ sourceGenex);
+
+ this->Internal
+ ->CachedLinkInterfaceSourcesEntries[config].push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge,
+ it->Value));
+ }
+ }
+
+ processSources(this,
+ this->Internal->CachedLinkInterfaceSourcesEntries[config],
+ files,
+ uniqueSrcs,
+ &dagChecker,
+ head,
+ config);
+
+ if (!this->Makefile->IsGeneratingBuildSystem())
+ {
+ deleteAndClear(this->Internal->CachedLinkInterfaceSourcesEntries);
+ }
+ else
+ {
+ this->Internal->CacheLinkInterfaceSourcesDone[config] = true;
+ }
+}
+
+//----------------------------------------------------------------------------
bool
cmTarget::GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const
{
@@ -639,10 +757,11 @@ cmTarget::GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const
//----------------------------------------------------------------------------
void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files,
- const std::string& config) const
+ const std::string& config,
+ cmTarget const* head) const
{
std::vector<std::string> srcs;
- this->GetSourceFiles(srcs, config);
+ this->GetSourceFiles(srcs, config, head);
std::set<cmSourceFile*> emitted;
@@ -5053,10 +5172,11 @@ bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p,
//----------------------------------------------------------------------------
void cmTarget::GetLanguages(std::set<std::string>& languages,
- const std::string& config) const
+ const std::string& config,
+ cmTarget const* head) const
{
std::vector<cmSourceFile*> sourceFiles;
- this->GetSourceFiles(sourceFiles, config);
+ this->GetSourceFiles(sourceFiles, config, head);
for(std::vector<cmSourceFile*>::const_iterator
i = sourceFiles.begin(); i != sourceFiles.end(); ++i)
{
@@ -5111,7 +5231,7 @@ void cmTarget::GetLanguages(std::set<std::string>& languages,
for(std::vector<cmTarget*>::const_iterator
i = objectLibraries.begin(); i != objectLibraries.end(); ++i)
{
- (*i)->GetLanguages(languages, config);
+ (*i)->GetLanguages(languages, config, head);
}
}
@@ -6050,7 +6170,7 @@ cmTarget::GetLinkImplementation(const std::string& config,
// Compute the link implementation for this configuration.
LinkImplementation impl;
this->ComputeLinkImplementation(config, impl, head);
- this->ComputeLinkImplementationLanguages(config, impl);
+ this->ComputeLinkImplementationLanguages(config, impl, head);
// Store the information for this configuration.
cmTargetInternals::LinkImplMapType::value_type entry(key, impl);
@@ -6058,7 +6178,7 @@ cmTarget::GetLinkImplementation(const std::string& config,
}
else if (i->second.Languages.empty())
{
- this->ComputeLinkImplementationLanguages(config, i->second);
+ this->ComputeLinkImplementationLanguages(config, i->second, head);
}
return &i->second;
@@ -6172,12 +6292,13 @@ void cmTarget::ComputeLinkImplementation(const std::string& config,
//----------------------------------------------------------------------------
void
cmTarget::ComputeLinkImplementationLanguages(const std::string& config,
- LinkImplementation& impl) const
+ LinkImplementation& impl,
+ cmTarget const* head) const
{
// This target needs runtime libraries for its source languages.
std::set<std::string> languages;
// Get languages used in our source files.
- this->GetLanguages(languages, config);
+ this->GetLanguages(languages, config, head);
// Copy the set of langauges to the link implementation.
for(std::set<std::string>::iterator li = languages.begin();
li != languages.end(); ++li)
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 042b441..15c49ea 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -136,9 +136,11 @@ public:
* Get the list of the source files used by this target
*/
void GetSourceFiles(std::vector<std::string> &files,
- const std::string& config) const;
+ const std::string& config,
+ cmTarget const* head = 0) const;
void GetSourceFiles(std::vector<cmSourceFile*> &files,
- const std::string& config) const;
+ const std::string& config,
+ cmTarget const* head = 0) const;
bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const;
/**
@@ -469,7 +471,8 @@ public:
// information to forward these property changes to the targets
// until we have per-target object file properties.
void GetLanguages(std::set<std::string>& languages,
- const std::string& config) const;
+ std::string const& config,
+ cmTarget const* head = 0) const;
/** Return whether this target is an executable with symbol exports
enabled. */
@@ -743,7 +746,8 @@ private:
LinkImplementation& impl,
cmTarget const* head) const;
void ComputeLinkImplementationLanguages(const std::string& config,
- LinkImplementation& impl) const;
+ LinkImplementation& impl,
+ cmTarget const* head) const;
void ComputeLinkClosure(const std::string& config, LinkClosure& lc,
cmTarget const* head) const;