ENH: Add HINTS option to find_* commands.

- Hints are searched after user locations but before system locations
  - The HINTS option should have paths provided by system introspection
  - The PATHS option should have paths that are hard-coded guesses
This commit is contained in:
Brad King 2008-06-09 15:08:59 -04:00
parent 2cadc9138f
commit 5b406c9044
6 changed files with 104 additions and 66 deletions

View File

@ -30,6 +30,7 @@ cmFindBase::cmFindBase()
" FIND_XXX(\n" " FIND_XXX(\n"
" <VAR>\n" " <VAR>\n"
" name | NAMES name1 [name2 ...]\n" " name | NAMES name1 [name2 ...]\n"
" [HINTS path1 [path2 ... ENV var]]\n"
" [PATHS path1 [path2 ... ENV var]]\n" " [PATHS path1 [path2 ... ENV var]]\n"
" [PATH_SUFFIXES suffix1 [suffix2 ...]]\n" " [PATH_SUFFIXES suffix1 [suffix2 ...]]\n"
" [DOC \"cache documentation string\"]\n" " [DOC \"cache documentation string\"]\n"
@ -55,7 +56,7 @@ cmFindBase::cmFindBase()
"is searched for is specified by the names listed " "is searched for is specified by the names listed "
"after the NAMES argument. Additional search locations " "after the NAMES argument. Additional search locations "
"can be specified after the PATHS argument. If ENV var is " "can be specified after the PATHS argument. If ENV var is "
"found in the PATHS section the environment variable var " "found in the HINTS or PATHS section the environment variable var "
"will be read and converted from a system environment variable to " "will be read and converted from a system environment variable to "
"a cmake style list of paths. For example ENV PATH would be a way " "a cmake style list of paths. For example ENV PATH would be a way "
"to list the system path variable. The argument " "to list the system path variable. The argument "
@ -80,18 +81,23 @@ cmFindBase::cmFindBase()
" <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n" " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n"
" CMAKE_XXX_PATH\n" " CMAKE_XXX_PATH\n"
" CMAKE_XXX_MAC_PATH\n" " CMAKE_XXX_MAC_PATH\n"
"3. Search the standard system environment variables. " "3. Search the paths specified by the HINTS option. "
"These should be paths computed by system introspection, such as a "
"hint provided by the location of another item already found. "
"Hard-coded guesses should be specified with the PATHS option.\n"
"4. Search the standard system environment variables. "
"This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is an argument.\n" "This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is an argument.\n"
" PATH\n" " PATH\n"
" XXX_SYSTEM\n" // replace with "", LIB, or INCLUDE " XXX_SYSTEM\n" // replace with "", LIB, or INCLUDE
"4. Search cmake variables defined in the Platform files " "5. Search cmake variables defined in the Platform files "
"for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH " "for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH "
"is passed.\n" "is passed.\n"
" <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_SYSTEM_PREFIX_PATH\n" " <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_SYSTEM_PREFIX_PATH\n"
" CMAKE_SYSTEM_XXX_PATH\n" " CMAKE_SYSTEM_XXX_PATH\n"
" CMAKE_SYSTEM_XXX_MAC_PATH\n" " CMAKE_SYSTEM_XXX_MAC_PATH\n"
"5. Search the paths specified after PATHS or in the short-hand version " "6. Search the paths specified by the PATHS option "
"of the command.\n" "or in the short-hand version of the command. "
"These are typically hard-coded guesses.\n"
; ;
this->GenericDocumentation += this->GenericDocumentationMacPolicy; this->GenericDocumentation += this->GenericDocumentationMacPolicy;
this->GenericDocumentation += this->GenericDocumentationRootPath; this->GenericDocumentation += this->GenericDocumentationRootPath;
@ -161,65 +167,59 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
// Find the current bundle/framework search policy. // Find the current bundle/framework search policy.
this->SelectDefaultMacMode(); this->SelectDefaultMacMode();
std::string doc;
bool doingNames = true; // assume it starts with a name
bool doingPaths = false;
bool doingPathSuf = false;
bool newStyle = false; bool newStyle = false;
enum Doing { DoingNone, DoingNames, DoingPaths, DoingPathSuffixes,
DoingHints };
Doing doing = DoingNames; // assume it starts with a name
for (unsigned int j = 1; j < args.size(); ++j) for (unsigned int j = 1; j < args.size(); ++j)
{ {
if(args[j] == "NAMES") if(args[j] == "NAMES")
{ {
doingNames = true; doing = DoingNames;
newStyle = true; newStyle = true;
doingPathSuf = false;
doingPaths = false;
} }
else if (args[j] == "PATHS") else if (args[j] == "PATHS")
{ {
doingPaths = true; doing = DoingPaths;
newStyle = true;
}
else if (args[j] == "HINTS")
{
doing = DoingHints;
newStyle = true; newStyle = true;
doingNames = false;
doingPathSuf = false;
} }
else if (args[j] == "PATH_SUFFIXES") else if (args[j] == "PATH_SUFFIXES")
{ {
doing = DoingPathSuffixes;
compatibility = false; compatibility = false;
doingPathSuf = true;
newStyle = true; newStyle = true;
doingNames = false;
doingPaths = false;
} }
else if (args[j] == "NO_SYSTEM_PATH") else if (args[j] == "NO_SYSTEM_PATH")
{ {
doingPaths = false; doing = DoingNone;
doingPathSuf = false;
doingNames = false;
this->NoDefaultPath = true; this->NoDefaultPath = true;
} }
else if (this->CheckCommonArgument(args[j])) else if (this->CheckCommonArgument(args[j]))
{ {
doing = DoingNone;
compatibility = false; compatibility = false;
doingPaths = false;
doingPathSuf = false;
doingNames = false;
newStyle = true; newStyle = true;
} }
else else if(doing == DoingNames)
{ {
if(doingNames) this->Names.push_back(args[j]);
{ }
this->Names.push_back(args[j]); else if(doing == DoingPaths)
} {
else if(doingPaths) this->AddUserPath(args[j], this->UserPaths);
{ }
this->AddUserPath(args[j]); else if(doing == DoingHints)
} {
else if(doingPathSuf) this->AddUserPath(args[j], this->UserHints);
{ }
this->AddPathSuffix(args[j]); else if(doing == DoingPathSuffixes)
} {
this->AddPathSuffix(args[j]);
} }
} }
@ -266,7 +266,7 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
this->Names.push_back(args[1]); this->Names.push_back(args[1]);
for(unsigned int j = 2; j < args.size(); ++j) for(unsigned int j = 2; j < args.size(); ++j)
{ {
this->AddUserPath(args[j]); this->AddUserPath(args[j], this->UserPaths);
} }
} }
this->ExpandPaths(); this->ExpandPaths();
@ -284,11 +284,10 @@ void cmFindBase::ExpandPaths()
{ {
this->AddCMakeEnvironmentPath(); this->AddCMakeEnvironmentPath();
this->AddCMakeVariablePath(); this->AddCMakeVariablePath();
this->AddUserHintsPath();
this->AddSystemEnvironmentPath(); this->AddSystemEnvironmentPath();
this->AddCMakeSystemVariablePath(); this->AddCMakeSystemVariablePath();
this->AddUserGuessPath();
// Add paths specified by the caller.
this->AddPathsInternal(this->UserPaths, CMakePath);
// Add suffixes and clean up paths. // Add suffixes and clean up paths.
this->AddPathSuffixes(); this->AddPathSuffixes();
@ -444,6 +443,18 @@ void cmFindBase::AddCMakeSystemVariablePath()
} }
} }
//----------------------------------------------------------------------------
void cmFindBase::AddUserHintsPath()
{
this->AddPathsInternal(this->UserHints, CMakePath);
}
//----------------------------------------------------------------------------
void cmFindBase::AddUserGuessPath()
{
this->AddPathsInternal(this->UserPaths, CMakePath);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindBase::AddPathSuffixes() void cmFindBase::AddPathSuffixes()
{ {

View File

@ -66,6 +66,8 @@ private:
void AddCMakeVariablePath(); void AddCMakeVariablePath();
void AddSystemEnvironmentPath(); void AddSystemEnvironmentPath();
void AddCMakeSystemVariablePath(); void AddCMakeSystemVariablePath();
void AddUserHintsPath();
void AddUserGuessPath();
// Helpers. // Helpers.
void AddCMakePrefixPath(const char* variable); void AddCMakePrefixPath(const char* variable);

View File

@ -76,14 +76,14 @@ cmFindCommon::cmFindCommon()
"then CMAKE_FIND_ROOT_PATH will not be used. If ONLY_CMAKE_FIND_ROOT_PATH " "then CMAKE_FIND_ROOT_PATH will not be used. If ONLY_CMAKE_FIND_ROOT_PATH "
"is used then only the re-rooted directories will be searched.\n"; "is used then only the re-rooted directories will be searched.\n";
this->GenericDocumentationPathsOrder = this->GenericDocumentationPathsOrder =
"The reason the paths listed in the call to the command are searched " "The default search order is designed to be most-specific to "
"last is that most users of CMake would expect things to be found " "least-specific for common use cases. "
"first in the locations specified by their environment. Projects may " "Projects may override the order by simply calling the command "
"override this behavior by simply calling the command twice:\n" "multiple times and using the NO_* options:\n"
" FIND_XXX(FIND_ARGS_XXX PATHS paths... NO_DEFAULT_PATH)\n" " FIND_XXX(FIND_ARGS_XXX PATHS paths... NO_DEFAULT_PATH)\n"
" FIND_XXX(FIND_ARGS_XXX)\n" " FIND_XXX(FIND_ARGS_XXX)\n"
"Once one of these calls succeeds the result variable will be set " "Once one of the calls succeeds the result variable will be set "
"and stored in the cache so that neither call will search again."; "and stored in the cache so that no call will search again.";
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -322,7 +322,8 @@ void cmFindCommon::AddPathSuffix(std::string const& arg)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindCommon::AddUserPath(std::string const& p) void cmFindCommon::AddUserPath(std::string const& p,
std::vector<std::string>& paths)
{ {
// We should view the registry as the target application would view // We should view the registry as the target application would view
// it. // it.
@ -341,7 +342,7 @@ void cmFindCommon::AddUserPath(std::string const& p)
// Expand using the view of the target application. // Expand using the view of the target application.
std::string expanded = p; std::string expanded = p;
cmSystemTools::ExpandRegistryValues(expanded, view); cmSystemTools::ExpandRegistryValues(expanded, view);
cmSystemTools::GlobDirs(expanded.c_str(), this->UserPaths); cmSystemTools::GlobDirs(expanded.c_str(), paths);
// Executables can be either 32-bit or 64-bit, so expand using the // Executables can be either 32-bit or 64-bit, so expand using the
// alternative view. // alternative view.
@ -349,7 +350,7 @@ void cmFindCommon::AddUserPath(std::string const& p)
{ {
expanded = p; expanded = p;
cmSystemTools::ExpandRegistryValues(expanded, other_view); cmSystemTools::ExpandRegistryValues(expanded, other_view);
cmSystemTools::GlobDirs(expanded.c_str(), this->UserPaths); cmSystemTools::GlobDirs(expanded.c_str(), paths);
} }
} }

View File

@ -58,7 +58,8 @@ protected:
bool CheckCommonArgument(std::string const& arg); bool CheckCommonArgument(std::string const& arg);
void AddPathSuffix(std::string const& arg); void AddPathSuffix(std::string const& arg);
void AddUserPath(std::string const& p); void AddUserPath(std::string const& p,
std::vector<std::string>& paths);
void AddCMakePath(const char* variable); void AddCMakePath(const char* variable);
void AddEnvPath(const char* variable); void AddEnvPath(const char* variable);
void AddPathsInternal(std::vector<std::string> const& in_paths, void AddPathsInternal(std::vector<std::string> const& in_paths,
@ -73,6 +74,7 @@ protected:
std::vector<std::string> SearchPathSuffixes; std::vector<std::string> SearchPathSuffixes;
std::vector<std::string> UserPaths; std::vector<std::string> UserPaths;
std::vector<std::string> UserHints;
std::vector<std::string> SearchPaths; std::vector<std::string> SearchPaths;
std::set<cmStdString> SearchPathsEmitted; std::set<cmStdString> SearchPathsEmitted;

View File

@ -112,6 +112,7 @@ cmFindPackageCommand::cmFindPackageCommand()
" [[REQUIRED|COMPONENTS] [components...]] [NO_MODULE]\n" " [[REQUIRED|COMPONENTS] [components...]] [NO_MODULE]\n"
" [NAMES name1 [name2 ...]]\n" " [NAMES name1 [name2 ...]]\n"
" [CONFIGS config1 [config2 ...]]\n" " [CONFIGS config1 [config2 ...]]\n"
" [HINTS path1 [path2 ... ]]\n"
" [PATHS path1 [path2 ... ]]\n" " [PATHS path1 [path2 ... ]]\n"
" [PATH_SUFFIXES suffix1 [suffix2 ...]]\n" " [PATH_SUFFIXES suffix1 [suffix2 ...]]\n"
" [NO_DEFAULT_PATH]\n" " [NO_DEFAULT_PATH]\n"
@ -251,22 +252,27 @@ cmFindPackageCommand::cmFindPackageCommand()
" CMAKE_PREFIX_PATH\n" " CMAKE_PREFIX_PATH\n"
" CMAKE_FRAMEWORK_PATH\n" " CMAKE_FRAMEWORK_PATH\n"
" CMAKE_APPBUNDLE_PATH\n" " CMAKE_APPBUNDLE_PATH\n"
"3. Search the standard system environment variables. " "3. Search paths specified by the HINTS option. "
"These should be paths computed by system introspection, such as a "
"hint provided by the location of another item already found. "
"Hard-coded guesses should be specified with the PATHS option.\n"
"4. Search the standard system environment variables. "
"This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is passed. " "This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is passed. "
"Path entries ending in \"/bin\" or \"/sbin\" are automatically " "Path entries ending in \"/bin\" or \"/sbin\" are automatically "
"converted to their parent directories.\n" "converted to their parent directories.\n"
" PATH\n" " PATH\n"
"4. Search project build trees recently configured in a CMake GUI. " "5. Search project build trees recently configured in a CMake GUI. "
"This can be skipped if NO_CMAKE_BUILDS_PATH is passed. " "This can be skipped if NO_CMAKE_BUILDS_PATH is passed. "
"It is intended for the case when a user is building multiple " "It is intended for the case when a user is building multiple "
"dependent projects one after another.\n" "dependent projects one after another.\n"
"5. Search cmake variables defined in the Platform files " "6. Search cmake variables defined in the Platform files "
"for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH " "for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH "
"is passed.\n" "is passed.\n"
" CMAKE_SYSTEM_PREFIX_PATH\n" " CMAKE_SYSTEM_PREFIX_PATH\n"
" CMAKE_SYSTEM_FRAMEWORK_PATH\n" " CMAKE_SYSTEM_FRAMEWORK_PATH\n"
" CMAKE_SYSTEM_APPBUNDLE_PATH\n" " CMAKE_SYSTEM_APPBUNDLE_PATH\n"
"6. Search paths specified by the PATHS option.\n" "7. Search paths specified by the PATHS option. "
"These are typically hard-coded guesses.\n"
; ;
this->CommandDocumentation += this->GenericDocumentationMacPolicy; this->CommandDocumentation += this->GenericDocumentationMacPolicy;
this->CommandDocumentation += this->GenericDocumentationRootPath; this->CommandDocumentation += this->GenericDocumentationRootPath;
@ -313,7 +319,7 @@ bool cmFindPackageCommand
// Parse the arguments. // Parse the arguments.
enum Doing { DoingNone, DoingComponents, DoingNames, DoingPaths, enum Doing { DoingNone, DoingComponents, DoingNames, DoingPaths,
DoingPathSuffixes, DoingConfigs }; DoingPathSuffixes, DoingConfigs, DoingHints };
Doing doing = DoingNone; Doing doing = DoingNone;
cmsys::RegularExpression version("^[0-9.]+$"); cmsys::RegularExpression version("^[0-9.]+$");
bool haveVersion = false; bool haveVersion = false;
@ -357,6 +363,12 @@ bool cmFindPackageCommand
this->Compatibility_1_6 = false; this->Compatibility_1_6 = false;
doing = DoingPaths; doing = DoingPaths;
} }
else if(args[i] == "HINTS")
{
this->NoModule = true;
this->Compatibility_1_6 = false;
doing = DoingHints;
}
else if(args[i] == "PATH_SUFFIXES") else if(args[i] == "PATH_SUFFIXES")
{ {
this->NoModule = true; this->NoModule = true;
@ -400,7 +412,11 @@ bool cmFindPackageCommand
} }
else if(doing == DoingPaths) else if(doing == DoingPaths)
{ {
this->AddUserPath(args[i]); this->AddUserPath(args[i], this->UserPaths);
}
else if(doing == DoingHints)
{
this->AddUserPath(args[i], this->UserHints);
} }
else if(doing == DoingPathSuffixes) else if(doing == DoingPathSuffixes)
{ {
@ -946,10 +962,11 @@ void cmFindPackageCommand::ComputePrefixes()
{ {
this->AddPrefixesCMakeEnvironment(); this->AddPrefixesCMakeEnvironment();
this->AddPrefixesCMakeVariable(); this->AddPrefixesCMakeVariable();
this->AddPrefixesUserHints();
this->AddPrefixesSystemEnvironment(); this->AddPrefixesSystemEnvironment();
this->AddPrefixesBuilds(); this->AddPrefixesBuilds();
this->AddPrefixesCMakeSystemVariable(); this->AddPrefixesCMakeSystemVariable();
this->AddPrefixesUser(); this->AddPrefixesUserGuess();
this->ComputeFinalPrefixes(); this->ComputeFinalPrefixes();
} }
@ -1049,13 +1066,17 @@ void cmFindPackageCommand::AddPrefixesCMakeSystemVariable()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesUser() void cmFindPackageCommand::AddPrefixesUserGuess()
{ {
if(!this->UserPaths.empty()) // Add guesses specified by the caller.
{ this->AddPathsInternal(this->UserPaths, CMakePath);
// Add paths specified by the caller. }
this->AddPathsInternal(this->UserPaths, CMakePath);
} //----------------------------------------------------------------------------
void cmFindPackageCommand::AddPrefixesUserHints()
{
// Add hints specified by the caller.
this->AddPathsInternal(this->UserHints, CMakePath);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -88,7 +88,8 @@ private:
void AddPrefixesSystemEnvironment(); void AddPrefixesSystemEnvironment();
void AddPrefixesBuilds(); void AddPrefixesBuilds();
void AddPrefixesCMakeSystemVariable(); void AddPrefixesCMakeSystemVariable();
void AddPrefixesUser(); void AddPrefixesUserGuess();
void AddPrefixesUserHints();
void ComputeFinalPrefixes(); void ComputeFinalPrefixes();
bool SearchDirectory(std::string const& dir); bool SearchDirectory(std::string const& dir);
bool CheckDirectory(std::string const& dir); bool CheckDirectory(std::string const& dir);