summaryrefslogtreecommitdiffstats
path: root/Source/cmTarget.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2014-04-03 16:51:53 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2014-04-03 16:51:53 (GMT)
commit5376151aa1d724b6d7ddef8d2e521d97cbfa74ae (patch)
tree88ceb52c0ff365ceb53ea408f45fe729cfbd7f3c /Source/cmTarget.cxx
parent93054aa84f283de17c58fa2ee19a2a4a1668027d (diff)
parent9407174b1a0f1b4f8edf7fe08cc85ab6e990d59f (diff)
downloadCMake-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.cxx321
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)