diff options
author | Stephen Kelly <steveire@gmail.com> | 2014-02-13 19:52:21 (GMT) |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2014-04-02 21:14:02 (GMT) |
commit | 3676fb49634efd01755aa5c12d58e2f2bf20d09f (patch) | |
tree | 9fa46bbd284083457ce0133ff27d03fd710e9c76 /Source/cmTarget.cxx | |
parent | e6971df6ab647031ba9689c9afbbde78cc62e35f (diff) | |
download | CMake-3676fb49634efd01755aa5c12d58e2f2bf20d09f.zip CMake-3676fb49634efd01755aa5c12d58e2f2bf20d09f.tar.gz CMake-3676fb49634efd01755aa5c12d58e2f2bf20d09f.tar.bz2 |
cmTarget: Allow transitive evaluation of SOURCES property.
Extend the cmGeneratorExpressionDAGChecker with an interface
returning the name of the top target. Use that to determine
when there is a DAG violation, as required by the RunCMake.Languages
tests.
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r-- | Source/cmTarget.cxx | 191 |
1 files changed, 156 insertions, 35 deletions
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) |