diff options
author | Stephen Kelly <steveire@gmail.com> | 2013-06-04 14:25:47 (GMT) |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2013-07-08 20:39:09 (GMT) |
commit | d0a76ea07cfc2a73900a9539e940e1e60dbba120 (patch) | |
tree | 8afdc5cb57a2ee3c88db5a677a2e642b40415326 /Source/cmTarget.cxx | |
parent | ddde61c0b2b46a452366acae690aca0095c0a49c (diff) | |
download | CMake-d0a76ea07cfc2a73900a9539e940e1e60dbba120.zip CMake-d0a76ea07cfc2a73900a9539e940e1e60dbba120.tar.gz CMake-d0a76ea07cfc2a73900a9539e940e1e60dbba120.tar.bz2 |
Introduce the INTERFACE_LINK_LIBRARIES property.
This property replaces the properties which
match (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?, and is enabled
for IMPORTED targets, and for non-IMPORTED targets only with a policy.
For static libraries, the INTERFACE_LINK_LIBRARIES property is
also used as the source of transitive usage requirements content.
Static libraries still require users to link to all entries in
their LINK_LIBRARIES, but usage requirements such as INCLUDE_DIRECTORIES
COMPILE_DEFINITIONS and COMPILE_OPTIONS can be restricted to only
certain interface libraries.
Because the INTERFACE_LINK_LIBRARIES property is populated unconditionally,
we need to compare the evaluated result of it with the link implementation
to determine whether to issue the policy warning for static libraries. For
shared libraries, the policy warning is issued if the contents of
the INTERFACE_LINK_LIBRARIES property differs from the contents of the
relevant config-specific old LINK_INTERFACE_LIBRARIES property.
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r-- | Source/cmTarget.cxx | 179 |
1 files changed, 172 insertions, 7 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index f7424a7..3bad407 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -197,6 +197,7 @@ cmTarget::cmTarget() this->PolicyStatusCMP0008 = cmPolicies::WARN; this->PolicyStatusCMP0020 = cmPolicies::WARN; this->PolicyStatusCMP0021 = cmPolicies::WARN; + this->PolicyStatusCMP0022 = cmPolicies::WARN; this->LinkLibrariesAnalyzed = false; this->HaveInstallRule = false; this->DLLPlatform = false; @@ -474,7 +475,7 @@ void cmTarget::DefineProperties(cmake *cm) "imported library. " "The list " "should be disjoint from the list of interface libraries in the " - "IMPORTED_LINK_INTERFACE_LIBRARIES property. On platforms requiring " + "INTERFACE_LINK_LIBRARIES property. On platforms requiring " "dependent shared libraries to be found at link time CMake uses this " "list to add appropriate files or paths to the link command line. " "Ignored for non-imported targets."); @@ -495,7 +496,10 @@ void cmTarget::DefineProperties(cmake *cm) "The libraries will be included on the link line for the target. " "Unlike the LINK_INTERFACE_LIBRARIES property, this property applies " "to all imported target types, including STATIC libraries. " - "This property is ignored for non-imported targets."); + "This property is ignored for non-imported targets.\n" + "This property is ignored if the target also has a non-empty " + "INTERFACE_LINK_LIBRARIES property.\n" + "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead."); cm->DefineProperty ("IMPORTED_LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET, @@ -503,7 +507,10 @@ void cmTarget::DefineProperties(cmake *cm) "Configuration names correspond to those provided by the project " "from which the target is imported. " "If set, this property completely overrides the generic property " - "for the named configuration."); + "for the named configuration.\n" + "This property is ignored if the target also has a non-empty " + "INTERFACE_LINK_LIBRARIES property.\n" + "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead."); cm->DefineProperty ("IMPORTED_LINK_INTERFACE_LANGUAGES", cmProperty::TARGET, @@ -820,7 +827,10 @@ void cmTarget::DefineProperties(cmake *cm) "This property is initialized by the value of the variable " "CMAKE_LINK_INTERFACE_LIBRARIES if it is set when a target is " "created. " - "This property is ignored for STATIC libraries."); + "This property is ignored for STATIC libraries.\n" + "This property is overriden by the INTERFACE_LINK_LIBRARIES property if " + "policy CMP0022 is NEW.\n" + "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead."); cm->DefineProperty ("LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET, @@ -828,7 +838,23 @@ void cmTarget::DefineProperties(cmake *cm) "This is the configuration-specific version of " "LINK_INTERFACE_LIBRARIES. " "If set, this property completely overrides the generic property " - "for the named configuration."); + "for the named configuration.\n" + "This property is overriden by the INTERFACE_LINK_LIBRARIES property if " + "policy CMP0022 is NEW.\n" + "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead."); + + cm->DefineProperty + ("INTERFACE_LINK_LIBRARIES", cmProperty::TARGET, + "List public interface libraries for a shared library or executable.", + "This property contains the list of transitive link dependencies. " + "When the target is linked into another target the libraries " + "listed (and recursively their link interface libraries) will be " + "provided to the other target also. " + "This property is overriden by the LINK_INTERFACE_LIBRARIES or " + "LINK_INTERFACE_LIBRARIES_<CONFIG> property if " + "policy CMP0022 is OLD or unset.\n" + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); cm->DefineProperty ("INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET, @@ -1678,6 +1704,8 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->Makefile->GetPolicyStatus(cmPolicies::CMP0020); this->PolicyStatusCMP0021 = this->Makefile->GetPolicyStatus(cmPolicies::CMP0021); + this->PolicyStatusCMP0022 = + this->Makefile->GetPolicyStatus(cmPolicies::CMP0022); } //---------------------------------------------------------------------------- @@ -3528,6 +3556,29 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES( } //---------------------------------------------------------------------------- +static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, + cmMakefile* context) +{ + // Look for link-type keywords in the value. + static cmsys::RegularExpression + keys("(^|;)(debug|optimized|general)(;|$)"); + if(!keys.find(value)) + { + return; + } + + // Report an error. + cmOStringStream e; + + e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type " + "keyword \"" << keys.match(2) << "\". The INTERFACE_LINK_LIBRARIES " + "property may contain configuration-sensitive generator-expressions " + "which may be used to specify per-configuration rules."; + + context->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- void cmTarget::CheckProperty(const char* prop, cmMakefile* context) { // Certain properties need checking. @@ -3545,6 +3596,13 @@ void cmTarget::CheckProperty(const char* prop, cmMakefile* context) cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true); } } + if(strncmp(prop, "INTERFACE_LINK_LIBRARIES", 24) == 0) + { + if(const char* value = this->GetProperty(prop)) + { + cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context); + } + } } //---------------------------------------------------------------------------- @@ -6013,8 +6071,34 @@ void cmTarget::GetTransitivePropertyLinkLibraries( { return; } + if(this->GetType() != STATIC_LIBRARY + || this->GetPolicyStatusCMP0022() == cmPolicies::WARN + || this->GetPolicyStatusCMP0022() == cmPolicies::OLD) + { + libs = iface->Libraries; + return; + } + + const char* linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; + const char* interfaceLibs = this->GetProperty(linkIfaceProp); - libs = iface->Libraries; + if (!interfaceLibs) + { + return; + } + + // The interface libraries have been explicitly set. + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(), + linkIfaceProp, 0, 0); + dagChecker.SetTransitivePropertiesOnly(); + cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate( + this->Makefile, + config, + false, + headTarget, + this, &dagChecker), libs); } //---------------------------------------------------------------------------- @@ -6035,6 +6119,8 @@ 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()) @@ -6050,6 +6136,81 @@ 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."; + 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: + { + 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."; + 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; + } + } + } } // There is no implicit link interface for executables or modules @@ -6113,7 +6274,11 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface, } } } - else + 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 { // The link implementation is the default link interface. LinkImplementation const* impl = this->GetLinkImplementation(config, |