mirror of
https://github.com/reactos/CMake.git
synced 2024-12-14 15:19:39 +00:00
1abd7cd930
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.
408 lines
11 KiB
C++
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;
|
|
}
|