|
@@ -34,6 +34,18 @@
|
|
|
#define UNORDERED_SET std::set
|
|
|
#endif
|
|
|
|
|
|
+class cmGeneratorTarget::TargetPropertyEntry {
|
|
|
+ static cmLinkImplItem NoLinkImplItem;
|
|
|
+public:
|
|
|
+ TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
|
|
|
+ cmLinkImplItem const& item = NoLinkImplItem)
|
|
|
+ : ge(cge), LinkImplItem(item)
|
|
|
+ {}
|
|
|
+ const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
|
|
|
+ cmLinkImplItem const& LinkImplItem;
|
|
|
+};
|
|
|
+cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
|
|
|
+
|
|
|
//----------------------------------------------------------------------------
|
|
|
void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib,
|
|
|
cmGeneratorTarget const* target, cmake *cm)
|
|
@@ -227,18 +239,64 @@ struct TagVisitor
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+void CreatePropertyGeneratorExpressions(
|
|
|
+ cmStringRange const& entries,
|
|
|
+ cmBacktraceRange const& backtraces,
|
|
|
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>& items,
|
|
|
+ bool evaluateForBuildsystem = false)
|
|
|
+{
|
|
|
+ std::vector<cmListFileBacktrace>::const_iterator btIt = backtraces.begin();
|
|
|
+ for (std::vector<std::string>::const_iterator it = entries.begin();
|
|
|
+ it != entries.end(); ++it, ++btIt)
|
|
|
+ {
|
|
|
+ cmGeneratorExpression ge(*btIt);
|
|
|
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*it);
|
|
|
+ cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
|
|
|
+ items.push_back(new cmGeneratorTarget::TargetPropertyEntry(cge));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
//----------------------------------------------------------------------------
|
|
|
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
|
|
|
: Target(t),
|
|
|
- SourceFileFlagsConstructed(false)
|
|
|
+ SourceFileFlagsConstructed(false),
|
|
|
+ PolicyWarnedCMP0022(false),
|
|
|
+ DebugIncludesDone(false),
|
|
|
+ DebugCompileOptionsDone(false),
|
|
|
+ DebugCompileFeaturesDone(false),
|
|
|
+ DebugCompileDefinitionsDone(false)
|
|
|
{
|
|
|
this->Makefile = this->Target->GetMakefile();
|
|
|
this->LocalGenerator = lg;
|
|
|
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
|
|
|
+
|
|
|
+ CreatePropertyGeneratorExpressions(
|
|
|
+ t->GetIncludeDirectoriesEntries(),
|
|
|
+ t->GetIncludeDirectoriesBacktraces(),
|
|
|
+ this->IncludeDirectoriesEntries);
|
|
|
+
|
|
|
+ CreatePropertyGeneratorExpressions(
|
|
|
+ t->GetCompileOptionsEntries(),
|
|
|
+ t->GetCompileOptionsBacktraces(),
|
|
|
+ this->CompileOptionsEntries);
|
|
|
+
|
|
|
+ CreatePropertyGeneratorExpressions(
|
|
|
+ t->GetCompileFeaturesEntries(),
|
|
|
+ t->GetCompileFeaturesBacktraces(),
|
|
|
+ this->CompileFeaturesEntries);
|
|
|
+
|
|
|
+ CreatePropertyGeneratorExpressions(
|
|
|
+ t->GetCompileDefinitionsEntries(),
|
|
|
+ t->GetCompileDefinitionsBacktraces(),
|
|
|
+ this->CompileDefinitionsEntries);
|
|
|
}
|
|
|
|
|
|
cmGeneratorTarget::~cmGeneratorTarget()
|
|
|
{
|
|
|
+ cmDeleteAll(this->IncludeDirectoriesEntries);
|
|
|
+ cmDeleteAll(this->CompileOptionsEntries);
|
|
|
+ cmDeleteAll(this->CompileFeaturesEntries);
|
|
|
+ cmDeleteAll(this->CompileDefinitionsEntries);
|
|
|
cmDeleteAll(this->LinkInformation);
|
|
|
this->LinkInformation.clear();
|
|
|
}
|
|
@@ -851,7 +909,7 @@ cmGeneratorTarget::NeedRelinkBeforeInstall(const std::string& config) const
|
|
|
// If either a build or install tree rpath is set then the rpath
|
|
|
// will likely change between the build tree and install tree and
|
|
|
// this target must be relinked.
|
|
|
- return this->Target->HaveBuildTreeRPATH(config)
|
|
|
+ return this->HaveBuildTreeRPATH(config)
|
|
|
|| this->Target->HaveInstallTreeRPATH();
|
|
|
}
|
|
|
|
|
@@ -1172,9 +1230,11 @@ public:
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- cmTarget::LinkInterface const* iface =
|
|
|
- item.Target->GetLinkInterface(this->Config, this->HeadTarget);
|
|
|
+ cmGeneratorTarget* gtgt =
|
|
|
+ this->Target->GetLocalGenerator()->GetGlobalGenerator()
|
|
|
+ ->GetGeneratorTarget(item.Target);
|
|
|
+ cmLinkInterface const* iface =
|
|
|
+ gtgt->GetLinkInterface(this->Config, this->HeadTarget);
|
|
|
if(!iface) { return; }
|
|
|
|
|
|
for(std::vector<std::string>::const_iterator
|
|
@@ -1275,8 +1335,8 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
|
|
|
{
|
|
|
// Get languages built in this target.
|
|
|
UNORDERED_SET<std::string> languages;
|
|
|
- cmTarget::LinkImplementation const* impl =
|
|
|
- this->Target->GetLinkImplementation(config);
|
|
|
+ cmLinkImplementation const* impl =
|
|
|
+ this->GetLinkImplementation(config);
|
|
|
assert(impl);
|
|
|
for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
|
|
|
li != impl->Languages.end(); ++li)
|
|
@@ -1505,20 +1565,22 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string> &result,
|
|
|
void processILibs(const std::string& config,
|
|
|
cmTarget const* headTarget,
|
|
|
cmLinkItem const& item,
|
|
|
+ cmGlobalGenerator* gg,
|
|
|
std::vector<cmTarget const*>& tgts,
|
|
|
std::set<cmTarget const*>& emitted)
|
|
|
{
|
|
|
if (item.Target && emitted.insert(item.Target).second)
|
|
|
{
|
|
|
tgts.push_back(item.Target);
|
|
|
- if(cmTarget::LinkInterfaceLibraries const* iface =
|
|
|
- item.Target->GetLinkInterfaceLibraries(config, headTarget, true))
|
|
|
+ cmGeneratorTarget* gt = gg->GetGeneratorTarget(item.Target);
|
|
|
+ if(cmLinkInterfaceLibraries const* iface =
|
|
|
+ gt->GetLinkInterfaceLibraries(config, headTarget, true))
|
|
|
{
|
|
|
for(std::vector<cmLinkItem>::const_iterator
|
|
|
it = iface->Libraries.begin();
|
|
|
it != iface->Libraries.end(); ++it)
|
|
|
{
|
|
|
- processILibs(config, headTarget, *it, tgts, emitted);
|
|
|
+ processILibs(config, headTarget, *it, gg, tgts, emitted);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1543,7 +1605,9 @@ cmGeneratorTarget::GetLinkImplementationClosure(
|
|
|
it = impl->Libraries.begin();
|
|
|
it != impl->Libraries.end(); ++it)
|
|
|
{
|
|
|
- processILibs(config, this->Target, *it, tgts , emitted);
|
|
|
+ processILibs(config, this->Target, *it,
|
|
|
+ this->LocalGenerator->GetGlobalGenerator(),
|
|
|
+ tgts , emitted);
|
|
|
}
|
|
|
}
|
|
|
return tgts;
|
|
@@ -1957,13 +2021,536 @@ cmGeneratorTarget::GetCreateRuleVariable(std::string const& lang,
|
|
|
}
|
|
|
return "";
|
|
|
}
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+static void processIncludeDirectories(cmGeneratorTarget const* tgt,
|
|
|
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
|
|
|
+ std::vector<std::string> &includes,
|
|
|
+ UNORDERED_SET<std::string> &uniqueIncludes,
|
|
|
+ cmGeneratorExpressionDAGChecker *dagChecker,
|
|
|
+ const std::string& config, bool debugIncludes,
|
|
|
+ const std::string& language)
|
|
|
+{
|
|
|
+ cmMakefile *mf = tgt->Target->GetMakefile();
|
|
|
+
|
|
|
+ for (std::vector<cmGeneratorTarget::TargetPropertyEntry*>::const_iterator
|
|
|
+ it = entries.begin(), end = entries.end(); it != end; ++it)
|
|
|
+ {
|
|
|
+ cmLinkImplItem const& item = (*it)->LinkImplItem;
|
|
|
+ std::string const& targetName = item;
|
|
|
+ bool const fromImported = item.Target && item.Target->IsImported();
|
|
|
+ bool const checkCMP0027 = item.FromGenex;
|
|
|
+ std::vector<std::string> entryIncludes;
|
|
|
+ cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
|
|
|
+ config,
|
|
|
+ false,
|
|
|
+ tgt->Target,
|
|
|
+ dagChecker, language),
|
|
|
+ entryIncludes);
|
|
|
+
|
|
|
+ std::string usedIncludes;
|
|
|
+ for(std::vector<std::string>::iterator
|
|
|
+ li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
|
|
|
+ {
|
|
|
+ if (fromImported
|
|
|
+ && !cmSystemTools::FileExists(li->c_str()))
|
|
|
+ {
|
|
|
+ std::ostringstream e;
|
|
|
+ cmake::MessageType messageType = cmake::FATAL_ERROR;
|
|
|
+ if (checkCMP0027)
|
|
|
+ {
|
|
|
+ switch(tgt->Target->GetPolicyStatusCMP0027())
|
|
|
+ {
|
|
|
+ case cmPolicies::WARN:
|
|
|
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n";
|
|
|
+ case cmPolicies::OLD:
|
|
|
+ messageType = cmake::AUTHOR_WARNING;
|
|
|
+ break;
|
|
|
+ case cmPolicies::REQUIRED_ALWAYS:
|
|
|
+ case cmPolicies::REQUIRED_IF_USED:
|
|
|
+ case cmPolicies::NEW:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ e << "Imported target \"" << targetName << "\" includes "
|
|
|
+ "non-existent path\n \"" << *li << "\"\nin its "
|
|
|
+ "INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n"
|
|
|
+ "* The path was deleted, renamed, or moved to another "
|
|
|
+ "location.\n"
|
|
|
+ "* An install or uninstall procedure did not complete "
|
|
|
+ "successfully.\n"
|
|
|
+ "* The installation package was faulty and references files it "
|
|
|
+ "does not provide.\n";
|
|
|
+ tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cmSystemTools::FileIsFullPath(li->c_str()))
|
|
|
+ {
|
|
|
+ std::ostringstream e;
|
|
|
+ bool noMessage = false;
|
|
|
+ cmake::MessageType messageType = cmake::FATAL_ERROR;
|
|
|
+ if (!targetName.empty())
|
|
|
+ {
|
|
|
+ e << "Target \"" << targetName << "\" contains relative "
|
|
|
+ "path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
|
|
|
+ " \"" << *li << "\"";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ switch(tgt->Target->GetPolicyStatusCMP0021())
|
|
|
+ {
|
|
|
+ case cmPolicies::WARN:
|
|
|
+ {
|
|
|
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n";
|
|
|
+ messageType = cmake::AUTHOR_WARNING;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case cmPolicies::OLD:
|
|
|
+ noMessage = true;
|
|
|
+ case cmPolicies::REQUIRED_IF_USED:
|
|
|
+ case cmPolicies::REQUIRED_ALWAYS:
|
|
|
+ case cmPolicies::NEW:
|
|
|
+ // Issue the fatal message.
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ e << "Found relative path while evaluating include directories of "
|
|
|
+ "\"" << tgt->GetName() << "\":\n \"" << *li << "\"\n";
|
|
|
+ }
|
|
|
+ if (!noMessage)
|
|
|
+ {
|
|
|
+ tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
|
|
|
+ if (messageType == cmake::FATAL_ERROR)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cmSystemTools::IsOff(li->c_str()))
|
|
|
+ {
|
|
|
+ cmSystemTools::ConvertToUnixSlashes(*li);
|
|
|
+ }
|
|
|
+ std::string inc = *li;
|
|
|
+
|
|
|
+ if(uniqueIncludes.insert(inc).second)
|
|
|
+ {
|
|
|
+ includes.push_back(inc);
|
|
|
+ if (debugIncludes)
|
|
|
+ {
|
|
|
+ usedIncludes += " * " + inc + "\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!usedIncludes.empty())
|
|
|
+ {
|
|
|
+ mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
|
|
|
+ std::string("Used includes for target ")
|
|
|
+ + tgt->GetName() + ":\n"
|
|
|
+ + usedIncludes, (*it)->ge->GetBacktrace());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+static void AddInterfaceEntries(
|
|
|
+ cmGeneratorTarget const* thisTarget, std::string const& config,
|
|
|
+ std::string const& prop,
|
|
|
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
|
|
|
+{
|
|
|
+ if(cmLinkImplementationLibraries const* impl =
|
|
|
+ thisTarget->Target->GetLinkImplementationLibraries(config))
|
|
|
+ {
|
|
|
+ for (std::vector<cmLinkImplItem>::const_iterator
|
|
|
+ it = impl->Libraries.begin(), end = impl->Libraries.end();
|
|
|
+ it != end; ++it)
|
|
|
+ {
|
|
|
+ if(it->Target)
|
|
|
+ {
|
|
|
+ std::string genex =
|
|
|
+ "$<TARGET_PROPERTY:" + *it + "," + prop + ">";
|
|
|
+ cmGeneratorExpression ge(it->Backtrace);
|
|
|
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
|
|
|
+ cge->SetEvaluateForBuildsystem(true);
|
|
|
+ entries.push_back(
|
|
|
+ new cmGeneratorTarget::TargetPropertyEntry(cge, *it));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
std::vector<std::string>
|
|
|
cmGeneratorTarget::GetIncludeDirectories(const std::string& config,
|
|
|
const std::string& lang) const
|
|
|
{
|
|
|
- return this->Target->GetIncludeDirectories(config, lang);
|
|
|
+ std::vector<std::string> includes;
|
|
|
+ UNORDERED_SET<std::string> uniqueIncludes;
|
|
|
+
|
|
|
+ cmGeneratorExpressionDAGChecker dagChecker(this->GetName(),
|
|
|
+ "INCLUDE_DIRECTORIES", 0, 0);
|
|
|
+
|
|
|
+ std::vector<std::string> debugProperties;
|
|
|
+ const char *debugProp =
|
|
|
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
|
|
|
+ if (debugProp)
|
|
|
+ {
|
|
|
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool debugIncludes = !this->DebugIncludesDone
|
|
|
+ && std::find(debugProperties.begin(),
|
|
|
+ debugProperties.end(),
|
|
|
+ "INCLUDE_DIRECTORIES")
|
|
|
+ != debugProperties.end();
|
|
|
+
|
|
|
+ if (this->Makefile->IsConfigured())
|
|
|
+ {
|
|
|
+ this->DebugIncludesDone = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ processIncludeDirectories(this,
|
|
|
+ this->IncludeDirectoriesEntries,
|
|
|
+ includes,
|
|
|
+ uniqueIncludes,
|
|
|
+ &dagChecker,
|
|
|
+ config,
|
|
|
+ debugIncludes,
|
|
|
+ lang);
|
|
|
+
|
|
|
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
|
|
|
+ linkInterfaceIncludeDirectoriesEntries;
|
|
|
+ AddInterfaceEntries(
|
|
|
+ this, config, "INTERFACE_INCLUDE_DIRECTORIES",
|
|
|
+ linkInterfaceIncludeDirectoriesEntries);
|
|
|
+
|
|
|
+ if(this->Makefile->IsOn("APPLE"))
|
|
|
+ {
|
|
|
+ cmLinkImplementationLibraries const* impl =
|
|
|
+ this->Target->GetLinkImplementationLibraries(config);
|
|
|
+ for(std::vector<cmLinkImplItem>::const_iterator
|
|
|
+ it = impl->Libraries.begin();
|
|
|
+ it != impl->Libraries.end(); ++it)
|
|
|
+ {
|
|
|
+ std::string libDir = cmSystemTools::CollapseFullPath(*it);
|
|
|
+
|
|
|
+ static cmsys::RegularExpression
|
|
|
+ frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
|
|
|
+ if(!frameworkCheck.find(libDir))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ libDir = frameworkCheck.match(1);
|
|
|
+
|
|
|
+ cmGeneratorExpression ge;
|
|
|
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
|
|
|
+ ge.Parse(libDir.c_str());
|
|
|
+ linkInterfaceIncludeDirectoriesEntries
|
|
|
+ .push_back(new cmGeneratorTarget::TargetPropertyEntry(cge));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ processIncludeDirectories(this,
|
|
|
+ linkInterfaceIncludeDirectoriesEntries,
|
|
|
+ includes,
|
|
|
+ uniqueIncludes,
|
|
|
+ &dagChecker,
|
|
|
+ config,
|
|
|
+ debugIncludes,
|
|
|
+ lang);
|
|
|
+
|
|
|
+ cmDeleteAll(linkInterfaceIncludeDirectoriesEntries);
|
|
|
+
|
|
|
+ return includes;
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+static void processCompileOptionsInternal(cmGeneratorTarget const* tgt,
|
|
|
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
|
|
|
+ std::vector<std::string> &options,
|
|
|
+ UNORDERED_SET<std::string> &uniqueOptions,
|
|
|
+ cmGeneratorExpressionDAGChecker *dagChecker,
|
|
|
+ const std::string& config, bool debugOptions, const char *logName,
|
|
|
+ std::string const& language)
|
|
|
+{
|
|
|
+ cmMakefile *mf = tgt->Target->GetMakefile();
|
|
|
+
|
|
|
+ for (std::vector<cmGeneratorTarget::TargetPropertyEntry*>::const_iterator
|
|
|
+ it = entries.begin(), end = entries.end(); it != end; ++it)
|
|
|
+ {
|
|
|
+ std::vector<std::string> entryOptions;
|
|
|
+ cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
|
|
|
+ config,
|
|
|
+ false,
|
|
|
+ tgt->Target,
|
|
|
+ dagChecker,
|
|
|
+ language),
|
|
|
+ entryOptions);
|
|
|
+ std::string usedOptions;
|
|
|
+ for(std::vector<std::string>::iterator
|
|
|
+ li = entryOptions.begin(); li != entryOptions.end(); ++li)
|
|
|
+ {
|
|
|
+ std::string const& opt = *li;
|
|
|
+
|
|
|
+ if(uniqueOptions.insert(opt).second)
|
|
|
+ {
|
|
|
+ options.push_back(opt);
|
|
|
+ if (debugOptions)
|
|
|
+ {
|
|
|
+ usedOptions += " * " + opt + "\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!usedOptions.empty())
|
|
|
+ {
|
|
|
+ mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
|
|
|
+ std::string("Used compile ") + logName
|
|
|
+ + std::string(" for target ")
|
|
|
+ + tgt->GetName() + ":\n"
|
|
|
+ + usedOptions, (*it)->ge->GetBacktrace());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+static void processCompileOptions(cmGeneratorTarget const* tgt,
|
|
|
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
|
|
|
+ std::vector<std::string> &options,
|
|
|
+ UNORDERED_SET<std::string> &uniqueOptions,
|
|
|
+ cmGeneratorExpressionDAGChecker *dagChecker,
|
|
|
+ const std::string& config, bool debugOptions,
|
|
|
+ std::string const& language)
|
|
|
+{
|
|
|
+ processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
|
|
+ dagChecker, config, debugOptions, "options",
|
|
|
+ language);
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void cmGeneratorTarget::GetCompileOptions(std::vector<std::string> &result,
|
|
|
+ const std::string& config,
|
|
|
+ const std::string& language) const
|
|
|
+{
|
|
|
+ UNORDERED_SET<std::string> uniqueOptions;
|
|
|
+
|
|
|
+ cmGeneratorExpressionDAGChecker dagChecker(this->GetName(),
|
|
|
+ "COMPILE_OPTIONS", 0, 0);
|
|
|
+
|
|
|
+ std::vector<std::string> debugProperties;
|
|
|
+ const char *debugProp =
|
|
|
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
|
|
|
+ if (debugProp)
|
|
|
+ {
|
|
|
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool debugOptions = !this->DebugCompileOptionsDone
|
|
|
+ && std::find(debugProperties.begin(),
|
|
|
+ debugProperties.end(),
|
|
|
+ "COMPILE_OPTIONS")
|
|
|
+ != debugProperties.end();
|
|
|
+
|
|
|
+ if (this->Makefile->IsConfigured())
|
|
|
+ {
|
|
|
+ this->DebugCompileOptionsDone = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ processCompileOptions(this,
|
|
|
+ this->CompileOptionsEntries,
|
|
|
+ result,
|
|
|
+ uniqueOptions,
|
|
|
+ &dagChecker,
|
|
|
+ config,
|
|
|
+ debugOptions,
|
|
|
+ language);
|
|
|
+
|
|
|
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
|
|
|
+ linkInterfaceCompileOptionsEntries;
|
|
|
+
|
|
|
+ AddInterfaceEntries(
|
|
|
+ this, config, "INTERFACE_COMPILE_OPTIONS",
|
|
|
+ linkInterfaceCompileOptionsEntries);
|
|
|
+
|
|
|
+ processCompileOptions(this,
|
|
|
+ linkInterfaceCompileOptionsEntries,
|
|
|
+ result,
|
|
|
+ uniqueOptions,
|
|
|
+ &dagChecker,
|
|
|
+ config,
|
|
|
+ debugOptions,
|
|
|
+ language);
|
|
|
+
|
|
|
+ cmDeleteAll(linkInterfaceCompileOptionsEntries);
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+static void processCompileFeatures(cmGeneratorTarget const* tgt,
|
|
|
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
|
|
|
+ std::vector<std::string> &options,
|
|
|
+ UNORDERED_SET<std::string> &uniqueOptions,
|
|
|
+ cmGeneratorExpressionDAGChecker *dagChecker,
|
|
|
+ const std::string& config, bool debugOptions)
|
|
|
+{
|
|
|
+ processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
|
|
+ dagChecker, config, debugOptions, "features",
|
|
|
+ std::string());
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string> &result,
|
|
|
+ const std::string& config) const
|
|
|
+{
|
|
|
+ UNORDERED_SET<std::string> uniqueFeatures;
|
|
|
+
|
|
|
+ cmGeneratorExpressionDAGChecker dagChecker(this->GetName(),
|
|
|
+ "COMPILE_FEATURES",
|
|
|
+ 0, 0);
|
|
|
+
|
|
|
+ std::vector<std::string> debugProperties;
|
|
|
+ const char *debugProp =
|
|
|
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
|
|
|
+ if (debugProp)
|
|
|
+ {
|
|
|
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool debugFeatures = !this->DebugCompileFeaturesDone
|
|
|
+ && std::find(debugProperties.begin(),
|
|
|
+ debugProperties.end(),
|
|
|
+ "COMPILE_FEATURES")
|
|
|
+ != debugProperties.end();
|
|
|
+
|
|
|
+ if (this->Makefile->IsConfigured())
|
|
|
+ {
|
|
|
+ this->DebugCompileFeaturesDone = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ processCompileFeatures(this,
|
|
|
+ this->CompileFeaturesEntries,
|
|
|
+ result,
|
|
|
+ uniqueFeatures,
|
|
|
+ &dagChecker,
|
|
|
+ config,
|
|
|
+ debugFeatures);
|
|
|
+
|
|
|
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
|
|
|
+ linkInterfaceCompileFeaturesEntries;
|
|
|
+ AddInterfaceEntries(
|
|
|
+ this, config, "INTERFACE_COMPILE_FEATURES",
|
|
|
+ linkInterfaceCompileFeaturesEntries);
|
|
|
+
|
|
|
+ processCompileFeatures(this,
|
|
|
+ linkInterfaceCompileFeaturesEntries,
|
|
|
+ result,
|
|
|
+ uniqueFeatures,
|
|
|
+ &dagChecker,
|
|
|
+ config,
|
|
|
+ debugFeatures);
|
|
|
+
|
|
|
+ cmDeleteAll(linkInterfaceCompileFeaturesEntries);
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+static void processCompileDefinitions(cmGeneratorTarget const* tgt,
|
|
|
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*> &entries,
|
|
|
+ std::vector<std::string> &options,
|
|
|
+ UNORDERED_SET<std::string> &uniqueOptions,
|
|
|
+ cmGeneratorExpressionDAGChecker *dagChecker,
|
|
|
+ const std::string& config, bool debugOptions,
|
|
|
+ std::string const& language)
|
|
|
+{
|
|
|
+ processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
|
|
+ dagChecker, config, debugOptions,
|
|
|
+ "definitions", language);
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void cmGeneratorTarget::GetCompileDefinitions(std::vector<std::string> &list,
|
|
|
+ const std::string& config,
|
|
|
+ const std::string& language) const
|
|
|
+{
|
|
|
+ UNORDERED_SET<std::string> uniqueOptions;
|
|
|
+
|
|
|
+ cmGeneratorExpressionDAGChecker dagChecker(this->GetName(),
|
|
|
+ "COMPILE_DEFINITIONS", 0, 0);
|
|
|
+
|
|
|
+ std::vector<std::string> debugProperties;
|
|
|
+ const char *debugProp =
|
|
|
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
|
|
|
+ if (debugProp)
|
|
|
+ {
|
|
|
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool debugDefines = !this->DebugCompileDefinitionsDone
|
|
|
+ && std::find(debugProperties.begin(),
|
|
|
+ debugProperties.end(),
|
|
|
+ "COMPILE_DEFINITIONS")
|
|
|
+ != debugProperties.end();
|
|
|
+
|
|
|
+ if (this->Makefile->IsConfigured())
|
|
|
+ {
|
|
|
+ this->DebugCompileDefinitionsDone = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ processCompileDefinitions(this,
|
|
|
+ this->CompileDefinitionsEntries,
|
|
|
+ list,
|
|
|
+ uniqueOptions,
|
|
|
+ &dagChecker,
|
|
|
+ config,
|
|
|
+ debugDefines,
|
|
|
+ language);
|
|
|
+
|
|
|
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
|
|
|
+ linkInterfaceCompileDefinitionsEntries;
|
|
|
+ AddInterfaceEntries(
|
|
|
+ this, config, "INTERFACE_COMPILE_DEFINITIONS",
|
|
|
+ linkInterfaceCompileDefinitionsEntries);
|
|
|
+ if (!config.empty())
|
|
|
+ {
|
|
|
+ std::string configPropName = "COMPILE_DEFINITIONS_"
|
|
|
+ + cmSystemTools::UpperCase(config);
|
|
|
+ const char *configProp = this->Target->GetProperty(configPropName);
|
|
|
+ if (configProp)
|
|
|
+ {
|
|
|
+ switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0043))
|
|
|
+ {
|
|
|
+ case cmPolicies::WARN:
|
|
|
+ {
|
|
|
+ std::ostringstream e;
|
|
|
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043);
|
|
|
+ this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING,
|
|
|
+ e.str());
|
|
|
+ }
|
|
|
+ case cmPolicies::OLD:
|
|
|
+ {
|
|
|
+ cmGeneratorExpression ge;
|
|
|
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
|
|
|
+ ge.Parse(configProp);
|
|
|
+ linkInterfaceCompileDefinitionsEntries
|
|
|
+ .push_back(new cmGeneratorTarget::TargetPropertyEntry(cge));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case cmPolicies::NEW:
|
|
|
+ case cmPolicies::REQUIRED_ALWAYS:
|
|
|
+ case cmPolicies::REQUIRED_IF_USED:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ processCompileDefinitions(this,
|
|
|
+ linkInterfaceCompileDefinitionsEntries,
|
|
|
+ list,
|
|
|
+ uniqueOptions,
|
|
|
+ &dagChecker,
|
|
|
+ config,
|
|
|
+ debugDefines,
|
|
|
+ language);
|
|
|
+
|
|
|
+ cmDeleteAll(linkInterfaceCompileDefinitionsEntries);
|
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
@@ -3354,3 +3941,613 @@ cmGeneratorTarget::ReportPropertyOrigin(const std::string &p,
|
|
|
|
|
|
this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, areport);
|
|
|
}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
|
|
|
+ std::vector<cmLinkItem>& items) const
|
|
|
+{
|
|
|
+ for(std::vector<std::string>::const_iterator i = names.begin();
|
|
|
+ i != names.end(); ++i)
|
|
|
+ {
|
|
|
+ std::string name = this->Target->CheckCMP0004(*i);
|
|
|
+ if(name == this->GetName() || name.empty())
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ items.push_back(cmLinkItem(name, this->Target->FindTargetToLink(name)));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
|
|
|
+ std::string const& value,
|
|
|
+ std::string const& config,
|
|
|
+ cmTarget const* headTarget,
|
|
|
+ bool usage_requirements_only,
|
|
|
+ std::vector<cmLinkItem>& items,
|
|
|
+ bool& hadHeadSensitiveCondition) const
|
|
|
+{
|
|
|
+ cmGeneratorExpression ge;
|
|
|
+ cmGeneratorExpressionDAGChecker dagChecker(this->GetName(), prop, 0, 0);
|
|
|
+ // The $<LINK_ONLY> expression may be in a link interface to specify private
|
|
|
+ // link dependencies that are otherwise excluded from usage requirements.
|
|
|
+ if(usage_requirements_only)
|
|
|
+ {
|
|
|
+ dagChecker.SetTransitivePropertiesOnly();
|
|
|
+ }
|
|
|
+ std::vector<std::string> libs;
|
|
|
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
|
|
|
+ cmSystemTools::ExpandListArgument(cge->Evaluate(
|
|
|
+ this->Makefile,
|
|
|
+ config,
|
|
|
+ false,
|
|
|
+ headTarget,
|
|
|
+ this->Target, &dagChecker), libs);
|
|
|
+ this->LookupLinkItems(libs, items);
|
|
|
+ hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+cmLinkInterface const*
|
|
|
+cmGeneratorTarget::GetLinkInterface(const std::string& config,
|
|
|
+ cmTarget const* head) const
|
|
|
+{
|
|
|
+ // Imported targets have their own link interface.
|
|
|
+ if(this->IsImported())
|
|
|
+ {
|
|
|
+ return this->GetImportLinkInterface(config, head, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Link interfaces are not supported for executables that do not
|
|
|
+ // export symbols.
|
|
|
+ if(this->GetType() == cmTarget::EXECUTABLE &&
|
|
|
+ !this->Target->IsExecutableWithExports())
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Lookup any existing link interface for this configuration.
|
|
|
+ cmHeadToLinkInterfaceMap& hm =
|
|
|
+ this->GetHeadToLinkInterfaceMap(config);
|
|
|
+
|
|
|
+ // If the link interface does not depend on the head target
|
|
|
+ // then return the one we computed first.
|
|
|
+ if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition)
|
|
|
+ {
|
|
|
+ return &hm.begin()->second;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmOptionalLinkInterface& iface = hm[head];
|
|
|
+ if(!iface.LibrariesDone)
|
|
|
+ {
|
|
|
+ iface.LibrariesDone = true;
|
|
|
+ this->ComputeLinkInterfaceLibraries(
|
|
|
+ config, iface, head, false);
|
|
|
+ }
|
|
|
+ if(!iface.AllDone)
|
|
|
+ {
|
|
|
+ iface.AllDone = true;
|
|
|
+ if(iface.Exists)
|
|
|
+ {
|
|
|
+ this->ComputeLinkInterface(config, iface, head);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return iface.Exists? &iface : 0;
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void cmGeneratorTarget::ComputeLinkInterface(const std::string& config,
|
|
|
+ cmOptionalLinkInterface &iface,
|
|
|
+ cmTarget const* headTarget) const
|
|
|
+{
|
|
|
+ if(iface.ExplicitLibraries)
|
|
|
+ {
|
|
|
+ if(this->GetType() == cmTarget::SHARED_LIBRARY
|
|
|
+ || this->GetType() == cmTarget::STATIC_LIBRARY
|
|
|
+ || this->GetType() == cmTarget::INTERFACE_LIBRARY)
|
|
|
+ {
|
|
|
+ // Shared libraries may have runtime implementation dependencies
|
|
|
+ // on other shared libraries that are not in the interface.
|
|
|
+ UNORDERED_SET<std::string> emitted;
|
|
|
+ for(std::vector<cmLinkItem>::const_iterator
|
|
|
+ li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li)
|
|
|
+ {
|
|
|
+ emitted.insert(*li);
|
|
|
+ }
|
|
|
+ if (this->GetType() != cmTarget::INTERFACE_LIBRARY)
|
|
|
+ {
|
|
|
+ cmLinkImplementation const* impl =
|
|
|
+ this->GetLinkImplementation(config);
|
|
|
+ for(std::vector<cmLinkImplItem>::const_iterator
|
|
|
+ li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li)
|
|
|
+ {
|
|
|
+ if(emitted.insert(*li).second)
|
|
|
+ {
|
|
|
+ if(li->Target)
|
|
|
+ {
|
|
|
+ // This is a runtime dependency on another shared library.
|
|
|
+ if(li->Target->GetType() == cmTarget::SHARED_LIBRARY)
|
|
|
+ {
|
|
|
+ iface.SharedDeps.push_back(*li);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // TODO: Recognize shared library file names. Perhaps this
|
|
|
+ // should be moved to cmComputeLinkInformation, but that creates
|
|
|
+ // a chicken-and-egg problem since this list is needed for its
|
|
|
+ // construction.
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN
|
|
|
+ || this->Target->GetPolicyStatusCMP0022() == cmPolicies::OLD)
|
|
|
+ {
|
|
|
+ // The link implementation is the default link interface.
|
|
|
+ cmLinkImplementationLibraries const*
|
|
|
+ impl = this->Target->GetLinkImplementationLibrariesInternal(config,
|
|
|
+ headTarget);
|
|
|
+ iface.ImplementationIsInterface = true;
|
|
|
+ iface.WrongConfigLibraries = impl->WrongConfigLibraries;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(this->Target->LinkLanguagePropagatesToDependents())
|
|
|
+ {
|
|
|
+ // Targets using this archive need its language runtime libraries.
|
|
|
+ if(cmLinkImplementation const* impl =
|
|
|
+ this->GetLinkImplementation(config))
|
|
|
+ {
|
|
|
+ iface.Languages = impl->Languages;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(this->GetType() == cmTarget::STATIC_LIBRARY)
|
|
|
+ {
|
|
|
+ // Construct the property name suffix for this configuration.
|
|
|
+ std::string suffix = "_";
|
|
|
+ if(!config.empty())
|
|
|
+ {
|
|
|
+ suffix += cmSystemTools::UpperCase(config);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ suffix += "NOCONFIG";
|
|
|
+ }
|
|
|
+
|
|
|
+ // How many repetitions are needed if this library has cyclic
|
|
|
+ // dependencies?
|
|
|
+ std::string propName = "LINK_INTERFACE_MULTIPLICITY";
|
|
|
+ propName += suffix;
|
|
|
+ if(const char* config_reps = this->GetProperty(propName))
|
|
|
+ {
|
|
|
+ sscanf(config_reps, "%u", &iface.Multiplicity);
|
|
|
+ }
|
|
|
+ else if(const char* reps =
|
|
|
+ this->GetProperty("LINK_INTERFACE_MULTIPLICITY"))
|
|
|
+ {
|
|
|
+ sscanf(reps, "%u", &iface.Multiplicity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+const cmLinkInterfaceLibraries *
|
|
|
+cmGeneratorTarget::GetLinkInterfaceLibraries(const std::string& config,
|
|
|
+ cmTarget const* head,
|
|
|
+ bool usage_requirements_only) const
|
|
|
+{
|
|
|
+ // Imported targets have their own link interface.
|
|
|
+ if(this->IsImported())
|
|
|
+ {
|
|
|
+ return this->GetImportLinkInterface(config, head,
|
|
|
+ usage_requirements_only);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Link interfaces are not supported for executables that do not
|
|
|
+ // export symbols.
|
|
|
+ if(this->GetType() == cmTarget::EXECUTABLE &&
|
|
|
+ !this->Target->IsExecutableWithExports())
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Lookup any existing link interface for this configuration.
|
|
|
+ std::string CONFIG = cmSystemTools::UpperCase(config);
|
|
|
+ cmHeadToLinkInterfaceMap& hm =
|
|
|
+ (usage_requirements_only ?
|
|
|
+ this->GetHeadToLinkInterfaceUsageRequirementsMap(config) :
|
|
|
+ this->GetHeadToLinkInterfaceMap(config));
|
|
|
+
|
|
|
+ // If the link interface does not depend on the head target
|
|
|
+ // then return the one we computed first.
|
|
|
+ if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition)
|
|
|
+ {
|
|
|
+ return &hm.begin()->second;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmOptionalLinkInterface& iface = hm[head];
|
|
|
+ if(!iface.LibrariesDone)
|
|
|
+ {
|
|
|
+ iface.LibrariesDone = true;
|
|
|
+ this->ComputeLinkInterfaceLibraries(
|
|
|
+ config, iface, head, usage_requirements_only);
|
|
|
+ }
|
|
|
+
|
|
|
+ return iface.Exists? &iface : 0;
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void
|
|
|
+cmGeneratorTarget::ComputeLinkInterfaceLibraries(
|
|
|
+ const std::string& config,
|
|
|
+ cmOptionalLinkInterface& iface,
|
|
|
+ cmTarget const* headTarget,
|
|
|
+ bool usage_requirements_only) const
|
|
|
+{
|
|
|
+ // Construct the property name suffix for this configuration.
|
|
|
+ std::string suffix = "_";
|
|
|
+ if(!config.empty())
|
|
|
+ {
|
|
|
+ suffix += cmSystemTools::UpperCase(config);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ suffix += "NOCONFIG";
|
|
|
+ }
|
|
|
+
|
|
|
+ // An explicit list of interface libraries may be set for shared
|
|
|
+ // libraries and executables that export symbols.
|
|
|
+ const char* explicitLibraries = 0;
|
|
|
+ std::string linkIfaceProp;
|
|
|
+ if(this->Target->GetPolicyStatusCMP0022() != cmPolicies::OLD &&
|
|
|
+ this->Target->GetPolicyStatusCMP0022() != cmPolicies::WARN)
|
|
|
+ {
|
|
|
+ // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
|
|
|
+ linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
|
|
|
+ explicitLibraries = this->GetProperty(linkIfaceProp);
|
|
|
+ }
|
|
|
+ else if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
+ this->Target->IsExecutableWithExports())
|
|
|
+ {
|
|
|
+ // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a
|
|
|
+ // shared lib or executable.
|
|
|
+
|
|
|
+ // Lookup the per-configuration property.
|
|
|
+ linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
|
|
|
+ linkIfaceProp += suffix;
|
|
|
+ explicitLibraries = this->GetProperty(linkIfaceProp);
|
|
|
+
|
|
|
+ // If not set, try the generic property.
|
|
|
+ if(!explicitLibraries)
|
|
|
+ {
|
|
|
+ linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
|
|
|
+ explicitLibraries = this->GetProperty(linkIfaceProp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(explicitLibraries &&
|
|
|
+ this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
|
|
|
+ !this->PolicyWarnedCMP0022)
|
|
|
+ {
|
|
|
+ // Compare the explicitly set old link interface properties to the
|
|
|
+ // preferred new link interface property one and warn if different.
|
|
|
+ const char* newExplicitLibraries =
|
|
|
+ this->GetProperty("INTERFACE_LINK_LIBRARIES");
|
|
|
+ if (newExplicitLibraries
|
|
|
+ && strcmp(newExplicitLibraries, explicitLibraries) != 0)
|
|
|
+ {
|
|
|
+ std::ostringstream w;
|
|
|
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n"
|
|
|
+ "Target \"" << this->GetName() << "\" has an "
|
|
|
+ "INTERFACE_LINK_LIBRARIES property which differs from its " <<
|
|
|
+ linkIfaceProp << " properties."
|
|
|
+ "\n"
|
|
|
+ "INTERFACE_LINK_LIBRARIES:\n"
|
|
|
+ " " << newExplicitLibraries << "\n" <<
|
|
|
+ linkIfaceProp << ":\n"
|
|
|
+ " " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n";
|
|
|
+ this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str());
|
|
|
+ this->PolicyWarnedCMP0022 = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // There is no implicit link interface for executables or modules
|
|
|
+ // so if none was explicitly set then there is no link interface.
|
|
|
+ if(!explicitLibraries &&
|
|
|
+ (this->GetType() == cmTarget::EXECUTABLE ||
|
|
|
+ (this->GetType() == cmTarget::MODULE_LIBRARY)))
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ iface.Exists = true;
|
|
|
+ iface.ExplicitLibraries = explicitLibraries;
|
|
|
+
|
|
|
+ if(explicitLibraries)
|
|
|
+ {
|
|
|
+ // The interface libraries have been explicitly set.
|
|
|
+ this->ExpandLinkItems(linkIfaceProp, explicitLibraries,
|
|
|
+ config,
|
|
|
+ headTarget, usage_requirements_only,
|
|
|
+ iface.Libraries,
|
|
|
+ iface.HadHeadSensitiveCondition);
|
|
|
+ }
|
|
|
+ else if (this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN
|
|
|
+ || this->Target->GetPolicyStatusCMP0022() == cmPolicies::OLD)
|
|
|
+ // If CMP0022 is NEW then the plain tll signature sets the
|
|
|
+ // INTERFACE_LINK_LIBRARIES, so if we get here then the project
|
|
|
+ // cleared the property explicitly and we should not fall back
|
|
|
+ // to the link implementation.
|
|
|
+ {
|
|
|
+ // The link implementation is the default link interface.
|
|
|
+ cmLinkImplementationLibraries const* impl =
|
|
|
+ this->Target->GetLinkImplementationLibrariesInternal(config,
|
|
|
+ headTarget);
|
|
|
+ iface.Libraries.insert(iface.Libraries.end(),
|
|
|
+ impl->Libraries.begin(), impl->Libraries.end());
|
|
|
+ if(this->Target->GetPolicyStatusCMP0022() == cmPolicies::WARN &&
|
|
|
+ !this->PolicyWarnedCMP0022 && !usage_requirements_only)
|
|
|
+ {
|
|
|
+ // Compare the link implementation fallback link interface to the
|
|
|
+ // preferred new link interface property and warn if different.
|
|
|
+ std::vector<cmLinkItem> ifaceLibs;
|
|
|
+ static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
|
|
|
+ if(const char* newExplicitLibraries = this->GetProperty(newProp))
|
|
|
+ {
|
|
|
+ bool hadHeadSensitiveConditionDummy = false;
|
|
|
+ this->ExpandLinkItems(newProp, newExplicitLibraries, config,
|
|
|
+ headTarget, usage_requirements_only,
|
|
|
+ ifaceLibs, hadHeadSensitiveConditionDummy);
|
|
|
+ }
|
|
|
+ if (ifaceLibs != iface.Libraries)
|
|
|
+ {
|
|
|
+ std::string oldLibraries = cmJoin(impl->Libraries, ";");
|
|
|
+ std::string newLibraries = cmJoin(ifaceLibs, ";");
|
|
|
+ if(oldLibraries.empty())
|
|
|
+ { oldLibraries = "(empty)"; }
|
|
|
+ if(newLibraries.empty())
|
|
|
+ { newLibraries = "(empty)"; }
|
|
|
+
|
|
|
+ std::ostringstream w;
|
|
|
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n"
|
|
|
+ "Target \"" << this->GetName() << "\" has an "
|
|
|
+ "INTERFACE_LINK_LIBRARIES property. "
|
|
|
+ "This should be preferred as the source of the link interface "
|
|
|
+ "for this library but because CMP0022 is not set CMake is "
|
|
|
+ "ignoring the property and using the link implementation "
|
|
|
+ "as the link interface instead."
|
|
|
+ "\n"
|
|
|
+ "INTERFACE_LINK_LIBRARIES:\n"
|
|
|
+ " " << newLibraries << "\n"
|
|
|
+ "Link implementation:\n"
|
|
|
+ " " << oldLibraries << "\n";
|
|
|
+ this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, w.str());
|
|
|
+ this->PolicyWarnedCMP0022 = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+const cmLinkInterface *
|
|
|
+cmGeneratorTarget::GetImportLinkInterface(const std::string& config,
|
|
|
+ cmTarget const* headTarget,
|
|
|
+ bool usage_requirements_only) const
|
|
|
+{
|
|
|
+ cmTarget::ImportInfo const* info = this->Target->GetImportInfo(config);
|
|
|
+ if(!info)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string CONFIG = cmSystemTools::UpperCase(config);
|
|
|
+ cmHeadToLinkInterfaceMap& hm =
|
|
|
+ (usage_requirements_only ?
|
|
|
+ this->GetHeadToLinkInterfaceUsageRequirementsMap(config) :
|
|
|
+ this->GetHeadToLinkInterfaceMap(config));
|
|
|
+
|
|
|
+ // If the link interface does not depend on the head target
|
|
|
+ // then return the one we computed first.
|
|
|
+ if(!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition)
|
|
|
+ {
|
|
|
+ return &hm.begin()->second;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmOptionalLinkInterface& iface = hm[headTarget];
|
|
|
+ if(!iface.AllDone)
|
|
|
+ {
|
|
|
+ iface.AllDone = true;
|
|
|
+ iface.Multiplicity = info->Multiplicity;
|
|
|
+ cmSystemTools::ExpandListArgument(info->Languages, iface.Languages);
|
|
|
+ this->ExpandLinkItems(info->LibrariesProp, info->Libraries,
|
|
|
+ config,
|
|
|
+ headTarget, usage_requirements_only,
|
|
|
+ iface.Libraries,
|
|
|
+ iface.HadHeadSensitiveCondition);
|
|
|
+ std::vector<std::string> deps;
|
|
|
+ cmSystemTools::ExpandListArgument(info->SharedDeps, deps);
|
|
|
+ this->LookupLinkItems(deps, iface.SharedDeps);
|
|
|
+ }
|
|
|
+
|
|
|
+ return &iface;
|
|
|
+}
|
|
|
+
|
|
|
+cmHeadToLinkInterfaceMap&
|
|
|
+cmGeneratorTarget::GetHeadToLinkInterfaceMap(const std::string &config) const
|
|
|
+{
|
|
|
+ std::string CONFIG = cmSystemTools::UpperCase(config);
|
|
|
+ return this->LinkInterfaceMap[CONFIG];
|
|
|
+}
|
|
|
+
|
|
|
+cmHeadToLinkInterfaceMap&
|
|
|
+cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap(
|
|
|
+ const std::string &config) const
|
|
|
+{
|
|
|
+ std::string CONFIG = cmSystemTools::UpperCase(config);
|
|
|
+ return this->LinkInterfaceUsageRequirementsOnlyMap[CONFIG];
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+const cmLinkImplementation *
|
|
|
+cmGeneratorTarget::GetLinkImplementation(const std::string& config) const
|
|
|
+{
|
|
|
+ // There is no link implementation for imported targets.
|
|
|
+ if(this->Target->IsImported())
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmOptionalLinkImplementation& impl = this->Target->GetLinkImplMap(config);
|
|
|
+ if(!impl.LibrariesDone)
|
|
|
+ {
|
|
|
+ impl.LibrariesDone = true;
|
|
|
+ this->Target->ComputeLinkImplementationLibraries(config, impl,
|
|
|
+ this->Target);
|
|
|
+ }
|
|
|
+ if(!impl.LanguagesDone)
|
|
|
+ {
|
|
|
+ impl.LanguagesDone = true;
|
|
|
+ this->ComputeLinkImplementationLanguages(config, impl);
|
|
|
+ }
|
|
|
+ return &impl;
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+bool cmGeneratorTarget::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->Target->GetSourceFiles(files, firstConfig);
|
|
|
+
|
|
|
+ for ( ; it != configs.end(); ++it)
|
|
|
+ {
|
|
|
+ std::vector<cmSourceFile*> configFiles;
|
|
|
+ this->Target->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 ";
|
|
|
+ }
|
|
|
+ std::ostringstream e;
|
|
|
+ e << "Target \"" << this->GetName()
|
|
|
+ << "\" has source files which vary by "
|
|
|
+ "configuration. This is not supported by the \""
|
|
|
+ << this->GlobalGenerator->GetName()
|
|
|
+ << "\" generator.\n"
|
|
|
+ "Config \"" << firstConfig << "\":\n"
|
|
|
+ " " << firstConfigFiles << "\n"
|
|
|
+ "Config \"" << *it << "\":\n"
|
|
|
+ " " << thisConfigFiles << "\n";
|
|
|
+ this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
|
|
|
+ const std::string& config) const
|
|
|
+{
|
|
|
+ std::vector<cmSourceFile*> sourceFiles;
|
|
|
+ this->GetSourceFiles(sourceFiles, config);
|
|
|
+ for(std::vector<cmSourceFile*>::const_iterator
|
|
|
+ i = sourceFiles.begin(); i != sourceFiles.end(); ++i)
|
|
|
+ {
|
|
|
+ const std::string& lang = (*i)->GetLanguage();
|
|
|
+ if(!lang.empty())
|
|
|
+ {
|
|
|
+ languages.insert(lang);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ std::vector<cmGeneratorTarget*> objectLibraries;
|
|
|
+ std::vector<cmSourceFile const*> externalObjects;
|
|
|
+ if (!this->Makefile->IsConfigured())
|
|
|
+ {
|
|
|
+ std::vector<cmTarget*> objectTargets;
|
|
|
+ this->Target->GetObjectLibrariesCMP0026(objectTargets);
|
|
|
+ objectLibraries.reserve(objectTargets.size());
|
|
|
+ for (std::vector<cmTarget*>::const_iterator it = objectTargets.begin();
|
|
|
+ it != objectTargets.end(); ++it)
|
|
|
+ {
|
|
|
+ objectLibraries.push_back(this->GlobalGenerator
|
|
|
+ ->GetGeneratorTarget(*it));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ this->GetExternalObjects(externalObjects, config);
|
|
|
+ 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(this->GlobalGenerator
|
|
|
+ ->GetGeneratorTarget(tgt));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for(std::vector<cmGeneratorTarget*>::const_iterator
|
|
|
+ i = objectLibraries.begin(); i != objectLibraries.end(); ++i)
|
|
|
+ {
|
|
|
+ (*i)->GetLanguages(languages, config);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+void cmGeneratorTarget::ComputeLinkImplementationLanguages(
|
|
|
+ const std::string& config,
|
|
|
+ cmOptionalLinkImplementation& impl) 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);
|
|
|
+ // Copy the set of langauges to the link implementation.
|
|
|
+ impl.Languages.insert(impl.Languages.begin(),
|
|
|
+ languages.begin(), languages.end());
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const
|
|
|
+{
|
|
|
+ if (this->Target->GetPropertyAsBool("SKIP_BUILD_RPATH"))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(cmLinkImplementationLibraries const* impl =
|
|
|
+ this->Target->GetLinkImplementationLibraries(config))
|
|
|
+ {
|
|
|
+ return !impl->Libraries.empty();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|