diff options
author | Brad King <brad.king@kitware.com> | 2008-01-31 20:45:31 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2008-01-31 20:45:31 (GMT) |
commit | 2cff26fa52cf9043f00d1efaaf31ab93e2db22e8 (patch) | |
tree | 4d403a91a70594893fc6b303a9cf693d4e538a9d /Source/cmTarget.cxx | |
parent | 52e75800b4731692f1e311f0d8701875ac98c96d (diff) | |
download | CMake-2cff26fa52cf9043f00d1efaaf31ab93e2db22e8.zip CMake-2cff26fa52cf9043f00d1efaaf31ab93e2db22e8.tar.gz CMake-2cff26fa52cf9043f00d1efaaf31ab93e2db22e8.tar.bz2 |
ENH: Support linking to shared libs with dependent libs
- Split IMPORTED_LINK_LIBRARIES into two parts:
IMPORTED_LINK_INTERFACE_LIBRARIES
IMPORTED_LINK_DEPENDENT_LIBRARIES
- Add CMAKE_DEPENDENT_SHARED_LIBRARY_MODE to select behavior
- Set mode to LINK for Darwin (fixes universal binary problem)
- Update ExportImport test to account for changes
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r-- | Source/cmTarget.cxx | 158 |
1 files changed, 129 insertions, 29 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e007367..b484a95 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -188,15 +188,38 @@ void cmTarget::DefineProperties(cmake *cm) "from which the target is imported."); cm->DefineProperty - ("IMPORTED_LINK_LIBRARIES", cmProperty::TARGET, - "Transitive link dependencies of an IMPORTED target.", - "Lists dependencies that must be linked when an IMPORTED library " + ("IMPORTED_LINK_DEPENDENT_LIBRARIES", cmProperty::TARGET, + "Dependent shared libraries of an imported shared library.", + "Shared libraries may be linked to other shared libraries as part " + "of their implementation. On some platforms the linker searches " + "for the dependent libraries of shared libraries they are including " + "in the link. CMake gives the paths to these libraries to the linker " + "by listing them on the link line explicitly. This property lists " + "the dependent shared libraries of an imported library. The list " + "should be disjoint from the list of interface libraries in the " + "IMPORTED_LINK_INTERFACE_LIBRARIES property. On platforms requiring " + "dependent shared libraries to be found at link time CMake uses this " + "list to add the dependent libraries to the link command line."); + + cm->DefineProperty + ("IMPORTED_LINK_DEPENDENT_LIBRARIES_<CONFIG>", cmProperty::TARGET, + "Per-configuration version of IMPORTED_LINK_DEPENDENT_LIBRARIES.", + "This property is used when loading settings for the <CONFIG> " + "configuration of an imported target. " + "Configuration names correspond to those provided by the project " + "from which the target is imported."); + + cm->DefineProperty + ("IMPORTED_LINK_INTERFACE_LIBRARIES", cmProperty::TARGET, + "Transitive link interface of an IMPORTED target.", + "Lists libraries whose interface is included when an IMPORTED library " "target is linked to another target. " + "The libraries will be included on the link line for the target. " "Ignored for non-imported targets."); cm->DefineProperty - ("IMPORTED_LINK_LIBRARIES_<CONFIG>", cmProperty::TARGET, - "Per-configuration version of IMPORTED_LINK_LIBRARIES property.", + ("IMPORTED_LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET, + "Per-configuration version of IMPORTED_LINK_INTERFACE_LIBRARIES.", "This property is used when loading settings for the <CONFIG> " "configuration of an imported target. " "Configuration names correspond to those provided by the project " @@ -3045,43 +3068,56 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, } } - // Get the link dependencies. + // Get the link interface. { - std::string linkProp = "IMPORTED_LINK_LIBRARIES"; + std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; linkProp += suffix; if(const char* config_libs = this->GetProperty(linkProp.c_str())) { - cmSystemTools::ExpandListArgument(config_libs, info.LinkLibraries); + cmSystemTools::ExpandListArgument(config_libs, + info.LinkInterface.Libraries); } - else if(const char* libs = this->GetProperty("IMPORTED_LINK_LIBRARIES")) + else if(const char* libs = + this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES")) { - cmSystemTools::ExpandListArgument(libs, info.LinkLibraries); + cmSystemTools::ExpandListArgument(libs, + info.LinkInterface.Libraries); } } -} -//---------------------------------------------------------------------------- -std::vector<std::string> const* -cmTarget::GetImportedLinkLibraries(const char* config) -{ - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + // Get the link dependencies. + { + std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES"; + linkProp += suffix; + if(const char* config_libs = this->GetProperty(linkProp.c_str())) { - return &info->LinkLibraries; + cmSystemTools::ExpandListArgument(config_libs, + info.LinkInterface.SharedDeps); } - else + else if(const char* libs = + this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES")) { - return 0; + cmSystemTools::ExpandListArgument(libs, info.LinkInterface.SharedDeps); } + } } //---------------------------------------------------------------------------- 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 && + // Imported targets have their own link interface. + if(this->IsImported()) + { + if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) + { + return &info->LinkInterface; + } + return 0; + } + + // Link interfaces are supported only for shared libraries and + // executables that export symbols. + if((this->GetType() != cmTarget::SHARED_LIBRARY && !this->IsExecutableWithExports())) { return 0; @@ -3139,13 +3175,77 @@ cmTargetLinkInterface* cmTarget::ComputeLinkInterface(const char* config) return 0; } - // Return the interface libraries even if the list is empty. - if(cmTargetLinkInterface* interface = new cmTargetLinkInterface) + // Allocate the interface. + cmTargetLinkInterface* interface = new cmTargetLinkInterface; + if(!interface) { - cmSystemTools::ExpandListArgument(libs, *interface); - return interface; + return 0; + } + + // Expand the list of libraries in the interface. + cmSystemTools::ExpandListArgument(libs, interface->Libraries); + + // Now we need to construct a list of shared library dependencies + // not included in the interface. + if(this->GetType() == cmTarget::SHARED_LIBRARY) + { + // Use a set to keep track of what libraries have been emitted to + // either list. + std::set<cmStdString> emitted; + for(std::vector<std::string>::const_iterator + li = interface->Libraries.begin(); + li != interface->Libraries.end(); ++li) + { + emitted.insert(*li); + } + + // Compute which library configuration to link. + cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED; + if(config && cmSystemTools::UpperCase(config) == "DEBUG") + { + linkType = cmTarget::DEBUG; + } + + // Construct the list of libs linked for this configuration. + cmTarget::LinkLibraryVectorType const& libs = + this->GetOriginalLinkLibraries(); + for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin(); + li != libs.end(); ++li) + { + // Skip entries that will resolve to the target itself, are empty, + // or are not meant for this configuration. + if(li->first == this->GetName() || li->first.empty() || + !(li->second == cmTarget::GENERAL || li->second == linkType)) + { + continue; + } + + // Skip entries that have already been emitted into either list. + if(!emitted.insert(li->first).second) + { + continue; + } + + // Add this entry if it is a shared library. + if(cmTarget* tgt = this->Makefile->FindTargetToUse(li->first.c_str())) + { + if(tgt->GetType() == cmTarget::SHARED_LIBRARY) + { + interface->SharedDeps.push_back(li->first); + } + } + else + { + // TODO: Recognize shared library file names. Perhaps this + // should be moved to cmComputeLinkInformation, but that creates + // a chicken-and-egg problem since this list is needed for its + // construction. + } + } } - return 0; + + // Return the completed interface. + return interface; } //---------------------------------------------------------------------------- |