summaryrefslogtreecommitdiffstats
path: root/Source/cmComputeLinkInformation.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-02-21 16:41:11 (GMT)
committerBrad King <brad.king@kitware.com>2008-02-21 16:41:11 (GMT)
commitfd37a6ec3d31e65eed2dfa88246e86b8d0ab66ab (patch)
treee40d02f354785ea8c43e90f266cded73bba5f340 /Source/cmComputeLinkInformation.cxx
parent9f2f456e7db1f84cc6d10a64a8e515ad69afbe65 (diff)
downloadCMake-fd37a6ec3d31e65eed2dfa88246e86b8d0ab66ab.zip
CMake-fd37a6ec3d31e65eed2dfa88246e86b8d0ab66ab.tar.gz
CMake-fd37a6ec3d31e65eed2dfa88246e86b8d0ab66ab.tar.bz2
ENH: Better linker search path computation.
- Use linker search path -L.. -lfoo for lib w/out soname when platform sets CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME - Rename cmOrderRuntimeDirectories to cmOrderDirectories and generalize it for both soname constraints and link library constraints - Use cmOrderDirectories to order -L directories based on all needed constraints - Avoid processing implicit link directories - For CMAKE_OLD_LINK_PATHS add constraints from libs producing them to produce old ordering
Diffstat (limited to 'Source/cmComputeLinkInformation.cxx')
-rw-r--r--Source/cmComputeLinkInformation.cxx224
1 files changed, 149 insertions, 75 deletions
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index dea08bc..1da512c 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -17,7 +17,7 @@
#include "cmComputeLinkInformation.h"
#include "cmComputeLinkDepends.h"
-#include "cmOrderRuntimeDirectories.h"
+#include "cmOrderDirectories.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
@@ -212,6 +212,30 @@ libraries that are also linked need to be listed in -L paths.
In our implementation we add all dependent libraries to the runtime
path computation. Then the auto-generated RPATH will find everything.
+------------------------------------------------------------------------------
+Notes about shared libraries with not builtin soname:
+
+Some UNIX shared libraries may be created with no builtin soname. On
+some platforms such libraries cannot be linked using the path to their
+location because the linker will copy the path into the field used to
+find the library at runtime.
+
+ Apple: ../libfoo.dylib ==> libfoo.dylib # ok, uses install_name
+ SGI: ../libfoo.so ==> libfoo.so # ok
+ AIX: ../libfoo.so ==> libfoo.so # ok
+ Linux: ../libfoo.so ==> ../libfoo.so # bad
+ HP-UX: ../libfoo.so ==> ../libfoo.so # bad
+ Sun: ../libfoo.so ==> ../libfoo.so # bad
+ FreeBSD: ../libfoo.so ==> ../libfoo.so # bad
+
+In order to link these libraries we need to use the old-style split
+into -L.. and -lfoo options. This should be fairly safe because most
+problems with -lfoo options were related to selecting shared libraries
+instead of static but in this case we want the shared lib. Link
+directory ordering needs to be done to make sure these shared
+libraries are found first. There should be very few restrictions
+because this need be done only for shared libraries without soname-s.
+
*/
//----------------------------------------------------------------------------
@@ -229,9 +253,12 @@ cmComputeLinkInformation
this->Config = config;
// Allocate internals.
+ this->OrderLinkerSearchPath =
+ new cmOrderDirectories(this->GlobalGenerator, target->GetName(),
+ "linker search path");
this->OrderRuntimeSearchPath =
- new cmOrderRuntimeDirectories(this->GlobalGenerator, target->GetName(),
- "runtime path");
+ new cmOrderDirectories(this->GlobalGenerator, target->GetName(),
+ "runtime search path");
this->OrderDependentRPath = 0;
// Get the language used for linking this target.
@@ -298,6 +325,18 @@ cmComputeLinkInformation
this->RPathLinkFlag = this->Makefile->GetSafeDefinition(rlVar.c_str());
}
+ // Check if we need to include the runtime search path at link time.
+ {
+ std::string var = "CMAKE_SHARED_LIBRARY_LINK_";
+ var += this->LinkLanguage;
+ var += "_WITH_RUNTIME_PATH";
+ this->LinkWithRuntimePath = this->Makefile->IsOn(var.c_str());
+ }
+
+ // Check the platform policy for missing soname case.
+ this->NoSONameUsesPath =
+ this->Makefile->IsOn("CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME");
+
// Get link type information.
this->ComputeLinkTypeInfo();
@@ -315,24 +354,16 @@ cmComputeLinkInformation
}
else if(this->Makefile->IsOn("CMAKE_LINK_DEPENDENT_LIBRARY_DIRS"))
{
- this->SharedDependencyMode = SharedDepModeDir;
+ this->SharedDependencyMode = SharedDepModeLibDir;
}
else if(!this->RPathLinkFlag.empty())
{
this->SharedDependencyMode = SharedDepModeDir;
- }
- if(this->SharedDependencyMode == SharedDepModeDir)
- {
this->OrderDependentRPath =
- new cmOrderRuntimeDirectories(this->GlobalGenerator, target->GetName(),
- "dependent library path");
+ new cmOrderDirectories(this->GlobalGenerator, target->GetName(),
+ "dependent library path");
}
- // Add the search path entries requested by the user to the runtime
- // path computation.
- this->OrderRuntimeSearchPath->AddDirectories(
- this->Target->GetLinkDirectories());
-
// Get the implicit link directories for this platform.
if(const char* implicitLinks =
(this->Makefile->GetDefinition
@@ -348,6 +379,21 @@ cmComputeLinkInformation
}
}
+ // Add the search path entries requested by the user to path ordering.
+ this->OrderLinkerSearchPath
+ ->AddUserDirectories(this->Target->GetLinkDirectories());
+ this->OrderRuntimeSearchPath
+ ->AddUserDirectories(this->Target->GetLinkDirectories());
+ this->OrderLinkerSearchPath
+ ->SetImplicitDirectories(this->ImplicitLinkDirs);
+ this->OrderRuntimeSearchPath
+ ->SetImplicitDirectories(this->ImplicitLinkDirs);
+ if(this->OrderDependentRPath)
+ {
+ this->OrderDependentRPath
+ ->SetImplicitDirectories(this->ImplicitLinkDirs);
+ }
+
// Initial state.
this->HaveUserFlagItem = false;
@@ -374,6 +420,7 @@ cmComputeLinkInformation
//----------------------------------------------------------------------------
cmComputeLinkInformation::~cmComputeLinkInformation()
{
+ delete this->OrderLinkerSearchPath;
delete this->OrderRuntimeSearchPath;
delete this->OrderDependentRPath;
}
@@ -388,7 +435,7 @@ cmComputeLinkInformation::GetItems()
//----------------------------------------------------------------------------
std::vector<std::string> const& cmComputeLinkInformation::GetDirectories()
{
- return this->Directories;
+ return this->OrderLinkerSearchPath->GetOrderedDirectories();
}
//----------------------------------------------------------------------------
@@ -396,7 +443,7 @@ std::string cmComputeLinkInformation::GetRPathLinkString()
{
// If there is no separate linker runtime search flag (-rpath-link)
// there is no reason to compute a string.
- if(!this->OrderDependentRPath || this->RPathLinkFlag.empty())
+ if(!this->OrderDependentRPath)
{
return "";
}
@@ -405,7 +452,7 @@ std::string cmComputeLinkInformation::GetRPathLinkString()
std::string rpath_link;
const char* sep = "";
std::vector<std::string> const& dirs =
- this->OrderDependentRPath->GetRuntimePath();
+ this->OrderDependentRPath->GetOrderedDirectories();
for(std::vector<std::string>::const_iterator di = dirs.begin();
di != dirs.end(); ++di)
{
@@ -487,8 +534,8 @@ bool cmComputeLinkInformation::Compute()
this->SetCurrentLinkType(this->StartLinkType);
}
- // Compute the linker search path.
- this->ComputeLinkerSearchDirectories();
+ // Finish setting up linker search directories.
+ this->FinishLinkerSearchDirectories();
return true;
}
@@ -637,19 +684,31 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
this->AddLibraryRuntimeInfo(lib);
}
- // Add the item to the separate dependent library search path if
- // this platform wants one.
- if(this->OrderDependentRPath)
+ // Check if we need to include the dependent shared library in other
+ // path ordering.
+ cmOrderDirectories* order = 0;
+ if(this->SharedDependencyMode == SharedDepModeLibDir &&
+ !this->LinkWithRuntimePath /* AddLibraryRuntimeInfo adds it */)
+ {
+ // Add the item to the linker search path.
+ order = this->OrderLinkerSearchPath;
+ }
+ else if(this->SharedDependencyMode == SharedDepModeDir)
+ {
+ // Add the item to the separate dependent library search path.
+ order = this->OrderDependentRPath;
+ }
+ if(order)
{
if(tgt)
{
std::string soName = tgt->GetSOName(this->Config);
const char* soname = soName.empty()? 0 : soName.c_str();
- this->OrderDependentRPath->AddLibrary(lib, soname);
+ order->AddRuntimeLibrary(lib, soname);
}
else
{
- this->OrderDependentRPath->AddLibrary(lib);
+ order->AddRuntimeLibrary(lib);
}
}
}
@@ -747,7 +806,8 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
// Create regex to remove any library extension.
std::string reg("(.*)");
reg += libext;
- this->RemoveLibraryExtension.compile(reg.c_str());
+ this->OrderLinkerSearchPath->SetLinkExtensionInfo(this->LinkExtensions,
+ reg);
// Create a regex to match a library name. Match index 1 will be
// the prefix if it exists and empty otherwise. Match index 2 will
@@ -913,18 +973,26 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item,
this->SetCurrentLinkType(LinkShared);
}
- // If this platform wants a flag before the full path, add it.
- if(!this->LibLinkFileFlag.empty())
- {
- 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);
}
+ // Handle case of an imported shared library with no soname.
+ if(this->NoSONameUsesPath &&
+ target->IsImportedSharedLibWithoutSOName(this->Config))
+ {
+ this->AddSharedLibNoSOName(item);
+ return;
+ }
+
+ // If this platform wants a flag before the full path, add it.
+ if(!this->LibLinkFileFlag.empty())
+ {
+ this->Items.push_back(Item(this->LibLinkFileFlag, false));
+ }
+
// Now add the full path to the library.
this->Items.push_back(Item(item, true));
}
@@ -938,6 +1006,12 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item)
return;
}
+ // Check for case of shared library with no builtin soname.
+ if(this->NoSONameUsesPath && this->CheckSharedLibNoSOName(item))
+ {
+ return;
+ }
+
// This is called to handle a link item that is a full path.
// If the target is not a static library make sure the link type is
// shared. This is because dynamic-mode linking can handle both
@@ -959,11 +1033,11 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item)
}
}
- // Record the directory in which the library appears because CMake
- // 2.4 in below added these as -L paths.
+ // For compatibility with CMake 2.4 include the item's directory in
+ // the linker search path.
if(this->OldLinkDirMode)
{
- this->OldLinkDirs.push_back(cmSystemTools::GetFilenamePath(item));
+ this->OldLinkDirItems.push_back(item);
}
// If this platform wants a flag before the full path, add it.
@@ -1184,55 +1258,47 @@ void cmComputeLinkInformation::AddFrameworkPath(std::string const& p)
}
//----------------------------------------------------------------------------
-void cmComputeLinkInformation::ComputeLinkerSearchDirectories()
+bool cmComputeLinkInformation::CheckSharedLibNoSOName(std::string const& item)
{
- // Some search paths should never be emitted.
- this->DirectoriesEmmitted = this->ImplicitLinkDirs;
- this->DirectoriesEmmitted.insert("");
-
- // Check if we need to include the runtime search path at link time.
- std::string var = "CMAKE_SHARED_LIBRARY_LINK_";
- var += this->LinkLanguage;
- var += "_WITH_RUNTIME_PATH";
- if(this->Makefile->IsOn(var.c_str()))
+ // This platform will use the path to a library as its soname if the
+ // library is given via path and was not built with an soname. If
+ // this is a shared library that might be the case. TODO: Check if
+ // the lib is a symlink to detect that it actually has an soname.
+ std::string file = cmSystemTools::GetFilenameName(item);
+ if(this->ExtractSharedLibraryName.find(file))
{
- // This platform requires the runtime library path for shared
- // libraries to be specified at link time as -L paths. It needs
- // them so that transitive dependencies of the libraries linked
- // may be found by the linker.
- this->AddLinkerSearchDirectories(this->GetRuntimeSearchPath());
+ this->AddSharedLibNoSOName(item);
+ return true;
}
+ return false;
+}
- // Get the search path entries requested by the user.
- this->AddLinkerSearchDirectories(this->Target->GetLinkDirectories());
-
- // Support broken projects if necessary.
- if(this->HaveUserFlagItem && this->OldLinkDirMode)
- {
- this->AddLinkerSearchDirectories(this->OldLinkDirs);
- }
+//----------------------------------------------------------------------------
+void cmComputeLinkInformation::AddSharedLibNoSOName(std::string const& item)
+{
+ // We have a full path to a shared library with no soname. We need
+ // to ask the linker to locate the item because otherwise the path
+ // we give to it will be embedded in the target linked. Then at
+ // runtime the dynamic linker will search for the library using the
+ // path instead of just the name.
+ std::string file = cmSystemTools::GetFilenameName(item);
+ this->AddUserItem(file);
- // If there is no separate linker runtime search flag (-rpath-link)
- // and we have a search path for dependent libraries add it to the
- // link directories.
- if(this->OrderDependentRPath && this->RPathLinkFlag.empty())
- {
- this->AddLinkerSearchDirectories
- (this->OrderDependentRPath->GetRuntimePath());
- }
+ // Make sure the link directory ordering will find the library.
+ this->OrderLinkerSearchPath->AddLinkLibrary(item);
}
//----------------------------------------------------------------------------
-void
-cmComputeLinkInformation
-::AddLinkerSearchDirectories(std::vector<std::string> const& dirs)
+void cmComputeLinkInformation::FinishLinkerSearchDirectories()
{
- for(std::vector<std::string>::const_iterator i = dirs.begin();
- i != dirs.end(); ++i)
+ // Support broken projects if necessary.
+ if(this->HaveUserFlagItem && this->OldLinkDirMode)
{
- if(this->DirectoriesEmmitted.insert(*i).second)
+ for(std::vector<std::string>::const_iterator
+ i = this->OldLinkDirItems.begin();
+ i != this->OldLinkDirItems.end(); ++i)
{
- this->Directories.push_back(*i);
+ this->OrderLinkerSearchPath->AddLinkLibrary(*i);
}
}
}
@@ -1241,7 +1307,7 @@ cmComputeLinkInformation
std::vector<std::string> const&
cmComputeLinkInformation::GetRuntimeSearchPath()
{
- return this->OrderRuntimeSearchPath->GetRuntimePath();
+ return this->OrderRuntimeSearchPath->GetOrderedDirectories();
}
//----------------------------------------------------------------------------
@@ -1261,7 +1327,11 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath,
const char* soname = soName.empty()? 0 : soName.c_str();
// Include this library in the runtime path ordering.
- this->OrderRuntimeSearchPath->AddLibrary(fullPath, soname);
+ this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath, soname);
+ if(this->LinkWithRuntimePath)
+ {
+ this->OrderLinkerSearchPath->AddRuntimeLibrary(fullPath, soname);
+ }
}
//----------------------------------------------------------------------------
@@ -1289,7 +1359,11 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath)
}
// Include this library in the runtime path ordering.
- this->OrderRuntimeSearchPath->AddLibrary(fullPath);
+ this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath);
+ if(this->LinkWithRuntimePath)
+ {
+ this->OrderLinkerSearchPath->AddRuntimeLibrary(fullPath);
+ }
}
//----------------------------------------------------------------------------