Merge topic 'policy-CMP0022-fixes-for-master'

b51696f CMP0022: Update target_link_libraries plain signature documentation
25b7f87 Merge branch 'policy-CMP0022-fixes' into policy-CMP0022-fixes-for-master
0a561a0 CMP0022: Warn about a given target at most once
23d21b7 Do not export INTERFACE_LINK_LIBRARIES from non-linkable targets
ef10b87 CMP0022: Plain target_link_libraries must populate link interface
0e06788 CMP0022: Add test for target_link_libraries plain signature
c0f4a61 CMP0022: Add unit test for null pointer check and message.
4b0cfa7 Merge branch 'output-CMP0022-entries' into policy-CMP0022-fixes
This commit is contained in:
Brad King
2013-11-04 07:54:20 -05:00
committed by CMake Topic Stage
23 changed files with 242 additions and 162 deletions

View File

@@ -191,6 +191,10 @@ bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
ImportPropertyMap &properties,
std::vector<std::string> &missingTargets)
{
if(!target->IsLinkable())
{
return false;
}
const char *input = target->GetProperty("INTERFACE_LINK_LIBRARIES");
if (input)
{
@@ -654,6 +658,7 @@ cmExportFileGenerator
if (iface->ImplementationIsInterface)
{
// Policy CMP0022 must not be NEW.
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LIBRARIES",
iface->Libraries, properties, missingTargets);

View File

@@ -81,10 +81,12 @@ class cmTargetInternals
public:
cmTargetInternals()
{
this->PolicyWarnedCMP0022 = false;
this->SourceFileFlagsConstructed = false;
}
cmTargetInternals(cmTargetInternals const&)
{
this->PolicyWarnedCMP0022 = false;
this->SourceFileFlagsConstructed = false;
}
~cmTargetInternals();
@@ -104,6 +106,7 @@ public:
typedef std::map<TargetConfigPair, OptionalLinkInterface>
LinkInterfaceMapType;
LinkInterfaceMapType LinkInterfaceMap;
bool PolicyWarnedCMP0022;
typedef std::map<cmStdString, cmTarget::OutputInfo> OutputInfoMapType;
OutputInfoMapType OutputInfoMap;
@@ -685,21 +688,10 @@ void cmTarget::MergeLinkLibraries( cmMakefile& mf,
i += this->PrevLinkedLibraries.size();
for( ; i != libs.end(); ++i )
{
const char *lib = i->first.c_str();
// We call this so that the dependencies get written to the cache
this->AddLinkLibrary( mf, selfname, lib, i->second );
if (this->GetType() == cmTarget::STATIC_LIBRARY)
{
std::string configLib = this->GetDebugGeneratorExpressions(lib,
i->second);
if (cmGeneratorExpression::IsValidTargetName(lib)
|| cmGeneratorExpression::Find(lib) != std::string::npos)
{
configLib = "$<LINK_ONLY:" + configLib + ">";
}
this->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib.c_str());
}
// This is equivalent to the target_link_libraries plain signature.
this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
this->AppendProperty("INTERFACE_LINK_LIBRARIES",
this->GetDebugGeneratorExpressions(i->first.c_str(), i->second).c_str());
}
this->PrevLinkedLibraries = libs;
}
@@ -5030,12 +5022,20 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
// An explicit list of interface libraries may be set for shared
// libraries and executables that export symbols.
const char* explicitLibraries = 0;
const char* newExplicitLibraries =
this->GetProperty("INTERFACE_LINK_LIBRARIES");
std::string linkIfaceProp;
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
this->IsExecutableWithExports())
if(this->PolicyStatusCMP0022 != cmPolicies::OLD &&
this->PolicyStatusCMP0022 != cmPolicies::WARN)
{
// CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
}
else if(this->GetType() == cmTarget::SHARED_LIBRARY ||
this->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;
@@ -5047,126 +5047,33 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
}
if (newExplicitLibraries
&& (!explicitLibraries ||
(explicitLibraries
&& strcmp(newExplicitLibraries, explicitLibraries) != 0)))
{
switch(this->GetPolicyStatusCMP0022())
{
case cmPolicies::WARN:
{
cmOStringStream w;
w << (this->Makefile->GetPolicies()
->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
<< "Target \"" << this->GetName() << "\" has a "
"INTERFACE_LINK_LIBRARIES property which differs from its "
<< linkIfaceProp << " properties."
"\n"
"INTERFACE_LINK_LIBRARIES:\n "
<< newExplicitLibraries
<< "\n"
<< linkIfaceProp << ":\n "
<< (explicitLibraries ? explicitLibraries : "(empty)") << "\n";
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
}
// Fall through
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
explicitLibraries = newExplicitLibraries;
linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
break;
}
}
}
else if(this->GetType() == cmTarget::STATIC_LIBRARY)
{
if (newExplicitLibraries)
{
cmListFileBacktrace lfbt;
cmGeneratorExpression ge(lfbt);
cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
"INTERFACE_LINK_LIBRARIES", 0, 0);
std::vector<std::string> ifaceLibs;
cmSystemTools::ExpandListArgument(
ge.Parse(newExplicitLibraries)->Evaluate(
this->Makefile,
config,
false,
headTarget,
this, &dagChecker), ifaceLibs);
LinkImplementation const* impl = this->GetLinkImplementation(config,
headTarget);
if (ifaceLibs != impl->Libraries)
{
switch(this->GetPolicyStatusCMP0022())
{
case cmPolicies::WARN:
{
std::string oldLibraries;
std::string newLibraries;
const char *sep = "";
for(std::vector<std::string>::const_iterator it
= impl->Libraries.begin(); it != impl->Libraries.end(); ++it)
{
oldLibraries += sep;
oldLibraries += *it;
sep = ";";
}
sep = "";
for(std::vector<std::string>::const_iterator it
= ifaceLibs.begin(); it != ifaceLibs.end(); ++it)
{
newLibraries += sep;
newLibraries += *it;
sep = ";";
}
cmOStringStream w;
w << (this->Makefile->GetPolicies()
->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
<< "Static library target \"" << this->GetName() << "\" has a "
"INTERFACE_LINK_LIBRARIES property. This should be preferred "
"as the source of the link interface for this library. "
"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->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
}
// Fall through
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
explicitLibraries = newExplicitLibraries;
linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
break;
}
}
else
{
iface.Libraries = impl->Libraries;
if(this->LinkLanguagePropagatesToDependents())
{
// Targets using this archive need its language runtime libraries.
iface.Languages = impl->Languages;
}
}
}
}
else if (this->GetType() == cmTarget::INTERFACE_LIBRARY)
if(explicitLibraries && this->PolicyStatusCMP0022 == cmPolicies::WARN &&
!this->Internal->PolicyWarnedCMP0022)
{
explicitLibraries = newExplicitLibraries;
linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
// 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)
{
cmOStringStream w;
w <<
(this->Makefile->GetPolicies()
->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->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
this->Internal->PolicyWarnedCMP0022 = true;
}
}
// There is no implicit link interface for executables or modules
@@ -5235,11 +5142,12 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
}
}
}
else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN
|| this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
// The implementation shouldn't be the interface if CMP0022 is NEW. That
// way, the LINK_LIBRARIES property can be set directly without having to
// empty the INTERFACE_LINK_LIBRARIES
else if (this->PolicyStatusCMP0022 == cmPolicies::WARN
|| this->PolicyStatusCMP0022 == 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.
LinkImplementation const* impl = this->GetLinkImplementation(config,
@@ -5252,6 +5160,70 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
// Targets using this archive need its language runtime libraries.
iface.Languages = impl->Languages;
}
if(this->PolicyStatusCMP0022 == cmPolicies::WARN &&
!this->Internal->PolicyWarnedCMP0022)
{
// Compare the link implementation fallback link interface to the
// preferred new link interface property and warn if different.
cmListFileBacktrace lfbt;
cmGeneratorExpression ge(lfbt);
cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
"INTERFACE_LINK_LIBRARIES", 0, 0);
std::vector<std::string> ifaceLibs;
const char* newExplicitLibraries =
this->GetProperty("INTERFACE_LINK_LIBRARIES");
cmSystemTools::ExpandListArgument(
ge.Parse(newExplicitLibraries)->Evaluate(this->Makefile,
config,
false,
headTarget,
this, &dagChecker),
ifaceLibs);
if (ifaceLibs != impl->Libraries)
{
std::string oldLibraries;
std::string newLibraries;
const char *sep = "";
for(std::vector<std::string>::const_iterator it
= impl->Libraries.begin(); it != impl->Libraries.end(); ++it)
{
oldLibraries += sep;
oldLibraries += *it;
sep = ";";
}
sep = "";
for(std::vector<std::string>::const_iterator it
= ifaceLibs.begin(); it != ifaceLibs.end(); ++it)
{
newLibraries += sep;
newLibraries += *it;
sep = ";";
}
if(oldLibraries.empty())
{ oldLibraries = "(empty)"; }
if(newLibraries.empty())
{ newLibraries = "(empty)"; }
cmOStringStream w;
w <<
(this->Makefile->GetPolicies()
->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->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
this->Internal->PolicyWarnedCMP0022 = true;
}
}
}
if(this->GetType() == cmTarget::STATIC_LIBRARY)

View File

@@ -390,8 +390,14 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
{
this->Makefile
->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
if (this->CurrentProcessingState != ProcessingKeywordPublicInterface
&& this->CurrentProcessingState != ProcessingPlainPublicInterface)
if(this->CurrentProcessingState == ProcessingLinkLibraries)
{
this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
return true;
}
else if(this->CurrentProcessingState != ProcessingKeywordPublicInterface
&& this->CurrentProcessingState != ProcessingPlainPublicInterface)
{
if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
{