diff options
author | Stephen Kelly <steveire@gmail.com> | 2014-02-13 20:52:21 +0100 |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2014-04-02 23:14:02 +0200 |
commit | 3676fb49634efd01755aa5c12d58e2f2bf20d09f (patch) | |
tree | 9fa46bbd284083457ce0133ff27d03fd710e9c76 /Source | |
parent | e6971df6ab647031ba9689c9afbbde78cc62e35f (diff) | |
download | cmake-3676fb49634efd01755aa5c12d58e2f2bf20d09f.tar.gz |
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')
-rw-r--r-- | Source/cmGeneratorExpressionDAGChecker.cxx | 12 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionDAGChecker.h | 5 | ||||
-rw-r--r-- | Source/cmGeneratorExpressionEvaluator.cxx | 7 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 191 | ||||
-rw-r--r-- | Source/cmTarget.h | 12 |
5 files changed, 185 insertions, 42 deletions
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 07efba9bc9..7f8e6943a7 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 6cbbd2a076..b3147f7e14 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 a3926750f9..59e3aec6ce 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 fbd7315865..0b5734de50 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 042b441d70..15c49ea024 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; |