From 2a9ac4bd83f7247539616545ef0772fea1f4a1fc Mon Sep 17 00:00:00 2001 From: Chuck Atkins Date: Wed, 15 Oct 2014 16:36:42 -0400 Subject: [PATCH] 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