diff options
author | Brad King <brad.king@kitware.com> | 2014-04-03 16:51:53 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2014-04-03 16:51:53 (GMT) |
commit | 5376151aa1d724b6d7ddef8d2e521d97cbfa74ae (patch) | |
tree | 88ceb52c0ff365ceb53ea408f45fe729cfbd7f3c /Source/cmTarget.cxx | |
parent | 93054aa84f283de17c58fa2ee19a2a4a1668027d (diff) | |
parent | 9407174b1a0f1b4f8edf7fe08cc85ab6e990d59f (diff) | |
download | CMake-5376151aa1d724b6d7ddef8d2e521d97cbfa74ae.zip CMake-5376151aa1d724b6d7ddef8d2e521d97cbfa74ae.tar.gz CMake-5376151aa1d724b6d7ddef8d2e521d97cbfa74ae.tar.bz2 |
Merge topic 'target-transitive-sources'
9407174b target_sources: New command to add sources to target.
81ad69e0 Make the SOURCES target property writable.
6e636f2e cmTarget: Make the SOURCES origin tracable.
3676fb49 cmTarget: Allow transitive evaluation of SOURCES property.
e6971df6 cmTarget: Make the source files depend on the config.
df753df9 cmGeneratorTarget: Don't add computed sources to the target.
869328aa cmComputeTargetDepends: Use valid config to compute target depends.
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r-- | Source/cmTarget.cxx | 321 |
1 files changed, 287 insertions, 34 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 573b816..a87ec31 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); } //---------------------------------------------------------------------------- @@ -220,6 +224,7 @@ cmTarget::cmTarget() this->DebugIncludesDone = false; this->DebugCompileOptionsDone = false; this->DebugCompileDefinitionsDone = false; + this->DebugSourcesDone = false; } //---------------------------------------------------------------------------- @@ -543,47 +548,253 @@ bool cmTarget::IsBundleOnApple() const } //---------------------------------------------------------------------------- -void cmTarget::GetSourceFiles(std::vector<std::string> &files) 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, bool debugSources) { - assert(this->GetType() != INTERFACE_LIBRARY); - for(std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator - si = this->Internal->SourceEntries.begin(); - si != this->Internal->SourceEntries.end(); ++si) + cmMakefile *mf = tgt->GetMakefile(); + + for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator + it = entries.begin(), end = entries.end(); it != end; ++it) { - std::vector<std::string> srcs; - cmSystemTools::ExpandListArgument((*si)->ge->Evaluate(this->Makefile, - "", - false, - this), - srcs); + bool cacheSources = false; + std::vector<std::string> entrySources = (*it)->CachedEntries; + if(entrySources.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>::const_iterator i = srcs.begin(); - i != srcs.end(); ++i) + for(std::vector<std::string>::iterator i = entrySources.begin(); + i != entrySources.end(); ++i) + { + std::string& src = *i; + + cmSourceFile* sf = mf->GetOrCreateSource(src); + std::string e; + src = sf->GetFullPath(&e); + if(src.empty()) + { + if(!e.empty()) + { + cmake* cm = mf->GetCMakeInstance(); + cm->IssueMessage(cmake::FATAL_ERROR, e, + tgt->GetBacktrace()); + } + return; + } + } + if (cacheSources) + { + (*it)->CachedEntries = entrySources; + } + } + std::string usedSources; + for(std::vector<std::string>::iterator + li = entrySources.begin(); li != entrySources.end(); ++li) { - std::string src = *i; - cmSourceFile* sf = this->Makefile->GetOrCreateSource(src); - std::string e; - src = sf->GetFullPath(&e); - if(src.empty()) + std::string src = *li; + + if(uniqueSrcs.insert(src).second) { - if(!e.empty()) + srcs.push_back(src); + if (debugSources) { - cmake* cm = this->Makefile->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e, - this->GetBacktrace()); + usedSources += " * " + src + "\n"; } - return; } - files.push_back(src); + } + if (!usedSources.empty()) + { + mf->GetCMakeInstance()->IssueMessage(cmake::LOG, + std::string("Used sources for target ") + + tgt->GetName() + ":\n" + + usedSources, (*it)->ge->GetBacktrace()); } } } //---------------------------------------------------------------------------- -void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const +void cmTarget::GetSourceFiles(std::vector<std::string> &files, + const std::string& config, + cmTarget const* head) const +{ + assert(this->GetType() != INTERFACE_LIBRARY); + + std::vector<std::string> debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugSources = !this->DebugSourcesDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "SOURCES") + != debugProperties.end(); + + if (this->Makefile->IsGeneratingBuildSystem()) + { + this->DebugSourcesDone = true; + } + + 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, + debugSources); + + 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, + debugSources); + + if (!this->Makefile->IsGeneratingBuildSystem()) + { + deleteAndClear(this->Internal->CachedLinkInterfaceSourcesEntries); + } + else + { + this->Internal->CacheLinkInterfaceSourcesDone[config] = true; + } +} + +//---------------------------------------------------------------------------- +bool +cmTarget::GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const +{ + std::vector<std::string> configs; + this->Makefile->GetConfigurations(configs); + if (configs.empty()) + { + configs.push_back(""); + } + + std::vector<std::string>::const_iterator it = configs.begin(); + const std::string& firstConfig = *it; + this->GetSourceFiles(files, firstConfig); + + for ( ; it != configs.end(); ++it) + { + std::vector<cmSourceFile*> configFiles; + this->GetSourceFiles(configFiles, *it); + if (configFiles != files) + { + std::string firstConfigFiles; + const char* sep = ""; + for (std::vector<cmSourceFile*>::const_iterator fi = files.begin(); + fi != files.end(); ++fi) + { + firstConfigFiles += sep; + firstConfigFiles += (*fi)->GetFullPath(); + sep = "\n "; + } + + std::string thisConfigFiles; + sep = ""; + for (std::vector<cmSourceFile*>::const_iterator fi = configFiles.begin(); + fi != configFiles.end(); ++fi) + { + thisConfigFiles += sep; + thisConfigFiles += (*fi)->GetFullPath(); + sep = "\n "; + } + cmOStringStream e; + e << "Target \"" << this->Name << "\" has source files which vary by " + "configuration. This is not supported by the \"" + << this->Makefile->GetLocalGenerator() + ->GetGlobalGenerator()->GetName() + << "\" generator.\n" + "Config \"" << firstConfig << "\":\n" + " " << firstConfigFiles << "\n" + "Config \"" << *it << "\":\n" + " " << thisConfigFiles << "\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files, + const std::string& config, + cmTarget const* head) const { std::vector<std::string> srcs; - this->GetSourceFiles(srcs); + this->GetSourceFiles(srcs, config, head); std::set<cmSourceFile*> emitted; @@ -1487,6 +1698,25 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->LinkImplementationPropertyEntries.push_back(entry); return; } + if (prop == "SOURCES") + { + if(this->IsImported()) + { + cmOStringStream e; + e << "SOURCES property can't be set on imported targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + this->Internal->SourceEntries.clear(); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + this->Internal->SourceEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } this->Properties.SetProperty(prop, value, cmProperty::TARGET); this->MaybeInvalidatePropertyCache(prop); } @@ -1554,6 +1784,25 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, this->Internal->LinkImplementationPropertyEntries.push_back(entry); return; } + if (prop == "SOURCES") + { + if(this->IsImported()) + { + cmOStringStream e; + e << "SOURCES property can't be set on imported targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + this->Internal->SourceEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString); this->MaybeInvalidatePropertyCache(prop); } @@ -4994,10 +5243,12 @@ bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, } //---------------------------------------------------------------------------- -void cmTarget::GetLanguages(std::set<std::string>& languages) const +void cmTarget::GetLanguages(std::set<std::string>& languages, + const std::string& config, + cmTarget const* head) const { std::vector<cmSourceFile*> sourceFiles; - this->GetSourceFiles(sourceFiles); + this->GetSourceFiles(sourceFiles, config, head); for(std::vector<cmSourceFile*>::const_iterator i = sourceFiles.begin(); i != sourceFiles.end(); ++i) { @@ -5038,7 +5289,7 @@ void cmTarget::GetLanguages(std::set<std::string>& languages) const cmGeneratorTarget* gt = this->Makefile->GetLocalGenerator() ->GetGlobalGenerator() ->GetGeneratorTarget(this); - gt->GetExternalObjects(externalObjects); + gt->GetExternalObjects(externalObjects, config); for(std::vector<cmSourceFile const*>::const_iterator i = externalObjects.begin(); i != externalObjects.end(); ++i) { @@ -5052,7 +5303,7 @@ void cmTarget::GetLanguages(std::set<std::string>& languages) const for(std::vector<cmTarget*>::const_iterator i = objectLibraries.begin(); i != objectLibraries.end(); ++i) { - (*i)->GetLanguages(languages); + (*i)->GetLanguages(languages, config, head); } } @@ -5991,7 +6242,7 @@ cmTarget::GetLinkImplementation(const std::string& config, // Compute the link implementation for this configuration. LinkImplementation impl; this->ComputeLinkImplementation(config, impl, head); - this->ComputeLinkImplementationLanguages(impl); + this->ComputeLinkImplementationLanguages(config, impl, head); // Store the information for this configuration. cmTargetInternals::LinkImplMapType::value_type entry(key, impl); @@ -5999,7 +6250,7 @@ cmTarget::GetLinkImplementation(const std::string& config, } else if (i->second.Languages.empty()) { - this->ComputeLinkImplementationLanguages(i->second); + this->ComputeLinkImplementationLanguages(config, i->second, head); } return &i->second; @@ -6112,12 +6363,14 @@ void cmTarget::ComputeLinkImplementation(const std::string& config, //---------------------------------------------------------------------------- void -cmTarget::ComputeLinkImplementationLanguages(LinkImplementation& impl) const +cmTarget::ComputeLinkImplementationLanguages(const std::string& config, + 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); + 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) |