diff options
Diffstat (limited to 'Source/cmFindBase.cxx')
-rw-r--r-- | Source/cmFindBase.cxx | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx new file mode 100644 index 0000000..fa9b381 --- /dev/null +++ b/Source/cmFindBase.cxx @@ -0,0 +1,397 @@ +/*============================================================================ + 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" + +#include "cmAlgorithms.h" +#include "cmState.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.empty()) + { + this->VariableDocumentation = "Where can "; + if(this->Names.empty()) + { + 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->VariableDocumentation += + cmJoin(cmMakeRange(this->Names).retreat(1), ", "); + 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]); + this->UserGuessArgs.insert(this->UserGuessArgs.end(), + shortArgs.begin() + 1, shortArgs.end()); + } + this->ExpandPaths(); + + this->ComputeFinalPaths(); + + return true; +} + +void cmFindBase::ExpandPaths() +{ + if(!this->NoDefaultPath) + { + if(!this->NoCMakePath) + { + this->FillCMakeVariablePath(); + } + if(!this->NoCMakeEnvironmentPath) + { + this->FillCMakeEnvironmentPath(); + } + } + this->FillUserHintsPath(); + if(!this->NoDefaultPath) + { + if(!this->NoSystemEnvironmentPath) + { + this->FillSystemEnvironmentPath(); + } + if(!this->NoCMakeSystemPath) + { + this->FillCMakeSystemVariablePath(); + } + } + 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); + paths.AddEnvPrefixPath("PATH", true); + } + // 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 " << cmJoin(this->Names, " ") << "\n"; + std::cerr << "\n"; + std::cerr << "SearchPathSuffixes "; + std::cerr << cmJoin(this->SearchPathSuffixes, "\n") << "\n"; + std::cerr << "SearchPaths\n"; + std::cerr << cmWrap("[", this->SearchPaths, "]", "\n") << "\n"; +} + +bool cmFindBase::CheckForVariableInCache() +{ + if(const char* cacheValue = + this->Makefile->GetDefinition(this->VariableName)) + { + cmState* state = this->Makefile->GetState(); + const char* cacheEntry = state->GetCacheEntryValue(this->VariableName); + bool found = !cmSystemTools::IsNOTFOUND(cacheValue); + bool cached = cacheEntry ? true : false; + 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 && state->GetCacheEntryType(this->VariableName) + == cmState::UNINITIALIZED) + { + this->AlreadyInCacheWithoutMetaInfo = true; + } + return true; + } + else if(cached) + { + const char* hs = state->GetCacheEntryProperty(this->VariableName, + "HELPSTRING"); + this->VariableDocumentation = hs?hs:"(none)"; + } + } + return false; +} |