Merge topic 'find_library-NAMES_PER_DIR'
66759ee
find_library: Optionally consider all names in each directory9cb68b1
find_library: Generalize helper macro in test caseb64dd76
find_library: Simplify framework search logic531c71b
find_library: Refactor internal name iteration
This commit is contained in:
commit
6df05b93b1
|
@ -15,6 +15,8 @@ cmFindBase::cmFindBase()
|
|||
{
|
||||
this->AlreadyInCache = false;
|
||||
this->AlreadyInCacheWithoutMetaInfo = false;
|
||||
this->NamesPerDir = false;
|
||||
this->NamesPerDirAllowed = false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -213,6 +215,19 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
|
|||
compatibility = false;
|
||||
newStyle = true;
|
||||
}
|
||||
else if (args[j] == "NAMES_PER_DIR")
|
||||
{
|
||||
doing = DoingNone;
|
||||
if(this->NamesPerDirAllowed)
|
||||
{
|
||||
this->NamesPerDir = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SetError("does not support NAMES_PER_DIR");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (args[j] == "NO_SYSTEM_PATH")
|
||||
{
|
||||
doing = DoingNone;
|
||||
|
|
|
@ -49,6 +49,8 @@ protected:
|
|||
cmStdString VariableDocumentation;
|
||||
cmStdString VariableName;
|
||||
std::vector<std::string> Names;
|
||||
bool NamesPerDir;
|
||||
bool NamesPerDirAllowed;
|
||||
|
||||
// CMAKE_*_PATH CMAKE_SYSTEM_*_PATH FRAMEWORK|LIBRARY|INCLUDE|PROGRAM
|
||||
cmStdString EnvironmentPath; // LIB,INCLUDE
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
cmFindLibraryCommand::cmFindLibraryCommand()
|
||||
{
|
||||
this->EnvironmentPath = "LIB";
|
||||
this->NamesPerDirAllowed = true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -44,6 +45,9 @@ void cmFindLibraryCommand::GenerateDocumentation()
|
|||
"SEARCH_XXX", "library");
|
||||
cmSystemTools::ReplaceString(this->GenericDocumentation,
|
||||
"XXX_SUBDIR", "lib");
|
||||
cmSystemTools::ReplaceString(this->GenericDocumentation,
|
||||
"NAMES name1 [name2 ...]",
|
||||
"NAMES name1 [name2 ...] [NAMES_PER_DIR]");
|
||||
cmSystemTools::ReplaceString(
|
||||
this->GenericDocumentation,
|
||||
"XXX_EXTRA_PREFIX_ENTRY",
|
||||
|
@ -52,6 +56,12 @@ void cmFindLibraryCommand::GenerateDocumentation()
|
|||
"CMAKE_FIND_ROOT_PATH_MODE_XXX",
|
||||
"CMAKE_FIND_ROOT_PATH_MODE_LIBRARY");
|
||||
this->GenericDocumentation +=
|
||||
"\n"
|
||||
"When more than one value is given to the NAMES option this command "
|
||||
"by default will consider one name at a time and search every directory "
|
||||
"for it. "
|
||||
"The NAMES_PER_DIR option tells this command to consider one directory "
|
||||
"at a time and search for all names in it."
|
||||
"\n"
|
||||
"If the library found is a framework, then VAR will be set to "
|
||||
"the full path to the framework <fullPath>/A.framework. "
|
||||
|
@ -220,18 +230,19 @@ struct cmFindLibraryHelper
|
|||
// Keep track of the best library file found so far.
|
||||
typedef std::vector<std::string>::size_type size_type;
|
||||
std::string BestPath;
|
||||
size_type BestPrefix;
|
||||
size_type BestSuffix;
|
||||
|
||||
// Support for OpenBSD shared library naming: lib<name>.so.<major>.<minor>
|
||||
bool OpenBSD;
|
||||
unsigned int BestMajor;
|
||||
unsigned int BestMinor;
|
||||
|
||||
// Current name under consideration.
|
||||
cmsys::RegularExpression NameRegex;
|
||||
bool TryRawName;
|
||||
std::string RawName;
|
||||
// Current names under consideration.
|
||||
struct Name
|
||||
{
|
||||
bool TryRaw;
|
||||
std::string Raw;
|
||||
cmsys::RegularExpression Regex;
|
||||
Name(): TryRaw(false) {}
|
||||
};
|
||||
std::vector<Name> Names;
|
||||
|
||||
// Current full path under consideration.
|
||||
std::string TestPath;
|
||||
|
@ -249,8 +260,9 @@ struct cmFindLibraryHelper
|
|||
suffix) - this->Suffixes.begin();
|
||||
}
|
||||
bool HasValidSuffix(std::string const& name);
|
||||
void SetName(std::string const& name);
|
||||
void AddName(std::string const& name);
|
||||
bool CheckDirectory(std::string const& path);
|
||||
bool CheckDirectoryForName(std::string const& path, Name& name);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -273,14 +285,6 @@ cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf):
|
|||
this->OpenBSD =
|
||||
this->Makefile->GetCMakeInstance()
|
||||
->GetPropertyAsBool("FIND_LIBRARY_USE_OPENBSD_VERSIONING");
|
||||
|
||||
this->TryRawName = false;
|
||||
|
||||
// No library file has yet been found.
|
||||
this->BestPrefix = this->Prefixes.size();
|
||||
this->BestSuffix = this->Suffixes.size();
|
||||
this->BestMajor = 0;
|
||||
this->BestMinor = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -353,11 +357,13 @@ bool cmFindLibraryHelper::HasValidSuffix(std::string const& name)
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmFindLibraryHelper::SetName(std::string const& name)
|
||||
void cmFindLibraryHelper::AddName(std::string const& name)
|
||||
{
|
||||
Name entry;
|
||||
|
||||
// Consider checking the raw name too.
|
||||
this->TryRawName = this->HasValidSuffix(name);
|
||||
this->RawName = name;
|
||||
entry.TryRaw = this->HasValidSuffix(name);
|
||||
entry.Raw = name;
|
||||
|
||||
// Build a regular expression to match library names.
|
||||
std::string regex = "^";
|
||||
|
@ -369,21 +375,37 @@ void cmFindLibraryHelper::SetName(std::string const& name)
|
|||
regex += "(\\.[0-9]+\\.[0-9]+)?";
|
||||
}
|
||||
regex += "$";
|
||||
this->NameRegex.compile(regex.c_str());
|
||||
entry.Regex.compile(regex.c_str());
|
||||
this->Names.push_back(entry);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
|
||||
{
|
||||
for(std::vector<Name>::iterator i = this->Names.begin();
|
||||
i != this->Names.end(); ++i)
|
||||
{
|
||||
if(this->CheckDirectoryForName(path, *i))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
|
||||
Name& name)
|
||||
{
|
||||
// If the original library name provided by the user matches one of
|
||||
// the suffixes, try it first. This allows users to search
|
||||
// specifically for a static library on some platforms (on MS tools
|
||||
// one cannot tell just from the library name whether it is a static
|
||||
// library or an import library).
|
||||
if(this->TryRawName)
|
||||
if(name.TryRaw)
|
||||
{
|
||||
this->TestPath = path;
|
||||
this->TestPath += this->RawName;
|
||||
this->TestPath += name.Raw;
|
||||
if(cmSystemTools::FileExists(this->TestPath.c_str(), true))
|
||||
{
|
||||
this->BestPath =
|
||||
|
@ -393,6 +415,12 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
|
|||
}
|
||||
}
|
||||
|
||||
// No library file has yet been found.
|
||||
size_type bestPrefix = this->Prefixes.size();
|
||||
size_type bestSuffix = this->Suffixes.size();
|
||||
unsigned int bestMajor = 0;
|
||||
unsigned int bestMinor = 0;
|
||||
|
||||
// Search for a file matching the library name regex.
|
||||
std::string dir = path;
|
||||
cmSystemTools::ConvertToUnixSlashes(dir);
|
||||
|
@ -406,7 +434,7 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
|
|||
#else
|
||||
std::string const& testName = origName;
|
||||
#endif
|
||||
if(this->NameRegex.find(testName))
|
||||
if(name.Regex.find(testName))
|
||||
{
|
||||
this->TestPath = path;
|
||||
this->TestPath += origName;
|
||||
|
@ -416,25 +444,25 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
|
|||
// best name found so far. Earlier prefixes are preferred,
|
||||
// followed by earlier suffixes. For OpenBSD, shared library
|
||||
// version extensions are compared.
|
||||
size_type prefix = this->GetPrefixIndex(this->NameRegex.match(1));
|
||||
size_type suffix = this->GetSuffixIndex(this->NameRegex.match(2));
|
||||
size_type prefix = this->GetPrefixIndex(name.Regex.match(1));
|
||||
size_type suffix = this->GetSuffixIndex(name.Regex.match(2));
|
||||
unsigned int major = 0;
|
||||
unsigned int minor = 0;
|
||||
if(this->OpenBSD)
|
||||
{
|
||||
sscanf(this->NameRegex.match(3).c_str(), ".%u.%u", &major, &minor);
|
||||
sscanf(name.Regex.match(3).c_str(), ".%u.%u", &major, &minor);
|
||||
}
|
||||
if(this->BestPath.empty() || prefix < this->BestPrefix ||
|
||||
(prefix == this->BestPrefix && suffix < this->BestSuffix) ||
|
||||
(prefix == this->BestPrefix && suffix == this->BestSuffix &&
|
||||
(major > this->BestMajor ||
|
||||
(major == this->BestMajor && minor > this->BestMinor))))
|
||||
if(this->BestPath.empty() || prefix < bestPrefix ||
|
||||
(prefix == bestPrefix && suffix < bestSuffix) ||
|
||||
(prefix == bestPrefix && suffix == bestSuffix &&
|
||||
(major > bestMajor ||
|
||||
(major == bestMajor && minor > bestMinor))))
|
||||
{
|
||||
this->BestPath = this->TestPath;
|
||||
this->BestPrefix = prefix;
|
||||
this->BestSuffix = suffix;
|
||||
this->BestMajor = major;
|
||||
this->BestMinor = minor;
|
||||
bestPrefix = prefix;
|
||||
bestSuffix = suffix;
|
||||
bestMajor = major;
|
||||
bestMinor = minor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -446,6 +474,42 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmFindLibraryCommand::FindNormalLibrary()
|
||||
{
|
||||
if(this->NamesPerDir)
|
||||
{
|
||||
return this->FindNormalLibraryNamesPerDir();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->FindNormalLibraryDirsPerName();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir()
|
||||
{
|
||||
// Search for all names in each directory.
|
||||
cmFindLibraryHelper helper(this->Makefile);
|
||||
for(std::vector<std::string>::const_iterator ni = this->Names.begin();
|
||||
ni != this->Names.end() ; ++ni)
|
||||
{
|
||||
helper.AddName(*ni);
|
||||
}
|
||||
// Search every directory.
|
||||
for(std::vector<std::string>::const_iterator
|
||||
p = this->SearchPaths.begin(); p != this->SearchPaths.end(); ++p)
|
||||
{
|
||||
if(helper.CheckDirectory(*p))
|
||||
{
|
||||
return helper.BestPath;
|
||||
}
|
||||
}
|
||||
// Couldn't find the library.
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmFindLibraryCommand::FindNormalLibraryDirsPerName()
|
||||
{
|
||||
// Search the entire path for each name.
|
||||
cmFindLibraryHelper helper(this->Makefile);
|
||||
|
@ -454,7 +518,7 @@ std::string cmFindLibraryCommand::FindNormalLibrary()
|
|||
{
|
||||
// Switch to searching for this name.
|
||||
std::string const& name = *ni;
|
||||
helper.SetName(name);
|
||||
helper.AddName(name);
|
||||
|
||||
// Search every directory.
|
||||
for(std::vector<std::string>::const_iterator
|
||||
|
@ -474,19 +538,60 @@ std::string cmFindLibraryCommand::FindNormalLibrary()
|
|||
//----------------------------------------------------------------------------
|
||||
std::string cmFindLibraryCommand::FindFrameworkLibrary()
|
||||
{
|
||||
// Search for a framework of each name in the entire search path.
|
||||
for(std::vector<std::string>::const_iterator ni = this->Names.begin();
|
||||
ni != this->Names.end() ; ++ni)
|
||||
if(this->NamesPerDir)
|
||||
{
|
||||
// Search the paths for a framework with this name.
|
||||
std::string fwName = *ni;
|
||||
fwName += ".framework";
|
||||
std::string fwPath = cmSystemTools::FindDirectory(fwName.c_str(),
|
||||
this->SearchPaths,
|
||||
true);
|
||||
if(!fwPath.empty())
|
||||
return this->FindFrameworkLibraryNamesPerDir();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->FindFrameworkLibraryDirsPerName();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir()
|
||||
{
|
||||
std::string fwPath;
|
||||
// Search for all names in each search path.
|
||||
for(std::vector<std::string>::const_iterator di = this->SearchPaths.begin();
|
||||
di != this->SearchPaths.end(); ++di)
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator ni = this->Names.begin();
|
||||
ni != this->Names.end() ; ++ni)
|
||||
{
|
||||
return fwPath;
|
||||
fwPath = *di;
|
||||
fwPath += *ni;
|
||||
fwPath += ".framework";
|
||||
if(cmSystemTools::FileIsDirectory(fwPath.c_str()))
|
||||
{
|
||||
return cmSystemTools::CollapseFullPath(fwPath.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No framework found.
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName()
|
||||
{
|
||||
std::string fwPath;
|
||||
// Search for each name in all search paths.
|
||||
for(std::vector<std::string>::const_iterator ni = this->Names.begin();
|
||||
ni != this->Names.end() ; ++ni)
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator
|
||||
di = this->SearchPaths.begin();
|
||||
di != this->SearchPaths.end(); ++di)
|
||||
{
|
||||
fwPath = *di;
|
||||
fwPath += *ni;
|
||||
fwPath += ".framework";
|
||||
if(cmSystemTools::FileIsDirectory(fwPath.c_str()))
|
||||
{
|
||||
return cmSystemTools::CollapseFullPath(fwPath.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,11 @@ protected:
|
|||
virtual void GenerateDocumentation();
|
||||
private:
|
||||
std::string FindNormalLibrary();
|
||||
std::string FindNormalLibraryNamesPerDir();
|
||||
std::string FindNormalLibraryDirsPerName();
|
||||
std::string FindFrameworkLibrary();
|
||||
std::string FindFrameworkLibraryNamesPerDir();
|
||||
std::string FindFrameworkLibraryDirsPerName();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3,34 +3,34 @@ project(FindLibraryTest NONE)
|
|||
|
||||
set(CMAKE_FIND_DEBUG_MODE 1)
|
||||
|
||||
macro(test_find_library expected)
|
||||
get_filename_component(dir ${expected} PATH)
|
||||
get_filename_component(name ${expected} NAME)
|
||||
string(REGEX REPLACE "lib/?64" "lib" dir "${dir}")
|
||||
macro(test_find_library desc expected)
|
||||
unset(LIB CACHE)
|
||||
find_library(LIB
|
||||
NAMES ${name}
|
||||
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
find_library(LIB ${ARGN} NO_DEFAULT_PATH)
|
||||
if(LIB)
|
||||
# Convert to relative path for comparison to expected location.
|
||||
file(RELATIVE_PATH REL_LIB "${CMAKE_CURRENT_SOURCE_DIR}" "${LIB}")
|
||||
|
||||
# Debugging output.
|
||||
if(CMAKE_FIND_DEBUG_MODE)
|
||||
message(STATUS "Library ${expected} searched as ${dir}, found as [${REL_LIB}].")
|
||||
endif()
|
||||
|
||||
# Check and report failure.
|
||||
if(NOT "${REL_LIB}" STREQUAL "${expected}")
|
||||
message(SEND_ERROR "Library ${l} should have been [${expected}] but was [${REL_LIB}]")
|
||||
message(SEND_ERROR "Library ${expected} found as [${REL_LIB}]${desc}")
|
||||
elseif(CMAKE_FIND_DEBUG_MODE)
|
||||
message(STATUS "Library ${expected} found as [${REL_LIB}]${desc}")
|
||||
endif()
|
||||
else()
|
||||
message(SEND_ERROR "Library ${expected} searched as ${dir}, NOT FOUND!")
|
||||
message(SEND_ERROR "Library ${expected} NOT FOUND${desc}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(test_find_library_subst expected)
|
||||
get_filename_component(dir ${expected} PATH)
|
||||
get_filename_component(name ${expected} NAME)
|
||||
string(REGEX REPLACE "lib/?64" "lib" dir "${dir}")
|
||||
test_find_library(", searched as ${dir}" "${expected}"
|
||||
NAMES ${name}
|
||||
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES "lib")
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
||||
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)
|
||||
|
@ -44,7 +44,7 @@ foreach(lib
|
|||
lib/libtest3.a
|
||||
lib/libtest3.a
|
||||
)
|
||||
test_find_library(${lib})
|
||||
test_find_library_subst(${lib})
|
||||
endforeach()
|
||||
|
||||
set(CMAKE_SIZEOF_VOID_P 8)
|
||||
|
@ -57,5 +57,18 @@ foreach(lib64
|
|||
lib64/A/libtest1.a
|
||||
lib64/libtest1.a
|
||||
)
|
||||
test_find_library(${lib64})
|
||||
test_find_library_subst(${lib64})
|
||||
endforeach()
|
||||
|
||||
test_find_library("" A/libtestA.a
|
||||
NAMES testA testB
|
||||
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B
|
||||
)
|
||||
test_find_library("" B/libtestB.a
|
||||
NAMES testB testA
|
||||
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B
|
||||
)
|
||||
test_find_library("" A/libtestA.a
|
||||
NAMES testB testA NAMES_PER_DIR
|
||||
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue