cmTarget: Add GetTransitiveTargetClosure method.

Replace calls to GetLinkInformation with calls to a method to get only
the target closure, not the link languages etc.  The replaced calls
are used while evaluating generator expressions only.  This makes
transitive generator expression evaluation independent from
the languages of a target.  In a follow-up topic, it will be possible
to make the languages depend on generator expression evaluation, via
evaluation of the SOURCES and INTERFACE_SOURCES target properties.

Because the order of entries is not the same as the final link line,
the order of debug output is different in the RunCMake.CompatibleInterface
test, because the BOOL_PROP7 target property is evaluated first. Adjust
the test to account for that new order.
This commit is contained in:
Stephen Kelly 2014-02-13 18:27:31 +01:00
parent a6dd4990db
commit 5771f81d91
3 changed files with 67 additions and 26 deletions

View File

@ -4424,12 +4424,13 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
assert((impliedByUse ^ explicitlySet)
|| (!impliedByUse && !explicitlySet));
cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
if(!info)
std::vector<cmTarget*> deps;
tgt->GetTransitiveTargetClosure(config, tgt, deps);
if(deps.empty())
{
return propContent;
}
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
bool propInitialized = explicitlySet;
std::string report = " * Target \"";
@ -4449,7 +4450,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
report += "\" property not set.\n";
}
for(cmComputeLinkInformation::ItemVector::const_iterator li =
for(std::vector<cmTarget*>::const_iterator li =
deps.begin();
li != deps.end(); ++li)
{
@ -4459,11 +4460,7 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt,
// target itself has a POSITION_INDEPENDENT_CODE which disagrees
// with a dependency.
cmTarget const* theTarget = li->Target;
if (!theTarget)
{
continue;
}
cmTarget const* theTarget = *li;
const bool ifaceIsSet = theTarget->GetProperties()
.find("INTERFACE_" + p)
@ -4643,23 +4640,19 @@ bool isLinkDependentProperty(cmTarget const* tgt, const std::string &p,
const char *interfaceProperty,
const char *config)
{
cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
if(!info)
std::vector<cmTarget*> deps;
tgt->GetTransitiveTargetClosure(config, tgt, deps);
if(deps.empty())
{
return false;
}
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator li =
for(std::vector<cmTarget*>::const_iterator li =
deps.begin();
li != deps.end(); ++li)
{
if (!li->Target)
{
continue;
}
const char *prop = li->Target->GetProperty(interfaceProperty);
const char *prop = (*li)->GetProperty(interfaceProperty);
if (!prop)
{
continue;
@ -5277,6 +5270,51 @@ cmTarget::GetLinkInterfaceLibraries(const char* config,
return i->second.Exists ? &i->second : 0;
}
//----------------------------------------------------------------------------
void processILibs(const char* config,
cmTarget const* headTarget,
std::string const& name,
std::vector<cmTarget*>& tgts, std::set<cmTarget*>& emitted)
{
if (cmTarget* tgt = headTarget->GetMakefile()
->FindTargetToUse(name.c_str()))
{
if (emitted.insert(tgt).second)
{
tgts.push_back(tgt);
std::vector<std::string> ilibs;
cmTarget::LinkInterface const* iface =
tgt->GetLinkInterfaceLibraries(config, headTarget);
if (iface)
{
for(std::vector<std::string>::const_iterator
it = iface->Libraries.begin();
it != iface->Libraries.end(); ++it)
{
processILibs(config, headTarget, *it, tgts, emitted);
}
}
}
}
}
//----------------------------------------------------------------------------
void cmTarget::GetTransitiveTargetClosure(const char* config,
cmTarget const* headTarget,
std::vector<cmTarget*> &tgts) const
{
std::set<cmTarget*> emitted;
cmTarget::LinkImplementation const* impl
= this->GetLinkImplementationLibraries(config, headTarget);
for(std::vector<std::string>::const_iterator it = impl->Libraries.begin();
it != impl->Libraries.end(); ++it)
{
processILibs(config, headTarget, *it, tgts, emitted);
}
}
//----------------------------------------------------------------------------
void cmTarget::GetTransitivePropertyTargets(const char* config,
cmTarget const* headTarget,

View File

@ -269,6 +269,9 @@ public:
void GetTransitivePropertyTargets(const char* config,
cmTarget const* headTarget,
std::vector<cmTarget*> &libs) const;
void GetTransitiveTargetClosure(const char* config,
cmTarget const* headTarget,
std::vector<cmTarget*> &libs) const;
/** The link implementation specifies the direct library
dependencies needed by the object files of the target. */

View File

@ -1,3 +1,10 @@
CMake Debug Log:
Boolean compatibility of property "BOOL_PROP7" for target
"CompatibleInterface" \(result: "FALSE"\):
\* Target "CompatibleInterface" property is implied by use.
\* Target "iface1" property value "FALSE" \(Agree\)
+
CMake Debug Log:
Boolean compatibility of property "BOOL_PROP1" for target
"CompatibleInterface" \(result: "TRUE"\):
@ -39,13 +46,6 @@ CMake Debug Log:
\* Target "iface1" property value "FALSE" \(Interface set\)
\* Target "iface2" property value "FALSE" \(Agree\)
+
CMake Debug Log:
Boolean compatibility of property "BOOL_PROP7" for target
"CompatibleInterface" \(result: "FALSE"\):
\* Target "CompatibleInterface" property is implied by use.
\* Target "iface1" property value "FALSE" \(Agree\)
+
CMake Debug Log:
String compatibility of property "STRING_PROP1" for target
"CompatibleInterface" \(result: "prop1"\):