CMake/Source/cmFindBase.cxx
Chuck Atkins 1abd7cd930 Use containers of labeled search paths instead of individual members
Manage classes of search paths in labeled containers.  This removes the
need to have a seperate member variable for each type of search path, but
also allows path types to be grouped togethor in various different ways
and manipulated as subsets of the full set of search paths.
2014-11-12 08:21:46 -05:00

408 lines
11 KiB
C++

/*============================================================================
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 "cmFindBase.h"
cmFindBase::cmFindBase()
{
this->AlreadyInCache = false;
this->AlreadyInCacheWithoutMetaInfo = false;
this->NamesPerDir = false;
this->NamesPerDirAllowed = false;
}
//----------------------------------------------------------------------------
bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
{
if(argsIn.size() < 2 )
{
this->SetError("called with incorrect number of arguments");
return false;
}
// copy argsIn into args so it can be modified,
// in the process extract the DOC "documentation"
size_t size = argsIn.size();
std::vector<std::string> args;
bool foundDoc = false;
for(unsigned int j = 0; j < size; ++j)
{
if(foundDoc || argsIn[j] != "DOC" )
{
if(argsIn[j] == "ENV")
{
if(j+1 < size)
{
j++;
cmSystemTools::GetPath(args, argsIn[j].c_str());
}
}
else
{
args.push_back(argsIn[j]);
}
}
else
{
if(j+1 < size)
{
foundDoc = true;
this->VariableDocumentation = argsIn[j+1];
j++;
if(j >= size)
{
break;
}
}
}
}
if(args.size() < 2 )
{
this->SetError("called with incorrect number of arguments");
return false;
}
this->VariableName = args[0];
if(this->CheckForVariableInCache())
{
this->AlreadyInCache = true;
return true;
}
this->AlreadyInCache = false;
// Find the current root path mode.
this->SelectDefaultRootPathMode();
// Find the current bundle/framework search policy.
this->SelectDefaultMacMode();
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)
{
if(args[j] == "NAMES")
{
doing = DoingNames;
newStyle = true;
}
else if (args[j] == "PATHS")
{
doing = DoingPaths;
newStyle = true;
}
else if (args[j] == "HINTS")
{
doing = DoingHints;
newStyle = true;
}
else if (args[j] == "PATH_SUFFIXES")
{
doing = DoingPathSuffixes;
newStyle = true;
}
else if (args[j] == "NAMES_PER_DIR")
{
doing = DoingNone;
if(this->NamesPerDirAllowed)
{
this->NamesPerDir = true;
}
else
{
this->SetError("does not support NAMES_PER_DIR");
return false;
}
}
else if (args[j] == "NO_SYSTEM_PATH")
{
doing = DoingNone;
this->NoDefaultPath = true;
}
else if (this->CheckCommonArgument(args[j]))
{
doing = DoingNone;
// Some common arguments were accidentally supported by CMake
// 2.4 and 2.6.0 in the short-hand form of the command, so we
// must support it even though it is not documented.
}
else if(doing == DoingNames)
{
this->Names.push_back(args[j]);
}
else if(doing == DoingPaths)
{
this->UserGuessArgs.push_back(args[j]);
}
else if(doing == DoingHints)
{
this->UserHintsArgs.push_back(args[j]);
}
else if(doing == DoingPathSuffixes)
{
this->AddPathSuffix(args[j]);
}
}
if(this->VariableDocumentation.size() == 0)
{
this->VariableDocumentation = "Where can ";
if(this->Names.size() == 0)
{
this->VariableDocumentation += "the (unknown) library be found";
}
else if(this->Names.size() == 1)
{
this->VariableDocumentation += "the "
+ this->Names[0] + " library be found";
}
else
{
this->VariableDocumentation += "one of the " + this->Names[0];
for (unsigned int j = 1; j < this->Names.size() - 1; ++j)
{
this->VariableDocumentation += ", " + this->Names[j];
}
this->VariableDocumentation += " or "
+ this->Names[this->Names.size() - 1] + " libraries be found";
}
}
// look for old style
// FIND_*(VAR name path1 path2 ...)
if(!newStyle)
{
// All the short-hand arguments have been recorded as names.
std::vector<std::string> shortArgs = this->Names;
this->Names.clear(); // clear out any values in Names
this->Names.push_back(shortArgs[0]);
for(unsigned int j = 1; j < shortArgs.size(); ++j)
{
this->UserGuessArgs.push_back(shortArgs[j]);
}
}
this->ExpandPaths();
this->ComputeFinalPaths();
return true;
}
void cmFindBase::ExpandPaths()
{
if(!this->NoDefaultPath)
{
if(!this->NoCMakePath)
{
this->FillCMakeVariablePath();
}
if(!this->NoCMakeEnvironmentPath)
{
this->FillCMakeEnvironmentPath();
}
if(!this->NoSystemEnvironmentPath)
{
this->FillSystemEnvironmentPath();
}
if(!this->NoCMakeSystemPath)
{
this->FillCMakeSystemVariablePath();
}
}
this->FillUserHintsPath();
this->FillUserGuessPath();
}
//----------------------------------------------------------------------------
void cmFindBase::FillCMakeEnvironmentPath()
{
cmSearchPath &paths = this->LabeledPaths[PathLabel::CMakeEnvironment];
// Add CMAKE_*_PATH environment variables
std::string var = "CMAKE_";
var += this->CMakePathName;
var += "_PATH";
paths.AddEnvPrefixPath("CMAKE_PREFIX_PATH");
paths.AddEnvPath(var);
if(this->CMakePathName == "PROGRAM")
{
paths.AddEnvPath("CMAKE_APPBUNDLE_PATH");
}
else
{
paths.AddEnvPath("CMAKE_FRAMEWORK_PATH");
}
paths.AddSuffixes(this->SearchPathSuffixes);
}
//----------------------------------------------------------------------------
void cmFindBase::FillCMakeVariablePath()
{
cmSearchPath &paths = this->LabeledPaths[PathLabel::CMake];
// Add CMake varibles of the same name as the previous environment
// varibles CMAKE_*_PATH to be used most of the time with -D
// command line options
std::string var = "CMAKE_";
var += this->CMakePathName;
var += "_PATH";
paths.AddCMakePrefixPath("CMAKE_PREFIX_PATH");
paths.AddCMakePath(var);
if(this->CMakePathName == "PROGRAM")
{
paths.AddCMakePath("CMAKE_APPBUNDLE_PATH");
}
else
{
paths.AddCMakePath("CMAKE_FRAMEWORK_PATH");
}
paths.AddSuffixes(this->SearchPathSuffixes);
}
//----------------------------------------------------------------------------
void cmFindBase::FillSystemEnvironmentPath()
{
cmSearchPath &paths = this->LabeledPaths[PathLabel::SystemEnvironment];
// Add LIB or INCLUDE
if(!this->EnvironmentPath.empty())
{
paths.AddEnvPath(this->EnvironmentPath);
}
// Add PATH
paths.AddEnvPath("PATH");
paths.AddSuffixes(this->SearchPathSuffixes);
}
//----------------------------------------------------------------------------
void cmFindBase::FillCMakeSystemVariablePath()
{
cmSearchPath &paths = this->LabeledPaths[PathLabel::CMakeSystem];
std::string var = "CMAKE_SYSTEM_";
var += this->CMakePathName;
var += "_PATH";
paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
paths.AddCMakePath(var);
if(this->CMakePathName == "PROGRAM")
{
paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");
}
else
{
paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
}
paths.AddSuffixes(this->SearchPathSuffixes);
}
//----------------------------------------------------------------------------
void cmFindBase::FillUserHintsPath()
{
cmSearchPath &paths = this->LabeledPaths[PathLabel::Hints];
for(std::vector<std::string>::const_iterator p = this->UserHintsArgs.begin();
p != this->UserHintsArgs.end(); ++p)
{
paths.AddUserPath(*p);
}
paths.AddSuffixes(this->SearchPathSuffixes);
}
//----------------------------------------------------------------------------
void cmFindBase::FillUserGuessPath()
{
cmSearchPath &paths = this->LabeledPaths[PathLabel::Guess];
for(std::vector<std::string>::const_iterator p = this->UserGuessArgs.begin();
p != this->UserGuessArgs.end(); ++p)
{
paths.AddUserPath(*p);
}
paths.AddSuffixes(this->SearchPathSuffixes);
}
//----------------------------------------------------------------------------
void cmFindBase::PrintFindStuff()
{
std::cerr << "SearchFrameworkLast: " << this->SearchFrameworkLast << "\n";
std::cerr << "SearchFrameworkOnly: " << this->SearchFrameworkOnly << "\n";
std::cerr << "SearchFrameworkFirst: " << this->SearchFrameworkFirst << "\n";
std::cerr << "SearchAppBundleLast: " << this->SearchAppBundleLast << "\n";
std::cerr << "SearchAppBundleOnly: " << this->SearchAppBundleOnly << "\n";
std::cerr << "SearchAppBundleFirst: " << this->SearchAppBundleFirst << "\n";
std::cerr << "VariableName " << this->VariableName << "\n";
std::cerr << "VariableDocumentation "
<< this->VariableDocumentation << "\n";
std::cerr << "NoDefaultPath " << this->NoDefaultPath << "\n";
std::cerr << "NoCMakeEnvironmentPath "
<< this->NoCMakeEnvironmentPath << "\n";
std::cerr << "NoCMakePath " << this->NoCMakePath << "\n";
std::cerr << "NoSystemEnvironmentPath "
<< this->NoSystemEnvironmentPath << "\n";
std::cerr << "NoCMakeSystemPath " << this->NoCMakeSystemPath << "\n";
std::cerr << "EnvironmentPath " << this->EnvironmentPath << "\n";
std::cerr << "CMakePathName " << this->CMakePathName << "\n";
std::cerr << "Names ";
for(unsigned int i =0; i < this->Names.size(); ++i)
{
std::cerr << this->Names[i] << " ";
}
std::cerr << "\n";
std::cerr << "\n";
std::cerr << "SearchPathSuffixes ";
for(unsigned int i =0; i < this->SearchPathSuffixes.size(); ++i)
{
std::cerr << this->SearchPathSuffixes[i] << "\n";
}
std::cerr << "\n";
std::cerr << "SearchPaths\n";
for(std::vector<std::string>::const_iterator i = this->SearchPaths.begin();
i != this->SearchPaths.end(); ++i)
{
std::cerr << "[" << *i << "]\n";
}
}
bool cmFindBase::CheckForVariableInCache()
{
if(const char* cacheValue =
this->Makefile->GetDefinition(this->VariableName))
{
cmCacheManager::CacheIterator it =
this->Makefile->GetCacheManager()->
GetCacheIterator(this->VariableName.c_str());
bool found = !cmSystemTools::IsNOTFOUND(cacheValue);
bool cached = !it.IsAtEnd();
if(found)
{
// If the user specifies the entry on the command line without a
// type we should add the type and docstring but keep the
// original value. Tell the subclass implementations to do
// this.
if(cached && it.GetType() == cmCacheManager::UNINITIALIZED)
{
this->AlreadyInCacheWithoutMetaInfo = true;
}
return true;
}
else if(cached)
{
const char* hs = it.GetProperty("HELPSTRING");
this->VariableDocumentation = hs?hs:"(none)";
}
}
return false;
}