From 2cff26fa52cf9043f00d1efaaf31ab93e2db22e8 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 31 Jan 2008 15:45:31 -0500 Subject: 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 --- Modules/Platform/Darwin.cmake | 6 ++ Source/cmComputeLinkDepends.cxx | 105 +++++++++++++++----- Source/cmComputeLinkDepends.h | 22 ++++- Source/cmComputeLinkInformation.cxx | 58 ++++++++++-- Source/cmComputeLinkInformation.h | 12 ++- Source/cmDocumentVariables.cxx | 2 + Source/cmExportFileGenerator.cxx | 31 ++++-- Source/cmExportFileGenerator.h | 8 +- Source/cmTarget.cxx | 158 +++++++++++++++++++++++++------ Source/cmTarget.h | 15 ++- Tests/ExportImport/Export/CMakeLists.txt | 15 +-- 11 files changed, 340 insertions(+), 92 deletions(-) diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index 4641269..5b497d6 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -103,6 +103,12 @@ IF(XCODE) SET(CMAKE_INCLUDE_SYSTEM_FLAG_CXX) ENDIF(XCODE) +# Need to list dependent shared libraries on link line. When building +# with -isysroot (for universal binaries), the linker always looks for +# dependent libraries under the sysroot. Listing them on the link +# line works around the problem. +SET(CMAKE_DEPENDENT_SHARED_LIBRARY_MODE "LINK") + SET(CMAKE_MacOSX_Content_COMPILE_OBJECT "\"${CMAKE_COMMAND}\" -E copy_if_different ") SET(CMAKE_C_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS -w) diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 1684641..e49312e 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -171,6 +171,14 @@ cmComputeLinkDepends::Compute() this->FollowLinkEntry(qe); } + // Complete the search of shared library dependencies. + while(!this->SharedDepQueue.empty()) + { + // Handle the next entry. + this->HandleSharedDependency(this->SharedDepQueue.front()); + this->SharedDepQueue.pop(); + } + // Infer dependencies of targets for which they were not known. this->InferDependencies(); @@ -198,6 +206,20 @@ cmComputeLinkDepends::Compute() } //---------------------------------------------------------------------------- +std::map::iterator +cmComputeLinkDepends::AllocateLinkEntry(std::string const& item) +{ + std::map::value_type + index_entry(item, static_cast(this->EntryList.size())); + std::map::iterator + lei = this->LinkEntryIndex.insert(index_entry).first; + this->EntryList.push_back(LinkEntry()); + this->InferredDependSets.push_back(0); + this->EntryConstraintGraph.push_back(EntryConstraintSet()); + return lei; +} + +//---------------------------------------------------------------------------- int cmComputeLinkDepends::AddLinkEntry(std::string const& item) { // Check if the item entry has already been added. @@ -209,14 +231,7 @@ int cmComputeLinkDepends::AddLinkEntry(std::string const& item) } // Allocate a spot for the item entry. - { - std::map::value_type - index_entry(item, static_cast(this->EntryList.size())); - lei = this->LinkEntryIndex.insert(index_entry).first; - this->EntryList.push_back(LinkEntry()); - this->InferredDependSets.push_back(0); - this->EntryConstraintGraph.push_back(EntryConstraintSet()); - } + lei = this->AllocateLinkEntry(item); // Initialize the item entry. int index = lei->second; @@ -263,18 +278,17 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) if(entry.Target) { // Follow the target dependencies. - if(entry.Target->IsImported()) - { - // Imported targets provide their own link information. - this->AddImportedLinkEntries(depender_index, entry.Target); - } - else if(cmTargetLinkInterface const* interface = - entry.Target->GetLinkInterface(this->Config)) + if(cmTargetLinkInterface const* interface = + entry.Target->GetLinkInterface(this->Config)) { // This target provides its own link interface information. - this->AddLinkEntries(depender_index, *interface); + this->AddLinkEntries(depender_index, interface->Libraries); + + // Handle dependent shared libraries. + this->QueueSharedDependencies(depender_index, interface->SharedDeps); } - else if(entry.Target->GetType() != cmTarget::EXECUTABLE) + else if(!entry.Target->IsImported() && + entry.Target->GetType() != cmTarget::EXECUTABLE) { // Use the target's link implementation as the interface. this->AddTargetLinkEntries(depender_index, @@ -289,13 +303,60 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) } //---------------------------------------------------------------------------- -void cmComputeLinkDepends::AddImportedLinkEntries(int depender_index, - cmTarget* target) +void +cmComputeLinkDepends +::QueueSharedDependencies(int depender_index, + std::vector const& deps) +{ + for(std::vector::const_iterator li = deps.begin(); + li != deps.end(); ++li) + { + SharedDepEntry qe; + qe.Item = *li; + qe.DependerIndex = depender_index; + this->SharedDepQueue.push(qe); + } +} + +//---------------------------------------------------------------------------- +void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) { - if(std::vector const* libs = - target->GetImportedLinkLibraries(this->Config)) + // Check if the target already has an entry. + std::map::iterator lei = + this->LinkEntryIndex.find(dep.Item); + if(lei == this->LinkEntryIndex.end()) { - this->AddLinkEntries(depender_index, *libs); + // Allocate a spot for the item entry. + lei = this->AllocateLinkEntry(dep.Item); + + // Initialize the item entry. + LinkEntry& entry = this->EntryList[lei->second]; + entry.Item = dep.Item; + entry.Target = this->Makefile->FindTargetToUse(dep.Item.c_str()); + + // This item was added specifically because it is a dependent + // shared library. It may get special treatment + // in cmComputeLinkInformation. + entry.IsSharedDep = true; + } + + // Get the link entry for this target. + int index = lei->second; + LinkEntry& entry = this->EntryList[index]; + + // This shared library dependency must be preceded by the item that + // listed it. + this->EntryConstraintGraph[index].insert(dep.DependerIndex); + + // Target items may have their own dependencies. + if(entry.Target) + { + if(cmTargetLinkInterface const* interface = + entry.Target->GetLinkInterface(this->Config)) + { + // We use just the shared dependencies, not the interface. + this->QueueSharedDependencies(index, interface->SharedDeps); + } } } diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 881d50f..1e422a6 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -41,8 +41,10 @@ public: { std::string Item; cmTarget* Target; - LinkEntry(): Item(), Target(0) {} - LinkEntry(LinkEntry const& r): Item(r.Item), Target(r.Target) {} + bool IsSharedDep; + LinkEntry(): Item(), Target(0), IsSharedDep(false) {} + LinkEntry(LinkEntry const& r): + Item(r.Item), Target(r.Target), IsSharedDep(r.IsSharedDep) {} }; typedef std::vector EntryVector; @@ -65,8 +67,9 @@ private: typedef cmTarget::LinkLibraryVectorType LinkLibraryVectorType; + std::map::iterator + AllocateLinkEntry(std::string const& item); int AddLinkEntry(std::string const& item); - void AddImportedLinkEntries(int depender_index, cmTarget* target); void AddVarLinkEntries(int depender_index, const char* value); void AddTargetLinkEntries(int depender_index, LinkLibraryVectorType const& libs); @@ -86,6 +89,19 @@ private: std::queue BFSQueue; void FollowLinkEntry(BFSEntry const&); + // Shared libraries that are included only because they are + // dependencies of other shared libraries, not because they are part + // of the interface. + struct SharedDepEntry + { + std::string Item; + int DependerIndex; + }; + std::queue SharedDepQueue; + void QueueSharedDependencies(int depender_index, + std::vector const& deps); + void HandleSharedDependency(SharedDepEntry const& dep); + // Dependency inferral for each link item. struct DependSet: public std::set {}; struct DependSetList: public std::vector {}; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index ec55c45..e7d83b0 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -234,6 +234,21 @@ cmComputeLinkInformation // Setup framework support. this->ComputeFrameworkInfo(); + // Choose a mode for dealing with shared library dependencies. + this->SharedDependencyMode = SharedDepModeNone; + if(const char* mode = + this->Makefile->GetDefinition("CMAKE_DEPENDENT_SHARED_LIBRARY_MODE")) + { + if(strcmp(mode, "LINK") == 0) + { + this->SharedDependencyMode = SharedDepModeLink; + } + else if(strcmp(mode, "DIR") == 0) + { + this->SharedDependencyMode = SharedDepModeDir; + } + } + // Get the implicit link directories for this platform. if(const char* implicitLinks = (this->Makefile->GetDefinition @@ -335,7 +350,7 @@ bool cmComputeLinkInformation::Compute() lei = linkEntries.begin(); lei != linkEntries.end(); ++lei) { - this->AddItem(lei->Item, lei->Target); + this->AddItem(lei->Item, lei->Target, lei->IsSharedDep); } // Restore the target link type so the correct system runtime @@ -358,8 +373,14 @@ bool cmComputeLinkInformation::Compute() //---------------------------------------------------------------------------- void cmComputeLinkInformation::AddItem(std::string const& item, - cmTarget* tgt) + cmTarget* tgt, bool isSharedDep) { + // If dropping shared library dependencies, ignore them. + if(isSharedDep && this->SharedDependencyMode == SharedDepModeNone) + { + return; + } + // Compute the proper name to use to link this library. const char* config = this->Config; bool impexe = (tgt && tgt->IsExecutableWithExports()); @@ -370,12 +391,6 @@ void cmComputeLinkInformation::AddItem(std::string const& item, return; } - // Keep track of shared libraries linked. - if(tgt && tgt->GetType() == cmTarget::SHARED_LIBRARY) - { - this->SharedLibrariesLinked.insert(tgt); - } - if(tgt && (tgt->GetType() == cmTarget::STATIC_LIBRARY || tgt->GetType() == cmTarget::SHARED_LIBRARY || tgt->GetType() == cmTarget::MODULE_LIBRARY || @@ -401,6 +416,14 @@ void cmComputeLinkInformation::AddItem(std::string const& item, (this->UseImportLibrary && (impexe || tgt->GetType() == cmTarget::SHARED_LIBRARY)); + // Handle shared dependencies in directory mode. + if(isSharedDep && this->SharedDependencyMode == SharedDepModeDir) + { + std::string dir = tgt->GetDirectory(config, implib); + this->SharedDependencyDirectories.push_back(dir); + return; + } + // Pass the full path to the target file. std::string lib = tgt->GetFullPath(config, implib); this->Depends.push_back(lib); @@ -411,6 +434,7 @@ void cmComputeLinkInformation::AddItem(std::string const& item, // link. std::string fw = tgt->GetDirectory(config, implib); this->AddFrameworkItem(fw); + this->SharedLibrariesLinked.insert(tgt); } else { @@ -705,6 +729,12 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item, this->Items.push_back(Item(this->LibLinkFileFlag, false)); } + // Keep track of shared library targets linked. + if(target->GetType() == cmTarget::SHARED_LIBRARY) + { + this->SharedLibrariesLinked.insert(target); + } + // Now add the full path to the library. this->Items.push_back(Item(item, true)); } @@ -991,6 +1021,18 @@ void cmComputeLinkInformation::ComputeLinkerSearchDirectories() { this->AddLinkerSearchDirectories(this->OldLinkDirs); } + + // Help the linker find dependent shared libraries. + if(this->SharedDependencyMode == SharedDepModeDir) + { + // TODO: These directories should probably be added to the runtime + // path ordering analysis. However they are a bit different. + // They should be placed both on the -L path and in the rpath. + // The link-with-runtime-path feature above should be replaced by + // this. + this->AddLinkerSearchDirectories(this->SharedDependencyDirectories); + } + } //---------------------------------------------------------------------------- diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 4ca3afa..2bbe05d 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -58,7 +58,7 @@ public: std::string GetChrpathTool(); std::set const& GetSharedLibrariesLinked(); private: - void AddItem(std::string const& item, cmTarget* tgt); + void AddItem(std::string const& item, cmTarget* tgt, bool isSharedDep); // Output information. ItemVector Items; @@ -78,6 +78,14 @@ private: const char* Config; const char* LinkLanguage; + // Modes for dealing with dependent shared libraries. + enum SharedDepMode + { + SharedDepModeNone, // Drop + SharedDepModeDir, // Use in runtime information + SharedDepModeLink // List file on link line + }; + // System info. bool UseImportLibrary; const char* LoaderFlag; @@ -88,6 +96,7 @@ private: std::string RuntimeSep; std::string RuntimeAlways; bool RuntimeUseChrpath; + SharedDepMode SharedDependencyMode; // Link type adjustment. void ComputeLinkTypeInfo(); @@ -134,6 +143,7 @@ private: void AddLinkerSearchDirectories(std::vector const& dirs); std::set DirectoriesEmmitted; std::set ImplicitLinkDirs; + std::vector SharedDependencyDirectories; // Linker search path compatibility mode. std::vector OldLinkDirs; diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index bcc9e8c..e7af505 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -1104,5 +1104,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_SHARED_MODULE_RUNTIME__FLAG_SEP", cmProperty::VARIABLE,0,0); + cm->DefineProperty("CMAKE_DEPENDENT_SHARED_LIBRARY_MODE", + cmProperty::VARIABLE,0,0); } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 5c4d0f2..7b23b18 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -139,7 +139,12 @@ cmExportFileGenerator target->GetLinkInterface(config)) { // This target provides a link interface, so use it. - this->SetImportLinkProperties(suffix, target, *interface, properties); + this->SetImportLinkProperty(suffix, target, + "IMPORTED_LINK_INTERFACE_LIBRARIES", + interface->Libraries, properties); + this->SetImportLinkProperty(suffix, target, + "IMPORTED_LINK_DEPENDENT_LIBRARIES", + interface->SharedDeps, properties); } else if(target->GetType() == cmTarget::STATIC_LIBRARY || target->GetType() == cmTarget::SHARED_LIBRARY) @@ -183,17 +188,26 @@ cmExportFileGenerator } // Store the entries in the property. - this->SetImportLinkProperties(suffix, target, actual_libs, properties); + this->SetImportLinkProperty(suffix, target, + "IMPORTED_LINK_INTERFACE_LIBRARIES", + actual_libs, properties); } //---------------------------------------------------------------------------- void cmExportFileGenerator -::SetImportLinkProperties(std::string const& suffix, - cmTarget* target, - std::vector const& libs, - ImportPropertyMap& properties) +::SetImportLinkProperty(std::string const& suffix, + cmTarget* target, + const char* propName, + std::vector const& libs, + ImportPropertyMap& properties) { + // Skip the property if there are no libraries. + if(libs.empty()) + { + return; + } + // Get the makefile in which to lookup target information. cmMakefile* mf = target->GetMakefile(); @@ -233,6 +247,9 @@ cmExportFileGenerator // known here. This is probably user-error. this->ComplainAboutMissingTarget(target, li->c_str()); } + // Assume the target will be exported by another command. + // Append it with the export namespace. + link_libs += this->Namespace; link_libs += *li; } } @@ -244,7 +261,7 @@ cmExportFileGenerator } // Store the property. - std::string prop = "IMPORTED_LINK_LIBRARIES"; + std::string prop = propName; prop += suffix; properties[prop] = link_libs; } diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 9412471..432bdb2 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -70,10 +70,10 @@ protected: void SetImportLinkProperties(const char* config, std::string const& suffix, cmTarget* target, ImportPropertyMap& properties); - void SetImportLinkProperties(std::string const& suffix, - cmTarget* target, - std::vector const& libs, - ImportPropertyMap& properties); + void SetImportLinkProperty(std::string const& suffix, + cmTarget* target, const char* propName, + std::vector const& libs, + ImportPropertyMap& properties); /** Each subclass knows how to generate its kind of export file. */ virtual bool GenerateMainFile(std::ostream& os) = 0; 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_", cmProperty::TARGET, + "Per-configuration version of IMPORTED_LINK_DEPENDENT_LIBRARIES.", + "This property is used when loading settings for the " + "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_", cmProperty::TARGET, - "Per-configuration version of IMPORTED_LINK_LIBRARIES property.", + ("IMPORTED_LINK_INTERFACE_LIBRARIES_", cmProperty::TARGET, + "Per-configuration version of IMPORTED_LINK_INTERFACE_LIBRARIES.", "This property is used when loading settings for the " "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 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 emitted; + for(std::vector::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; } //---------------------------------------------------------------------------- diff --git a/Source/cmTarget.h b/Source/cmTarget.h index bbcdafc..4d08af6 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -35,9 +35,13 @@ struct cmTargetLinkInformationMap: ~cmTargetLinkInformationMap(); }; -struct cmTargetLinkInterface: public std::vector +struct cmTargetLinkInterface { - typedef std::vector derived; + // Libraries listed in the interface. + std::vector Libraries; + + // Shared library dependencies needed for linking on some platforms. + std::vector SharedDeps; }; struct cmTargetLinkInterfaceMap: @@ -218,11 +222,6 @@ public: bool IsImported() const {return this->IsImportedTarget;} - /** Get link libraries for the given configuration of an imported - target. */ - std::vector const* - GetImportedLinkLibraries(const char* config); - /** Get the library interface dependencies. This is the set of libraries from which something that links to this target may also receive symbols. Returns 0 if the user has not specified @@ -487,7 +486,7 @@ private: std::string Location; std::string SOName; std::string ImportLibrary; - std::vector LinkLibraries; + cmTargetLinkInterface LinkInterface; }; typedef std::map ImportInfoMapType; ImportInfoMapType ImportInfoMap; diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 8f0b304..a9c6e51 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -32,18 +32,12 @@ set_property(TARGET testLib4 PROPERTY FRAMEWORK 1) add_executable(testExe3 testExe3.c) set_property(TARGET testExe3 PROPERTY MACOSX_BUNDLE 1) -# Install helper targets that are not part of the interface. -install( - TARGETS testExe2libImp testLib3Imp - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - ) - # Install and export from install tree. install( - TARGETS testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3 - testExe2lib + TARGETS + testExe2libImp testLib3Imp + testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3 + testExe2lib EXPORT exp RUNTIME DESTINATION bin LIBRARY DESTINATION lib @@ -55,6 +49,7 @@ install(EXPORT exp NAMESPACE exp_ DESTINATION lib/exp) # Export from build tree. export(TARGETS testExe1 testLib1 testLib2 testLib3 + testExe2libImp testLib3Imp NAMESPACE bld_ FILE ExportBuildTree.cmake ) -- cgit v0.12