mirror of
https://github.com/reactos/CMake.git
synced 2024-12-12 13:56:00 +00:00
54475018ae
The fix in commit commit v3.6.0-rc1~82^2 (Drop find_(library|file|path) prefixes from PATH on non-Windows, 2016-05-09) aggressively dropped search of the entries in PATH itself in addition to the prefixes derived from it. This regresses find modules that (incorrectly) depended on the behavior, including some of our own modules such as FindImageMagick. Restore the search of entries in PATH itself. If we want to drop it later we will need to do so with a policy. Fixes #16192.
332 lines
10 KiB
C++
332 lines
10 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"
|
|
|
|
#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);
|
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
|
paths.AddEnvPrefixPath("PATH", true);
|
|
#endif
|
|
}
|
|
// 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;
|
|
}
|