summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/Platform/Darwin.cmake6
-rw-r--r--Source/cmComputeLinkDepends.cxx105
-rw-r--r--Source/cmComputeLinkDepends.h22
-rw-r--r--Source/cmComputeLinkInformation.cxx58
-rw-r--r--Source/cmComputeLinkInformation.h12
-rw-r--r--Source/cmDocumentVariables.cxx2
-rw-r--r--Source/cmExportFileGenerator.cxx31
-rw-r--r--Source/cmExportFileGenerator.h8
-rw-r--r--Source/cmTarget.cxx158
-rw-r--r--Source/cmTarget.h15
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt15
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 <SOURCE> <OBJECT>")
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<cmStdString, int>::iterator
+cmComputeLinkDepends::AllocateLinkEntry(std::string const& item)
+{
+ std::map<cmStdString, int>::value_type
+ index_entry(item, static_cast<int>(this->EntryList.size()));
+ std::map<cmStdString, int>::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<cmStdString, int>::value_type
- index_entry(item, static_cast<int>(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<std::string> const& deps)
+{
+ for(std::vector<std::string>::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<std::string> const* libs =
- target->GetImportedLinkLibraries(this->Config))
+ // Check if the target already has an entry.
+ std::map<cmStdString, int>::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<LinkEntry> EntryVector;
@@ -65,8 +67,9 @@ private:
typedef cmTarget::LinkLibraryVectorType LinkLibraryVectorType;
+ std::map<cmStdString, int>::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<BFSEntry> 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<SharedDepEntry> SharedDepQueue;
+ void QueueSharedDependencies(int depender_index,
+ std::vector<std::string> const& deps);
+ void HandleSharedDependency(SharedDepEntry const& dep);
+
// Dependency inferral for each link item.
struct DependSet: public std::set<int> {};
struct DependSetList: public std::vector<DependSet> {};
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<cmTarget*> 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<std::string> const& dirs);
std::set<cmStdString> DirectoriesEmmitted;
std::set<cmStdString> ImplicitLinkDirs;
+ std::vector<std::string> SharedDependencyDirectories;
// Linker search path compatibility mode.
std::vector<std::string> 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_<LANG>_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<std::string> const& libs,
- ImportPropertyMap& properties)
+::SetImportLinkProperty(std::string const& suffix,
+ cmTarget* target,
+ const char* propName,
+ std::vector<std::string> 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<std::string> const& libs,
- ImportPropertyMap& properties);
+ void SetImportLinkProperty(std::string const& suffix,
+ cmTarget* target, const char* propName,
+ std::vector<std::string> 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_<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;
}
//----------------------------------------------------------------------------
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<std::string>
+struct cmTargetLinkInterface
{
- typedef std::vector<std::string> derived;
+ // Libraries listed in the interface.
+ std::vector<std::string> Libraries;
+
+ // Shared library dependencies needed for linking on some platforms.
+ std::vector<std::string> 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<std::string> 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<std::string> LinkLibraries;
+ cmTargetLinkInterface LinkInterface;
};
typedef std::map<cmStdString, ImportInfo> 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
)