summaryrefslogtreecommitdiffstats
path: root/Source/cmTarget.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r--Source/cmTarget.cxx313
1 files changed, 251 insertions, 62 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 32aaccc..573b816 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -150,6 +150,7 @@ public:
std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
std::vector<TargetPropertyEntry*> CompileOptionsEntries;
std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
+ std::vector<TargetPropertyEntry*> SourceEntries;
std::vector<cmValueWithOrigin> LinkImplementationPropertyEntries;
mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
@@ -542,35 +543,58 @@ bool cmTarget::IsBundleOnApple() const
}
//----------------------------------------------------------------------------
-void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const
+void cmTarget::GetSourceFiles(std::vector<std::string> &files) const
{
assert(this->GetType() != INTERFACE_LIBRARY);
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->SourceFiles.begin();
- si != this->SourceFiles.end(); ++si)
+ for(std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
+ si = this->Internal->SourceEntries.begin();
+ si != this->Internal->SourceEntries.end(); ++si)
{
- std::string e;
- if((*si)->GetFullPath(&e).empty())
+ std::vector<std::string> srcs;
+ cmSystemTools::ExpandListArgument((*si)->ge->Evaluate(this->Makefile,
+ "",
+ false,
+ this),
+ srcs);
+
+ for(std::vector<std::string>::const_iterator i = srcs.begin();
+ i != srcs.end(); ++i)
{
- if(!e.empty())
+ std::string src = *i;
+ cmSourceFile* sf = this->Makefile->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 = this->Makefile->GetCMakeInstance();
+ cm->IssueMessage(cmake::FATAL_ERROR, e,
+ this->GetBacktrace());
+ }
+ return;
}
- return;
+ files.push_back(src);
}
}
- files = this->SourceFiles;
}
//----------------------------------------------------------------------------
-void cmTarget::AddSourceFile(cmSourceFile* sf)
+void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const
{
- if (std::find(this->SourceFiles.begin(), this->SourceFiles.end(), sf)
- == this->SourceFiles.end())
+ std::vector<std::string> srcs;
+ this->GetSourceFiles(srcs);
+
+ std::set<cmSourceFile*> emitted;
+
+ for(std::vector<std::string>::const_iterator i = srcs.begin();
+ i != srcs.end(); ++i)
{
- this->SourceFiles.push_back(sf);
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
+ if (emitted.insert(sf).second)
+ {
+ files.push_back(sf);
+ }
}
}
@@ -583,17 +607,17 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
const char* src = i->c_str();
if(src[0] == '$' && src[1] == '<')
{
- this->ProcessSourceExpression(*i);
+ this->AddSource(src);
}
else
{
- this->AddSource(src);
+ this->AddSourceCMP0049(src);
}
}
}
//----------------------------------------------------------------------------
-cmSourceFile* cmTarget::AddSource(const std::string& s)
+cmSourceFile* cmTarget::AddSourceCMP0049(const std::string& s)
{
std::string src = s;
@@ -632,28 +656,91 @@ cmSourceFile* cmTarget::AddSource(const std::string& s)
}
}
}
-
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(src);
- this->AddSourceFile(sf);
- return sf;
+ return this->AddSource(src);
}
//----------------------------------------------------------------------------
-void cmTarget::ProcessSourceExpression(std::string const& expr)
+struct CreateLocation
+{
+ cmMakefile const* Makefile;
+
+ CreateLocation(cmMakefile const* mf)
+ : Makefile(mf)
+ {
+
+ }
+
+ cmSourceFileLocation operator()(const std::string& filename)
+ {
+ return cmSourceFileLocation(this->Makefile, filename);
+ }
+};
+
+//----------------------------------------------------------------------------
+struct LocationMatcher
{
- if(cmHasLiteralPrefix(expr.c_str(), "$<TARGET_OBJECTS:") &&
- expr[expr.size()-1] == '>')
+ const cmSourceFileLocation& Needle;
+
+ LocationMatcher(const cmSourceFileLocation& needle)
+ : Needle(needle)
+ {
+
+ }
+
+ bool operator()(cmSourceFileLocation &loc)
+ {
+ return loc.Matches(this->Needle);
+ }
+};
+
+
+//----------------------------------------------------------------------------
+struct TargetPropertyEntryFinder
+{
+private:
+ const cmSourceFileLocation& Needle;
+public:
+ TargetPropertyEntryFinder(const cmSourceFileLocation& needle)
+ : Needle(needle)
+ {
+
+ }
+
+ bool operator()(cmTargetInternals::TargetPropertyEntry* entry)
+ {
+ std::vector<std::string> files;
+ cmSystemTools::ExpandListArgument(entry->ge->GetInput(), files);
+ std::vector<cmSourceFileLocation> locations(files.size());
+ std::transform(files.begin(), files.end(), locations.begin(),
+ CreateLocation(this->Needle.GetMakefile()));
+
+ return std::find_if(locations.begin(), locations.end(),
+ LocationMatcher(this->Needle)) != locations.end();
+ }
+};
+
+//----------------------------------------------------------------------------
+cmSourceFile* cmTarget::AddSource(const std::string& src)
+{
+ cmSourceFileLocation sfl(this->Makefile, src);
+ if (std::find_if(this->Internal->SourceEntries.begin(),
+ this->Internal->SourceEntries.end(),
+ TargetPropertyEntryFinder(sfl))
+ == this->Internal->SourceEntries.end())
{
- std::string objLibName = expr.substr(17, expr.size()-18);
- this->ObjectLibraries.push_back(objLibName);
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmGeneratorExpression ge(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src);
+ cge->SetEvaluateForBuildsystem(true);
+ this->Internal->SourceEntries.push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge));
}
- else
+ if (cmGeneratorExpression::Find(src) != std::string::npos)
{
- cmOStringStream e;
- e << "Unrecognized generator expression:\n"
- << " " << expr;
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return 0;
}
+ return this->Makefile->GetOrCreateSource(src);
}
//----------------------------------------------------------------------------
@@ -2766,25 +2853,90 @@ const char *cmTarget::GetProperty(const std::string& prop,
{
cmOStringStream ss;
const char* sep = "";
- for(std::vector<cmSourceFile*>::const_iterator
- i = this->SourceFiles.begin();
- i != this->SourceFiles.end(); ++i)
+ typedef cmTargetInternals::TargetPropertyEntry
+ TargetPropertyEntry;
+ for(std::vector<TargetPropertyEntry*>::const_iterator
+ i = this->Internal->SourceEntries.begin();
+ i != this->Internal->SourceEntries.end(); ++i)
{
- // Separate from the previous list entries.
- ss << sep;
- sep = ";";
+ std::string entry = (*i)->ge->GetInput();
- // Construct what is known about this source file location.
- cmSourceFileLocation const& location = (*i)->GetLocation();
- std::string sname = location.GetDirectory();
- if(!sname.empty())
+ std::vector<std::string> files;
+ cmSystemTools::ExpandListArgument(entry, files);
+ for (std::vector<std::string>::const_iterator
+ li = files.begin(); li != files.end(); ++li)
{
- sname += "/";
- }
- sname += location.GetName();
+ if(cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") &&
+ (*li)[li->size() - 1] == '>')
+ {
+ std::string objLibName = li->substr(17, li->size()-18);
+
+ if (cmGeneratorExpression::Find(objLibName) != std::string::npos)
+ {
+ ss << sep;
+ sep = ";";
+ ss << *li;
+ continue;
+ }
+
+ bool addContent = false;
+ bool noMessage = true;
+ cmOStringStream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0051))
+ {
+ case cmPolicies::WARN:
+ e << (this->Makefile->GetPolicies()
+ ->GetPolicyWarning(cmPolicies::CMP0051)) << "\n";
+ noMessage = false;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ addContent = true;
+ }
+ if (!noMessage)
+ {
+ e << "Target \"" << this->Name << "\" contains $<TARGET_OBJECTS> "
+ "generator expression in its sources list. This content was not "
+ "previously part of the SOURCES property when that property was "
+ "read at configure time. Code reading that property needs to be "
+ "adapted to ignore the generator expression using the "
+ "string(GENEX_STRIP) command.";
+ this->Makefile->IssueMessage(messageType, e.str());
+ }
+ if (addContent)
+ {
+ ss << sep;
+ sep = ";";
+ ss << *li;
+ }
+ }
+ else if (cmGeneratorExpression::Find(*li) == std::string::npos)
+ {
+ ss << sep;
+ sep = ";";
+ ss << *li;
+ }
+ else
+ {
+ cmSourceFile *sf = this->Makefile->GetOrCreateSource(*li);
+ // Construct what is known about this source file location.
+ cmSourceFileLocation const& location = sf->GetLocation();
+ std::string sname = location.GetDirectory();
+ if(!sname.empty())
+ {
+ sname += "/";
+ }
+ sname += location.GetName();
- // Append this list entry.
- ss << sname;
+ ss << sep;
+ sep = ";";
+ // Append this list entry.
+ ss << sname;
+ }
+ }
}
this->Properties.SetProperty("SOURCES", ss.str().c_str(),
cmProperty::TARGET);
@@ -4844,8 +4996,10 @@ bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p,
//----------------------------------------------------------------------------
void cmTarget::GetLanguages(std::set<std::string>& languages) const
{
+ std::vector<cmSourceFile*> sourceFiles;
+ this->GetSourceFiles(sourceFiles);
for(std::vector<cmSourceFile*>::const_iterator
- i = this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i)
+ i = sourceFiles.begin(); i != sourceFiles.end(); ++i)
{
const std::string& lang = (*i)->GetLanguage();
if(!lang.empty())
@@ -4853,6 +5007,53 @@ void cmTarget::GetLanguages(std::set<std::string>& languages) const
languages.insert(lang);
}
}
+
+ std::vector<cmTarget*> objectLibraries;
+ std::vector<cmSourceFile const*> externalObjects;
+ if (this->Makefile->GetGeneratorTargets().empty())
+ {
+ // At configure-time, this method can be called as part of getting the
+ // LOCATION property or to export() a file to be include()d. However
+ // there is no cmGeneratorTarget at configure-time, so search the SOURCES
+ // for TARGET_OBJECTS instead for backwards compatibility with OLD
+ // behavior of CMP0024 and CMP0026 only.
+ std::vector<std::string> srcs;
+ cmSystemTools::ExpandListArgument(this->GetProperty("SOURCES"), srcs);
+ for(std::vector<std::string>::const_iterator it = srcs.begin();
+ it != srcs.end(); ++it)
+ {
+ if (cmHasLiteralPrefix(*it, "$<TARGET_OBJECTS:")
+ && cmHasLiteralSuffix(*it, ">"))
+ {
+ std::string objLibName = it->substr(17, it->size()-18);
+ if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLibName))
+ {
+ objectLibraries.push_back(tgt);
+ }
+ }
+ }
+ }
+ else
+ {
+ cmGeneratorTarget* gt = this->Makefile->GetLocalGenerator()
+ ->GetGlobalGenerator()
+ ->GetGeneratorTarget(this);
+ gt->GetExternalObjects(externalObjects);
+ for(std::vector<cmSourceFile const*>::const_iterator
+ i = externalObjects.begin(); i != externalObjects.end(); ++i)
+ {
+ std::string objLib = (*i)->GetObjectLibrary();
+ if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLib))
+ {
+ objectLibraries.push_back(tgt);
+ }
+ }
+ }
+ for(std::vector<cmTarget*>::const_iterator
+ i = objectLibraries.begin(); i != objectLibraries.end(); ++i)
+ {
+ (*i)->GetLanguages(languages);
+ }
}
//----------------------------------------------------------------------------
@@ -5917,19 +6118,6 @@ cmTarget::ComputeLinkImplementationLanguages(LinkImplementation& impl) const
std::set<std::string> languages;
// Get languages used in our source files.
this->GetLanguages(languages);
- // Get languages used in object library sources.
- for(std::vector<std::string>::const_iterator
- i = this->ObjectLibraries.begin();
- i != this->ObjectLibraries.end(); ++i)
- {
- if(cmTarget* objLib = this->Makefile->FindTargetToUse(*i))
- {
- if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
- {
- objLib->GetLanguages(languages);
- }
- }
- }
// Copy the set of langauges to the link implementation.
for(std::set<std::string>::iterator li = languages.begin();
li != languages.end(); ++li)
@@ -6395,6 +6583,7 @@ cmTargetInternalPointer::~cmTargetInternalPointer()
deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
deleteAndClear(this->Pointer->CompileOptionsEntries);
deleteAndClear(this->Pointer->CompileDefinitionsEntries);
+ deleteAndClear(this->Pointer->SourceEntries);
delete this->Pointer;
}