Refactor and seperate search path construction for find commands

Prior to this commit, the set of search paths to traverse for find commands
was incrementally constructed.  This change allows each group of paths, i.e.
CMakeVariablePaths, UserHintsPaths, SystemEnvironmentPaths, etc. to be
constructed and manipulated independently, and then all combined togethor.
This commit is contained in:
Chuck Atkins 2014-10-09 13:52:54 -04:00
parent f476b41fd8
commit 32922840e7
7 changed files with 409 additions and 335 deletions

View File

@ -140,11 +140,11 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
} }
else if(doing == DoingPaths) else if(doing == DoingPaths)
{ {
this->AddUserPath(args[j], this->UserPaths); this->AddUserPath(args[j], this->UserGuessPaths);
} }
else if(doing == DoingHints) else if(doing == DoingHints)
{ {
this->AddUserPath(args[j], this->UserHints); this->AddUserPath(args[j], this->UserHintsPaths);
} }
else if(doing == DoingPathSuffixes) else if(doing == DoingPathSuffixes)
{ {
@ -186,16 +186,11 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
this->Names.push_back(shortArgs[0]); this->Names.push_back(shortArgs[0]);
for(unsigned int j = 1; j < shortArgs.size(); ++j) for(unsigned int j = 1; j < shortArgs.size(); ++j)
{ {
this->AddUserPath(shortArgs[j], this->UserPaths); this->AddUserPath(shortArgs[j], this->UserGuessPaths);
} }
} }
this->ExpandPaths(); this->ExpandPaths();
// Filter out ignored paths from the prefix list
std::set<std::string> ignored;
this->GetIgnoredPaths(ignored);
this->FilterPaths(this->SearchPaths, ignored);
this->ComputeFinalPaths(); this->ComputeFinalPaths();
return true; return true;
@ -203,20 +198,40 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
void cmFindBase::ExpandPaths() void cmFindBase::ExpandPaths()
{ {
this->AddCMakeVariablePath(); if(!this->NoDefaultPath)
this->AddCMakeEnvironmentPath(); {
this->AddUserHintsPath(); if(!this->NoCMakePath)
this->AddSystemEnvironmentPath(); {
this->AddCMakeSystemVariablePath(); this->FillCMakeVariablePath();
this->AddUserGuessPath(); this->AddPathSuffixes(this->CMakeVariablePaths);
}
if(!this->NoCMakeEnvironmentPath)
{
this->FillCMakeEnvironmentPath();
this->AddPathSuffixes(this->CMakeEnvironmentPaths);
}
if(!this->NoSystemEnvironmentPath)
{
this->FillSystemEnvironmentPath();
this->AddPathSuffixes(this->SystemEnvironmentPaths);
}
if(!this->NoCMakeSystemPath)
{
this->FillCMakeSystemVariablePath();
this->AddPathSuffixes(this->CMakeSystemVariablePaths);
}
}
// Add suffixes and clean up paths. this->FillUserHintsPath();
this->AddPathSuffixes(); this->AddPathSuffixes(this->UserHintsPaths);
this->FillUserGuessPath();
this->AddPathSuffixes(this->UserGuessPaths);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths, void cmFindBase::AddPrefixPaths(std::vector<std::string> const& inPaths,
PathType pathType) PathType pt,
std::vector<std::string>& outPaths)
{ {
// default for programs // default for programs
std::string subdir = "bin"; std::string subdir = "bin";
@ -234,8 +249,8 @@ void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths,
subdir = ""; // ? what to do for frameworks ? subdir = ""; // ? what to do for frameworks ?
} }
for(std::vector<std::string>::const_iterator it = in_paths.begin(); for(std::vector<std::string>::const_iterator it = inPaths.begin();
it != in_paths.end(); ++it) it != inPaths.end(); ++it)
{ {
std::string dir = *it; std::string dir = *it;
if(!subdir.empty() && !dir.empty() && dir[dir.size()-1] != '/') if(!subdir.empty() && !dir.empty() && dir[dir.size()-1] != '/')
@ -248,178 +263,173 @@ void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths,
this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE");
if(arch && *arch) if(arch && *arch)
{ {
this->AddPathInternal(dir+subdir+"/"+arch, pathType); this->AddPathInternal(this->MakeFullPath(dir+subdir+"/"+arch, pt),
outPaths);
} }
} }
std::string add = dir + subdir; std::string add = dir + subdir;
if(add != "/") if(add != "/")
{ {
this->AddPathInternal(add, pathType); this->AddPathInternal(this->MakeFullPath(add, pt), outPaths);
} }
if (subdir == "bin") if (subdir == "bin")
{ {
this->AddPathInternal(dir+"sbin", pathType); this->AddPathInternal(this->MakeFullPath(dir+"sbin", pt), outPaths);
} }
if(!subdir.empty() && *it != "/") if(!subdir.empty() && *it != "/")
{ {
this->AddPathInternal(*it, pathType); this->AddPathInternal(this->MakeFullPath(*it, pt), outPaths);
} }
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddCMakePrefixPath(const std::string& variable) void cmFindBase::AddCMakePrefixPath(const std::string& variable,
std::vector<std::string>& outPaths)
{ {
// Get a path from a CMake variable. // Get a path from a CMake variable.
if(const char* varPath = this->Makefile->GetDefinition(variable)) if(const char* varPath = this->Makefile->GetDefinition(variable))
{ {
std::vector<std::string> tmp; std::vector<std::string> tmp;
cmSystemTools::ExpandListArgument(varPath, tmp); cmSystemTools::ExpandListArgument(varPath, tmp);
this->AddPrefixPaths(tmp, CMakePath); this->AddPrefixPaths(tmp, CMakePath, outPaths);
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddEnvPrefixPath(const std::string& variable) void cmFindBase::AddEnvPrefixPath(const std::string& variable,
std::vector<std::string>& outPaths)
{ {
// Get a path from the environment. // Get a path from the environment.
std::vector<std::string> tmp; std::vector<std::string> tmp;
cmSystemTools::GetPath(tmp, variable.c_str()); cmSystemTools::GetPath(tmp, variable.c_str());
this->AddPrefixPaths(tmp, EnvPath); this->AddPrefixPaths(tmp, EnvPath, outPaths);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddCMakeEnvironmentPath() void cmFindBase::FillCMakeEnvironmentPath()
{ {
if(!this->NoCMakeEnvironmentPath && !this->NoDefaultPath)
{
// Add CMAKE_*_PATH environment variables // Add CMAKE_*_PATH environment variables
std::string var = "CMAKE_"; std::string var = "CMAKE_";
var += this->CMakePathName; var += this->CMakePathName;
var += "_PATH"; var += "_PATH";
this->AddEnvPrefixPath("CMAKE_PREFIX_PATH"); this->AddEnvPrefixPath("CMAKE_PREFIX_PATH", this->CMakeEnvironmentPaths);
this->AddEnvPath(var.c_str()); this->AddEnvPath(var.c_str(), this->CMakeEnvironmentPaths);
if(this->CMakePathName == "PROGRAM") if(this->CMakePathName == "PROGRAM")
{ {
this->AddEnvPath("CMAKE_APPBUNDLE_PATH"); this->AddEnvPath("CMAKE_APPBUNDLE_PATH", this->CMakeEnvironmentPaths);
} }
else else
{ {
this->AddEnvPath("CMAKE_FRAMEWORK_PATH"); this->AddEnvPath("CMAKE_FRAMEWORK_PATH", this->CMakeEnvironmentPaths);
}
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddCMakeVariablePath() void cmFindBase::FillCMakeVariablePath()
{ {
if(!this->NoCMakePath && !this->NoDefaultPath)
{
// Add CMake varibles of the same name as the previous environment // Add CMake varibles of the same name as the previous environment
// varibles CMAKE_*_PATH to be used most of the time with -D // varibles CMAKE_*_PATH to be used most of the time with -D
// command line options // command line options
std::string var = "CMAKE_"; std::string var = "CMAKE_";
var += this->CMakePathName; var += this->CMakePathName;
var += "_PATH"; var += "_PATH";
this->AddCMakePrefixPath("CMAKE_PREFIX_PATH"); this->AddCMakePrefixPath("CMAKE_PREFIX_PATH", this->CMakeVariablePaths);
this->AddCMakePath(var); this->AddCMakePath(var, this->CMakeVariablePaths);
if(this->CMakePathName == "PROGRAM") if(this->CMakePathName == "PROGRAM")
{ {
this->AddCMakePath("CMAKE_APPBUNDLE_PATH"); this->AddCMakePath("CMAKE_APPBUNDLE_PATH", this->CMakeVariablePaths);
} }
else else
{ {
this->AddCMakePath("CMAKE_FRAMEWORK_PATH"); this->AddCMakePath("CMAKE_FRAMEWORK_PATH", this->CMakeVariablePaths);
}
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddSystemEnvironmentPath() void cmFindBase::FillSystemEnvironmentPath()
{ {
if(!this->NoSystemEnvironmentPath && !this->NoDefaultPath)
{
// Add LIB or INCLUDE // Add LIB or INCLUDE
if(!this->EnvironmentPath.empty()) if(!this->EnvironmentPath.empty())
{ {
this->AddEnvPath(this->EnvironmentPath.c_str()); this->AddEnvPath(this->EnvironmentPath.c_str(),
this->SystemEnvironmentPaths);
} }
// Add PATH // Add PATH
this->AddEnvPath(0); this->AddEnvPath(0, this->SystemEnvironmentPaths);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddCMakeSystemVariablePath() void cmFindBase::FillCMakeSystemVariablePath()
{ {
if(!this->NoCMakeSystemPath && !this->NoDefaultPath)
{
std::string var = "CMAKE_SYSTEM_"; std::string var = "CMAKE_SYSTEM_";
var += this->CMakePathName; var += this->CMakePathName;
var += "_PATH"; var += "_PATH";
this->AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH"); this->AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH",
this->AddCMakePath(var); this->CMakeSystemVariablePaths);
this->AddCMakePath(var, this->CMakeSystemVariablePaths);
if(this->CMakePathName == "PROGRAM") if(this->CMakePathName == "PROGRAM")
{ {
this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH"); this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH",
this->CMakeSystemVariablePaths);
} }
else else
{ {
this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH",
} this->CMakeSystemVariablePaths);
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddUserHintsPath() void cmFindBase::FillUserHintsPath()
{ {
this->AddPathsInternal(this->UserHints, CMakePath); std::vector<std::string> inPaths;
inPaths.swap(this->UserHintsPaths);
this->AddPathsInternal(inPaths, CMakePath, this->UserHintsPaths);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddUserGuessPath() void cmFindBase::FillUserGuessPath()
{ {
this->AddPathsInternal(this->UserPaths, CMakePath); std::vector<std::string> inPaths;
inPaths.swap(this->UserGuessPaths);
this->AddPathsInternal(inPaths, CMakePath, this->UserGuessPaths);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddPathSuffixes() void cmFindBase::AddPathSuffixes(std::vector<std::string>& paths)
{ {
std::vector<std::string>& paths = this->SearchPaths; std::vector<std::string> inPaths;
std::vector<std::string> finalPath = paths; inPaths.swap(paths);
std::vector<std::string>::iterator i; paths.reserve(inPaths.size()*(this->SearchPathSuffixes.size()+1));
// clear the path
paths.clear(); for(std::vector<std::string>::iterator ip = inPaths.begin();
// convert all paths to unix slashes and add search path suffixes ip != inPaths.end(); ++ip)
// if there are any
for(i = finalPath.begin();
i != finalPath.end(); ++i)
{
cmSystemTools::ConvertToUnixSlashes(*i);
// copy each finalPath combined with SearchPathSuffixes
// to the SearchPaths ivar
for(std::vector<std::string>::iterator j =
this->SearchPathSuffixes.begin();
j != this->SearchPathSuffixes.end(); ++j)
{ {
cmSystemTools::ConvertToUnixSlashes(*ip);
// if *i is only / then do not add a // // if *i is only / then do not add a //
// this will get incorrectly considered a network // this will get incorrectly considered a network
// path on windows and cause huge delays. // path on windows and cause huge delays.
std::string p = *i; std::string p = *ip;
if(p.size() && p[p.size()-1] != '/') if(!p.empty() && *p.rbegin() != '/')
{ {
p += std::string("/"); p += "/";
} }
p += *j;
for(std::vector<std::string>::iterator sps =
this->SearchPathSuffixes.begin();
sps != this->SearchPathSuffixes.end(); ++sps)
{
// add to all paths because the search path may be modified // add to all paths because the search path may be modified
// later with lib being replaced for lib64 which may exist // later with lib being replaced for lib64 which may exist
paths.push_back(p); paths.push_back(p+*sps);
} }
// now put the path without the path suffixes in the SearchPaths // now put the path without the path suffixes in the SearchPaths
paths.push_back(*i); paths.push_back(*ip);
} }
} }
@ -457,9 +467,10 @@ void cmFindBase::PrintFindStuff()
} }
std::cerr << "\n"; std::cerr << "\n";
std::cerr << "SearchPaths\n"; std::cerr << "SearchPaths\n";
for(unsigned int i =0; i < this->SearchPaths.size(); ++i) for(std::vector<std::string>::const_iterator i = this->SearchPaths.begin();
i != this->SearchPaths.end(); ++i)
{ {
std::cerr << "[" << this->SearchPaths[i] << "]\n"; std::cerr << "[" << *i << "]\n";
} }
} }

View File

@ -34,7 +34,7 @@ public:
protected: protected:
void PrintFindStuff(); void PrintFindStuff();
void ExpandPaths(); void ExpandPaths();
void AddPathSuffixes(); void AddPathSuffixes(std::vector<std::string>& paths);
// see if the VariableName is already set in the cache, // see if the VariableName is already set in the cache,
// also copy the documentation from the cache to VariableDocumentation // also copy the documentation from the cache to VariableDocumentation
@ -55,18 +55,20 @@ protected:
bool AlreadyInCacheWithoutMetaInfo; bool AlreadyInCacheWithoutMetaInfo;
private: private:
// Add pieces of the search. // Add pieces of the search.
void AddCMakeEnvironmentPath(); void FillCMakeVariablePath();
void AddCMakeVariablePath(); void FillCMakeEnvironmentPath();
void AddSystemEnvironmentPath(); void FillUserHintsPath();
void AddCMakeSystemVariablePath(); void FillSystemEnvironmentPath();
void AddUserHintsPath(); void FillCMakeSystemVariablePath();
void AddUserGuessPath(); void FillUserGuessPath();
// Helpers. // Helpers.
void AddCMakePrefixPath(const std::string& variable); void AddCMakePrefixPath(const std::string& variable,
void AddEnvPrefixPath(const std::string& variable); std::vector<std::string>& outPaths);
void AddPrefixPaths(std::vector<std::string> const& in_paths, void AddEnvPrefixPath(const std::string& variable,
PathType pathType); std::vector<std::string>& outPaths);
void AddPrefixPaths(std::vector<std::string> const& inPaths,
PathType pathType, std::vector<std::string>& outPaths);
}; };

View File

@ -10,6 +10,8 @@
See the License for more information. See the License for more information.
============================================================================*/ ============================================================================*/
#include "cmFindCommon.h" #include "cmFindCommon.h"
#include <functional>
#include <algorithm>
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmFindCommon::cmFindCommon() cmFindCommon::cmFindCommon()
@ -41,6 +43,22 @@ cmFindCommon::~cmFindCommon()
{ {
} }
//----------------------------------------------------------------------------
std::string cmFindCommon::MakeFullPath(const std::string& path,
PathType pathType)
{
// Select the base path with which to interpret relative paths.
if(pathType == CMakePath)
{
return cmSystemTools::CollapseFullPath(
path, this->Makefile->GetCurrentDirectory());
}
else
{
return cmSystemTools::CollapseFullPath(path, 0);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindCommon::SelectDefaultRootPathMode() void cmFindCommon::SelectDefaultRootPathMode()
{ {
@ -212,24 +230,20 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindCommon::FilterPaths(std::vector<std::string>& paths, void cmFindCommon::FilterPaths(const std::vector<std::string>& inPaths,
const std::set<std::string>& ignore) const std::set<std::string>& ignore,
std::vector<std::string>& outPaths)
{ {
// Now filter out anything that's in the ignore set. for(std::vector<std::string>::const_iterator i = inPaths.begin();
std::vector<std::string> unfiltered; i != inPaths.end(); ++i)
unfiltered.swap(paths);
for(std::vector<std::string>::iterator pi = unfiltered.begin();
pi != unfiltered.end(); ++pi)
{ {
if (ignore.count(*pi) == 0) if(ignore.count(*i) == 0)
{ {
paths.push_back(*pi); outPaths.push_back(*i);
} }
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore) void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore)
{ {
@ -345,8 +359,8 @@ void cmFindCommon::AddPathSuffix(std::string const& arg)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindCommon::AddUserPath(std::string const& p, void cmFindCommon::AddUserPath(std::string const& inPath,
std::vector<std::string>& paths) std::vector<std::string>& outPaths)
{ {
// We should view the registry as the target application would view // We should view the registry as the target application would view
// it. // it.
@ -359,22 +373,23 @@ void cmFindCommon::AddUserPath(std::string const& p,
} }
// Expand using the view of the target application. // Expand using the view of the target application.
std::string expanded = p; std::string expanded = inPath;
cmSystemTools::ExpandRegistryValues(expanded, view); cmSystemTools::ExpandRegistryValues(expanded, view);
cmSystemTools::GlobDirs(expanded, paths); cmSystemTools::GlobDirs(expanded, outPaths);
// Executables can be either 32-bit or 64-bit, so expand using the // Executables can be either 32-bit or 64-bit, so expand using the
// alternative view. // alternative view.
if(expanded != p && this->CMakePathName == "PROGRAM") if(expanded != inPath && this->CMakePathName == "PROGRAM")
{ {
expanded = p; expanded = inPath;
cmSystemTools::ExpandRegistryValues(expanded, other_view); cmSystemTools::ExpandRegistryValues(expanded, other_view);
cmSystemTools::GlobDirs(expanded, paths); cmSystemTools::GlobDirs(expanded, outPaths);
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindCommon::AddCMakePath(const std::string& variable) void cmFindCommon::AddCMakePath(const std::string& variable,
std::vector<std::string>& outPaths)
{ {
// Get a path from a CMake variable. // Get a path from a CMake variable.
if(const char* varPath = this->Makefile->GetDefinition(variable)) if(const char* varPath = this->Makefile->GetDefinition(variable))
@ -384,77 +399,83 @@ void cmFindCommon::AddCMakePath(const std::string& variable)
// Relative paths are interpreted with respect to the current // Relative paths are interpreted with respect to the current
// source directory. // source directory.
this->AddPathsInternal(tmp, CMakePath); this->AddPathsInternal(tmp, CMakePath, outPaths);
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindCommon::AddEnvPath(const char* variable) void cmFindCommon::AddEnvPath(const char* variable,
std::vector<std::string>& outPaths)
{ {
// Get a path from the environment. // Get a path from the environment.
std::vector<std::string> tmp; std::vector<std::string> tmp;
cmSystemTools::GetPath(tmp, variable); cmSystemTools::GetPath(tmp, variable);
// Relative paths are interpreted with respect to the current // Relative paths are interpreted with respect to the current
// working directory. // working directory.
this->AddPathsInternal(tmp, EnvPath); this->AddPathsInternal(tmp, EnvPath, outPaths);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindCommon::AddPathsInternal(std::vector<std::string> const& in_paths, void cmFindCommon::AddPathsInternal(std::vector<std::string> const& inPaths,
PathType pathType) PathType pathType,
std::vector<std::string>& outPaths)
{ {
for(std::vector<std::string>::const_iterator i = in_paths.begin(); for(std::vector<std::string>::const_iterator i = inPaths.begin();
i != in_paths.end(); ++i) i != inPaths.end(); ++i)
{ {
this->AddPathInternal(*i, pathType); this->AddPathInternal(this->MakeFullPath(*i, pathType), outPaths);
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindCommon::AddPathInternal(std::string const& in_path, void cmFindCommon::AddPathInternal(std::string const& inPath,
PathType pathType) std::vector<std::string>& outPaths)
{ {
if(in_path.empty()) if(inPath.empty())
{ {
return; return;
} }
// Select the base path with which to interpret relative paths.
const char* relbase = 0;
if(pathType == CMakePath)
{
relbase = this->Makefile->GetCurrentDirectory();
}
// Convert to clean full path.
std::string fullPath =
cmSystemTools::CollapseFullPath(in_path, relbase);
// Insert the path if has not already been emitted. // Insert the path if has not already been emitted.
if(this->SearchPathsEmitted.insert(fullPath).second) if(this->SearchPathsEmitted.insert(inPath).second)
{ {
this->SearchPaths.push_back(fullPath); outPaths.push_back(inPath);
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void AddTrailingSlash(std::string& s)
{
if(!s.empty() && *s.rbegin() != '/')
{
s += '/';
}
}
void cmFindCommon::ComputeFinalPaths() void cmFindCommon::ComputeFinalPaths()
{ {
std::vector<std::string>& paths = this->SearchPaths; // Filter out ignored paths from the prefix list
std::set<std::string> ignored;
this->GetIgnoredPaths(ignored);
// Combine the seperate path types, filtering out ignores
this->SearchPaths.clear();
this->FilterPaths(this->CMakeVariablePaths, ignored, this->SearchPaths);
this->FilterPaths(this->CMakeEnvironmentPaths, ignored, this->SearchPaths);
this->FilterPaths(this->UserHintsPaths, ignored, this->SearchPaths);
this->FilterPaths(this->SystemEnvironmentPaths, ignored, this->SearchPaths);
this->FilterPaths(this->UserRegistryPaths, ignored, this->SearchPaths);
this->FilterPaths(this->BuildPaths, ignored, this->SearchPaths);
this->FilterPaths(this->CMakeSystemVariablePaths, ignored,
this->SearchPaths);
this->FilterPaths(this->SystemRegistryPaths, ignored, this->SearchPaths);
this->FilterPaths(this->UserGuessPaths, ignored, this->SearchPaths);
// Expand list of paths inside all search roots. // Expand list of paths inside all search roots.
this->RerootPaths(paths); this->RerootPaths(this->SearchPaths);
// Add a trailing slash to all paths to aid the search process. // Add a trailing slash to all paths to aid the search process.
for(std::vector<std::string>::iterator i = paths.begin(); std::for_each(this->SearchPaths.begin(), this->SearchPaths.end(),
i != paths.end(); ++i) &AddTrailingSlash);
{
std::string& p = *i;
if(!p.empty() && p[p.size()-1] != '/')
{
p += "/";
}
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -36,6 +36,9 @@ protected:
enum PathType { FullPath, CMakePath, EnvPath }; enum PathType { FullPath, CMakePath, EnvPath };
/** Generate a full path based on the particular path type */
std::string MakeFullPath(const std::string& path, PathType pathType);
/** Place a set of search paths under the search roots. */ /** Place a set of search paths under the search roots. */
void RerootPaths(std::vector<std::string>& paths); void RerootPaths(std::vector<std::string>& paths);
@ -44,8 +47,9 @@ protected:
void GetIgnoredPaths(std::set<std::string>& ignore); void GetIgnoredPaths(std::set<std::string>& ignore);
/** Remove paths in the ignore set from the supplied vector. */ /** Remove paths in the ignore set from the supplied vector. */
void FilterPaths(std::vector<std::string>& paths, void FilterPaths(const std::vector<std::string>& inPaths,
const std::set<std::string>& ignore); const std::set<std::string>& ignore,
std::vector<std::string>& outPaths);
/** Compute final search path list (reroot + trailing slash). */ /** Compute final search path list (reroot + trailing slash). */
void ComputeFinalPaths(); void ComputeFinalPaths();
@ -62,12 +66,14 @@ protected:
bool CheckCommonArgument(std::string const& arg); bool CheckCommonArgument(std::string const& arg);
void AddPathSuffix(std::string const& arg); void AddPathSuffix(std::string const& arg);
void AddUserPath(std::string const& p, void AddUserPath(std::string const& p,
std::vector<std::string>& paths); std::vector<std::string>& outPaths);
void AddCMakePath(const std::string& variable); void AddCMakePath(const std::string& variable,
void AddEnvPath(const char* variable); std::vector<std::string>& outPaths);
void AddPathsInternal(std::vector<std::string> const& in_paths, void AddEnvPath(const char* variable, std::vector<std::string>& outPaths);
PathType pathType); void AddPathsInternal(std::vector<std::string> const& inPaths,
void AddPathInternal(std::string const& in_path, PathType pathType); PathType pathType, std::vector<std::string>& outPaths);
void AddPathInternal(std::string const& inPath,
std::vector<std::string>& outPaths);
void SetMakefile(cmMakefile* makefile); void SetMakefile(cmMakefile* makefile);
@ -78,8 +84,16 @@ protected:
bool NoCMakeSystemPath; bool NoCMakeSystemPath;
std::vector<std::string> SearchPathSuffixes; std::vector<std::string> SearchPathSuffixes;
std::vector<std::string> UserPaths; std::vector<std::string> CMakeVariablePaths;
std::vector<std::string> UserHints; std::vector<std::string> CMakeEnvironmentPaths;
std::vector<std::string> UserHintsPaths;
std::vector<std::string> SystemEnvironmentPaths;
std::vector<std::string> UserRegistryPaths;
std::vector<std::string> BuildPaths;
std::vector<std::string> CMakeSystemVariablePaths;
std::vector<std::string> SystemRegistryPaths;
std::vector<std::string> UserGuessPaths;
std::vector<std::string> SearchPaths; std::vector<std::string> SearchPaths;
std::set<std::string> SearchPathsEmitted; std::set<std::string> SearchPathsEmitted;

View File

@ -88,7 +88,7 @@ void cmFindLibraryCommand::AddArchitecturePaths(const char* suffix)
{ {
std::vector<std::string> original; std::vector<std::string> original;
original.swap(this->SearchPaths); original.swap(this->SearchPaths);
for(std::vector<std::string>::iterator i = original.begin(); for(std::vector<std::string>::const_iterator i = original.begin();
i != original.end(); ++i) i != original.end(); ++i)
{ {
this->AddArchitecturePath(*i, 0, suffix); this->AddArchitecturePath(*i, 0, suffix);

View File

@ -248,11 +248,11 @@ bool cmFindPackageCommand
} }
else if(doing == DoingPaths) else if(doing == DoingPaths)
{ {
this->AddUserPath(args[i], this->UserPaths); this->AddUserPath(args[i], this->UserGuessPaths);
} }
else if(doing == DoingHints) else if(doing == DoingHints)
{ {
this->AddUserPath(args[i], this->UserHints); this->AddUserPath(args[i], this->UserHintsPaths);
} }
else if(doing == DoingPathSuffixes) else if(doing == DoingPathSuffixes)
{ {
@ -1111,54 +1111,72 @@ void cmFindPackageCommand::AppendSuccessInformation()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::ComputePrefixes() void cmFindPackageCommand::ComputePrefixes()
{ {
this->AddPrefixesCMakeVariable(); if(!this->NoDefaultPath)
this->AddPrefixesCMakeEnvironment(); {
this->AddPrefixesUserHints(); if(!this->NoCMakePath)
this->AddPrefixesSystemEnvironment(); {
this->AddPrefixesUserRegistry(); this->FillPrefixesCMakeVariable();
this->AddPrefixesBuilds(); }
this->AddPrefixesCMakeSystemVariable(); if(!this->NoCMakeEnvironmentPath)
this->AddPrefixesSystemRegistry(); {
this->AddPrefixesUserGuess(); this->FillPrefixesCMakeEnvironment();
}
if(!this->NoSystemEnvironmentPath)
{
this->FillPrefixesSystemEnvironment();
}
if(!this->NoUserRegistry)
{
this->FillPrefixesUserRegistry();
}
if(!this->NoBuilds)
{
this->FillPrefixesBuilds();
}
if(!this->NoCMakeSystemPath)
{
this->FillPrefixesCMakeSystemVariable();
}
if(!this->NoSystemRegistry)
{
this->FillPrefixesSystemRegistry();
}
}
this->FillPrefixesUserHints();
this->FillPrefixesUserGuess();
this->ComputeFinalPaths(); this->ComputeFinalPaths();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesCMakeEnvironment() void cmFindPackageCommand::FillPrefixesCMakeEnvironment()
{ {
if(!this->NoCMakeEnvironmentPath && !this->NoDefaultPath)
{
// Check the environment variable with the same name as the cache // Check the environment variable with the same name as the cache
// entry. // entry.
std::string env; std::string env;
if(cmSystemTools::GetEnv(this->Variable.c_str(), env) && env.length() > 0) if(cmSystemTools::GetEnv(this->Variable.c_str(), env) && env.length() > 0)
{ {
cmSystemTools::ConvertToUnixSlashes(env); cmSystemTools::ConvertToUnixSlashes(env);
this->AddPathInternal(env, EnvPath); this->AddPathInternal(MakeFullPath(env, EnvPath),
this->CMakeEnvironmentPaths);
} }
this->AddEnvPath("CMAKE_PREFIX_PATH"); this->AddEnvPath("CMAKE_PREFIX_PATH", this->CMakeEnvironmentPaths);
this->AddEnvPath("CMAKE_FRAMEWORK_PATH"); this->AddEnvPath("CMAKE_FRAMEWORK_PATH", this->CMakeEnvironmentPaths);
this->AddEnvPath("CMAKE_APPBUNDLE_PATH"); this->AddEnvPath("CMAKE_APPBUNDLE_PATH", this->CMakeEnvironmentPaths);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesCMakeVariable() void cmFindPackageCommand::FillPrefixesCMakeVariable()
{ {
if(!this->NoCMakePath && !this->NoDefaultPath) this->AddCMakePath("CMAKE_PREFIX_PATH", this->CMakeVariablePaths);
{ this->AddCMakePath("CMAKE_FRAMEWORK_PATH", this->CMakeVariablePaths);
this->AddCMakePath("CMAKE_PREFIX_PATH"); this->AddCMakePath("CMAKE_APPBUNDLE_PATH", this->CMakeVariablePaths);
this->AddCMakePath("CMAKE_FRAMEWORK_PATH");
this->AddCMakePath("CMAKE_APPBUNDLE_PATH");
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesSystemEnvironment() void cmFindPackageCommand::FillPrefixesSystemEnvironment()
{ {
if(!this->NoSystemEnvironmentPath && !this->NoDefaultPath)
{
// Use the system search path to generate prefixes. // Use the system search path to generate prefixes.
// Relative paths are interpreted with respect to the current // Relative paths are interpreted with respect to the current
// working directory. // working directory.
@ -1167,30 +1185,25 @@ void cmFindPackageCommand::AddPrefixesSystemEnvironment()
for(std::vector<std::string>::iterator i = tmp.begin(); for(std::vector<std::string>::iterator i = tmp.begin();
i != tmp.end(); ++i) i != tmp.end(); ++i)
{ {
std::string const& d = *i;
// If the path is a PREFIX/bin case then add its parent instead. // If the path is a PREFIX/bin case then add its parent instead.
if((cmHasLiteralSuffix(d, "/bin")) || if((cmHasLiteralSuffix(*i, "/bin")) ||
(cmHasLiteralSuffix(d, "/sbin"))) (cmHasLiteralSuffix(*i, "/sbin")))
{ {
this->AddPathInternal(cmSystemTools::GetFilenamePath(d), EnvPath); this->AddPathInternal(MakeFullPath(cmSystemTools::GetFilenamePath(*i),
EnvPath),
this->SystemEnvironmentPaths);
} }
else else
{ {
this->AddPathInternal(d, EnvPath); this->AddPathInternal(MakeFullPath(*i, EnvPath),
} this->SystemEnvironmentPaths);
} }
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesUserRegistry() void cmFindPackageCommand::FillPrefixesUserRegistry()
{ {
if(this->NoUserRegistry || this->NoDefaultPath)
{
return;
}
#if defined(_WIN32) && !defined(__CYGWIN__) #if defined(_WIN32) && !defined(__CYGWIN__)
this->LoadPackageRegistryWinUser(); this->LoadPackageRegistryWinUser();
#elif defined(__HAIKU__) #elif defined(__HAIKU__)
@ -1201,7 +1214,7 @@ void cmFindPackageCommand::AddPrefixesUserRegistry()
std::string fname = dir; std::string fname = dir;
fname += "/cmake/packages/"; fname += "/cmake/packages/";
fname += Name; fname += Name;
this->LoadPackageRegistryDir(fname); this->LoadPackageRegistryDir(fname, this->UserRegistryPaths);
} }
#else #else
if(const char* home = cmSystemTools::GetEnv("HOME")) if(const char* home = cmSystemTools::GetEnv("HOME"))
@ -1209,13 +1222,13 @@ void cmFindPackageCommand::AddPrefixesUserRegistry()
std::string dir = home; std::string dir = home;
dir += "/.cmake/packages/"; dir += "/.cmake/packages/";
dir += this->Name; dir += this->Name;
this->LoadPackageRegistryDir(dir); this->LoadPackageRegistryDir(dir, this->UserRegistryPaths);
} }
#endif #endif
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesSystemRegistry() void cmFindPackageCommand::FillPrefixesSystemRegistry()
{ {
if(this->NoSystemRegistry || this->NoDefaultPath) if(this->NoSystemRegistry || this->NoDefaultPath)
{ {
@ -1241,7 +1254,7 @@ void cmFindPackageCommand::AddPrefixesSystemRegistry()
void cmFindPackageCommand::LoadPackageRegistryWinUser() void cmFindPackageCommand::LoadPackageRegistryWinUser()
{ {
// HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views. // HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views.
this->LoadPackageRegistryWin(true, 0); this->LoadPackageRegistryWin(true, 0, this->UserRegistryPaths);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1251,19 +1264,23 @@ void cmFindPackageCommand::LoadPackageRegistryWinSystem()
// Prefer the target platform view first. // Prefer the target platform view first.
if(this->Makefile->PlatformIs64Bit()) if(this->Makefile->PlatformIs64Bit())
{ {
this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY); this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY,
this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY); this->SystemRegistryPaths);
this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY,
this->SystemRegistryPaths);
} }
else else
{ {
this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY); this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY,
this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY); this->SystemRegistryPaths);
this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY,
this->SystemRegistryPaths);
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::LoadPackageRegistryWin(bool user, void cmFindPackageCommand::LoadPackageRegistryWin(bool user, unsigned int view,
unsigned int view) std::vector<std::string>& outPaths)
{ {
std::wstring key = L"Software\\Kitware\\CMake\\Packages\\"; std::wstring key = L"Software\\Kitware\\CMake\\Packages\\";
key += cmsys::Encoding::ToWide(this->Name); key += cmsys::Encoding::ToWide(this->Name);
@ -1289,8 +1306,8 @@ void cmFindPackageCommand::LoadPackageRegistryWin(bool user,
if(valueType == REG_SZ) if(valueType == REG_SZ)
{ {
data[dataSize] = 0; data[dataSize] = 0;
cmsys_ios::stringstream ss(cmsys::Encoding::ToNarrow(&data[0])); if(!this->CheckPackageRegistryEntry(
if(!this->CheckPackageRegistryEntry(ss)) cmsys::Encoding::ToNarrow(&data[0]), outPaths))
{ {
// The entry is invalid. // The entry is invalid.
bad.insert(name); bad.insert(name);
@ -1332,7 +1349,8 @@ public:
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir) void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir,
std::vector<std::string>& outPaths)
{ {
cmsys::Directory files; cmsys::Directory files;
if(!files.Load(dir)) if(!files.Load(dir))
@ -1354,7 +1372,9 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir)
// Load the file. // Load the file.
cmsys::ifstream fin(fname.c_str(), std::ios::in | cmsys_ios_binary); cmsys::ifstream fin(fname.c_str(), std::ios::in | cmsys_ios_binary);
if(fin && this->CheckPackageRegistryEntry(fin)) std::string fentry;
if(fin && cmSystemTools::GetLineFromStream(fin, fentry) &&
this->CheckPackageRegistryEntry(fentry, outPaths))
{ {
// The file references an existing package, so release it. // The file references an existing package, so release it.
holdFile.Release(); holdFile.Release();
@ -1367,12 +1387,11 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir)
#endif #endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmFindPackageCommand::CheckPackageRegistryEntry(std::istream& is) bool cmFindPackageCommand::CheckPackageRegistryEntry(const std::string& fname,
std::vector<std::string>& outPaths)
{ {
// Parse the content of one package registry entry. // Parse the content of one package registry entry.
std::string fname; if(cmSystemTools::FileIsFullPath(fname.c_str()))
if(cmSystemTools::GetLineFromStream(is, fname) &&
cmSystemTools::FileIsFullPath(fname.c_str()))
{ {
// The first line in the stream is the full path to a file or // The first line in the stream is the full path to a file or
// directory containing the package. // directory containing the package.
@ -1381,9 +1400,14 @@ bool cmFindPackageCommand::CheckPackageRegistryEntry(std::istream& is)
// The path exists. Look for the package here. // The path exists. Look for the package here.
if(!cmSystemTools::FileIsDirectory(fname)) if(!cmSystemTools::FileIsDirectory(fname))
{ {
fname = cmSystemTools::GetFilenamePath(fname); this->AddPathInternal(
MakeFullPath(cmSystemTools::GetFilenamePath(fname), FullPath),
outPaths);
}
else
{
this->AddPathInternal(MakeFullPath(fname, FullPath), outPaths);
} }
this->AddPathInternal(fname, FullPath);
return true; return true;
} }
else else
@ -1404,10 +1428,8 @@ bool cmFindPackageCommand::CheckPackageRegistryEntry(std::istream& is)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesBuilds() void cmFindPackageCommand::FillPrefixesBuilds()
{ {
if(!this->NoBuilds && !this->NoDefaultPath)
{
// It is likely that CMake will have recently built the project. // It is likely that CMake will have recently built the project.
for(int i=0; i <= 10; ++i) for(int i=0; i <= 10; ++i)
{ {
@ -1419,37 +1441,38 @@ void cmFindPackageCommand::AddPrefixesBuilds()
cmSystemTools::ExpandRegistryValues(f); cmSystemTools::ExpandRegistryValues(f);
cmSystemTools::ConvertToUnixSlashes(f); cmSystemTools::ConvertToUnixSlashes(f);
if(cmSystemTools::FileIsFullPath(f.c_str()) && if(cmSystemTools::FileIsFullPath(f.c_str()) &&
cmSystemTools::FileIsDirectory(f)) cmSystemTools::FileIsDirectory(f.c_str()))
{ {
this->AddPathInternal(f, FullPath); this->AddPathInternal(MakeFullPath(f, FullPath), this->BuildPaths);
}
} }
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesCMakeSystemVariable() void cmFindPackageCommand::FillPrefixesCMakeSystemVariable()
{ {
if(!this->NoCMakeSystemPath && !this->NoDefaultPath) this->AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH",
{ this->CMakeSystemVariablePaths);
this->AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH",
this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); this->CMakeSystemVariablePaths);
this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH"); this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH",
} this->CMakeSystemVariablePaths);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesUserGuess() void cmFindPackageCommand::FillPrefixesUserGuess()
{ {
// Add guesses specified by the caller. std::vector<std::string> inPaths;
this->AddPathsInternal(this->UserPaths, CMakePath); inPaths.swap(this->UserGuessPaths);
this->AddPathsInternal(inPaths, CMakePath, this->UserGuessPaths);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesUserHints() void cmFindPackageCommand::FillPrefixesUserHints()
{ {
// Add hints specified by the caller. std::vector<std::string> inPaths;
this->AddPathsInternal(this->UserHints, CMakePath); inPaths.swap(this->UserHintsPaths);
this->AddPathsInternal(inPaths, CMakePath, this->UserHintsPaths);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -69,20 +69,23 @@ private:
void StoreVersionFound(); void StoreVersionFound();
void ComputePrefixes(); void ComputePrefixes();
void AddPrefixesCMakeEnvironment(); void FillPrefixesCMakeEnvironment();
void AddPrefixesCMakeVariable(); void FillPrefixesCMakeVariable();
void AddPrefixesSystemEnvironment(); void FillPrefixesSystemEnvironment();
void AddPrefixesUserRegistry(); void FillPrefixesUserRegistry();
void AddPrefixesSystemRegistry(); void FillPrefixesSystemRegistry();
void AddPrefixesBuilds(); void FillPrefixesBuilds();
void AddPrefixesCMakeSystemVariable(); void FillPrefixesCMakeSystemVariable();
void AddPrefixesUserGuess(); void FillPrefixesUserGuess();
void AddPrefixesUserHints(); void FillPrefixesUserHints();
void LoadPackageRegistryDir(std::string const& dir); void LoadPackageRegistryDir(std::string const& dir,
std::vector<std::string>& outPaths);
void LoadPackageRegistryWinUser(); void LoadPackageRegistryWinUser();
void LoadPackageRegistryWinSystem(); void LoadPackageRegistryWinSystem();
void LoadPackageRegistryWin(bool user, unsigned int view); void LoadPackageRegistryWin(bool user, unsigned int view,
bool CheckPackageRegistryEntry(std::istream& is); std::vector<std::string>& outPaths);
bool CheckPackageRegistryEntry(const std::string& fname,
std::vector<std::string>& outPaths);
bool SearchDirectory(std::string const& dir); bool SearchDirectory(std::string const& dir);
bool CheckDirectory(std::string const& dir); bool CheckDirectory(std::string const& dir);
bool FindConfigFile(std::string const& dir, std::string& file); bool FindConfigFile(std::string const& dir, std::string& file);