summaryrefslogtreecommitdiff
path: root/Source/cmTarget.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r--Source/cmTarget.cxx221
1 files changed, 169 insertions, 52 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index ca53a39d22..25054c5360 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -72,6 +72,11 @@ struct cmTarget::ImportInfo
cmTarget::LinkInterface LinkInterface;
};
+struct TargetConfigPair : public std::pair<cmTarget*, std::string> {
+ TargetConfigPair(cmTarget* tgt, const std::string &config)
+ : std::pair<cmTarget*, std::string>(tgt, config) {}
+};
+
//----------------------------------------------------------------------------
class cmTargetInternals
{
@@ -100,20 +105,24 @@ public:
OptionalLinkInterface(): Exists(false) {}
bool Exists;
};
- typedef std::map<cmStdString, OptionalLinkInterface> LinkInterfaceMapType;
+ typedef std::map<TargetConfigPair, OptionalLinkInterface>
+ LinkInterfaceMapType;
LinkInterfaceMapType LinkInterfaceMap;
typedef std::map<cmStdString, cmTarget::OutputInfo> OutputInfoMapType;
OutputInfoMapType OutputInfoMap;
- typedef std::map<cmStdString, cmTarget::ImportInfo> ImportInfoMapType;
+ typedef std::map<TargetConfigPair, cmTarget::ImportInfo>
+ ImportInfoMapType;
ImportInfoMapType ImportInfoMap;
// Cache link implementation computation from each configuration.
- typedef std::map<cmStdString, cmTarget::LinkImplementation> LinkImplMapType;
+ typedef std::map<TargetConfigPair,
+ cmTarget::LinkImplementation> LinkImplMapType;
LinkImplMapType LinkImplMap;
- typedef std::map<cmStdString, cmTarget::LinkClosure> LinkClosureMapType;
+ typedef std::map<TargetConfigPair, cmTarget::LinkClosure>
+ LinkClosureMapType;
LinkClosureMapType LinkClosureMap;
struct SourceEntry { std::vector<cmSourceFile*> Depends; };
@@ -511,6 +520,22 @@ void cmTarget::DefineProperties(cmake *cm)
"undefined behavior.");
cm->DefineProperty
+ ("LINK_LIBRARIES", cmProperty::TARGET,
+ "List of direct link dependencies.",
+ "This property specifies the list of libraries or targets which will be "
+ "used for linking. "
+ "In addition to accepting values from the target_link_libraries "
+ "command, values may be set directly on any target using the "
+ "set_property command. "
+ "\n"
+ "The target property values are used by the generators to set "
+ "the link libraries for the compiler. "
+ "See also the target_link_libraries command.\n"
+ "Contents of LINK_LIBRARIES may use \"generator expressions\" with "
+ "the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+
+ cm->DefineProperty
("INCLUDE_DIRECTORIES", cmProperty::TARGET,
"List of preprocessor include file search directories.",
"This property specifies the list of directories given "
@@ -2131,6 +2156,66 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname)
}
//----------------------------------------------------------------------------
+void cmTarget::GetDirectLinkLibraries(const char *config,
+ std::vector<std::string> &libs, cmTarget *head)
+{
+ const char *prop = this->GetProperty("LINK_LIBRARIES");
+ if (prop)
+ {
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "LINK_LIBRARIES", 0, 0);
+ cmSystemTools::ExpandListArgument(ge.Parse(prop)->Evaluate(this->Makefile,
+ config,
+ false,
+ head,
+ &dagChecker),
+ libs);
+ }
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value,
+ cmTarget::LinkLibraryType llt)
+{
+ if (llt == GENERAL)
+ {
+ return value;
+ }
+
+ // Get the list of configurations considered to be DEBUG.
+ std::vector<std::string> const& debugConfigs =
+ this->Makefile->GetCMakeInstance()->GetDebugConfigs();
+
+ std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";
+
+ if (debugConfigs.size() > 1)
+ {
+ for(std::vector<std::string>::const_iterator
+ li = debugConfigs.begin() + 1; li != debugConfigs.end(); ++li)
+ {
+ configString += ",$<CONFIG:" + *li + ">";
+ }
+ configString = "$<OR:" + configString + ">";
+ }
+
+ if (llt == OPTIMIZED)
+ {
+ configString = "$<NOT:" + configString + ">";
+ }
+ return "$<" + configString + ":" + value + ">";
+}
+
+//----------------------------------------------------------------------------
+static std::string targetNameGenex(const char *lib)
+{
+ return std::string("$<TARGET_NAME:") + lib + ">";
+}
+
+//----------------------------------------------------------------------------
void cmTarget::AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib,
LinkLibraryType llt)
@@ -2140,6 +2225,18 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
{
return;
}
+
+ {
+ cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
+ const bool isNonImportedTarget = tgt && !tgt->IsImported();
+
+ std::string libName = isNonImportedTarget ? targetNameGenex(lib)
+ : std::string(lib);
+ this->AppendProperty("LINK_LIBRARIES",
+ this->GetDebugGeneratorExpressions(libName,
+ llt).c_str());
+ }
+
cmTarget::LibraryID tmp;
tmp.first = lib;
tmp.second = llt;
@@ -3024,8 +3121,11 @@ class cmTargetCollectLinkLanguages
{
public:
cmTargetCollectLinkLanguages(cmTarget* target, const char* config,
- std::set<cmStdString>& languages):
- Config(config), Languages(languages) { this->Visited.insert(target); }
+ std::set<cmStdString>& languages,
+ cmTarget* head):
+ Config(config), Languages(languages), HeadTarget(head)
+ { this->Visited.insert(target); }
+
void Visit(cmTarget* target)
{
if(!target || !this->Visited.insert(target).second)
@@ -3034,7 +3134,7 @@ public:
}
cmTarget::LinkInterface const* iface =
- target->GetLinkInterface(this->Config);
+ target->GetLinkInterface(this->Config, this->HeadTarget);
if(!iface) { return; }
for(std::vector<std::string>::const_iterator
@@ -3053,26 +3153,30 @@ public:
private:
const char* Config;
std::set<cmStdString>& Languages;
+ cmTarget* HeadTarget;
std::set<cmTarget*> Visited;
};
//----------------------------------------------------------------------------
-const char* cmTarget::GetLinkerLanguage(const char* config)
+const char* cmTarget::GetLinkerLanguage(const char* config, cmTarget *head)
{
- const char* lang = this->GetLinkClosure(config)->LinkerLanguage.c_str();
+ cmTarget *headTarget = head ? head : this;
+ const char* lang = this->GetLinkClosure(config, headTarget)
+ ->LinkerLanguage.c_str();
return *lang? lang : 0;
}
//----------------------------------------------------------------------------
-cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config)
+cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config,
+ cmTarget *head)
{
- std::string key = cmSystemTools::UpperCase(config? config : "");
+ TargetConfigPair key(head, cmSystemTools::UpperCase(config ? config : ""));
cmTargetInternals::LinkClosureMapType::iterator
i = this->Internal->LinkClosureMap.find(key);
if(i == this->Internal->LinkClosureMap.end())
{
LinkClosure lc;
- this->ComputeLinkClosure(config, lc);
+ this->ComputeLinkClosure(config, lc, head);
cmTargetInternals::LinkClosureMapType::value_type entry(key, lc);
i = this->Internal->LinkClosureMap.insert(entry).first;
}
@@ -3133,11 +3237,12 @@ public:
};
//----------------------------------------------------------------------------
-void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
+void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc,
+ cmTarget *head)
{
// Get languages built in this target.
std::set<cmStdString> languages;
- LinkImplementation const* impl = this->GetLinkImplementation(config);
+ LinkImplementation const* impl = this->GetLinkImplementation(config, head);
for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
li != impl->Languages.end(); ++li)
{
@@ -3145,7 +3250,7 @@ void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
}
// Add interface languages from linked targets.
- cmTargetCollectLinkLanguages cll(this, config, languages);
+ cmTargetCollectLinkLanguages cll(this, config, languages, head);
for(std::vector<std::string>::const_iterator li = impl->Libraries.begin();
li != impl->Libraries.end(); ++li)
{
@@ -3284,7 +3389,8 @@ bool cmTarget::HasSOName(const char* config)
return ((this->GetType() == cmTarget::SHARED_LIBRARY ||
this->GetType() == cmTarget::MODULE_LIBRARY) &&
!this->GetPropertyAsBool("NO_SONAME") &&
- this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config)));
+ this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config,
+ this)));
}
//----------------------------------------------------------------------------
@@ -3293,7 +3399,7 @@ std::string cmTarget::GetSOName(const char* config)
if(this->IsImported())
{
// Lookup the imported soname.
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
{
if(info->NoSOName)
{
@@ -3330,7 +3436,7 @@ bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config)
{
if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY)
{
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
{
return info->NoSOName;
}
@@ -3444,7 +3550,7 @@ std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
std::string cmTarget::ImportedGetFullPath(const char* config, bool implib)
{
std::string result;
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
{
result = implib? info->ImportLibrary : info->Location;
}
@@ -3529,7 +3635,7 @@ void cmTarget::GetFullNameInternal(const char* config,
const char* suffixVar = this->GetSuffixVariableInternal(implib);
// Check for language-specific default prefix and suffix.
- if(const char* ll = this->GetLinkerLanguage(config))
+ if(const char* ll = this->GetLinkerLanguage(config, this))
{
if(!targetSuffix && suffixVar && *suffixVar)
{
@@ -3900,7 +4006,7 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config)
}
// Check for rpath support on this platform.
- if(const char* ll = this->GetLinkerLanguage(config))
+ if(const char* ll = this->GetLinkerLanguage(config, this))
{
std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
flagVar += ll;
@@ -4322,7 +4428,7 @@ bool cmTarget::IsChrpathUsed(const char* config)
// Enable if the rpath flag uses a separator and the target uses ELF
// binaries.
- if(const char* ll = this->GetLinkerLanguage(config))
+ if(const char* ll = this->GetLinkerLanguage(config, this))
{
std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
sepVar += ll;
@@ -4346,7 +4452,7 @@ bool cmTarget::IsChrpathUsed(const char* config)
//----------------------------------------------------------------------------
cmTarget::ImportInfo const*
-cmTarget::GetImportInfo(const char* config)
+cmTarget::GetImportInfo(const char* config, cmTarget *headTarget)
{
// There is no imported information for non-imported targets.
if(!this->IsImported())
@@ -4365,14 +4471,16 @@ cmTarget::GetImportInfo(const char* config)
{
config_upper = "NOCONFIG";
}
+ TargetConfigPair key(headTarget, config_upper);
typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType;
+
ImportInfoMapType::const_iterator i =
- this->Internal->ImportInfoMap.find(config_upper);
+ this->Internal->ImportInfoMap.find(key);
if(i == this->Internal->ImportInfoMap.end())
{
ImportInfo info;
- this->ComputeImportInfo(config_upper, info);
- ImportInfoMapType::value_type entry(config_upper, info);
+ this->ComputeImportInfo(config_upper, info, headTarget);
+ ImportInfoMapType::value_type entry(key, info);
i = this->Internal->ImportInfoMap.insert(entry).first;
}
@@ -4511,8 +4619,10 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
//----------------------------------------------------------------------------
void cmTarget::ComputeImportInfo(std::string const& desired_config,
- ImportInfo& info)
+ ImportInfo& info,
+ cmTarget *headTarget)
{
+ (void)headTarget;
// This method finds information about an imported target from its
// properties. The "IMPORTED_" namespace is reserved for properties
// defined by the project exporting the target.
@@ -4669,12 +4779,13 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
}
//----------------------------------------------------------------------------
-cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config)
+cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config,
+ cmTarget *head)
{
// Imported targets have their own link interface.
if(this->IsImported())
{
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head))
{
return &info->LinkInterface;
}
@@ -4690,14 +4801,15 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config)
}
// Lookup any existing link interface for this configuration.
- std::string key = cmSystemTools::UpperCase(config? config : "");
+ TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
+
cmTargetInternals::LinkInterfaceMapType::iterator
i = this->Internal->LinkInterfaceMap.find(key);
if(i == this->Internal->LinkInterfaceMap.end())
{
// Compute the link interface for this configuration.
cmTargetInternals::OptionalLinkInterface iface;
- iface.Exists = this->ComputeLinkInterface(config, iface);
+ iface.Exists = this->ComputeLinkInterface(config, iface, head);
// Store the information for this configuration.
cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface);
@@ -4708,7 +4820,8 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config)
}
//----------------------------------------------------------------------------
-bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
+bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
+ cmTarget *headTarget)
{
// Construct the property name suffix for this configuration.
std::string suffix = "_";
@@ -4765,7 +4878,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
{
emitted.insert(*li);
}
- LinkImplementation const* impl = this->GetLinkImplementation(config);
+ LinkImplementation const* impl = this->GetLinkImplementation(config,
+ headTarget);
for(std::vector<std::string>::const_iterator
li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li)
{
@@ -4793,7 +4907,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
else
{
// The link implementation is the default link interface.
- LinkImplementation const* impl = this->GetLinkImplementation(config);
+ LinkImplementation const* impl = this->GetLinkImplementation(config,
+ headTarget);
iface.Libraries = impl->Libraries;
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
if(this->GetType() == cmTarget::STATIC_LIBRARY)
@@ -4825,7 +4940,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
//----------------------------------------------------------------------------
cmTarget::LinkImplementation const*
-cmTarget::GetLinkImplementation(const char* config)
+cmTarget::GetLinkImplementation(const char* config, cmTarget *head)
{
// There is no link implementation for imported targets.
if(this->IsImported())
@@ -4834,14 +4949,15 @@ cmTarget::GetLinkImplementation(const char* config)
}
// Lookup any existing link implementation for this configuration.
- std::string key = cmSystemTools::UpperCase(config? config : "");
+ TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
+
cmTargetInternals::LinkImplMapType::iterator
i = this->Internal->LinkImplMap.find(key);
if(i == this->Internal->LinkImplMap.end())
{
// Compute the link implementation for this configuration.
LinkImplementation impl;
- this->ComputeLinkImplementation(config, impl);
+ this->ComputeLinkImplementation(config, impl, head);
// Store the information for this configuration.
cmTargetInternals::LinkImplMapType::value_type entry(key, impl);
@@ -4853,27 +4969,26 @@ cmTarget::GetLinkImplementation(const char* config)
//----------------------------------------------------------------------------
void cmTarget::ComputeLinkImplementation(const char* config,
- LinkImplementation& impl)
+ LinkImplementation& impl,
+ cmTarget *head)
{
// Compute which library configuration to link.
cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
// Collect libraries directly linked in this configuration.
- LinkLibraryVectorType const& llibs = this->GetOriginalLinkLibraries();
- for(cmTarget::LinkLibraryVectorType::const_iterator li = llibs.begin();
+ std::vector<std::string> llibs;
+ this->GetDirectLinkLibraries(config, llibs, head);
+ for(std::vector<std::string>::const_iterator li = llibs.begin();
li != llibs.end(); ++li)
{
// Skip entries that resolve to the target itself or are empty.
- std::string item = this->CheckCMP0004(li->first);
+ std::string item = this->CheckCMP0004(*li);
if(item == this->GetName() || item.empty())
{
continue;
}
- if(li->second == cmTarget::GENERAL || li->second == linkType)
- {
- // The entry is meant for this configuration.
- impl.Libraries.push_back(item);
- }
+ // The entry is meant for this configuration.
+ impl.Libraries.push_back(item);
}
LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries();
@@ -4977,16 +5092,19 @@ std::string cmTarget::CheckCMP0004(std::string const& item)
//----------------------------------------------------------------------------
cmComputeLinkInformation*
-cmTarget::GetLinkInformation(const char* config)
+cmTarget::GetLinkInformation(const char* config, cmTarget *head)
{
+ cmTarget *headTarget = head ? head : this;
// Lookup any existing information for this configuration.
- std::map<cmStdString, cmComputeLinkInformation*>::iterator
- i = this->LinkInformation.find(config?config:"");
+ TargetConfigPair key(headTarget,
+ cmSystemTools::UpperCase(config?config:""));
+ cmTargetLinkInformationMap::iterator
+ i = this->LinkInformation.find(key);
if(i == this->LinkInformation.end())
{
// Compute information for this configuration.
cmComputeLinkInformation* info =
- new cmComputeLinkInformation(this, config);
+ new cmComputeLinkInformation(this, config, headTarget);
if(!info || !info->Compute())
{
delete info;
@@ -4994,8 +5112,7 @@ cmTarget::GetLinkInformation(const char* config)
}
// Store the information for this configuration.
- std::map<cmStdString, cmComputeLinkInformation*>::value_type
- entry(config?config:"", info);
+ cmTargetLinkInformationMap::value_type entry(key, info);
i = this->LinkInformation.insert(entry).first;
}
return i->second;