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)
{
this->AddUserPath(args[j], this->UserPaths);
this->AddUserPath(args[j], this->UserGuessPaths);
}
else if(doing == DoingHints)
{
this->AddUserPath(args[j], this->UserHints);
this->AddUserPath(args[j], this->UserHintsPaths);
}
else if(doing == DoingPathSuffixes)
{
@ -186,16 +186,11 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
this->Names.push_back(shortArgs[0]);
for(unsigned int j = 1; j < shortArgs.size(); ++j)
{
this->AddUserPath(shortArgs[j], this->UserPaths);
this->AddUserPath(shortArgs[j], this->UserGuessPaths);
}
}
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();
return true;
@ -203,20 +198,40 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
void cmFindBase::ExpandPaths()
{
this->AddCMakeVariablePath();
this->AddCMakeEnvironmentPath();
this->AddUserHintsPath();
this->AddSystemEnvironmentPath();
this->AddCMakeSystemVariablePath();
this->AddUserGuessPath();
if(!this->NoDefaultPath)
{
if(!this->NoCMakePath)
{
this->FillCMakeVariablePath();
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->AddPathSuffixes();
this->FillUserHintsPath();
this->AddPathSuffixes(this->UserHintsPaths);
this->FillUserGuessPath();
this->AddPathSuffixes(this->UserGuessPaths);
}
//----------------------------------------------------------------------------
void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths,
PathType pathType)
void cmFindBase::AddPrefixPaths(std::vector<std::string> const& inPaths,
PathType pt,
std::vector<std::string>& outPaths)
{
// default for programs
std::string subdir = "bin";
@ -234,8 +249,8 @@ void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths,
subdir = ""; // ? what to do for frameworks ?
}
for(std::vector<std::string>::const_iterator it = in_paths.begin();
it != in_paths.end(); ++it)
for(std::vector<std::string>::const_iterator it = inPaths.begin();
it != inPaths.end(); ++it)
{
std::string dir = *it;
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");
if(arch && *arch)
{
this->AddPathInternal(dir+subdir+"/"+arch, pathType);
this->AddPathInternal(this->MakeFullPath(dir+subdir+"/"+arch, pt),
outPaths);
}
}
std::string add = dir + subdir;
if(add != "/")
{
this->AddPathInternal(add, pathType);
this->AddPathInternal(this->MakeFullPath(add, pt), outPaths);
}
if (subdir == "bin")
{
this->AddPathInternal(dir+"sbin", pathType);
this->AddPathInternal(this->MakeFullPath(dir+"sbin", pt), outPaths);
}
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.
if(const char* varPath = this->Makefile->GetDefinition(variable))
{
std::vector<std::string> 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.
std::vector<std::string> tmp;
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
std::string var = "CMAKE_";
var += this->CMakePathName;
var += "_PATH";
this->AddEnvPrefixPath("CMAKE_PREFIX_PATH");
this->AddEnvPath(var.c_str());
// Add CMAKE_*_PATH environment variables
std::string var = "CMAKE_";
var += this->CMakePathName;
var += "_PATH";
this->AddEnvPrefixPath("CMAKE_PREFIX_PATH", this->CMakeEnvironmentPaths);
this->AddEnvPath(var.c_str(), this->CMakeEnvironmentPaths);
if(this->CMakePathName == "PROGRAM")
{
this->AddEnvPath("CMAKE_APPBUNDLE_PATH");
}
else
{
this->AddEnvPath("CMAKE_FRAMEWORK_PATH");
}
if(this->CMakePathName == "PROGRAM")
{
this->AddEnvPath("CMAKE_APPBUNDLE_PATH", this->CMakeEnvironmentPaths);
}
else
{
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
// varibles CMAKE_*_PATH to be used most of the time with -D
// command line options
std::string var = "CMAKE_";
var += this->CMakePathName;
var += "_PATH";
this->AddCMakePrefixPath("CMAKE_PREFIX_PATH");
this->AddCMakePath(var);
// Add CMake varibles of the same name as the previous environment
// varibles CMAKE_*_PATH to be used most of the time with -D
// command line options
std::string var = "CMAKE_";
var += this->CMakePathName;
var += "_PATH";
this->AddCMakePrefixPath("CMAKE_PREFIX_PATH", this->CMakeVariablePaths);
this->AddCMakePath(var, this->CMakeVariablePaths);
if(this->CMakePathName == "PROGRAM")
{
this->AddCMakePath("CMAKE_APPBUNDLE_PATH");
}
else
{
this->AddCMakePath("CMAKE_FRAMEWORK_PATH");
}
if(this->CMakePathName == "PROGRAM")
{
this->AddCMakePath("CMAKE_APPBUNDLE_PATH", this->CMakeVariablePaths);
}
else
{
this->AddCMakePath("CMAKE_FRAMEWORK_PATH", this->CMakeVariablePaths);
}
}
//----------------------------------------------------------------------------
void cmFindBase::AddSystemEnvironmentPath()
void cmFindBase::FillSystemEnvironmentPath()
{
if(!this->NoSystemEnvironmentPath && !this->NoDefaultPath)
// Add LIB or INCLUDE
if(!this->EnvironmentPath.empty())
{
// Add LIB or INCLUDE
if(!this->EnvironmentPath.empty())
{
this->AddEnvPath(this->EnvironmentPath.c_str());
}
// Add PATH
this->AddEnvPath(0);
this->AddEnvPath(this->EnvironmentPath.c_str(),
this->SystemEnvironmentPaths);
}
// Add PATH
this->AddEnvPath(0, this->SystemEnvironmentPaths);
}
//----------------------------------------------------------------------------
void cmFindBase::FillCMakeSystemVariablePath()
{
std::string var = "CMAKE_SYSTEM_";
var += this->CMakePathName;
var += "_PATH";
this->AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH",
this->CMakeSystemVariablePaths);
this->AddCMakePath(var, this->CMakeSystemVariablePaths);
if(this->CMakePathName == "PROGRAM")
{
this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH",
this->CMakeSystemVariablePaths);
}
else
{
this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH",
this->CMakeSystemVariablePaths);
}
}
//----------------------------------------------------------------------------
void cmFindBase::AddCMakeSystemVariablePath()
void cmFindBase::FillUserHintsPath()
{
if(!this->NoCMakeSystemPath && !this->NoDefaultPath)
std::vector<std::string> inPaths;
inPaths.swap(this->UserHintsPaths);
this->AddPathsInternal(inPaths, CMakePath, this->UserHintsPaths);
}
//----------------------------------------------------------------------------
void cmFindBase::FillUserGuessPath()
{
std::vector<std::string> inPaths;
inPaths.swap(this->UserGuessPaths);
this->AddPathsInternal(inPaths, CMakePath, this->UserGuessPaths);
}
//----------------------------------------------------------------------------
void cmFindBase::AddPathSuffixes(std::vector<std::string>& paths)
{
std::vector<std::string> inPaths;
inPaths.swap(paths);
paths.reserve(inPaths.size()*(this->SearchPathSuffixes.size()+1));
for(std::vector<std::string>::iterator ip = inPaths.begin();
ip != inPaths.end(); ++ip)
{
std::string var = "CMAKE_SYSTEM_";
var += this->CMakePathName;
var += "_PATH";
this->AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
this->AddCMakePath(var);
cmSystemTools::ConvertToUnixSlashes(*ip);
if(this->CMakePathName == "PROGRAM")
// if *i is only / then do not add a //
// this will get incorrectly considered a network
// path on windows and cause huge delays.
std::string p = *ip;
if(!p.empty() && *p.rbegin() != '/')
{
this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");
p += "/";
}
else
{
this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
}
}
}
//----------------------------------------------------------------------------
void cmFindBase::AddUserHintsPath()
{
this->AddPathsInternal(this->UserHints, CMakePath);
}
//----------------------------------------------------------------------------
void cmFindBase::AddUserGuessPath()
{
this->AddPathsInternal(this->UserPaths, CMakePath);
}
//----------------------------------------------------------------------------
void cmFindBase::AddPathSuffixes()
{
std::vector<std::string>& paths = this->SearchPaths;
std::vector<std::string> finalPath = paths;
std::vector<std::string>::iterator i;
// clear the path
paths.clear();
// convert all paths to unix slashes and add search path suffixes
// 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 =
for(std::vector<std::string>::iterator sps =
this->SearchPathSuffixes.begin();
j != this->SearchPathSuffixes.end(); ++j)
sps != this->SearchPathSuffixes.end(); ++sps)
{
// if *i is only / then do not add a //
// this will get incorrectly considered a network
// path on windows and cause huge delays.
std::string p = *i;
if(p.size() && p[p.size()-1] != '/')
{
p += std::string("/");
}
p += *j;
// add to all paths because the search path may be modified
// 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
paths.push_back(*i);
paths.push_back(*ip);
}
}
@ -457,9 +467,10 @@ void cmFindBase::PrintFindStuff()
}
std::cerr << "\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:
void PrintFindStuff();
void ExpandPaths();
void AddPathSuffixes();
void AddPathSuffixes(std::vector<std::string>& paths);
// see if the VariableName is already set in the cache,
// also copy the documentation from the cache to VariableDocumentation
@ -55,18 +55,20 @@ protected:
bool AlreadyInCacheWithoutMetaInfo;
private:
// Add pieces of the search.
void AddCMakeEnvironmentPath();
void AddCMakeVariablePath();
void AddSystemEnvironmentPath();
void AddCMakeSystemVariablePath();
void AddUserHintsPath();
void AddUserGuessPath();
void FillCMakeVariablePath();
void FillCMakeEnvironmentPath();
void FillUserHintsPath();
void FillSystemEnvironmentPath();
void FillCMakeSystemVariablePath();
void FillUserGuessPath();
// Helpers.
void AddCMakePrefixPath(const std::string& variable);
void AddEnvPrefixPath(const std::string& variable);
void AddPrefixPaths(std::vector<std::string> const& in_paths,
PathType pathType);
void AddCMakePrefixPath(const std::string& variable,
std::vector<std::string>& outPaths);
void AddEnvPrefixPath(const std::string& variable,
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.
============================================================================*/
#include "cmFindCommon.h"
#include <functional>
#include <algorithm>
//----------------------------------------------------------------------------
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()
{
@ -212,24 +230,20 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
}
//----------------------------------------------------------------------------
void cmFindCommon::FilterPaths(std::vector<std::string>& paths,
const std::set<std::string>& ignore)
void cmFindCommon::FilterPaths(const std::vector<std::string>& inPaths,
const std::set<std::string>& ignore,
std::vector<std::string>& outPaths)
{
// Now filter out anything that's in the ignore set.
std::vector<std::string> unfiltered;
unfiltered.swap(paths);
for(std::vector<std::string>::iterator pi = unfiltered.begin();
pi != unfiltered.end(); ++pi)
for(std::vector<std::string>::const_iterator i = inPaths.begin();
i != inPaths.end(); ++i)
{
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)
{
@ -345,8 +359,8 @@ void cmFindCommon::AddPathSuffix(std::string const& arg)
}
//----------------------------------------------------------------------------
void cmFindCommon::AddUserPath(std::string const& p,
std::vector<std::string>& paths)
void cmFindCommon::AddUserPath(std::string const& inPath,
std::vector<std::string>& outPaths)
{
// We should view the registry as the target application would view
// it.
@ -359,22 +373,23 @@ void cmFindCommon::AddUserPath(std::string const& p,
}
// Expand using the view of the target application.
std::string expanded = p;
std::string expanded = inPath;
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
// alternative view.
if(expanded != p && this->CMakePathName == "PROGRAM")
if(expanded != inPath && this->CMakePathName == "PROGRAM")
{
expanded = p;
expanded = inPath;
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.
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
// 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.
std::vector<std::string> tmp;
cmSystemTools::GetPath(tmp, variable);
// Relative paths are interpreted with respect to the current
// working directory.
this->AddPathsInternal(tmp, EnvPath);
this->AddPathsInternal(tmp, EnvPath, outPaths);
}
//----------------------------------------------------------------------------
void cmFindCommon::AddPathsInternal(std::vector<std::string> const& in_paths,
PathType pathType)
void cmFindCommon::AddPathsInternal(std::vector<std::string> const& inPaths,
PathType pathType,
std::vector<std::string>& outPaths)
{
for(std::vector<std::string>::const_iterator i = in_paths.begin();
i != in_paths.end(); ++i)
for(std::vector<std::string>::const_iterator i = inPaths.begin();
i != inPaths.end(); ++i)
{
this->AddPathInternal(*i, pathType);
this->AddPathInternal(this->MakeFullPath(*i, pathType), outPaths);
}
}
//----------------------------------------------------------------------------
void cmFindCommon::AddPathInternal(std::string const& in_path,
PathType pathType)
void cmFindCommon::AddPathInternal(std::string const& inPath,
std::vector<std::string>& outPaths)
{
if(in_path.empty())
if(inPath.empty())
{
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.
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()
{
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.
this->RerootPaths(paths);
this->RerootPaths(this->SearchPaths);
// Add a trailing slash to all paths to aid the search process.
for(std::vector<std::string>::iterator i = paths.begin();
i != paths.end(); ++i)
{
std::string& p = *i;
if(!p.empty() && p[p.size()-1] != '/')
{
p += "/";
}
}
std::for_each(this->SearchPaths.begin(), this->SearchPaths.end(),
&AddTrailingSlash);
}
//----------------------------------------------------------------------------

View File

@ -36,6 +36,9 @@ protected:
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. */
void RerootPaths(std::vector<std::string>& paths);
@ -44,8 +47,9 @@ protected:
void GetIgnoredPaths(std::set<std::string>& ignore);
/** Remove paths in the ignore set from the supplied vector. */
void FilterPaths(std::vector<std::string>& paths,
const std::set<std::string>& ignore);
void FilterPaths(const std::vector<std::string>& inPaths,
const std::set<std::string>& ignore,
std::vector<std::string>& outPaths);
/** Compute final search path list (reroot + trailing slash). */
void ComputeFinalPaths();
@ -62,12 +66,14 @@ protected:
bool CheckCommonArgument(std::string const& arg);
void AddPathSuffix(std::string const& arg);
void AddUserPath(std::string const& p,
std::vector<std::string>& paths);
void AddCMakePath(const std::string& variable);
void AddEnvPath(const char* variable);
void AddPathsInternal(std::vector<std::string> const& in_paths,
PathType pathType);
void AddPathInternal(std::string const& in_path, PathType pathType);
std::vector<std::string>& outPaths);
void AddCMakePath(const std::string& variable,
std::vector<std::string>& outPaths);
void AddEnvPath(const char* variable, std::vector<std::string>& outPaths);
void AddPathsInternal(std::vector<std::string> const& inPaths,
PathType pathType, std::vector<std::string>& outPaths);
void AddPathInternal(std::string const& inPath,
std::vector<std::string>& outPaths);
void SetMakefile(cmMakefile* makefile);
@ -78,8 +84,16 @@ protected:
bool NoCMakeSystemPath;
std::vector<std::string> SearchPathSuffixes;
std::vector<std::string> UserPaths;
std::vector<std::string> UserHints;
std::vector<std::string> CMakeVariablePaths;
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::set<std::string> SearchPathsEmitted;

View File

@ -88,7 +88,7 @@ void cmFindLibraryCommand::AddArchitecturePaths(const char* suffix)
{
std::vector<std::string> original;
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)
{
this->AddArchitecturePath(*i, 0, suffix);

View File

@ -248,11 +248,11 @@ bool cmFindPackageCommand
}
else if(doing == DoingPaths)
{
this->AddUserPath(args[i], this->UserPaths);
this->AddUserPath(args[i], this->UserGuessPaths);
}
else if(doing == DoingHints)
{
this->AddUserPath(args[i], this->UserHints);
this->AddUserPath(args[i], this->UserHintsPaths);
}
else if(doing == DoingPathSuffixes)
{
@ -1111,86 +1111,99 @@ void cmFindPackageCommand::AppendSuccessInformation()
//----------------------------------------------------------------------------
void cmFindPackageCommand::ComputePrefixes()
{
this->AddPrefixesCMakeVariable();
this->AddPrefixesCMakeEnvironment();
this->AddPrefixesUserHints();
this->AddPrefixesSystemEnvironment();
this->AddPrefixesUserRegistry();
this->AddPrefixesBuilds();
this->AddPrefixesCMakeSystemVariable();
this->AddPrefixesSystemRegistry();
this->AddPrefixesUserGuess();
if(!this->NoDefaultPath)
{
if(!this->NoCMakePath)
{
this->FillPrefixesCMakeVariable();
}
if(!this->NoCMakeEnvironmentPath)
{
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();
}
//----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesCMakeEnvironment()
void cmFindPackageCommand::FillPrefixesCMakeEnvironment()
{
if(!this->NoCMakeEnvironmentPath && !this->NoDefaultPath)
// Check the environment variable with the same name as the cache
// entry.
std::string env;
if(cmSystemTools::GetEnv(this->Variable.c_str(), env) && env.length() > 0)
{
// Check the environment variable with the same name as the cache
// entry.
std::string env;
if(cmSystemTools::GetEnv(this->Variable.c_str(), env) && env.length() > 0)
cmSystemTools::ConvertToUnixSlashes(env);
this->AddPathInternal(MakeFullPath(env, EnvPath),
this->CMakeEnvironmentPaths);
}
this->AddEnvPath("CMAKE_PREFIX_PATH", this->CMakeEnvironmentPaths);
this->AddEnvPath("CMAKE_FRAMEWORK_PATH", this->CMakeEnvironmentPaths);
this->AddEnvPath("CMAKE_APPBUNDLE_PATH", this->CMakeEnvironmentPaths);
}
//----------------------------------------------------------------------------
void cmFindPackageCommand::FillPrefixesCMakeVariable()
{
this->AddCMakePath("CMAKE_PREFIX_PATH", this->CMakeVariablePaths);
this->AddCMakePath("CMAKE_FRAMEWORK_PATH", this->CMakeVariablePaths);
this->AddCMakePath("CMAKE_APPBUNDLE_PATH", this->CMakeVariablePaths);
}
//----------------------------------------------------------------------------
void cmFindPackageCommand::FillPrefixesSystemEnvironment()
{
// Use the system search path to generate prefixes.
// Relative paths are interpreted with respect to the current
// working directory.
std::vector<std::string> tmp;
cmSystemTools::GetPath(tmp);
for(std::vector<std::string>::iterator i = tmp.begin();
i != tmp.end(); ++i)
{
// If the path is a PREFIX/bin case then add its parent instead.
if((cmHasLiteralSuffix(*i, "/bin")) ||
(cmHasLiteralSuffix(*i, "/sbin")))
{
cmSystemTools::ConvertToUnixSlashes(env);
this->AddPathInternal(env, EnvPath);
this->AddPathInternal(MakeFullPath(cmSystemTools::GetFilenamePath(*i),
EnvPath),
this->SystemEnvironmentPaths);
}
this->AddEnvPath("CMAKE_PREFIX_PATH");
this->AddEnvPath("CMAKE_FRAMEWORK_PATH");
this->AddEnvPath("CMAKE_APPBUNDLE_PATH");
}
}
//----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesCMakeVariable()
{
if(!this->NoCMakePath && !this->NoDefaultPath)
{
this->AddCMakePath("CMAKE_PREFIX_PATH");
this->AddCMakePath("CMAKE_FRAMEWORK_PATH");
this->AddCMakePath("CMAKE_APPBUNDLE_PATH");
}
}
//----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesSystemEnvironment()
{
if(!this->NoSystemEnvironmentPath && !this->NoDefaultPath)
{
// Use the system search path to generate prefixes.
// Relative paths are interpreted with respect to the current
// working directory.
std::vector<std::string> tmp;
cmSystemTools::GetPath(tmp);
for(std::vector<std::string>::iterator i = tmp.begin();
i != tmp.end(); ++i)
else
{
std::string const& d = *i;
// If the path is a PREFIX/bin case then add its parent instead.
if((cmHasLiteralSuffix(d, "/bin")) ||
(cmHasLiteralSuffix(d, "/sbin")))
{
this->AddPathInternal(cmSystemTools::GetFilenamePath(d), EnvPath);
}
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__)
this->LoadPackageRegistryWinUser();
#elif defined(__HAIKU__)
@ -1201,7 +1214,7 @@ void cmFindPackageCommand::AddPrefixesUserRegistry()
std::string fname = dir;
fname += "/cmake/packages/";
fname += Name;
this->LoadPackageRegistryDir(fname);
this->LoadPackageRegistryDir(fname, this->UserRegistryPaths);
}
#else
if(const char* home = cmSystemTools::GetEnv("HOME"))
@ -1209,13 +1222,13 @@ void cmFindPackageCommand::AddPrefixesUserRegistry()
std::string dir = home;
dir += "/.cmake/packages/";
dir += this->Name;
this->LoadPackageRegistryDir(dir);
this->LoadPackageRegistryDir(dir, this->UserRegistryPaths);
}
#endif
}
//----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesSystemRegistry()
void cmFindPackageCommand::FillPrefixesSystemRegistry()
{
if(this->NoSystemRegistry || this->NoDefaultPath)
{
@ -1241,7 +1254,7 @@ void cmFindPackageCommand::AddPrefixesSystemRegistry()
void cmFindPackageCommand::LoadPackageRegistryWinUser()
{
// 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.
if(this->Makefile->PlatformIs64Bit())
{
this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY);
this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY);
this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY,
this->SystemRegistryPaths);
this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY,
this->SystemRegistryPaths);
}
else
{
this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY);
this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY);
this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY,
this->SystemRegistryPaths);
this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY,
this->SystemRegistryPaths);
}
}
//----------------------------------------------------------------------------
void cmFindPackageCommand::LoadPackageRegistryWin(bool user,
unsigned int view)
void cmFindPackageCommand::LoadPackageRegistryWin(bool user, unsigned int view,
std::vector<std::string>& outPaths)
{
std::wstring key = L"Software\\Kitware\\CMake\\Packages\\";
key += cmsys::Encoding::ToWide(this->Name);
@ -1289,8 +1306,8 @@ void cmFindPackageCommand::LoadPackageRegistryWin(bool user,
if(valueType == REG_SZ)
{
data[dataSize] = 0;
cmsys_ios::stringstream ss(cmsys::Encoding::ToNarrow(&data[0]));
if(!this->CheckPackageRegistryEntry(ss))
if(!this->CheckPackageRegistryEntry(
cmsys::Encoding::ToNarrow(&data[0]), outPaths))
{
// The entry is invalid.
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;
if(!files.Load(dir))
@ -1354,7 +1372,9 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir)
// Load the file.
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.
holdFile.Release();
@ -1367,12 +1387,11 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir)
#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.
std::string fname;
if(cmSystemTools::GetLineFromStream(is, fname) &&
cmSystemTools::FileIsFullPath(fname.c_str()))
if(cmSystemTools::FileIsFullPath(fname.c_str()))
{
// The first line in the stream is the full path to a file or
// directory containing the package.
@ -1381,9 +1400,14 @@ bool cmFindPackageCommand::CheckPackageRegistryEntry(std::istream& is)
// The path exists. Look for the package here.
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;
}
else
@ -1404,52 +1428,51 @@ 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.
for(int i=0; i <= 10; ++i)
{
// It is likely that CMake will have recently built the project.
for(int i=0; i <= 10; ++i)
cmOStringStream r;
r <<
"[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\"
"Settings\\StartPath;WhereBuild" << i << "]";
std::string f = r.str();
cmSystemTools::ExpandRegistryValues(f);
cmSystemTools::ConvertToUnixSlashes(f);
if(cmSystemTools::FileIsFullPath(f.c_str()) &&
cmSystemTools::FileIsDirectory(f.c_str()))
{
cmOStringStream r;
r <<
"[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\"
"Settings\\StartPath;WhereBuild" << i << "]";
std::string f = r.str();
cmSystemTools::ExpandRegistryValues(f);
cmSystemTools::ConvertToUnixSlashes(f);
if(cmSystemTools::FileIsFullPath(f.c_str()) &&
cmSystemTools::FileIsDirectory(f))
{
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->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");
}
this->AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH",
this->CMakeSystemVariablePaths);
this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH",
this->CMakeSystemVariablePaths);
this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH",
this->CMakeSystemVariablePaths);
}
//----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesUserGuess()
void cmFindPackageCommand::FillPrefixesUserGuess()
{
// Add guesses specified by the caller.
this->AddPathsInternal(this->UserPaths, CMakePath);
std::vector<std::string> inPaths;
inPaths.swap(this->UserGuessPaths);
this->AddPathsInternal(inPaths, CMakePath, this->UserGuessPaths);
}
//----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesUserHints()
void cmFindPackageCommand::FillPrefixesUserHints()
{
// Add hints specified by the caller.
this->AddPathsInternal(this->UserHints, CMakePath);
std::vector<std::string> inPaths;
inPaths.swap(this->UserHintsPaths);
this->AddPathsInternal(inPaths, CMakePath, this->UserHintsPaths);
}
//----------------------------------------------------------------------------

View File

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