ENH: Major improvements to the FIND_PACKAGE command. See bug #3659.

- Use CMAKE_PREFIX_PATH and CMAKE_SYSTEM_PREFIX_PATH among other means
    to locate package configuration files.
  - Create cmFindCommon as base for cmFindBase and cmFindPackageCommand
  - Move common functionality up to cmFindCommon
  - Improve documentation of FIND_* commands.
  - Fix FIND_* commands to not add framework/app paths in wrong place.
This commit is contained in:
Brad King 2008-01-17 09:02:31 -05:00
parent 491d5d0104
commit b424df917d
10 changed files with 1862 additions and 601 deletions

View File

@ -42,6 +42,7 @@
#include "cmExecProgramCommand.cxx"
#include "cmExternalMakefileProjectGenerator.cxx"
#include "cmFindBase.cxx"
#include "cmFindCommon.cxx"
#include "cmFileCommand.cxx"
#include "cmFindFileCommand.cxx"
#include "cmFindLibraryCommand.cxx"

View File

@ -18,26 +18,10 @@
cmFindBase::cmFindBase()
{
cmSystemTools::ReplaceString(this->GenericDocumentationPathsOrder,
"FIND_ARGS_XXX", "<VAR> NAMES name");
this->AlreadyInCache = false;
this->AlreadyInCacheWithoutMetaInfo = false;
this->NoDefaultPath = false;
this->NoCMakePath = false;
this->NoCMakeEnvironmentPath = false;
this->NoSystemEnvironmentPath = false;
this->NoCMakeSystemPath = false;
this->FindRootPathMode = RootPathModeBoth;
// default is to search frameworks first on apple
#if defined(__APPLE__)
this->SearchFrameworkFirst = true;
this->SearchAppBundleFirst = true;
#else
this->SearchFrameworkFirst = false;
this->SearchAppBundleFirst = false;
#endif
this->SearchFrameworkOnly = false;
this->SearchFrameworkLast = false;
this->SearchAppBundleOnly = false;
this->SearchAppBundleLast = false;
this->GenericDocumentation =
" FIND_XXX(<VAR> name1 path1 path2 ...)\n"
"This is the short-hand signature for the command that "
@ -54,8 +38,9 @@ cmFindBase::cmFindBase()
" [NO_CMAKE_PATH]\n"
" [NO_SYSTEM_ENVIRONMENT_PATH]\n"
" [NO_CMAKE_SYSTEM_PATH]\n"
" [CMAKE_FIND_ROOT_PATH_BOTH | ONLY_CMAKE_FIND_ROOT_PATH | "
"NO_CMAKE_FIND_ROOT_PATH ]\n"
" [CMAKE_FIND_ROOT_PATH_BOTH |\n"
" ONLY_CMAKE_FIND_ROOT_PATH |\n"
" NO_CMAKE_FIND_ROOT_PATH]\n"
" )\n"
""
"This command is used to find a SEARCH_XXX_DESC. "
@ -84,9 +69,8 @@ cmFindBase::cmFindBase()
"can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed.\n"
""
" <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n"
" CMAKE_FRAMEWORK_PATH\n"
" CMAKE_APPBUNDLE_PATH\n"
" CMAKE_XXX_PATH\n"
" CMAKE_XXX_MAC_PATH\n"
"2. Search cmake variables with the same names as "
"the cmake specific environment variables. These "
"are intended to be used on the command line with a "
@ -94,9 +78,8 @@ cmFindBase::cmFindBase()
"is passed.\n"
""
" <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_PREFIX_PATH\n"
" CMAKE_FRAMEWORK_PATH\n"
" CMAKE_APPBUNDLE_PATH\n"
" CMAKE_XXX_PATH\n"
" CMAKE_XXX_MAC_PATH\n"
"3. Search the standard system environment variables. "
"This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is an argument.\n"
" PATH\n"
@ -105,51 +88,14 @@ cmFindBase::cmFindBase()
"for the current system. This can be skipped if NO_CMAKE_SYSTEM_PATH "
"is passed.\n"
" <prefix>/XXX_SUBDIR for each <prefix> in CMAKE_SYSTEM_PREFIX_PATH\n"
" CMAKE_SYSTEM_FRAMEWORK_PATH\n"
" CMAKE_SYSTEM_APPBUNDLE_PATH\n"
" CMAKE_SYSTEM_XXX_PATH\n"
" CMAKE_SYSTEM_XXX_MAC_PATH\n"
"5. Search the paths specified after PATHS or in the short-hand version "
"of the command.\n"
"On Darwin or systems supporting OSX Frameworks, the cmake variable"
" CMAKE_FIND_FRAMEWORK can be set to empty or one of the following:\n"
" \"FIRST\" - Try to find frameworks before standard\n"
" libraries or headers. This is the default on Darwin.\n"
" \"LAST\" - Try to find frameworks after standard\n"
" libraries or headers.\n"
" \"ONLY\" - Only try to find frameworks.\n"
" \"NEVER\". - Never try to find frameworks.\n"
"On Darwin or systems supporting OSX Application Bundles, the cmake "
"variable CMAKE_FIND_APPBUNDLE can be set to empty or one of the "
"following:\n"
" \"FIRST\" - Try to find application bundles before standard\n"
" programs. This is the default on Darwin.\n"
" \"LAST\" - Try to find application bundles after standard\n"
" programs.\n"
" \"ONLY\" - Only try to find application bundles.\n"
" \"NEVER\". - Never try to find application bundles.\n"
"The CMake variable CMAKE_FIND_ROOT_PATH specifies one or more "
"directories to be prepended to all other search directories. "
"This effectively \"re-roots\" the entire search under given locations. "
"By default it is empty. It is especially useful when "
"cross-compiling to point to the root directory of the "
"target environment and CMake will search there too. By default at first "
"the directories listed in CMAKE_FIND_ROOT_PATH and then the non-rooted "
"directories will be searched. "
"The default behavior can be adjusted by setting "
"CMAKE_FIND_ROOT_PATH_MODE_XXX. This behavior can be manually "
"overridden on a per-call basis. "
"By using CMAKE_FIND_ROOT_PATH_BOTH the search order will "
"be as described above. If NO_CMAKE_FIND_ROOT_PATH is used "
"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"
"The reason the paths listed in the call to the command are searched "
"last is that most users of CMake would expect things to be found "
"first in the locations specified by their environment. Projects may "
"override this behavior by simply calling the command twice:\n"
" FIND_XXX(<VAR> NAMES name PATHS paths NO_DEFAULT_PATH)\n"
" FIND_XXX(<VAR> NAMES name)\n"
"Once one of these calls succeeds the result variable will be set "
"and stored in the cache so that neither call will search again.";
;
this->GenericDocumentation += this->GenericDocumentationMacPolicy;
this->GenericDocumentation += this->GenericDocumentationRootPath;
this->GenericDocumentation += this->GenericDocumentationPathsOrder;
}
bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
@ -159,57 +105,6 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
this->SetError("called with incorrect number of arguments");
return false;
}
std::string ff = this->Makefile->GetSafeDefinition("CMAKE_FIND_FRAMEWORK");
if(ff == "NEVER")
{
this->SearchFrameworkLast = false;
this->SearchFrameworkFirst = false;
this->SearchFrameworkOnly = false;
}
else if (ff == "ONLY")
{
this->SearchFrameworkLast = false;
this->SearchFrameworkFirst = false;
this->SearchFrameworkOnly = true;
}
else if (ff == "FIRST")
{
this->SearchFrameworkLast = false;
this->SearchFrameworkFirst = true;
this->SearchFrameworkOnly = false;
}
else if (ff == "LAST")
{
this->SearchFrameworkLast = true;
this->SearchFrameworkFirst = false;
this->SearchFrameworkOnly = false;
}
std::string fab = this->Makefile->GetSafeDefinition("CMAKE_FIND_APPBUNDLE");
if(fab == "NEVER")
{
this->SearchAppBundleLast = false;
this->SearchAppBundleFirst = false;
this->SearchAppBundleOnly = false;
}
else if (fab == "ONLY")
{
this->SearchAppBundleLast = false;
this->SearchAppBundleFirst = false;
this->SearchAppBundleOnly = true;
}
else if (fab == "FIRST")
{
this->SearchAppBundleLast = false;
this->SearchAppBundleFirst = true;
this->SearchAppBundleOnly = false;
}
else if (fab == "LAST")
{
this->SearchAppBundleLast = true;
this->SearchAppBundleFirst = false;
this->SearchAppBundleOnly = false;
}
// CMake versions below 2.3 did not search all these extra
// locations. Preserve compatibility unless a modern argument is
@ -271,23 +166,12 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
return true;
}
this->AlreadyInCache = false;
std::string findRootPathVar = "CMAKE_FIND_ROOT_PATH_MODE_";
findRootPathVar += this->CMakePathName;
std::string rootPathMode =
this->Makefile->GetSafeDefinition(findRootPathVar.c_str());
if (rootPathMode=="NEVER")
{
this->FindRootPathMode = RootPathModeNoRootPath;
}
else if (rootPathMode=="ONLY")
{
this->FindRootPathMode = RootPathModeOnlyRootPath;
}
else if (rootPathMode=="BOTH")
{
this->FindRootPathMode = RootPathModeBoth;
}
// Find the current root path mode.
this->SelectDefaultRootPathMode();
// Find the current bundle/framework search policy.
this->SelectDefaultMacMode();
std::vector<std::string> userPaths;
std::string doc;
@ -327,60 +211,12 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
doingNames = false;
this->NoDefaultPath = true;
}
else if (args[j] == "NO_DEFAULT_PATH")
else if (this->CheckCommonArgument(args[j]))
{
compatibility = false;
doingPaths = false;
doingPathSuf = false;
doingNames = false;
this->NoDefaultPath = true;
}
else if (args[j] == "NO_CMAKE_ENVIRONMENT_PATH")
{
compatibility = false;
doingPaths = false;
doingPathSuf = false;
doingNames = false;
this->NoCMakeEnvironmentPath = true;
}
else if (args[j] == "NO_CMAKE_PATH")
{
compatibility = false;
doingPaths = false;
doingPathSuf = false;
doingNames = false;
this->NoCMakePath = true;
}
else if (args[j] == "NO_SYSTEM_ENVIRONMENT_PATH")
{
compatibility = false;
doingPaths = false;
doingPathSuf = false;
doingNames = false;
this->NoSystemEnvironmentPath = true;
}
else if (args[j] == "NO_CMAKE_SYSTEM_PATH")
{
compatibility = false;
doingPaths = false;
doingPathSuf = false;
doingNames = false;
this->NoCMakeSystemPath = true;
}
else if (args[j] == "NO_CMAKE_FIND_ROOT_PATH")
{
compatibility = false;
this->FindRootPathMode = RootPathModeNoRootPath;
}
else if (args[j] == "ONLY_CMAKE_FIND_ROOT_PATH")
{
compatibility = false;
this->FindRootPathMode = RootPathModeOnlyRootPath;
}
else if (args[j] == "CMAKE_FIND_ROOT_PATH_BOTH")
{
compatibility = false;
this->FindRootPathMode = RootPathModeBoth;
}
else
{
@ -393,8 +229,8 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
userPaths.push_back(args[j]);
}
else if(doingPathSuf)
{
this->SearchPathSuffixes.push_back(args[j]);
{
this->AddPathSuffix(args[j]);
}
}
}
@ -446,8 +282,9 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
}
}
this->ExpandPaths(userPaths);
this->HandleCMakeFindRootPath();
// Handle search root stuff.
this->RerootPaths(this->SearchPaths);
return true;
}
@ -457,11 +294,11 @@ void cmFindBase::ExpandPaths(std::vector<std::string> userPaths)
// standard search paths.
if(!this->NoDefaultPath)
{
if(this->SearchFrameworkFirst)
if(this->SearchFrameworkFirst || this->SearchFrameworkOnly)
{
this->AddFrameWorkPaths();
}
if(this->SearchAppBundleFirst)
if(this->SearchAppBundleFirst || this->SearchAppBundleOnly)
{
this->AddAppBundlePaths();
}
@ -509,55 +346,7 @@ void cmFindBase::ExpandPaths(std::vector<std::string> userPaths)
this->AddPaths(paths);
}
void cmFindBase::HandleCMakeFindRootPath()
{
if (this->FindRootPathMode == RootPathModeNoRootPath)
{
return;
}
const char* rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
if ((rootPath == 0) || (strlen(rootPath) == 0))
{
return;
}
std::vector<std::string> roots;
cmSystemTools::ExpandListArgument(rootPath, roots);
std::vector<std::string> unrootedPaths=this->SearchPaths;
this->SearchPaths.clear();
for (std::vector<std::string>::const_iterator rootIt = roots.begin();
rootIt != roots.end();
++rootIt )
{
for (std::vector<std::string>::const_iterator it = unrootedPaths.begin();
it != unrootedPaths.end();
++it )
{
// if the current directory is already inside the current root, don't
// add the root again
std::string rootedDir;
if (cmSystemTools::IsSubDirectory(it->c_str(), rootIt->c_str()))
{
rootedDir = *it;
}
else
{
rootedDir=*rootIt;
rootedDir+=*it;
}
this->SearchPaths.push_back(rootedDir);
}
}
if (this->FindRootPathMode == RootPathModeBoth)
{
this->AddPaths(unrootedPaths);
}
}
//----------------------------------------------------------------------------
void cmFindBase::AddEnvironmentVariables()
{
std::vector<std::string> paths;
@ -570,14 +359,6 @@ void cmFindBase::AddEnvironmentVariables()
var += this->CMakePathName;
var += "_PATH";
cmSystemTools::GetPath(paths, var.c_str());
if(this->SearchAppBundleLast)
{
cmSystemTools::GetPath(paths, "CMAKE_APPBUNDLE_PATH");
}
if(this->SearchFrameworkLast)
{
cmSystemTools::GetPath(paths, "CMAKE_FRAMEWORK_PATH");
}
this->AddPaths(paths);
}
@ -585,15 +366,15 @@ void cmFindBase::AddFindPrefix(std::vector<std::string>& dest,
const std::vector<std::string>& src)
{
// default for programs
std::string subdir = "/bin";
std::string subdir = "bin";
if (this->CMakePathName == "INCLUDE")
{
subdir = "/include";
subdir = "include";
}
else if (this->CMakePathName == "LIBRARY")
{
subdir = "/lib";
subdir = "lib";
}
else if (this->CMakePathName == "FRAMEWORK")
{
@ -604,14 +385,15 @@ void cmFindBase::AddFindPrefix(std::vector<std::string>& dest,
it != src.end();
++it)
{
std::string dirWithSubdir = it->c_str();
dirWithSubdir += subdir;
dest.push_back(dirWithSubdir);
if (subdir == "/bin")
std::string dir = it->c_str();
if(!subdir.empty() && !dir.empty() && dir[dir.size()-1] != '/')
{
dirWithSubdir = it->c_str();
dirWithSubdir += "/sbin";
dest.push_back(dirWithSubdir);
dir += "/";
}
dest.push_back(dir + subdir);
if (subdir == "bin")
{
dest.push_back(dir + "sbin");
}
if(!subdir.empty())
{
@ -622,35 +404,9 @@ void cmFindBase::AddFindPrefix(std::vector<std::string>& dest,
void cmFindBase::AddFrameWorkPaths()
{
if(this->NoDefaultPath)
{
return;
}
std::vector<std::string> paths;
// first environment variables
if(!this->NoCMakeEnvironmentPath)
{
cmSystemTools::GetPath(paths, "CMAKE_FRAMEWORK_PATH");
}
// add cmake variables
if(!this->NoCMakePath)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_FRAMEWORK_PATH"))
{
cmSystemTools::ExpandListArgument(path, paths);
}
}
// AddCMakeSystemVariables
if(!this->NoCMakeSystemPath)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_SYSTEM_FRAMEWORK_PATH"))
{
cmSystemTools::ExpandListArgument(path, paths);
}
}
this->AddPaths(paths);
this->GetFrameworkPaths(paths);
this->AddPaths(paths);
}
void cmFindBase::AddPaths(std::vector<std::string> & paths)
@ -665,35 +421,9 @@ void cmFindBase::AddPaths(std::vector<std::string> & paths)
void cmFindBase::AddAppBundlePaths()
{
if(this->NoDefaultPath)
{
return;
}
std::vector<std::string> paths;
// first environment variables
if(!this->NoCMakeEnvironmentPath)
{
cmSystemTools::GetPath(paths, "CMAKE_APPBUNDLE_PATH");
}
// add cmake variables
if(!this->NoCMakePath)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_APPBUNDLE_PATH"))
{
cmSystemTools::ExpandListArgument(path, paths);
}
}
// AddCMakeSystemVariables
if(!this->NoCMakeSystemPath)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_SYSTEM_APPBUNDLE_PATH"))
{
cmSystemTools::ExpandListArgument(path, paths);
}
}
this->AddPaths(paths);
this->GetAppBundlePaths(paths);
this->AddPaths(paths);
}
void cmFindBase::AddCMakeVariables()
@ -715,22 +445,6 @@ void cmFindBase::AddCMakeVariables()
{
cmSystemTools::ExpandListArgument(path, paths);
}
if(this->SearchAppBundleLast)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_APPBUNDLE_PATH"))
{
cmSystemTools::ExpandListArgument(path, paths);
}
}
if(this->SearchFrameworkLast)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_FRAMEWORK_PATH"))
{
cmSystemTools::ExpandListArgument(path, paths);
}
}
this->AddPaths(paths);
}
@ -764,22 +478,6 @@ void cmFindBase::AddCMakeSystemVariables()
{
cmSystemTools::ExpandListArgument(path, paths);
}
if(this->SearchAppBundleLast)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_SYSTEM_APPBUNDLE_PATH"))
{
cmSystemTools::ExpandListArgument(path, paths);
}
}
if(this->SearchFrameworkLast)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_SYSTEM_FRAMEWORK_PATH"))
{
cmSystemTools::ExpandListArgument(path, paths);
}
}
this->AddPaths(paths);
}

View File

@ -17,15 +17,15 @@
#ifndef cmFindBase_h
#define cmFindBase_h
#include "cmCommand.h"
#include "cmFindCommon.h"
/** \class cmFindBase
* \brief Define a command to search for an executable program.
* \brief Base class for most FIND_XXX commands.
*
* cmFindBase is a parent class for cmFindProgramCommand, cmFindPathCommand,
* and cmFindLibraryCommand, cmFindFile
* and cmFindLibraryCommand, cmFindFileCommand
*/
class cmFindBase : public cmCommand
class cmFindBase : public cmFindCommon
{
public:
cmFindBase();
@ -34,20 +34,15 @@ public:
* the CMakeLists.txt file.
*/
virtual bool ParseArguments(std::vector<std::string> const& args);
cmTypeMacro(cmFindBase, cmCommand);
cmTypeMacro(cmFindBase, cmFindCommon);
virtual const char* GetFullDocumentation()
{return this->GenericDocumentation.c_str();}
enum RootPathMode { RootPathModeBoth,
RootPathModeOnlyRootPath,
RootPathModeNoRootPath };
protected:
void PrintFindStuff();
void ExpandPaths(std::vector<std::string> userPaths);
void HandleCMakeFindRootPath();
// add to the SearchPaths
void AddPaths(std::vector<std::string>& paths);
void AddFrameWorkPaths();
@ -70,29 +65,12 @@ protected:
cmStdString VariableName;
std::vector<std::string> Names;
std::vector<std::string> SearchPaths;
std::vector<std::string> SearchPathSuffixes;
// CMAKE_*_PATH CMAKE_SYSTEM_*_PATH FRAMEWORK|LIBRARY|INCLUDE|PROGRAM
cmStdString CMakePathName;
cmStdString EnvironmentPath; // LIB,INCLUDE
bool AlreadyInCache;
bool AlreadyInCacheWithoutMetaInfo;
bool NoDefaultPath;
bool NoCMakePath;
bool NoCMakeEnvironmentPath;
bool NoSystemEnvironmentPath;
bool NoCMakeSystemPath;
RootPathMode FindRootPathMode;
bool SearchFrameworkFirst;
bool SearchFrameworkOnly;
bool SearchFrameworkLast;
bool SearchAppBundleFirst;
bool SearchAppBundleOnly;
bool SearchAppBundleLast;
};

479
Source/cmFindCommon.cxx Normal file
View File

@ -0,0 +1,479 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "cmFindCommon.h"
//----------------------------------------------------------------------------
cmFindCommon::cmFindCommon()
{
this->FindRootPathMode = RootPathModeBoth;
this->NoDefaultPath = false;
this->NoCMakePath = false;
this->NoCMakeEnvironmentPath = false;
this->NoSystemEnvironmentPath = false;
this->NoCMakeSystemPath = false;
// OS X Bundle and Framework search policy. The default is to
// search frameworks first on apple.
#if defined(__APPLE__)
this->SearchFrameworkFirst = true;
this->SearchAppBundleFirst = true;
#else
this->SearchFrameworkFirst = false;
this->SearchAppBundleFirst = false;
#endif
this->SearchFrameworkOnly = false;
this->SearchFrameworkLast = false;
this->SearchAppBundleOnly = false;
this->SearchAppBundleLast = false;
// Documentation components.
this->GenericDocumentationMacPolicy =
"On Darwin or systems supporting OS X Frameworks, the cmake variable"
" CMAKE_FIND_FRAMEWORK can be set to empty or one of the following:\n"
" \"FIRST\" - Try to find frameworks before standard\n"
" libraries or headers. This is the default on Darwin.\n"
" \"LAST\" - Try to find frameworks after standard\n"
" libraries or headers.\n"
" \"ONLY\" - Only try to find frameworks.\n"
" \"NEVER\". - Never try to find frameworks.\n"
"On Darwin or systems supporting OS X Application Bundles, the cmake "
"variable CMAKE_FIND_APPBUNDLE can be set to empty or one of the "
"following:\n"
" \"FIRST\" - Try to find application bundles before standard\n"
" programs. This is the default on Darwin.\n"
" \"LAST\" - Try to find application bundles after standard\n"
" programs.\n"
" \"ONLY\" - Only try to find application bundles.\n"
" \"NEVER\". - Never try to find application bundles.\n";
this->GenericDocumentationRootPath =
"The CMake variable CMAKE_FIND_ROOT_PATH specifies one or more "
"directories to be prepended to all other search directories. "
"This effectively \"re-roots\" the entire search under given locations. "
"By default it is empty. It is especially useful when "
"cross-compiling to point to the root directory of the "
"target environment and CMake will search there too. By default at first "
"the directories listed in CMAKE_FIND_ROOT_PATH and then the non-rooted "
"directories will be searched. "
"The default behavior can be adjusted by setting "
"CMAKE_FIND_ROOT_PATH_MODE_XXX. This behavior can be manually "
"overridden on a per-call basis. "
"By using CMAKE_FIND_ROOT_PATH_BOTH the search order will "
"be as described above. If NO_CMAKE_FIND_ROOT_PATH is used "
"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";
this->GenericDocumentationPathsOrder =
"The reason the paths listed in the call to the command are searched "
"last is that most users of CMake would expect things to be found "
"first in the locations specified by their environment. Projects may "
"override this behavior by simply calling the command twice:\n"
" FIND_XXX(FIND_ARGS_XXX PATHS paths... NO_DEFAULT_PATH)\n"
" FIND_XXX(FIND_ARGS_XXX)\n"
"Once one of these calls succeeds the result variable will be set "
"and stored in the cache so that neither call will search again.";
}
//----------------------------------------------------------------------------
cmFindCommon::~cmFindCommon()
{
}
//----------------------------------------------------------------------------
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;
std::string rootPathMode =
this->Makefile->GetSafeDefinition(findRootPathVar.c_str());
if (rootPathMode=="NEVER")
{
this->FindRootPathMode = RootPathModeNoRootPath;
}
else if (rootPathMode=="ONLY")
{
this->FindRootPathMode = RootPathModeOnlyRootPath;
}
else if (rootPathMode=="BOTH")
{
this->FindRootPathMode = RootPathModeBoth;
}
}
//----------------------------------------------------------------------------
void cmFindCommon::SelectDefaultMacMode()
{
std::string ff = this->Makefile->GetSafeDefinition("CMAKE_FIND_FRAMEWORK");
if(ff == "NEVER")
{
this->SearchFrameworkLast = false;
this->SearchFrameworkFirst = false;
this->SearchFrameworkOnly = false;
}
else if(ff == "ONLY")
{
this->SearchFrameworkLast = false;
this->SearchFrameworkFirst = false;
this->SearchFrameworkOnly = true;
}
else if(ff == "FIRST")
{
this->SearchFrameworkLast = false;
this->SearchFrameworkFirst = true;
this->SearchFrameworkOnly = false;
}
else if(ff == "LAST")
{
this->SearchFrameworkLast = true;
this->SearchFrameworkFirst = false;
this->SearchFrameworkOnly = false;
}
std::string fab = this->Makefile->GetSafeDefinition("CMAKE_FIND_APPBUNDLE");
if(fab == "NEVER")
{
this->SearchAppBundleLast = false;
this->SearchAppBundleFirst = false;
this->SearchAppBundleOnly = false;
}
else if(fab == "ONLY")
{
this->SearchAppBundleLast = false;
this->SearchAppBundleFirst = false;
this->SearchAppBundleOnly = true;
}
else if(fab == "FIRST")
{
this->SearchAppBundleLast = false;
this->SearchAppBundleFirst = true;
this->SearchAppBundleOnly = false;
}
else if(fab == "LAST")
{
this->SearchAppBundleLast = true;
this->SearchAppBundleFirst = false;
this->SearchAppBundleOnly = false;
}
}
//----------------------------------------------------------------------------
void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
{
#if 0
for(std::vector<std::string>::const_iterator i = paths.begin();
i != paths.end(); ++i)
{
fprintf(stderr, "[%s]\n", i->c_str());
}
#endif
// Short-circuit if there is nothing to do.
if(this->FindRootPathMode == RootPathModeNoRootPath)
{
return;
}
const char* rootPath =
this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
if((rootPath == 0) || (strlen(rootPath) == 0))
{
return;
}
// Construct the list of path roots with no trailing slashes.
std::vector<std::string> roots;
cmSystemTools::ExpandListArgument(rootPath, roots);
for(std::vector<std::string>::iterator ri = roots.begin();
ri != roots.end(); ++ri)
{
cmSystemTools::ConvertToUnixSlashes(*ri);
}
// Copy the original set of unrooted paths.
std::vector<std::string> unrootedPaths = paths;
paths.clear();
for(std::vector<std::string>::const_iterator ri = roots.begin();
ri != roots.end(); ++ri)
{
for(std::vector<std::string>::const_iterator ui = unrootedPaths.begin();
ui != unrootedPaths.end(); ++ui)
{
// Place the unrooted path under the current root if it is not
// already inside. Skip the unrooted path if it is relative to
// a user home directory or is empty.
std::string rootedDir;
if(cmSystemTools::IsSubDirectory(ui->c_str(), ri->c_str()))
{
rootedDir = *ui;
}
else if(!ui->empty() && (*ui)[0] != '~')
{
// Start with the new root.
rootedDir = *ri;
rootedDir += "/";
// Append the original path with its old root removed.
rootedDir += cmSystemTools::SplitPathRootComponent(ui->c_str());
}
// Store the new path.
paths.push_back(rootedDir);
}
}
// If searching both rooted and unrooted paths add the original
// paths again.
if(this->FindRootPathMode == RootPathModeBoth)
{
paths.insert(paths.end(), unrootedPaths.begin(), unrootedPaths.end());
}
}
//----------------------------------------------------------------------------
bool cmFindCommon::CheckCommonArgument(std::string const& arg)
{
if(arg == "NO_DEFAULT_PATH")
{
this->NoDefaultPath = true;
}
else if(arg == "NO_CMAKE_ENVIRONMENT_PATH")
{
this->NoCMakeEnvironmentPath = true;
}
else if(arg == "NO_CMAKE_PATH")
{
this->NoCMakePath = true;
}
else if(arg == "NO_SYSTEM_ENVIRONMENT_PATH")
{
this->NoSystemEnvironmentPath = true;
}
else if(arg == "NO_CMAKE_SYSTEM_PATH")
{
this->NoCMakeSystemPath = true;
}
else if(arg == "NO_CMAKE_FIND_ROOT_PATH")
{
this->FindRootPathMode = RootPathModeNoRootPath;
}
else if(arg == "ONLY_CMAKE_FIND_ROOT_PATH")
{
this->FindRootPathMode = RootPathModeOnlyRootPath;
}
else if(arg == "CMAKE_FIND_ROOT_PATH_BOTH")
{
this->FindRootPathMode = RootPathModeBoth;
}
else
{
// The argument is not one of the above.
return false;
}
// The argument is one of the above.
return true;
}
//----------------------------------------------------------------------------
void cmFindCommon::AddPathSuffix(std::string const& arg)
{
std::string suffix = arg;
// Strip leading and trailing slashes.
if(suffix.empty())
{
return;
}
if(suffix[0] == '/')
{
suffix = suffix.substr(1, suffix.npos);
}
if(suffix.empty())
{
return;
}
if(suffix[suffix.size()-1] == '/')
{
suffix = suffix.substr(0, suffix.size()-1);
}
if(suffix.empty())
{
return;
}
// Store the suffix.
this->SearchPathSuffixes.push_back(suffix);
}
//----------------------------------------------------------------------------
void cmFindCommon::GetAppBundlePaths(std::vector<std::string>& paths)
{
if(this->NoDefaultPath)
{
return;
}
std::vector<std::string> tmp;
// first environment variables
if(!this->NoCMakeEnvironmentPath)
{
cmSystemTools::GetPath(tmp, "CMAKE_APPBUNDLE_PATH");
this->AddPathsInternal(paths, tmp, EnvPath);
tmp.clear();
}
// add cmake variables
if(!this->NoCMakePath)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_APPBUNDLE_PATH"))
{
cmSystemTools::ExpandListArgument(path, tmp);
this->AddPathsInternal(paths, tmp, CMakePath);
tmp.clear();
}
}
// add cmake system variables
if(!this->NoCMakeSystemPath)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_SYSTEM_APPBUNDLE_PATH"))
{
cmSystemTools::ExpandListArgument(path, tmp);
this->AddPathsInternal(paths, tmp, CMakePath);
tmp.clear();
}
}
}
//----------------------------------------------------------------------------
void cmFindCommon::GetFrameworkPaths(std::vector<std::string>& paths)
{
if(this->NoDefaultPath)
{
return;
}
std::vector<std::string> tmp;
// first environment variables
if(!this->NoCMakeEnvironmentPath)
{
cmSystemTools::GetPath(tmp, "CMAKE_FRAMEWORK_PATH");
this->AddPathsInternal(paths, tmp, EnvPath);
tmp.clear();
}
// add cmake variables
if(!this->NoCMakePath)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_FRAMEWORK_PATH"))
{
cmSystemTools::ExpandListArgument(path, tmp);
this->AddPathsInternal(paths, tmp, CMakePath);
tmp.clear();
}
}
// add cmake system variables
if(!this->NoCMakeSystemPath)
{
if(const char* path =
this->Makefile->GetDefinition("CMAKE_SYSTEM_FRAMEWORK_PATH"))
{
cmSystemTools::ExpandListArgument(path, tmp);
this->AddPathsInternal(paths, tmp, CMakePath);
tmp.clear();
}
}
}
//----------------------------------------------------------------------------
void cmFindCommon::AddCMakePath(std::vector<std::string>& out_paths,
const char* variable,
std::set<cmStdString>* emmitted)
{
// Get a path from a CMake variable.
if(const char* varPath = this->Makefile->GetDefinition(variable))
{
std::vector<std::string> tmp;
cmSystemTools::ExpandListArgument(varPath, tmp);
// Relative paths are interpreted with respect to the current
// source directory.
this->AddPathsInternal(out_paths, tmp, CMakePath, emmitted);
}
}
//----------------------------------------------------------------------------
void cmFindCommon::AddEnvPath(std::vector<std::string>& out_paths,
const char* variable,
std::set<cmStdString>* emmitted)
{
// Get a path from the environment.
std::vector<std::string> tmp;
cmSystemTools::GetPath(tmp, variable);
// Relative paths are interpreted with respect to the current
// working directory.
this->AddPathsInternal(out_paths, tmp, EnvPath, emmitted);
}
//----------------------------------------------------------------------------
void cmFindCommon::AddPathsInternal(std::vector<std::string>& out_paths,
std::vector<std::string> const& in_paths,
PathType pathType,
std::set<cmStdString>* emmitted)
{
for(std::vector<std::string>::const_iterator i = in_paths.begin();
i != in_paths.end(); ++i)
{
this->AddPathInternal(out_paths, *i, pathType, emmitted);
}
}
//----------------------------------------------------------------------------
void cmFindCommon::AddPathInternal(std::vector<std::string>& out_paths,
std::string const& in_path,
PathType pathType,
std::set<cmStdString>* emmitted)
{
if(in_path.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.c_str(), relbase);
// Insert the path if has not already been emmitted.
if(!emmitted || emmitted->insert(fullPath).second)
{
out_paths.push_back(fullPath.c_str());
}
}

95
Source/cmFindCommon.h Normal file
View File

@ -0,0 +1,95 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef cmFindCommon_h
#define cmFindCommon_h
#include "cmCommand.h"
/** \class cmFindCommon
* \brief Base class for FIND_XXX implementations.
*
* cmFindCommon is a parent class for cmFindBase,
* cmFindProgramCommand, cmFindPathCommand, cmFindLibraryCommand,
* cmFindFileCommand, and cmFindPackageCommand.
*/
class cmFindCommon : public cmCommand
{
public:
cmFindCommon();
~cmFindCommon();
cmTypeMacro(cmFindCommon, cmCommand);
protected:
enum RootPathMode { RootPathModeBoth,
RootPathModeOnlyRootPath,
RootPathModeNoRootPath };
enum PathType { FullPath, CMakePath, EnvPath };
/** Place a set of search paths under the search roots. */
void RerootPaths(std::vector<std::string>& paths);
/** Compute the current default root path mode. */
void SelectDefaultRootPathMode();
/** Compute the current default bundle/framework search policy. */
void SelectDefaultMacMode();
cmStdString CMakePathName;
RootPathMode FindRootPathMode;
bool CheckCommonArgument(std::string const& arg);
void AddPathSuffix(std::string const& arg);
void GetAppBundlePaths(std::vector<std::string>& paths);
void GetFrameworkPaths(std::vector<std::string>& paths);
void AddCMakePath(std::vector<std::string>& out_paths,
const char* variable, std::set<cmStdString>* emmitted = 0);
void AddEnvPath(std::vector<std::string>& out_paths,
const char* variable, std::set<cmStdString>* emmitted = 0);
void AddPathsInternal(std::vector<std::string>& out_paths,
std::vector<std::string> const& in_paths,
PathType pathType,
std::set<cmStdString>* emmitted = 0);
void AddPathInternal(std::vector<std::string>& out_paths,
std::string const& in_path,
PathType pathType,
std::set<cmStdString>* emmitted = 0);
bool NoDefaultPath;
bool NoCMakePath;
bool NoCMakeEnvironmentPath;
bool NoSystemEnvironmentPath;
bool NoCMakeSystemPath;
std::vector<std::string> SearchPathSuffixes;
std::string GenericDocumentationMacPolicy;
std::string GenericDocumentationRootPath;
std::string GenericDocumentationPathsOrder;
bool SearchFrameworkFirst;
bool SearchFrameworkOnly;
bool SearchFrameworkLast;
bool SearchAppBundleFirst;
bool SearchAppBundleOnly;
bool SearchAppBundleLast;
};
#endif

View File

@ -23,6 +23,12 @@ cmFindLibraryCommand::cmFindLibraryCommand()
"FIND_XXX", "find_library");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_XXX_PATH", "CMAKE_LIBRARY_PATH");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_XXX_MAC_PATH",
"CMAKE_FRAMEWORK_PATH");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_SYSTEM_XXX_MAC_PATH",
"CMAKE_SYSTEM_FRAMEWORK_PATH");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_SYSTEM", "LIB");
cmSystemTools::ReplaceString(this->GenericDocumentation,

File diff suppressed because it is too large Load Diff

View File

@ -17,16 +17,20 @@
#ifndef cmFindPackageCommand_h
#define cmFindPackageCommand_h
#include "cmCommand.h"
#include "cmFindCommon.h"
class cmFindPackageFileList;
/** \class cmFindPackageCommand
* \brief Load settings from an external project.
*
* cmFindPackageCommand
*/
class cmFindPackageCommand : public cmCommand
class cmFindPackageCommand : public cmFindCommon
{
public:
cmFindPackageCommand();
/**
* This is a virtual constructor for the command.
*/
@ -62,51 +66,45 @@ public:
/**
* More documentation.
*/
virtual const char* GetFullDocumentation()
{
return
" find_package(<name> [major.minor] [QUIET] [NO_MODULE]\n"
" [[REQUIRED|COMPONENTS] [components...]])\n"
"Finds and loads settings from an external project. <name>_FOUND will "
"be set to indicate whether the package was found. Settings that "
"can be used when <name>_FOUND is true are package-specific. The "
"package is found through several steps. "
"Directories listed in CMAKE_MODULE_PATH are searched for files called "
"\"Find<name>.cmake\". If such a file is found, it is read and "
"processed by CMake, and is responsible for finding the package. "
"This first step may be skipped by using the NO_MODULE option. "
"If no such file is found, it is expected that the package is another "
"project built by CMake that has a \"<name>Config.cmake\" file. "
"A cache entry called <name>_DIR is created and is expected to be set "
"to the directory containing this file. If the file is found, it is "
"read and processed by CMake to load the settings of the package. If "
"<name>_DIR has not been set during a configure step, the command "
"will generate an error describing the problem unless the QUIET "
"argument is specified. If <name>_DIR has been set to a directory "
"not containing a \"<name>Config.cmake\" file, an error is always "
"generated. If REQUIRED is specified and the package is not found, "
"a FATAL_ERROR is generated and the configure step stops executing. "
"A package-specific list of components may be listed after the "
"REQUIRED option, or after the COMPONENTS option if no REQUIRED "
"option is given.";
}
virtual const char* GetFullDocumentation();
cmTypeMacro(cmFindPackageCommand, cmCommand);
cmTypeMacro(cmFindPackageCommand, cmFindCommon);
private:
void AppendSuccessInformation(bool quiet);
void AppendSuccessInformation();
void AppendToProperty(const char* propertyName);
bool FindModule(bool& found, bool quiet, bool required);
bool FindConfig();
std::string SearchForConfig() const;
bool FindModule(bool& found);
bool HandlePackageMode();
void FindConfig();
bool FindPrefixedConfig();
bool FindFrameworkConfig();
bool FindAppBundleConfig();
bool ReadListFile(const char* f);
void AddUserPath(std::string const& p);
void ComputePrefixes();
bool SearchDirectory(std::string const& dir);
bool CheckDirectory(std::string const& dir);
bool FindConfigFile(std::string const& dir, std::string& file);
bool SearchPrefix(std::string const& prefix);
bool SearchFrameworkPrefix(std::string const& prefix_in);
bool SearchAppBundlePrefix(std::string const& prefix_in);
friend class cmFindPackageFileList;
std::string CommandDocumentation;
cmStdString Name;
cmStdString Variable;
cmStdString Config;
std::vector<cmStdString> Builds;
std::vector<cmStdString> Prefixes;
std::vector<cmStdString> Relatives;
cmStdString FileFound;
bool Quiet;
bool Required;
bool Compatibility_1_6;
bool NoModule;
bool NoBuilds;
bool DebugMode;
std::vector<std::string> Names;
std::vector<std::string> Configs;
std::vector<std::string> Prefixes;
std::vector<std::string> UserPaths;
};
#endif

View File

@ -27,6 +27,12 @@ cmFindPathCommand::cmFindPathCommand()
"FIND_XXX", "find_path");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_XXX_PATH", "CMAKE_INCLUDE_PATH");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_XXX_MAC_PATH",
"CMAKE_FRAMEWORK_PATH");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_SYSTEM_XXX_MAC_PATH",
"CMAKE_SYSTEM_FRAMEWORK_PATH");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_SYSTEM", "INCLUDE");
cmSystemTools::ReplaceString(this->GenericDocumentation,

View File

@ -28,6 +28,12 @@ cmFindProgramCommand::cmFindProgramCommand()
"FIND_XXX", "find_program");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_XXX_PATH", "CMAKE_PROGRAM_PATH");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_XXX_MAC_PATH",
"CMAKE_APPBUNDLE_PATH");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_SYSTEM_XXX_MAC_PATH",
"CMAKE_SYSTEM_APPBUNDLE_PATH");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_SYSTEM", "");
cmSystemTools::ReplaceString(this->GenericDocumentation,