ENH: Improve linking to third-party shared libraries on soname platforms
- Reduce false positives in cases of unknown soname - Make library extension regular expressions match only at end of string - When linking to libraries in implicit dirs convert to the -l option only if the file name is one that can be found by the linker (ex. /usr/lib/libfoo.so.1 should be linked by full path) - Add cmSystemTools::GuessLibrarySOName to guess the soname of a library based on presence of a symlink - In cmComputeLinkInformation try to guess an soname before assuming that a third-party library is built without an soname - In cmOrderDirectories guess the soname of shared libraries in cases it is otherwise unknown
This commit is contained in:
parent
fd37a6ec3d
commit
782e9f7ffe
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
//#define CM_COMPUTE_LINK_INFO_DEBUG
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Notes about linking on various platforms:
|
Notes about linking on various platforms:
|
||||||
|
|
||||||
|
@ -905,7 +907,7 @@ cmComputeLinkInformation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish the list.
|
// Finish the list.
|
||||||
libext += ").*";
|
libext += ")$";
|
||||||
return libext;
|
return libext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1070,6 +1072,13 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only apply the policy below if the library file is one that can
|
||||||
|
// be found by the linker.
|
||||||
|
if(!this->ExtractAnyLibraryName.find(item))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Many system linkers support multiple architectures by
|
// Many system linkers support multiple architectures by
|
||||||
// automatically selecting the implicit linker search path for the
|
// automatically selecting the implicit linker search path for the
|
||||||
// current architecture. If the library appears in an implicit link
|
// current architecture. If the library appears in an implicit link
|
||||||
|
@ -1262,13 +1271,19 @@ bool cmComputeLinkInformation::CheckSharedLibNoSOName(std::string const& item)
|
||||||
{
|
{
|
||||||
// This platform will use the path to a library as its soname if the
|
// 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
|
// 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
|
// this is a shared library that might be the case.
|
||||||
// the lib is a symlink to detect that it actually has an soname.
|
|
||||||
std::string file = cmSystemTools::GetFilenameName(item);
|
std::string file = cmSystemTools::GetFilenameName(item);
|
||||||
if(this->ExtractSharedLibraryName.find(file))
|
if(this->ExtractSharedLibraryName.find(file))
|
||||||
{
|
{
|
||||||
this->AddSharedLibNoSOName(item);
|
// If we can guess the soname fairly reliably then assume the
|
||||||
return true;
|
// library has one. Otherwise assume the library has no builtin
|
||||||
|
// soname.
|
||||||
|
std::string soname;
|
||||||
|
if(!cmSystemTools::GuessLibrarySOName(item, soname))
|
||||||
|
{
|
||||||
|
this->AddSharedLibNoSOName(item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,15 @@ public:
|
||||||
const char* soname):
|
const char* soname):
|
||||||
cmOrderDirectoriesConstraint(od, file), SOName(soname? soname : "")
|
cmOrderDirectoriesConstraint(od, file), SOName(soname? soname : "")
|
||||||
{
|
{
|
||||||
|
if(this->SOName.empty())
|
||||||
|
{
|
||||||
|
// Try to guess the soname.
|
||||||
|
std::string soguess;
|
||||||
|
if(cmSystemTools::GuessLibrarySOName(file, soguess))
|
||||||
|
{
|
||||||
|
this->SOName = soguess;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Report(std::ostream& e)
|
virtual void Report(std::ostream& e)
|
||||||
|
@ -164,7 +173,6 @@ bool cmOrderDirectoriesConstraintSOName::FindConflict(std::string const& dir)
|
||||||
// Get the set of files that might conflict. Since we do not
|
// Get the set of files that might conflict. Since we do not
|
||||||
// know the soname just look at all files that start with the
|
// know the soname just look at all files that start with the
|
||||||
// file name. Usually the soname starts with the library name.
|
// file name. Usually the soname starts with the library name.
|
||||||
// TODO: Check if the library is a symlink and guess the soname.
|
|
||||||
std::string base = this->FileName;
|
std::string base = this->FileName;
|
||||||
std::set<cmStdString>::const_iterator first = files.lower_bound(base);
|
std::set<cmStdString>::const_iterator first = files.lower_bound(base);
|
||||||
++base[base.size()-1];
|
++base[base.size()-1];
|
||||||
|
|
|
@ -2150,3 +2150,34 @@ void cmSystemTools::MakefileColorEcho(int color, const char* message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
|
||||||
|
std::string& soname)
|
||||||
|
{
|
||||||
|
// If the file is not a symlink we have no guess for its soname.
|
||||||
|
if(!cmSystemTools::FileIsSymlink(fullPath.c_str()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!cmSystemTools::ReadSymlink(fullPath.c_str(), soname))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the symlink has a path component we have no guess for the soname.
|
||||||
|
if(!cmSystemTools::GetFilenamePath(soname).empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the symlink points at an extended version of the same name
|
||||||
|
// assume it is the soname.
|
||||||
|
std::string name = cmSystemTools::GetFilenameName(fullPath);
|
||||||
|
if(soname.length() > name.length() &&
|
||||||
|
soname.substr(0, name.length()) == name)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -377,6 +377,10 @@ public:
|
||||||
bool newLine, bool enabled);
|
bool newLine, bool enabled);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Try to guess the soname of a shared library. */
|
||||||
|
static bool GuessLibrarySOName(std::string const& fullPath,
|
||||||
|
std::string& soname);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool s_ForceUnixPaths;
|
static bool s_ForceUnixPaths;
|
||||||
static bool s_RunCommandHideConsole;
|
static bool s_RunCommandHideConsole;
|
||||||
|
|
Loading…
Reference in New Issue