From 32922840e7ea8a0536fec393352ede5b75087543 Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Thu, 9 Oct 2014 13:52:54 -0400 Subject: [PATCH 1/3] 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. --- Source/cmFindBase.cxx | 273 +++++++++++++++++--------------- Source/cmFindBase.h | 24 +-- Source/cmFindCommon.cxx | 129 ++++++++------- Source/cmFindCommon.h | 34 ++-- Source/cmFindLibraryCommand.cxx | 2 +- Source/cmFindPackageCommand.cxx | 255 +++++++++++++++-------------- Source/cmFindPackageCommand.h | 27 ++-- 7 files changed, 409 insertions(+), 335 deletions(-) diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index e4e819a00..2b9acae42 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -140,11 +140,11 @@ bool cmFindBase::ParseArguments(std::vector 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 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 ignored; - this->GetIgnoredPaths(ignored); - this->FilterPaths(this->SearchPaths, ignored); - this->ComputeFinalPaths(); return true; @@ -203,20 +198,40 @@ bool cmFindBase::ParseArguments(std::vector 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 const& in_paths, - PathType pathType) +void cmFindBase::AddPrefixPaths(std::vector const& inPaths, + PathType pt, + std::vector& outPaths) { // default for programs std::string subdir = "bin"; @@ -234,8 +249,8 @@ void cmFindBase::AddPrefixPaths(std::vector const& in_paths, subdir = ""; // ? what to do for frameworks ? } - for(std::vector::const_iterator it = in_paths.begin(); - it != in_paths.end(); ++it) + for(std::vector::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 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& outPaths) { // Get a path from a CMake variable. if(const char* varPath = this->Makefile->GetDefinition(variable)) { std::vector 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& outPaths) { // Get a path from the environment. std::vector 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 inPaths; + inPaths.swap(this->UserHintsPaths); + this->AddPathsInternal(inPaths, CMakePath, this->UserHintsPaths); +} + +//---------------------------------------------------------------------------- +void cmFindBase::FillUserGuessPath() +{ + std::vector inPaths; + inPaths.swap(this->UserGuessPaths); + this->AddPathsInternal(inPaths, CMakePath, this->UserGuessPaths); +} + +//---------------------------------------------------------------------------- +void cmFindBase::AddPathSuffixes(std::vector& paths) +{ + std::vector inPaths; + inPaths.swap(paths); + paths.reserve(inPaths.size()*(this->SearchPathSuffixes.size()+1)); + + for(std::vector::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& paths = this->SearchPaths; - std::vector finalPath = paths; - std::vector::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::iterator j = + for(std::vector::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::const_iterator i = this->SearchPaths.begin(); + i != this->SearchPaths.end(); ++i) { - std::cerr << "[" << this->SearchPaths[i] << "]\n"; + std::cerr << "[" << *i << "]\n"; } } diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index 42d9bc1c0..14f22c216 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -34,7 +34,7 @@ public: protected: void PrintFindStuff(); void ExpandPaths(); - void AddPathSuffixes(); + void AddPathSuffixes(std::vector& 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 const& in_paths, - PathType pathType); + void AddCMakePrefixPath(const std::string& variable, + std::vector& outPaths); + void AddEnvPrefixPath(const std::string& variable, + std::vector& outPaths); + void AddPrefixPaths(std::vector const& inPaths, + PathType pathType, std::vector& outPaths); }; diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 6376d4272..aea8e4e80 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -10,6 +10,8 @@ See the License for more information. ============================================================================*/ #include "cmFindCommon.h" +#include +#include //---------------------------------------------------------------------------- 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& paths) } //---------------------------------------------------------------------------- -void cmFindCommon::FilterPaths(std::vector& paths, - const std::set& ignore) +void cmFindCommon::FilterPaths(const std::vector& inPaths, + const std::set& ignore, + std::vector& outPaths) { - // Now filter out anything that's in the ignore set. - std::vector unfiltered; - unfiltered.swap(paths); - - for(std::vector::iterator pi = unfiltered.begin(); - pi != unfiltered.end(); ++pi) + for(std::vector::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& ignore) { @@ -345,8 +359,8 @@ void cmFindCommon::AddPathSuffix(std::string const& arg) } //---------------------------------------------------------------------------- -void cmFindCommon::AddUserPath(std::string const& p, - std::vector& paths) +void cmFindCommon::AddUserPath(std::string const& inPath, + std::vector& 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& 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& outPaths) { // Get a path from the environment. std::vector 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 const& in_paths, - PathType pathType) +void cmFindCommon::AddPathsInternal(std::vector const& inPaths, + PathType pathType, + std::vector& outPaths) { - for(std::vector::const_iterator i = in_paths.begin(); - i != in_paths.end(); ++i) + for(std::vector::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& 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& paths = this->SearchPaths; + // Filter out ignored paths from the prefix list + std::set 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::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); } //---------------------------------------------------------------------------- diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h index 5a905cd20..dfb942ff4 100644 --- a/Source/cmFindCommon.h +++ b/Source/cmFindCommon.h @@ -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& paths); @@ -44,8 +47,9 @@ protected: void GetIgnoredPaths(std::set& ignore); /** Remove paths in the ignore set from the supplied vector. */ - void FilterPaths(std::vector& paths, - const std::set& ignore); + void FilterPaths(const std::vector& inPaths, + const std::set& ignore, + std::vector& 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& paths); - void AddCMakePath(const std::string& variable); - void AddEnvPath(const char* variable); - void AddPathsInternal(std::vector const& in_paths, - PathType pathType); - void AddPathInternal(std::string const& in_path, PathType pathType); + std::vector& outPaths); + void AddCMakePath(const std::string& variable, + std::vector& outPaths); + void AddEnvPath(const char* variable, std::vector& outPaths); + void AddPathsInternal(std::vector const& inPaths, + PathType pathType, std::vector& outPaths); + void AddPathInternal(std::string const& inPath, + std::vector& outPaths); void SetMakefile(cmMakefile* makefile); @@ -78,8 +84,16 @@ protected: bool NoCMakeSystemPath; std::vector SearchPathSuffixes; - std::vector UserPaths; - std::vector UserHints; + std::vector CMakeVariablePaths; + std::vector CMakeEnvironmentPaths; + std::vector UserHintsPaths; + std::vector SystemEnvironmentPaths; + std::vector UserRegistryPaths; + std::vector BuildPaths; + std::vector CMakeSystemVariablePaths; + std::vector SystemRegistryPaths; + std::vector UserGuessPaths; + std::vector SearchPaths; std::set SearchPathsEmitted; diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 16deaabf4..78f0e9e52 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -88,7 +88,7 @@ void cmFindLibraryCommand::AddArchitecturePaths(const char* suffix) { std::vector original; original.swap(this->SearchPaths); - for(std::vector::iterator i = original.begin(); + for(std::vector::const_iterator i = original.begin(); i != original.end(); ++i) { this->AddArchitecturePath(*i, 0, suffix); diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 4633e7183..ded6eeed5 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -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 tmp; + cmSystemTools::GetPath(tmp); + for(std::vector::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 tmp; - cmSystemTools::GetPath(tmp); - for(std::vector::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& 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& 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& 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 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 inPaths; + inPaths.swap(this->UserHintsPaths); + this->AddPathsInternal(inPaths, CMakePath, this->UserHintsPaths); } //---------------------------------------------------------------------------- diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 224945948..f22433e2a 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -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& 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& outPaths); + bool CheckPackageRegistryEntry(const std::string& fname, + std::vector& outPaths); bool SearchDirectory(std::string const& dir); bool CheckDirectory(std::string const& dir); bool FindConfigFile(std::string const& dir, std::string& file); From 2a9ac4bd83f7247539616545ef0772fea1f4a1fc Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Wed, 15 Oct 2014 16:36:42 -0400 Subject: [PATCH 2/3] Encapsulate search path manipulation functions into a seperate class. The functions for adding the various different types of paths have been factored out into a new class, cmSearchPath. It is to be used as a helper container class for the various find_* commands. --- Source/cmBootstrapCommands1.cxx | 1 + Source/cmFindBase.cxx | 179 +++++------------------ Source/cmFindBase.h | 9 -- Source/cmFindCommon.cxx | 145 +++---------------- Source/cmFindCommon.h | 45 +++--- Source/cmFindPackageCommand.cxx | 72 +++++----- Source/cmFindPackageCommand.h | 7 +- Source/cmSearchPath.cxx | 243 ++++++++++++++++++++++++++++++++ Source/cmSearchPath.h | 60 ++++++++ 9 files changed, 415 insertions(+), 346 deletions(-) create mode 100644 Source/cmSearchPath.cxx create mode 100644 Source/cmSearchPath.h diff --git a/Source/cmBootstrapCommands1.cxx b/Source/cmBootstrapCommands1.cxx index 9093579dc..29d36710e 100644 --- a/Source/cmBootstrapCommands1.cxx +++ b/Source/cmBootstrapCommands1.cxx @@ -43,6 +43,7 @@ #include "cmExecuteProcessCommand.cxx" #include "cmExternalMakefileProjectGenerator.cxx" #include "cmFindBase.cxx" +#include "cmSearchPath.cxx" #include "cmFindCommon.cxx" #include "cmFileCommand.cxx" #include "cmFindFileCommand.cxx" diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 2b9acae42..52f04ad30 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -140,11 +140,11 @@ bool cmFindBase::ParseArguments(std::vector const& argsIn) } else if(doing == DoingPaths) { - this->AddUserPath(args[j], this->UserGuessPaths); + this->UserGuessArgs.push_back(args[j]); } else if(doing == DoingHints) { - this->AddUserPath(args[j], this->UserHintsPaths); + this->UserHintsArgs.push_back(args[j]); } else if(doing == DoingPathSuffixes) { @@ -186,7 +186,7 @@ bool cmFindBase::ParseArguments(std::vector const& argsIn) this->Names.push_back(shortArgs[0]); for(unsigned int j = 1; j < shortArgs.size(); ++j) { - this->AddUserPath(shortArgs[j], this->UserGuessPaths); + this->UserGuessArgs.push_back(shortArgs[j]); } } this->ExpandPaths(); @@ -203,107 +203,23 @@ void cmFindBase::ExpandPaths() 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); } } this->FillUserHintsPath(); - this->AddPathSuffixes(this->UserHintsPaths); this->FillUserGuessPath(); - this->AddPathSuffixes(this->UserGuessPaths); -} - -//---------------------------------------------------------------------------- -void cmFindBase::AddPrefixPaths(std::vector const& inPaths, - PathType pt, - std::vector& outPaths) -{ - // default for programs - std::string subdir = "bin"; - - if (this->CMakePathName == "INCLUDE") - { - subdir = "include"; - } - else if (this->CMakePathName == "LIBRARY") - { - subdir = "lib"; - } - else if (this->CMakePathName == "FRAMEWORK") - { - subdir = ""; // ? what to do for frameworks ? - } - - for(std::vector::const_iterator it = inPaths.begin(); - it != inPaths.end(); ++it) - { - std::string dir = *it; - if(!subdir.empty() && !dir.empty() && dir[dir.size()-1] != '/') - { - dir += "/"; - } - if(subdir == "include" || subdir == "lib") - { - const char* arch = - this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); - if(arch && *arch) - { - this->AddPathInternal(this->MakeFullPath(dir+subdir+"/"+arch, pt), - outPaths); - } - } - std::string add = dir + subdir; - if(add != "/") - { - this->AddPathInternal(this->MakeFullPath(add, pt), outPaths); - } - if (subdir == "bin") - { - this->AddPathInternal(this->MakeFullPath(dir+"sbin", pt), outPaths); - } - if(!subdir.empty() && *it != "/") - { - this->AddPathInternal(this->MakeFullPath(*it, pt), outPaths); - } - } -} - -//---------------------------------------------------------------------------- -void cmFindBase::AddCMakePrefixPath(const std::string& variable, - std::vector& outPaths) -{ - // Get a path from a CMake variable. - if(const char* varPath = this->Makefile->GetDefinition(variable)) - { - std::vector tmp; - cmSystemTools::ExpandListArgument(varPath, tmp); - this->AddPrefixPaths(tmp, CMakePath, outPaths); - } -} - -//---------------------------------------------------------------------------- -void cmFindBase::AddEnvPrefixPath(const std::string& variable, - std::vector& outPaths) -{ - // Get a path from the environment. - std::vector tmp; - cmSystemTools::GetPath(tmp, variable.c_str()); - this->AddPrefixPaths(tmp, EnvPath, outPaths); } //---------------------------------------------------------------------------- @@ -313,17 +229,18 @@ void cmFindBase::FillCMakeEnvironmentPath() std::string var = "CMAKE_"; var += this->CMakePathName; var += "_PATH"; - this->AddEnvPrefixPath("CMAKE_PREFIX_PATH", this->CMakeEnvironmentPaths); - this->AddEnvPath(var.c_str(), this->CMakeEnvironmentPaths); + this->CMakeEnvironmentPaths.AddEnvPrefixPath("CMAKE_PREFIX_PATH"); + this->CMakeEnvironmentPaths.AddEnvPath(var); if(this->CMakePathName == "PROGRAM") { - this->AddEnvPath("CMAKE_APPBUNDLE_PATH", this->CMakeEnvironmentPaths); + this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_APPBUNDLE_PATH"); } else { - this->AddEnvPath("CMAKE_FRAMEWORK_PATH", this->CMakeEnvironmentPaths); + this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_FRAMEWORK_PATH"); } + this->CMakeEnvironmentPaths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- @@ -335,17 +252,18 @@ void cmFindBase::FillCMakeVariablePath() std::string var = "CMAKE_"; var += this->CMakePathName; var += "_PATH"; - this->AddCMakePrefixPath("CMAKE_PREFIX_PATH", this->CMakeVariablePaths); - this->AddCMakePath(var, this->CMakeVariablePaths); + this->CMakeVariablePaths.AddCMakePrefixPath("CMAKE_PREFIX_PATH"); + this->CMakeVariablePaths.AddCMakePath(var); if(this->CMakePathName == "PROGRAM") { - this->AddCMakePath("CMAKE_APPBUNDLE_PATH", this->CMakeVariablePaths); + this->CMakeVariablePaths.AddCMakePath("CMAKE_APPBUNDLE_PATH"); } else { - this->AddCMakePath("CMAKE_FRAMEWORK_PATH", this->CMakeVariablePaths); + this->CMakeVariablePaths.AddCMakePath("CMAKE_FRAMEWORK_PATH"); } + this->CMakeVariablePaths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- @@ -354,11 +272,11 @@ void cmFindBase::FillSystemEnvironmentPath() // Add LIB or INCLUDE if(!this->EnvironmentPath.empty()) { - this->AddEnvPath(this->EnvironmentPath.c_str(), - this->SystemEnvironmentPaths); + this->SystemEnvironmentPaths.AddEnvPath(this->EnvironmentPath); } // Add PATH - this->AddEnvPath(0, this->SystemEnvironmentPaths); + this->SystemEnvironmentPaths.AddEnvPath("PATH"); + this->SystemEnvironmentPaths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- @@ -367,72 +285,45 @@ 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); + this->CMakeSystemVariablePaths.AddCMakePrefixPath( + "CMAKE_SYSTEM_PREFIX_PATH"); + this->CMakeSystemVariablePaths.AddCMakePath(var); if(this->CMakePathName == "PROGRAM") { - this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH", - this->CMakeSystemVariablePaths); + this->CMakeSystemVariablePaths.AddCMakePath( + "CMAKE_SYSTEM_APPBUNDLE_PATH"); } else { - this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH", - this->CMakeSystemVariablePaths); + this->CMakeSystemVariablePaths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); } + this->CMakeSystemVariablePaths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- void cmFindBase::FillUserHintsPath() { - std::vector inPaths; - inPaths.swap(this->UserHintsPaths); - this->AddPathsInternal(inPaths, CMakePath, this->UserHintsPaths); + for(std::vector::const_iterator p = this->UserHintsArgs.begin(); + p != this->UserHintsArgs.end(); ++p) + { + this->UserHintsPaths.AddUserPath(*p); + } + this->UserHintsPaths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- void cmFindBase::FillUserGuessPath() { - std::vector inPaths; - inPaths.swap(this->UserGuessPaths); - this->AddPathsInternal(inPaths, CMakePath, this->UserGuessPaths); + for(std::vector::const_iterator p = this->UserGuessArgs.begin(); + p != this->UserGuessArgs.end(); ++p) + { + this->UserGuessPaths.AddUserPath(*p); + } + this->UserGuessPaths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- -void cmFindBase::AddPathSuffixes(std::vector& paths) -{ - std::vector inPaths; - inPaths.swap(paths); - paths.reserve(inPaths.size()*(this->SearchPathSuffixes.size()+1)); - - for(std::vector::iterator ip = inPaths.begin(); - ip != inPaths.end(); ++ip) - { - cmSystemTools::ConvertToUnixSlashes(*ip); - - // 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() != '/') - { - p += "/"; - } - - for(std::vector::iterator sps = - this->SearchPathSuffixes.begin(); - sps != this->SearchPathSuffixes.end(); ++sps) - { - // 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+*sps); - } - // now put the path without the path suffixes in the SearchPaths - paths.push_back(*ip); - } -} - void cmFindBase::PrintFindStuff() { std::cerr << "SearchFrameworkLast: " << this->SearchFrameworkLast << "\n"; diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index 14f22c216..8ca311dd2 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -34,7 +34,6 @@ public: protected: void PrintFindStuff(); void ExpandPaths(); - void AddPathSuffixes(std::vector& paths); // see if the VariableName is already set in the cache, // also copy the documentation from the cache to VariableDocumentation @@ -61,14 +60,6 @@ private: void FillSystemEnvironmentPath(); void FillCMakeSystemVariablePath(); void FillUserGuessPath(); - - // Helpers. - void AddCMakePrefixPath(const std::string& variable, - std::vector& outPaths); - void AddEnvPrefixPath(const std::string& variable, - std::vector& outPaths); - void AddPrefixPaths(std::vector const& inPaths, - PathType pathType, std::vector& outPaths); }; diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index aea8e4e80..87e98c198 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -15,6 +15,15 @@ //---------------------------------------------------------------------------- cmFindCommon::cmFindCommon() +: CMakeVariablePaths(this, "CMAKE"), + CMakeEnvironmentPaths(this, "CMAKE_ENVIRONMENT"), + UserHintsPaths(this, "HINTS"), + SystemEnvironmentPaths(this, "SYSTEM_ENVIRONMENT"), + UserRegistryPaths(this, "USER_REGISTRY"), + BuildPaths(this, "BUILD"), + CMakeSystemVariablePaths(this, "CMAKE_SYSTEM_VARIABLE"), + SystemRegistryPaths(this, "SYSTEM_REGISTRY"), + UserGuessPaths(this, "GUESS") { this->FindRootPathMode = RootPathModeBoth; this->NoDefaultPath = false; @@ -43,28 +52,9 @@ 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() { - // Use both by default. - this->FindRootPathMode = RootPathModeBoth; - // Check the policy variable for this find command type. std::string findRootPathVar = "CMAKE_FIND_ROOT_PATH_MODE_"; findRootPathVar += this->CMakePathName; @@ -72,11 +62,11 @@ void cmFindCommon::SelectDefaultRootPathMode() this->Makefile->GetSafeDefinition(findRootPathVar); if (rootPathMode=="NEVER") { - this->FindRootPathMode = RootPathModeNoRootPath; + this->FindRootPathMode = RootPathModeNever; } else if (rootPathMode=="ONLY") { - this->FindRootPathMode = RootPathModeOnlyRootPath; + this->FindRootPathMode = RootPathModeOnly; } else if (rootPathMode=="BOTH") { @@ -152,7 +142,7 @@ void cmFindCommon::RerootPaths(std::vector& paths) #endif // Short-circuit if there is nothing to do. - if(this->FindRootPathMode == RootPathModeNoRootPath) + if(this->FindRootPathMode == RootPathModeNever) { return; } @@ -280,8 +270,6 @@ void cmFindCommon::GetIgnoredPaths(std::set& ignore) ignore.insert(ignoreVec.begin(), ignoreVec.end()); } - - //---------------------------------------------------------------------------- bool cmFindCommon::CheckCommonArgument(std::string const& arg) { @@ -307,11 +295,11 @@ bool cmFindCommon::CheckCommonArgument(std::string const& arg) } else if(arg == "NO_CMAKE_FIND_ROOT_PATH") { - this->FindRootPathMode = RootPathModeNoRootPath; + this->FindRootPathMode = RootPathModeNever; } else if(arg == "ONLY_CMAKE_FIND_ROOT_PATH") { - this->FindRootPathMode = RootPathModeOnlyRootPath; + this->FindRootPathMode = RootPathModeOnly; } else if(arg == "CMAKE_FIND_ROOT_PATH_BOTH") { @@ -358,91 +346,6 @@ void cmFindCommon::AddPathSuffix(std::string const& arg) this->SearchPathSuffixes.push_back(suffix); } -//---------------------------------------------------------------------------- -void cmFindCommon::AddUserPath(std::string const& inPath, - std::vector& outPaths) -{ - // We should view the registry as the target application would view - // it. - cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32; - cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64; - if(this->Makefile->PlatformIs64Bit()) - { - view = cmSystemTools::KeyWOW64_64; - other_view = cmSystemTools::KeyWOW64_32; - } - - // Expand using the view of the target application. - std::string expanded = inPath; - cmSystemTools::ExpandRegistryValues(expanded, view); - cmSystemTools::GlobDirs(expanded, outPaths); - - // Executables can be either 32-bit or 64-bit, so expand using the - // alternative view. - if(expanded != inPath && this->CMakePathName == "PROGRAM") - { - expanded = inPath; - cmSystemTools::ExpandRegistryValues(expanded, other_view); - cmSystemTools::GlobDirs(expanded, outPaths); - } -} - -//---------------------------------------------------------------------------- -void cmFindCommon::AddCMakePath(const std::string& variable, - std::vector& outPaths) -{ - // Get a path from a CMake variable. - if(const char* varPath = this->Makefile->GetDefinition(variable)) - { - std::vector tmp; - cmSystemTools::ExpandListArgument(varPath, tmp); - - // Relative paths are interpreted with respect to the current - // source directory. - this->AddPathsInternal(tmp, CMakePath, outPaths); - } -} - -//---------------------------------------------------------------------------- -void cmFindCommon::AddEnvPath(const char* variable, - std::vector& outPaths) -{ - // Get a path from the environment. - std::vector tmp; - cmSystemTools::GetPath(tmp, variable); - // Relative paths are interpreted with respect to the current - // working directory. - this->AddPathsInternal(tmp, EnvPath, outPaths); -} - -//---------------------------------------------------------------------------- -void cmFindCommon::AddPathsInternal(std::vector const& inPaths, - PathType pathType, - std::vector& outPaths) -{ - for(std::vector::const_iterator i = inPaths.begin(); - i != inPaths.end(); ++i) - { - this->AddPathInternal(this->MakeFullPath(*i, pathType), outPaths); - } -} - -//---------------------------------------------------------------------------- -void cmFindCommon::AddPathInternal(std::string const& inPath, - std::vector& outPaths) -{ - if(inPath.empty()) - { - return; - } - - // Insert the path if has not already been emitted. - if(this->SearchPathsEmitted.insert(inPath).second) - { - outPaths.push_back(inPath); - } -} - //---------------------------------------------------------------------------- void AddTrailingSlash(std::string& s) { @@ -458,17 +361,15 @@ void cmFindCommon::ComputeFinalPaths() 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); + this->CMakeVariablePaths.ExtractWithout(ignored, this->SearchPaths, true); + this->CMakeEnvironmentPaths.ExtractWithout(ignored, this->SearchPaths); + this->UserHintsPaths.ExtractWithout(ignored, this->SearchPaths); + this->SystemEnvironmentPaths.ExtractWithout(ignored, this->SearchPaths); + this->UserRegistryPaths.ExtractWithout(ignored, this->SearchPaths); + this->BuildPaths.ExtractWithout(ignored, this->SearchPaths); + this->CMakeSystemVariablePaths.ExtractWithout(ignored, this->SearchPaths); + this->SystemRegistryPaths.ExtractWithout(ignored, this->SearchPaths); + this->UserGuessPaths.ExtractWithout(ignored, this->SearchPaths); // Expand list of paths inside all search roots. this->RerootPaths(this->SearchPaths); diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h index dfb942ff4..810239231 100644 --- a/Source/cmFindCommon.h +++ b/Source/cmFindCommon.h @@ -13,6 +13,7 @@ #define cmFindCommon_h #include "cmCommand.h" +#include "cmSearchPath.h" /** \class cmFindCommon * \brief Base class for FIND_XXX implementations. @@ -29,15 +30,11 @@ public: cmTypeMacro(cmFindCommon, cmCommand); protected: + friend class cmSearchPath; - enum RootPathMode { RootPathModeBoth, - RootPathModeOnlyRootPath, - RootPathModeNoRootPath }; - - enum PathType { FullPath, CMakePath, EnvPath }; - - /** Generate a full path based on the particular path type */ - std::string MakeFullPath(const std::string& path, PathType pathType); + enum RootPathMode { RootPathModeNever, + RootPathModeOnly, + RootPathModeBoth }; /** Place a set of search paths under the search roots. */ void RerootPaths(std::vector& paths); @@ -60,21 +57,15 @@ protected: /** Compute the current default bundle/framework search policy. */ void SelectDefaultMacMode(); + // Path arguments prior to path manipulation routines + std::vector UserHintsArgs; + std::vector UserGuessArgs; + std::string CMakePathName; RootPathMode FindRootPathMode; bool CheckCommonArgument(std::string const& arg); void AddPathSuffix(std::string const& arg); - void AddUserPath(std::string const& p, - std::vector& outPaths); - void AddCMakePath(const std::string& variable, - std::vector& outPaths); - void AddEnvPath(const char* variable, std::vector& outPaths); - void AddPathsInternal(std::vector const& inPaths, - PathType pathType, std::vector& outPaths); - void AddPathInternal(std::string const& inPath, - std::vector& outPaths); - void SetMakefile(cmMakefile* makefile); bool NoDefaultPath; @@ -84,15 +75,15 @@ protected: bool NoCMakeSystemPath; std::vector SearchPathSuffixes; - std::vector CMakeVariablePaths; - std::vector CMakeEnvironmentPaths; - std::vector UserHintsPaths; - std::vector SystemEnvironmentPaths; - std::vector UserRegistryPaths; - std::vector BuildPaths; - std::vector CMakeSystemVariablePaths; - std::vector SystemRegistryPaths; - std::vector UserGuessPaths; + cmSearchPath CMakeVariablePaths; + cmSearchPath CMakeEnvironmentPaths; + cmSearchPath UserHintsPaths; + cmSearchPath SystemEnvironmentPaths; + cmSearchPath UserRegistryPaths; + cmSearchPath BuildPaths; + cmSearchPath CMakeSystemVariablePaths; + cmSearchPath SystemRegistryPaths; + cmSearchPath UserGuessPaths; std::vector SearchPaths; std::set SearchPathsEmitted; diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index ded6eeed5..258678d48 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -248,11 +248,11 @@ bool cmFindPackageCommand } else if(doing == DoingPaths) { - this->AddUserPath(args[i], this->UserGuessPaths); + this->UserGuessArgs.push_back(args[i]); } else if(doing == DoingHints) { - this->AddUserPath(args[i], this->UserHintsPaths); + this->UserHintsArgs.push_back(args[i]); } else if(doing == DoingPathSuffixes) { @@ -1153,25 +1153,20 @@ void cmFindPackageCommand::FillPrefixesCMakeEnvironment() { // 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->CMakeEnvironmentPaths.AddEnvPath(this->Variable); - this->AddEnvPath("CMAKE_PREFIX_PATH", this->CMakeEnvironmentPaths); - this->AddEnvPath("CMAKE_FRAMEWORK_PATH", this->CMakeEnvironmentPaths); - this->AddEnvPath("CMAKE_APPBUNDLE_PATH", this->CMakeEnvironmentPaths); + // And now the general CMake environment variables + this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_PREFIX_PATH"); + this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_FRAMEWORK_PATH"); + this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_APPBUNDLE_PATH"); } //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesCMakeVariable() { - this->AddCMakePath("CMAKE_PREFIX_PATH", this->CMakeVariablePaths); - this->AddCMakePath("CMAKE_FRAMEWORK_PATH", this->CMakeVariablePaths); - this->AddCMakePath("CMAKE_APPBUNDLE_PATH", this->CMakeVariablePaths); + this->CMakeVariablePaths.AddCMakePath("CMAKE_PREFIX_PATH"); + this->CMakeVariablePaths.AddCMakePath("CMAKE_FRAMEWORK_PATH"); + this->CMakeVariablePaths.AddCMakePath("CMAKE_APPBUNDLE_PATH"); } //---------------------------------------------------------------------------- @@ -1189,14 +1184,12 @@ void cmFindPackageCommand::FillPrefixesSystemEnvironment() if((cmHasLiteralSuffix(*i, "/bin")) || (cmHasLiteralSuffix(*i, "/sbin"))) { - this->AddPathInternal(MakeFullPath(cmSystemTools::GetFilenamePath(*i), - EnvPath), - this->SystemEnvironmentPaths); + this->SystemEnvironmentPaths.AddPath( + cmSystemTools::GetFilenamePath(*i)); } else { - this->AddPathInternal(MakeFullPath(*i, EnvPath), - this->SystemEnvironmentPaths); + this->SystemEnvironmentPaths.AddPath(*i); } } } @@ -1280,7 +1273,7 @@ void cmFindPackageCommand::LoadPackageRegistryWinSystem() //---------------------------------------------------------------------------- void cmFindPackageCommand::LoadPackageRegistryWin(bool user, unsigned int view, - std::vector& outPaths) + cmSearchPath& outPaths) { std::wstring key = L"Software\\Kitware\\CMake\\Packages\\"; key += cmsys::Encoding::ToWide(this->Name); @@ -1350,7 +1343,7 @@ public: //---------------------------------------------------------------------------- void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir, - std::vector& outPaths) + cmSearchPath& outPaths) { cmsys::Directory files; if(!files.Load(dir)) @@ -1388,7 +1381,7 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir, //---------------------------------------------------------------------------- bool cmFindPackageCommand::CheckPackageRegistryEntry(const std::string& fname, - std::vector& outPaths) + cmSearchPath& outPaths) { // Parse the content of one package registry entry. if(cmSystemTools::FileIsFullPath(fname.c_str())) @@ -1400,13 +1393,11 @@ bool cmFindPackageCommand::CheckPackageRegistryEntry(const std::string& fname, // The path exists. Look for the package here. if(!cmSystemTools::FileIsDirectory(fname)) { - this->AddPathInternal( - MakeFullPath(cmSystemTools::GetFilenamePath(fname), FullPath), - outPaths); + outPaths.AddPath(cmSystemTools::GetFilenamePath(fname)); } else { - this->AddPathInternal(MakeFullPath(fname, FullPath), outPaths); + outPaths.AddPath(fname); } return true; } @@ -1443,7 +1434,7 @@ void cmFindPackageCommand::FillPrefixesBuilds() if(cmSystemTools::FileIsFullPath(f.c_str()) && cmSystemTools::FileIsDirectory(f.c_str())) { - this->AddPathInternal(MakeFullPath(f, FullPath), this->BuildPaths); + this->BuildPaths.AddPath(f); } } } @@ -1451,28 +1442,29 @@ void cmFindPackageCommand::FillPrefixesBuilds() //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesCMakeSystemVariable() { - this->AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH", - this->CMakeSystemVariablePaths); - this->AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH", - this->CMakeSystemVariablePaths); - this->AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH", - this->CMakeSystemVariablePaths); + this->CMakeSystemVariablePaths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); + this->CMakeSystemVariablePaths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); + this->CMakeSystemVariablePaths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH"); } //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesUserGuess() { - std::vector inPaths; - inPaths.swap(this->UserGuessPaths); - this->AddPathsInternal(inPaths, CMakePath, this->UserGuessPaths); + for(std::vector::const_iterator p = this->UserGuessArgs.begin(); + p != this->UserGuessArgs.end(); ++p) + { + this->UserGuessPaths.AddUserPath(*p); + } } //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesUserHints() { - std::vector inPaths; - inPaths.swap(this->UserHintsPaths); - this->AddPathsInternal(inPaths, CMakePath, this->UserHintsPaths); + for(std::vector::const_iterator p = this->UserHintsArgs.begin(); + p != this->UserHintsArgs.end(); ++p) + { + this->UserHintsPaths.AddUserPath(*p); + } } //---------------------------------------------------------------------------- diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index f22433e2a..17bc45627 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -78,14 +78,13 @@ private: void FillPrefixesCMakeSystemVariable(); void FillPrefixesUserGuess(); void FillPrefixesUserHints(); - void LoadPackageRegistryDir(std::string const& dir, - std::vector& outPaths); + void LoadPackageRegistryDir(std::string const& dir, cmSearchPath& outPaths); void LoadPackageRegistryWinUser(); void LoadPackageRegistryWinSystem(); void LoadPackageRegistryWin(bool user, unsigned int view, - std::vector& outPaths); + cmSearchPath& outPaths); bool CheckPackageRegistryEntry(const std::string& fname, - std::vector& outPaths); + cmSearchPath& outPaths); bool SearchDirectory(std::string const& dir); bool CheckDirectory(std::string const& dir); bool FindConfigFile(std::string const& dir, std::string& file); diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx new file mode 100644 index 000000000..19f2c3fe5 --- /dev/null +++ b/Source/cmSearchPath.cxx @@ -0,0 +1,243 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmSearchPath.h" +#include "cmFindCommon.h" + +//---------------------------------------------------------------------------- +cmSearchPath::cmSearchPath(cmFindCommon* findCmd, + const std::string& groupLabel) +: FindName(findCmd->CMakePathName), Makefile(findCmd->Makefile), + Emitted(findCmd->SearchPathsEmitted), Label(groupLabel) +{ +} + +//---------------------------------------------------------------------------- +cmSearchPath::~cmSearchPath() +{ +} + +//---------------------------------------------------------------------------- + +void cmSearchPath::ExtractWithout(const std::set& ignore, + std::vector& outPaths, + bool clear) const +{ + if(clear) + { + outPaths.clear(); + } + for(std::vector::const_iterator p = this->Paths.begin(); + p != this->Paths.end(); ++p) + { + if(ignore.count(*p) == 0) + { + outPaths.push_back(*p); + } + } +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddPath(const std::string& path) +{ + this->AddPathInternal(path); +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddUserPath(const std::string& path) +{ + std::vector outPaths; + + // We should view the registry as the target application would view + // it. + cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32; + cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64; + if(this->Makefile->PlatformIs64Bit()) + { + view = cmSystemTools::KeyWOW64_64; + other_view = cmSystemTools::KeyWOW64_32; + } + + // Expand using the view of the target application. + std::string expanded = path; + cmSystemTools::ExpandRegistryValues(expanded, view); + cmSystemTools::GlobDirs(expanded, outPaths); + + // Executables can be either 32-bit or 64-bit, so expand using the + // alternative view. + if(expanded != path && this->FindName == "PROGRAM") + { + expanded = path; + cmSystemTools::ExpandRegistryValues(expanded, other_view); + cmSystemTools::GlobDirs(expanded, outPaths); + } + + // Process them all from the current directory + for(std::vector::const_iterator p = outPaths.begin(); + p != outPaths.end(); ++p) + { + this->AddPathInternal(*p, this->Makefile->GetCurrentDirectory()); + } +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddCMakePath(const std::string& variable) +{ + // Get a path from a CMake variable. + if(const char* value = this->Makefile->GetDefinition(variable)) + { + std::vector expanded; + cmSystemTools::ExpandListArgument(value, expanded); + + for(std::vector::const_iterator p = expanded.begin(); + p!= expanded.end(); ++p) + { + this->AddPathInternal(*p, this->Makefile->GetCurrentDirectory()); + } + } +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddEnvPath(const std::string& variable) +{ + std::vector expanded; + cmSystemTools::GetPath(expanded, variable.c_str()); + for(std::vector::const_iterator p = expanded.begin(); + p!= expanded.end(); ++p) + { + this->AddPathInternal(*p); + } +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddCMakePrefixPath(const std::string& variable) +{ + // Get a path from a CMake variable. + if(const char* value = this->Makefile->GetDefinition(variable)) + { + std::vector expanded; + cmSystemTools::ExpandListArgument(value, expanded); + + this->AddPrefixPaths(expanded, this->Makefile->GetCurrentDirectory()); + } +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddEnvPrefixPath(const std::string& variable) +{ + std::vector expanded; + cmSystemTools::GetPath(expanded, variable.c_str()); + this->AddPrefixPaths(expanded); +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddSuffixes(const std::vector& suffixes) +{ + std::vector inPaths; + inPaths.swap(this->Paths); + this->Paths.reserve(inPaths.size()*(suffixes.size()+1)); + + for(std::vector::iterator ip = inPaths.begin(); + ip != inPaths.end(); ++ip) + { + cmSystemTools::ConvertToUnixSlashes(*ip); + + // 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() != '/') + { + p += "/"; + } + + // Combine with all the suffixes + for(std::vector::const_iterator s = suffixes.begin(); + s != suffixes.end(); ++s) + { + this->Paths.push_back(p+*s); + } + + // And now the original w/o any suffix + this->Paths.push_back(*ip); + } +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddPrefixPaths(const std::vector& paths, + const char *base) +{ + // default for programs + std::string subdir = "bin"; + + if (this->FindName == "INCLUDE") + { + subdir = "include"; + } + else if (this->FindName == "LIBRARY") + { + subdir = "lib"; + } + else if (this->FindName == "FRAMEWORK") + { + subdir = ""; // ? what to do for frameworks ? + } + + for(std::vector::const_iterator p = paths.begin(); + p != paths.end(); ++p) + { + std::string dir = *p; + if(!subdir.empty() && !dir.empty() && *dir.rbegin() != '/') + { + dir += "/"; + } + if(subdir == "include" || subdir == "lib") + { + const char* arch = + this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); + if(arch && *arch) + { + this->AddPathInternal(dir+subdir+"/"+arch, base); + } + } + std::string add = dir + subdir; + if(add != "/") + { + this->AddPathInternal(add, base); + } + if (subdir == "bin") + { + this->AddPathInternal(dir+"sbin", base); + } + if(!subdir.empty() && *p != "/") + { + this->AddPathInternal(*p, base); + } + } +} + +//---------------------------------------------------------------------------- +void cmSearchPath::AddPathInternal(const std::string& path, const char *base) +{ + std::string collapsed = cmSystemTools::CollapseFullPath(path, base); + + if(collapsed.empty()) + { + return; + } + + // Insert the path if has not already been emitted. + if(this->Emitted.insert(collapsed).second) + { + this->Paths.push_back(collapsed); + } +} diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h new file mode 100644 index 000000000..88ef0ff25 --- /dev/null +++ b/Source/cmSearchPath.h @@ -0,0 +1,60 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmSearchPath_h +#define cmSearchPath_h + +#include "cmStandardIncludes.h" + +class cmFindCommon; + +/** \class cmSearchPath + * \brief Base class for FIND_XXX implementations. + * + * cmSearchPath is a container that encapsulates search path construction and + * management + */ +class cmSearchPath +{ +public: + cmSearchPath(cmFindCommon* findCmd, const std::string& groupLabel); + ~cmSearchPath(); + + const std::string& GetLabel() const { return this->Label; } + const std::vector& GetPaths() const { return this->Paths; } + + void ExtractWithout(const std::set& ignore, + std::vector& outPaths, + bool clear = false) const; + + void AddPath(const std::string& path); + void AddUserPath(const std::string& path); + void AddCMakePath(const std::string& variable); + void AddEnvPath(const std::string& variable); + void AddCMakePrefixPath(const std::string& variable); + void AddEnvPrefixPath(const std::string& variable); + void AddSuffixes(const std::vector& suffixes); + +protected: + void AddPrefixPaths(const std::vector& paths, + const char *base = 0); + void AddPathInternal(const std::string& path, const char *base = 0); + + // Members collected from the calling find command + const std::string& FindName; + cmMakefile* const& Makefile; + std::set& Emitted; + + std::string Label; + std::vector Paths; +}; + +#endif From 1abd7cd930022ba045c3c0cd34406cbe19db84d3 Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Fri, 17 Oct 2014 13:07:26 -0400 Subject: [PATCH 3/3] Use containers of labeled search paths instead of individual members Manage classes of search paths in labeled containers. This removes the need to have a seperate member variable for each type of search path, but also allows path types to be grouped togethor in various different ways and manipulated as subsets of the full set of search paths. --- Source/cmBootstrapCommands1.cxx | 3 +- Source/cmFindBase.cxx | 58 ++++++++++-------- Source/cmFindCommon.cxx | 76 ++++++++++++++++------- Source/cmFindCommon.h | 50 +++++++++++++--- Source/cmFindPackageCommand.cxx | 103 +++++++++++++++++++++++--------- Source/cmFindPackageCommand.h | 15 +++++ Source/cmPathLabel.cxx | 41 +++++++++++++ Source/cmPathLabel.h | 44 ++++++++++++++ Source/cmSearchPath.cxx | 40 ++++++++----- Source/cmSearchPath.h | 15 ++--- 10 files changed, 339 insertions(+), 106 deletions(-) create mode 100644 Source/cmPathLabel.cxx create mode 100644 Source/cmPathLabel.h diff --git a/Source/cmBootstrapCommands1.cxx b/Source/cmBootstrapCommands1.cxx index 29d36710e..55026099f 100644 --- a/Source/cmBootstrapCommands1.cxx +++ b/Source/cmBootstrapCommands1.cxx @@ -43,7 +43,6 @@ #include "cmExecuteProcessCommand.cxx" #include "cmExternalMakefileProjectGenerator.cxx" #include "cmFindBase.cxx" -#include "cmSearchPath.cxx" #include "cmFindCommon.cxx" #include "cmFileCommand.cxx" #include "cmFindFileCommand.cxx" @@ -53,6 +52,8 @@ #include "cmFindProgramCommand.cxx" #include "cmForEachCommand.cxx" #include "cmFunctionCommand.cxx" +#include "cmPathLabel.cxx" +#include "cmSearchPath.cxx" void GetBootstrapCommands1(std::list& commands) { diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 52f04ad30..beb6dde74 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -225,102 +225,112 @@ void cmFindBase::ExpandPaths() //---------------------------------------------------------------------------- void cmFindBase::FillCMakeEnvironmentPath() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::CMakeEnvironment]; + // Add CMAKE_*_PATH environment variables std::string var = "CMAKE_"; var += this->CMakePathName; var += "_PATH"; - this->CMakeEnvironmentPaths.AddEnvPrefixPath("CMAKE_PREFIX_PATH"); - this->CMakeEnvironmentPaths.AddEnvPath(var); + paths.AddEnvPrefixPath("CMAKE_PREFIX_PATH"); + paths.AddEnvPath(var); if(this->CMakePathName == "PROGRAM") { - this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_APPBUNDLE_PATH"); + paths.AddEnvPath("CMAKE_APPBUNDLE_PATH"); } else { - this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_FRAMEWORK_PATH"); + paths.AddEnvPath("CMAKE_FRAMEWORK_PATH"); } - this->CMakeEnvironmentPaths.AddSuffixes(this->SearchPathSuffixes); + paths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- void cmFindBase::FillCMakeVariablePath() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::CMake]; + // 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->CMakeVariablePaths.AddCMakePrefixPath("CMAKE_PREFIX_PATH"); - this->CMakeVariablePaths.AddCMakePath(var); + paths.AddCMakePrefixPath("CMAKE_PREFIX_PATH"); + paths.AddCMakePath(var); if(this->CMakePathName == "PROGRAM") { - this->CMakeVariablePaths.AddCMakePath("CMAKE_APPBUNDLE_PATH"); + paths.AddCMakePath("CMAKE_APPBUNDLE_PATH"); } else { - this->CMakeVariablePaths.AddCMakePath("CMAKE_FRAMEWORK_PATH"); + paths.AddCMakePath("CMAKE_FRAMEWORK_PATH"); } - this->CMakeVariablePaths.AddSuffixes(this->SearchPathSuffixes); + paths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- void cmFindBase::FillSystemEnvironmentPath() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::SystemEnvironment]; + // Add LIB or INCLUDE if(!this->EnvironmentPath.empty()) { - this->SystemEnvironmentPaths.AddEnvPath(this->EnvironmentPath); + paths.AddEnvPath(this->EnvironmentPath); } // Add PATH - this->SystemEnvironmentPaths.AddEnvPath("PATH"); - this->SystemEnvironmentPaths.AddSuffixes(this->SearchPathSuffixes); + paths.AddEnvPath("PATH"); + paths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- void cmFindBase::FillCMakeSystemVariablePath() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::CMakeSystem]; + std::string var = "CMAKE_SYSTEM_"; var += this->CMakePathName; var += "_PATH"; - this->CMakeSystemVariablePaths.AddCMakePrefixPath( - "CMAKE_SYSTEM_PREFIX_PATH"); - this->CMakeSystemVariablePaths.AddCMakePath(var); + paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH"); + paths.AddCMakePath(var); if(this->CMakePathName == "PROGRAM") { - this->CMakeSystemVariablePaths.AddCMakePath( - "CMAKE_SYSTEM_APPBUNDLE_PATH"); + paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH"); } else { - this->CMakeSystemVariablePaths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); + paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); } - this->CMakeSystemVariablePaths.AddSuffixes(this->SearchPathSuffixes); + paths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- void cmFindBase::FillUserHintsPath() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::Hints]; + for(std::vector::const_iterator p = this->UserHintsArgs.begin(); p != this->UserHintsArgs.end(); ++p) { - this->UserHintsPaths.AddUserPath(*p); + paths.AddUserPath(*p); } - this->UserHintsPaths.AddSuffixes(this->SearchPathSuffixes); + paths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- void cmFindBase::FillUserGuessPath() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::Guess]; + for(std::vector::const_iterator p = this->UserGuessArgs.begin(); p != this->UserGuessArgs.end(); ++p) { - this->UserGuessPaths.AddUserPath(*p); + paths.AddUserPath(*p); } - this->UserGuessPaths.AddSuffixes(this->SearchPathSuffixes); + paths.AddSuffixes(this->SearchPathSuffixes); } //---------------------------------------------------------------------------- diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 87e98c198..913985fdb 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -13,17 +13,19 @@ #include #include +//---------------------------------------------------------------------------- +cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL"); +cmFindCommon::PathLabel cmFindCommon::PathLabel::CMake("CMAKE"); +cmFindCommon::PathLabel + cmFindCommon::PathLabel::CMakeEnvironment("CMAKE_ENVIRONMENT"); +cmFindCommon::PathLabel cmFindCommon::PathLabel::Hints("HINTS"); +cmFindCommon::PathLabel + cmFindCommon::PathLabel::SystemEnvironment("SYSTM_ENVIRONMENT"); +cmFindCommon::PathLabel cmFindCommon::PathLabel::CMakeSystem("CMAKE_SYSTEM"); +cmFindCommon::PathLabel cmFindCommon::PathLabel::Guess("GUESS"); + //---------------------------------------------------------------------------- cmFindCommon::cmFindCommon() -: CMakeVariablePaths(this, "CMAKE"), - CMakeEnvironmentPaths(this, "CMAKE_ENVIRONMENT"), - UserHintsPaths(this, "HINTS"), - SystemEnvironmentPaths(this, "SYSTEM_ENVIRONMENT"), - UserRegistryPaths(this, "USER_REGISTRY"), - BuildPaths(this, "BUILD"), - CMakeSystemVariablePaths(this, "CMAKE_SYSTEM_VARIABLE"), - SystemRegistryPaths(this, "SYSTEM_REGISTRY"), - UserGuessPaths(this, "GUESS") { this->FindRootPathMode = RootPathModeBoth; this->NoDefaultPath = false; @@ -45,6 +47,8 @@ cmFindCommon::cmFindCommon() this->SearchFrameworkLast = false; this->SearchAppBundleOnly = false; this->SearchAppBundleLast = false; + + this->InitializeSearchPathGroups(); } //---------------------------------------------------------------------------- @@ -52,6 +56,40 @@ cmFindCommon::~cmFindCommon() { } +//---------------------------------------------------------------------------- +void cmFindCommon::InitializeSearchPathGroups() +{ + std::vector* labels; + + // Define the varoius different groups of path types + + // All search paths + labels = &this->PathGroupLabelMap[PathGroup::All]; + labels->push_back(PathLabel::CMake); + labels->push_back(PathLabel::CMakeEnvironment); + labels->push_back(PathLabel::Hints); + labels->push_back(PathLabel::SystemEnvironment); + labels->push_back(PathLabel::CMakeSystem); + labels->push_back(PathLabel::Guess); + + // Define the search group order + this->PathGroupOrder.push_back(PathGroup::All); + + // Create the idividual labeld search paths + this->LabeledPaths.insert(std::make_pair(PathLabel::CMake, + cmSearchPath(this))); + this->LabeledPaths.insert(std::make_pair(PathLabel::CMakeEnvironment, + cmSearchPath(this))); + this->LabeledPaths.insert(std::make_pair(PathLabel::Hints, + cmSearchPath(this))); + this->LabeledPaths.insert(std::make_pair(PathLabel::SystemEnvironment, + cmSearchPath(this))); + this->LabeledPaths.insert(std::make_pair(PathLabel::CMakeSystem, + cmSearchPath(this))); + this->LabeledPaths.insert(std::make_pair(PathLabel::Guess, + cmSearchPath(this))); +} + //---------------------------------------------------------------------------- void cmFindCommon::SelectDefaultRootPathMode() { @@ -140,12 +178,12 @@ void cmFindCommon::RerootPaths(std::vector& paths) fprintf(stderr, "[%s]\n", i->c_str()); } #endif - // Short-circuit if there is nothing to do. if(this->FindRootPathMode == RootPathModeNever) { return; } + const char* sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT"); const char* rootPath = @@ -293,7 +331,7 @@ bool cmFindCommon::CheckCommonArgument(std::string const& arg) { this->NoCMakeSystemPath = true; } - else if(arg == "NO_CMAKE_FIND_ROOT_PATH") + else if(arg == "NO_CMAKE_FIND_ROOT_PATH") { this->FindRootPathMode = RootPathModeNever; } @@ -361,15 +399,13 @@ void cmFindCommon::ComputeFinalPaths() this->GetIgnoredPaths(ignored); // Combine the seperate path types, filtering out ignores - this->CMakeVariablePaths.ExtractWithout(ignored, this->SearchPaths, true); - this->CMakeEnvironmentPaths.ExtractWithout(ignored, this->SearchPaths); - this->UserHintsPaths.ExtractWithout(ignored, this->SearchPaths); - this->SystemEnvironmentPaths.ExtractWithout(ignored, this->SearchPaths); - this->UserRegistryPaths.ExtractWithout(ignored, this->SearchPaths); - this->BuildPaths.ExtractWithout(ignored, this->SearchPaths); - this->CMakeSystemVariablePaths.ExtractWithout(ignored, this->SearchPaths); - this->SystemRegistryPaths.ExtractWithout(ignored, this->SearchPaths); - this->UserGuessPaths.ExtractWithout(ignored, this->SearchPaths); + this->SearchPaths.clear(); + std::vector& allLabels = this->PathGroupLabelMap[PathGroup::All]; + for(std::vector::const_iterator l = allLabels.begin(); + l != allLabels.end(); ++l) + { + this->LabeledPaths[*l].ExtractWithout(ignored, this->SearchPaths); + } // Expand list of paths inside all search roots. this->RerootPaths(this->SearchPaths); diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h index 810239231..e65b2fcce 100644 --- a/Source/cmFindCommon.h +++ b/Source/cmFindCommon.h @@ -14,6 +14,7 @@ #include "cmCommand.h" #include "cmSearchPath.h" +#include "cmPathLabel.h" /** \class cmFindCommon * \brief Base class for FIND_XXX implementations. @@ -32,10 +33,45 @@ public: protected: friend class cmSearchPath; +/* VS6 is broken and can't pass protected class definitions to child classes */ +#if defined(_MSC_VER) && (_MSC_VER < 1300) +public: +#endif + /** Used to define groups of path labels */ + class PathGroup : public cmPathLabel + { + protected: + PathGroup(); + public: + PathGroup(const std::string& label) : cmPathLabel(label) { } + static PathGroup All; + }; + + /* Individual path types */ + class PathLabel : public cmPathLabel + { + protected: + PathLabel(); + public: + PathLabel(const std::string& label) : cmPathLabel(label) { } + static PathLabel CMake; + static PathLabel CMakeEnvironment; + static PathLabel Hints; + static PathLabel SystemEnvironment; + static PathLabel CMakeSystem; + static PathLabel Guess; + }; +#if defined(_MSC_VER) && (_MSC_VER < 1300) +protected: +#endif + enum RootPathMode { RootPathModeNever, RootPathModeOnly, RootPathModeBoth }; + /** Construct the various path groups and labels */ + void InitializeSearchPathGroups(); + /** Place a set of search paths under the search roots. */ void RerootPaths(std::vector& paths); @@ -75,15 +111,11 @@ protected: bool NoCMakeSystemPath; std::vector SearchPathSuffixes; - cmSearchPath CMakeVariablePaths; - cmSearchPath CMakeEnvironmentPaths; - cmSearchPath UserHintsPaths; - cmSearchPath SystemEnvironmentPaths; - cmSearchPath UserRegistryPaths; - cmSearchPath BuildPaths; - cmSearchPath CMakeSystemVariablePaths; - cmSearchPath SystemRegistryPaths; - cmSearchPath UserGuessPaths; + + std::map > PathGroupLabelMap; + std::vector PathGroupOrder; + std::map PathLabelStringMap; + std::map LabeledPaths; std::vector SearchPaths; std::set SearchPathsEmitted; diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 258678d48..51f33fda2 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -25,6 +25,14 @@ #include #endif +//---------------------------------------------------------------------------- +cmFindPackageCommand::PathLabel + cmFindPackageCommand::PathLabel::UserRegistry("PACKAGE_REGISTRY"); +cmFindPackageCommand::PathLabel + cmFindPackageCommand::PathLabel::Builds("BUILDS"); +cmFindPackageCommand::PathLabel + cmFindPackageCommand::PathLabel::SystemRegistry("SYSTEM_PACKAGE_REGISTRY"); + //---------------------------------------------------------------------------- cmFindPackageCommand::cmFindPackageCommand() { @@ -51,6 +59,33 @@ cmFindPackageCommand::cmFindPackageCommand() this->VersionFoundTweak = 0; this->VersionFoundCount = 0; this->RequiredCMakeVersion = 0; + + this->AppendSearchPathGroups(); +} + +//---------------------------------------------------------------------------- +void cmFindPackageCommand::AppendSearchPathGroups() +{ + std::vector* labels; + + // Update the All group with new paths + labels = &this->PathGroupLabelMap[PathGroup::All]; + labels->insert(std::find(labels->begin(), labels->end(), + PathLabel::CMakeSystem), + PathLabel::UserRegistry); + labels->insert(std::find(labels->begin(), labels->end(), + PathLabel::CMakeSystem), + PathLabel::Builds); + labels->insert(std::find(labels->begin(), labels->end(), PathLabel::Guess), + PathLabel::SystemRegistry); + + // Create the new path objects + this->LabeledPaths.insert(std::make_pair(PathLabel::UserRegistry, + cmSearchPath(this))); + this->LabeledPaths.insert(std::make_pair(PathLabel::Builds, + cmSearchPath(this))); + this->LabeledPaths.insert(std::make_pair(PathLabel::SystemRegistry, + cmSearchPath(this))); } //---------------------------------------------------------------------------- @@ -1151,27 +1186,33 @@ void cmFindPackageCommand::ComputePrefixes() //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesCMakeEnvironment() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::CMakeEnvironment]; + // Check the environment variable with the same name as the cache // entry. - this->CMakeEnvironmentPaths.AddEnvPath(this->Variable); + paths.AddEnvPath(this->Variable); // And now the general CMake environment variables - this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_PREFIX_PATH"); - this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_FRAMEWORK_PATH"); - this->CMakeEnvironmentPaths.AddEnvPath("CMAKE_APPBUNDLE_PATH"); + paths.AddEnvPath("CMAKE_PREFIX_PATH"); + paths.AddEnvPath("CMAKE_FRAMEWORK_PATH"); + paths.AddEnvPath("CMAKE_APPBUNDLE_PATH"); } //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesCMakeVariable() { - this->CMakeVariablePaths.AddCMakePath("CMAKE_PREFIX_PATH"); - this->CMakeVariablePaths.AddCMakePath("CMAKE_FRAMEWORK_PATH"); - this->CMakeVariablePaths.AddCMakePath("CMAKE_APPBUNDLE_PATH"); + cmSearchPath &paths = this->LabeledPaths[PathLabel::CMake]; + + paths.AddCMakePath("CMAKE_PREFIX_PATH"); + paths.AddCMakePath("CMAKE_FRAMEWORK_PATH"); + paths.AddCMakePath("CMAKE_APPBUNDLE_PATH"); } //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesSystemEnvironment() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::SystemEnvironment]; + // Use the system search path to generate prefixes. // Relative paths are interpreted with respect to the current // working directory. @@ -1184,12 +1225,11 @@ void cmFindPackageCommand::FillPrefixesSystemEnvironment() if((cmHasLiteralSuffix(*i, "/bin")) || (cmHasLiteralSuffix(*i, "/sbin"))) { - this->SystemEnvironmentPaths.AddPath( - cmSystemTools::GetFilenamePath(*i)); + paths.AddPath(cmSystemTools::GetFilenamePath(*i)); } else { - this->SystemEnvironmentPaths.AddPath(*i); + paths.AddPath(*i); } } } @@ -1207,7 +1247,8 @@ void cmFindPackageCommand::FillPrefixesUserRegistry() std::string fname = dir; fname += "/cmake/packages/"; fname += Name; - this->LoadPackageRegistryDir(fname, this->UserRegistryPaths); + this->LoadPackageRegistryDir(fname, + this->LabeledPaths[PathLabel::UserRegistry]); } #else if(const char* home = cmSystemTools::GetEnv("HOME")) @@ -1215,7 +1256,8 @@ void cmFindPackageCommand::FillPrefixesUserRegistry() std::string dir = home; dir += "/.cmake/packages/"; dir += this->Name; - this->LoadPackageRegistryDir(dir, this->UserRegistryPaths); + this->LoadPackageRegistryDir(dir, + this->LabeledPaths[PathLabel::UserRegistry]); } #endif } @@ -1247,27 +1289,26 @@ void cmFindPackageCommand::FillPrefixesSystemRegistry() void cmFindPackageCommand::LoadPackageRegistryWinUser() { // HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views. - this->LoadPackageRegistryWin(true, 0, this->UserRegistryPaths); + this->LoadPackageRegistryWin(true, 0, + this->LabeledPaths[PathLabel::UserRegistry]); } //---------------------------------------------------------------------------- void cmFindPackageCommand::LoadPackageRegistryWinSystem() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::SystemRegistry]; + // HKEY_LOCAL_MACHINE\\SOFTWARE has separate 32-bit and 64-bit views. // Prefer the target platform view first. if(this->Makefile->PlatformIs64Bit()) { - this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, - this->SystemRegistryPaths); - this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, - this->SystemRegistryPaths); + this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, paths); + this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, paths); } else { - this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, - this->SystemRegistryPaths); - this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, - this->SystemRegistryPaths); + this->LoadPackageRegistryWin(false, KEY_WOW64_32KEY, paths); + this->LoadPackageRegistryWin(false, KEY_WOW64_64KEY, paths); } } @@ -1421,6 +1462,8 @@ bool cmFindPackageCommand::CheckPackageRegistryEntry(const std::string& fname, //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesBuilds() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::Builds]; + // It is likely that CMake will have recently built the project. for(int i=0; i <= 10; ++i) { @@ -1434,7 +1477,7 @@ void cmFindPackageCommand::FillPrefixesBuilds() if(cmSystemTools::FileIsFullPath(f.c_str()) && cmSystemTools::FileIsDirectory(f.c_str())) { - this->BuildPaths.AddPath(f); + paths.AddPath(f); } } } @@ -1442,28 +1485,34 @@ void cmFindPackageCommand::FillPrefixesBuilds() //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesCMakeSystemVariable() { - this->CMakeSystemVariablePaths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); - this->CMakeSystemVariablePaths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); - this->CMakeSystemVariablePaths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH"); + cmSearchPath &paths = this->LabeledPaths[PathLabel::CMakeSystem]; + + paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH"); + paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH"); + paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH"); } //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesUserGuess() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::Guess]; + for(std::vector::const_iterator p = this->UserGuessArgs.begin(); p != this->UserGuessArgs.end(); ++p) { - this->UserGuessPaths.AddUserPath(*p); + paths.AddUserPath(*p); } } //---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesUserHints() { + cmSearchPath &paths = this->LabeledPaths[PathLabel::Hints]; + for(std::vector::const_iterator p = this->UserHintsArgs.begin(); p != this->UserHintsArgs.end(); ++p) { - this->UserHintsPaths.AddUserPath(*p); + paths.AddUserPath(*p); } } diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 17bc45627..949dcb1d8 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -53,6 +53,21 @@ public: cmTypeMacro(cmFindPackageCommand, cmFindCommon); private: + class PathLabel : public cmFindCommon::PathLabel + { + protected: + PathLabel(); + public: + PathLabel(const std::string& label) : cmFindCommon::PathLabel(label) { } + static PathLabel UserRegistry; + static PathLabel Builds; + static PathLabel SystemRegistry; + }; + + // Add additional search path labels and groups not present in the + // parent class + void AppendSearchPathGroups(); + void AppendSuccessInformation(); void AppendToFoundProperty(bool found); void SetModuleVariables(const std::string& components); diff --git a/Source/cmPathLabel.cxx b/Source/cmPathLabel.cxx new file mode 100644 index 000000000..67d56e180 --- /dev/null +++ b/Source/cmPathLabel.cxx @@ -0,0 +1,41 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmPathLabel.h" + +//---------------------------------------------------------------------------- +cmPathLabel::cmPathLabel(const std::string& label) +: Label(label), Hash(0) +{ + // Use a Jenkins one-at-a-time hash with under/over-flow protection + for(size_t i = 0; i < this->Label.size(); ++i) + { + this->Hash += this->Label[i]; + this->Hash += ((this->Hash & 0x003FFFFF) << 10); + this->Hash ^= ((this->Hash & 0xFFFFFFC0) >> 6); + } + this->Hash += ((this->Hash & 0x1FFFFFFF) << 3); + this->Hash ^= ((this->Hash & 0xFFFFF800) >> 11); + this->Hash += ((this->Hash & 0x0001FFFF) << 15); +} + +//---------------------------------------------------------------------------- +bool cmPathLabel::operator < (const cmPathLabel& l) const +{ + return this->Hash < l.Hash; +} + +//---------------------------------------------------------------------------- +bool cmPathLabel::operator == (const cmPathLabel& l) const +{ + return this->Hash == l.Hash; +} diff --git a/Source/cmPathLabel.h b/Source/cmPathLabel.h new file mode 100644 index 000000000..02d526123 --- /dev/null +++ b/Source/cmPathLabel.h @@ -0,0 +1,44 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmPathLabel_h +#define cmPathLabel_h + +#include "cmStandardIncludes.h" + +/** \class cmPathLabel + * \brief Helper class for text based labels + * + * cmPathLabel is extended in different classes to act as an inheritable + * enum. Comparisons are done on a precomputed Jenkins hash of the string + * label for indexing and searchig. + */ +class cmPathLabel +{ +public: + cmPathLabel(const std::string& label); + + // The comparison operators are only for quick sorting and searching and + // in no way imply any lexicographical order of the label + bool operator < (const cmPathLabel& l) const; + bool operator == (const cmPathLabel& l) const; + + const std::string& GetLabel() const { return this->Label; } + const unsigned int& GetHash() const { return this->Hash; } + +protected: + cmPathLabel(); + + std::string Label; + unsigned int Hash; +}; + +#endif diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index 19f2c3fe5..861dbf178 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -14,10 +14,8 @@ #include "cmFindCommon.h" //---------------------------------------------------------------------------- -cmSearchPath::cmSearchPath(cmFindCommon* findCmd, - const std::string& groupLabel) -: FindName(findCmd->CMakePathName), Makefile(findCmd->Makefile), - Emitted(findCmd->SearchPathsEmitted), Label(groupLabel) +cmSearchPath::cmSearchPath(cmFindCommon* findCmd) +: FC(findCmd) { } @@ -55,13 +53,15 @@ void cmSearchPath::AddPath(const std::string& path) //---------------------------------------------------------------------------- void cmSearchPath::AddUserPath(const std::string& path) { + assert(this->FC != NULL); + std::vector outPaths; // We should view the registry as the target application would view // it. cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32; cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64; - if(this->Makefile->PlatformIs64Bit()) + if(this->FC->Makefile->PlatformIs64Bit()) { view = cmSystemTools::KeyWOW64_64; other_view = cmSystemTools::KeyWOW64_32; @@ -74,7 +74,7 @@ void cmSearchPath::AddUserPath(const std::string& path) // Executables can be either 32-bit or 64-bit, so expand using the // alternative view. - if(expanded != path && this->FindName == "PROGRAM") + if(expanded != path && this->FC->CMakePathName == "PROGRAM") { expanded = path; cmSystemTools::ExpandRegistryValues(expanded, other_view); @@ -85,15 +85,17 @@ void cmSearchPath::AddUserPath(const std::string& path) for(std::vector::const_iterator p = outPaths.begin(); p != outPaths.end(); ++p) { - this->AddPathInternal(*p, this->Makefile->GetCurrentDirectory()); + this->AddPathInternal(*p, this->FC->Makefile->GetCurrentDirectory()); } } //---------------------------------------------------------------------------- void cmSearchPath::AddCMakePath(const std::string& variable) { + assert(this->FC != NULL); + // Get a path from a CMake variable. - if(const char* value = this->Makefile->GetDefinition(variable)) + if(const char* value = this->FC->Makefile->GetDefinition(variable)) { std::vector expanded; cmSystemTools::ExpandListArgument(value, expanded); @@ -101,7 +103,7 @@ void cmSearchPath::AddCMakePath(const std::string& variable) for(std::vector::const_iterator p = expanded.begin(); p!= expanded.end(); ++p) { - this->AddPathInternal(*p, this->Makefile->GetCurrentDirectory()); + this->AddPathInternal(*p, this->FC->Makefile->GetCurrentDirectory()); } } } @@ -121,13 +123,15 @@ void cmSearchPath::AddEnvPath(const std::string& variable) //---------------------------------------------------------------------------- void cmSearchPath::AddCMakePrefixPath(const std::string& variable) { + assert(this->FC != NULL); + // Get a path from a CMake variable. - if(const char* value = this->Makefile->GetDefinition(variable)) + if(const char* value = this->FC->Makefile->GetDefinition(variable)) { std::vector expanded; cmSystemTools::ExpandListArgument(value, expanded); - this->AddPrefixPaths(expanded, this->Makefile->GetCurrentDirectory()); + this->AddPrefixPaths(expanded, this->FC->Makefile->GetCurrentDirectory()); } } @@ -176,18 +180,20 @@ void cmSearchPath::AddSuffixes(const std::vector& suffixes) void cmSearchPath::AddPrefixPaths(const std::vector& paths, const char *base) { + assert(this->FC != NULL); + // default for programs std::string subdir = "bin"; - if (this->FindName == "INCLUDE") + if (this->FC->CMakePathName == "INCLUDE") { subdir = "include"; } - else if (this->FindName == "LIBRARY") + else if (this->FC->CMakePathName == "LIBRARY") { subdir = "lib"; } - else if (this->FindName == "FRAMEWORK") + else if (this->FC->CMakePathName == "FRAMEWORK") { subdir = ""; // ? what to do for frameworks ? } @@ -203,7 +209,7 @@ void cmSearchPath::AddPrefixPaths(const std::vector& paths, if(subdir == "include" || subdir == "lib") { const char* arch = - this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); + this->FC->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE"); if(arch && *arch) { this->AddPathInternal(dir+subdir+"/"+arch, base); @@ -228,6 +234,8 @@ void cmSearchPath::AddPrefixPaths(const std::vector& paths, //---------------------------------------------------------------------------- void cmSearchPath::AddPathInternal(const std::string& path, const char *base) { + assert(this->FC != NULL); + std::string collapsed = cmSystemTools::CollapseFullPath(path, base); if(collapsed.empty()) @@ -236,7 +244,7 @@ void cmSearchPath::AddPathInternal(const std::string& path, const char *base) } // Insert the path if has not already been emitted. - if(this->Emitted.insert(collapsed).second) + if(this->FC->SearchPathsEmitted.insert(collapsed).second) { this->Paths.push_back(collapsed); } diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h index 88ef0ff25..51a6149ea 100644 --- a/Source/cmSearchPath.h +++ b/Source/cmSearchPath.h @@ -17,7 +17,7 @@ class cmFindCommon; /** \class cmSearchPath - * \brief Base class for FIND_XXX implementations. + * \brief Container for encapsulating a set of search paths * * cmSearchPath is a container that encapsulates search path construction and * management @@ -25,10 +25,12 @@ class cmFindCommon; class cmSearchPath { public: - cmSearchPath(cmFindCommon* findCmd, const std::string& groupLabel); + // cmSearchPath must be initialized from a valid pointer. The only reason + // for teh default is to allow it to be easily used in stl containers. + // Attempting to initialize with a NULL value will fail an assertion + cmSearchPath(cmFindCommon* findCmd = 0); ~cmSearchPath(); - const std::string& GetLabel() const { return this->Label; } const std::vector& GetPaths() const { return this->Paths; } void ExtractWithout(const std::set& ignore, @@ -48,12 +50,7 @@ protected: const char *base = 0); void AddPathInternal(const std::string& path, const char *base = 0); - // Members collected from the calling find command - const std::string& FindName; - cmMakefile* const& Makefile; - std::set& Emitted; - - std::string Label; + cmFindCommon *FC; std::vector Paths; };