diff options
author | Brad King <brad.king@kitware.com> | 2008-01-30 22:25:52 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2008-01-30 22:25:52 (GMT) |
commit | 7902bc06aae07a9d4cde81ab41c3c86694d80a9b (patch) | |
tree | 20810436488a804ffadb37c349d8db594d368a36 /Source/cmTarget.cxx | |
parent | 22be36f8d52fae0f509725253f175b0c1ec65dcc (diff) | |
download | CMake-7902bc06aae07a9d4cde81ab41c3c86694d80a9b.zip CMake-7902bc06aae07a9d4cde81ab41c3c86694d80a9b.tar.gz CMake-7902bc06aae07a9d4cde81ab41c3c86694d80a9b.tar.bz2 |
ENH: Implemented link-interface specification feature.
- Shared libs and executables with exports may now have
explicit transitive link dependencies specified
- Created LINK_INTERFACE_LIBRARIES and related properties
- Exported targets get the interface libraries as their
IMPORTED_LINK_LIBRARIES property.
- The export() and install(EXPORT) commands now give
an error when a linked target is not included since
the user can change the interface libraries instead
of adding the target.
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r-- | Source/cmTarget.cxx | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 706a45f..6575140 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -312,6 +312,28 @@ void cmTarget::DefineProperties(cmake *cm) "The property is defined only for library and executable targets."); cm->DefineProperty + ("LINK_INTERFACE_LIBRARIES", cmProperty::TARGET, + "List public interface libraries for a shared library or executable.", + "By default linking to a shared library target transitively " + "links to targets with which the library itself was linked. " + "For an executable with exports (see the ENABLE_EXPORTS property) " + "no default transitive link dependencies are used. " + "This property replaces the default transitive link dependencies with " + "an explict list. " + "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. " + "If the list is empty then no transitive link dependencies will be " + "incorporated when this target is linked into another target even if " + "the default set is non-empty."); + + cm->DefineProperty + ("LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET, + "Per-configuration list of public interface libraries for a target.", + "This is the configuration-specific version of " + "LINK_INTERFACE_LIBRARIES."); + + cm->DefineProperty ("MAP_IMPORTED_CONFIG_<CONFIG>", cmProperty::TARGET, "Map from project configuration to IMPORTED target's configuration.", "List configurations of an imported target that may be used for " @@ -3041,6 +3063,80 @@ cmTarget::GetImportedLinkLibraries(const char* config) } //---------------------------------------------------------------------------- +cmTargetLinkInterface const* cmTarget::GetLinkInterface(const char* config) +{ + // Link interfaces are supported only for non-imported shared + // libraries and executables that export symbols. Imported targets + // provide their own link information. + if(this->IsImported() || + (this->GetType() != cmTarget::SHARED_LIBRARY && + !this->IsExecutableWithExports())) + { + return 0; + } + + // Lookup any existing link interface for this configuration. + std::map<cmStdString, cmTargetLinkInterface*>::iterator + i = this->LinkInterface.find(config?config:""); + if(i == this->LinkInterface.end()) + { + // Compute the link interface for this configuration. + cmTargetLinkInterface* interface = this->ComputeLinkInterface(config); + + // Store the information for this configuration. + std::map<cmStdString, cmTargetLinkInterface*>::value_type + entry(config?config:"", interface); + i = this->LinkInterface.insert(entry).first; + } + + return i->second; +} + +//---------------------------------------------------------------------------- +cmTargetLinkInterface* cmTarget::ComputeLinkInterface(const char* config) +{ + // Construct the property name suffix for this configuration. + std::string suffix = "_"; + if(config && *config) + { + suffix += cmSystemTools::UpperCase(config); + } + else + { + suffix += "NOCONFIG"; + } + + // Lookup the link interface libraries. + const char* libs = 0; + { + // Lookup the per-configuration property. + std::string propName = "LINK_INTERFACE_LIBRARIES"; + propName += suffix; + libs = this->GetProperty(propName.c_str()); + + // If not set, try the generic property. + if(!libs) + { + libs = this->GetProperty("LINK_INTERFACE_LIBRARIES"); + } + } + + // If still not set, there is no link interface. + if(!libs) + { + return 0; + } + + // Return the interface libraries even if the list is empty. + if(cmTargetLinkInterface* interface = new cmTargetLinkInterface) + { + cmSystemTools::ExpandListArgument(libs, *interface); + return interface; + } + return 0; +} + +//---------------------------------------------------------------------------- cmComputeLinkInformation* cmTarget::GetLinkInformation(const char* config) { @@ -3088,3 +3184,26 @@ cmTargetLinkInformationMap::~cmTargetLinkInformationMap() delete i->second; } } + +//---------------------------------------------------------------------------- +cmTargetLinkInterfaceMap +::cmTargetLinkInterfaceMap(cmTargetLinkInterfaceMap const& r): derived() +{ + // Ideally cmTarget instances should never be copied. However until + // we can make a sweep to remove that, this copy constructor avoids + // allowing the resources (LinkInterface) from getting copied. In + // the worst case this will lead to extra cmTargetLinkInterface + // instances. We also enforce in debug mode that the map be emptied + // when copied. + static_cast<void>(r); + assert(r.empty()); +} + +//---------------------------------------------------------------------------- +cmTargetLinkInterfaceMap::~cmTargetLinkInterfaceMap() +{ + for(derived::iterator i = this->begin(); i != this->end(); ++i) + { + delete i->second; + } +} |