mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-02 20:29:49 -05:00
Merge topic 'find_item-validation-function'
f3b5a7d6df find_(program,library,file,path): add validation function
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !7364
This commit is contained in:
+60
-2
@@ -2,15 +2,20 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmFindBase.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmCMakePath.h"
|
||||
#include "cmExecutionStatus.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmPolicies.h"
|
||||
@@ -24,8 +29,6 @@
|
||||
#include "cmWindowsRegistry.h"
|
||||
#include "cmake.h"
|
||||
|
||||
class cmExecutionStatus;
|
||||
|
||||
cmFindBase::cmFindBase(std::string findCommandName, cmExecutionStatus& status)
|
||||
: cmFindCommon(status)
|
||||
, FindCommandName(std::move(findCommandName))
|
||||
@@ -138,6 +141,31 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
|
||||
cmStrCat("given invalid value for \"REGISTRY_VIEW\": ", args[j]));
|
||||
return false;
|
||||
}
|
||||
} else if (args[j] == "VALIDATOR") {
|
||||
if (++j == args.size()) {
|
||||
this->SetError("missing required argument for \"VALIDATOR\"");
|
||||
return false;
|
||||
}
|
||||
auto command = this->Makefile->GetState()->GetCommand(args[j]);
|
||||
if (command == nullptr) {
|
||||
this->SetError(cmStrCat(
|
||||
"command specified for \"VALIDATOR\" is undefined: ", args[j], '.'));
|
||||
return false;
|
||||
}
|
||||
// ensure a macro is not specified as validator
|
||||
const auto& validatorName = args[j];
|
||||
auto macros = cmExpandedList(this->Makefile->GetProperty("MACROS"));
|
||||
if (std::find_if(macros.begin(), macros.end(),
|
||||
[&validatorName](const std::string& item) {
|
||||
return cmSystemTools::Strucmp(validatorName.c_str(),
|
||||
item.c_str()) == 0;
|
||||
}) != macros.end()) {
|
||||
this->SetError(cmStrCat(
|
||||
"command specified for \"VALIDATOR\" is not a function: ", args[j],
|
||||
'.'));
|
||||
return false;
|
||||
}
|
||||
this->ValidatorName = args[j];
|
||||
} else if (this->CheckCommonArgument(args[j])) {
|
||||
doing = DoingNone;
|
||||
} else {
|
||||
@@ -188,6 +216,36 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmFindBase::Validate(const std::string& path) const
|
||||
{
|
||||
if (this->ValidatorName.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The validator command will be executed in an isolated scope.
|
||||
cmMakefile::ScopePushPop varScope(this->Makefile);
|
||||
cmMakefile::PolicyPushPop polScope(this->Makefile);
|
||||
static_cast<void>(varScope);
|
||||
static_cast<void>(polScope);
|
||||
|
||||
auto resultName =
|
||||
cmStrCat("CMAKE_"_s, cmSystemTools::UpperCase(this->FindCommandName),
|
||||
"_VALIDATOR_STATUS"_s);
|
||||
|
||||
this->Makefile->AddDefinitionBool(resultName, true);
|
||||
|
||||
cmListFileFunction validator(
|
||||
this->ValidatorName, 0, 0,
|
||||
{ cmListFileArgument(resultName, cmListFileArgument::Unquoted, 0),
|
||||
cmListFileArgument(path, cmListFileArgument::Quoted, 0) });
|
||||
cmExecutionStatus status(*this->Makefile);
|
||||
|
||||
if (this->Makefile->ExecuteCommand(validator, status)) {
|
||||
return this->Makefile->GetDefinition(resultName).IsOn();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cmFindBase::ExpandPaths()
|
||||
{
|
||||
if (!this->NoDefaultPath) {
|
||||
|
||||
@@ -31,6 +31,11 @@ public:
|
||||
*/
|
||||
virtual bool ParseArguments(std::vector<std::string> const& args);
|
||||
|
||||
/**
|
||||
* To check validity of a found path using user's validator, if any
|
||||
*/
|
||||
bool Validate(const std::string& path) const;
|
||||
|
||||
protected:
|
||||
friend class cmFindBaseDebugState;
|
||||
void ExpandPaths();
|
||||
@@ -63,6 +68,8 @@ protected:
|
||||
|
||||
bool Required = false;
|
||||
|
||||
std::string ValidatorName;
|
||||
|
||||
private:
|
||||
// Add pieces of the search.
|
||||
void FillPackageRootPath();
|
||||
|
||||
@@ -192,6 +192,7 @@ struct cmFindLibraryHelper
|
||||
|
||||
// Context information.
|
||||
cmMakefile* Makefile;
|
||||
cmFindBase const* FindBase;
|
||||
cmGlobalGenerator* GG;
|
||||
|
||||
// List of valid prefixes and suffixes.
|
||||
@@ -239,6 +240,11 @@ struct cmFindLibraryHelper
|
||||
bool CheckDirectory(std::string const& path);
|
||||
bool CheckDirectoryForName(std::string const& path, Name& name);
|
||||
|
||||
bool Validate(const std::string& path) const
|
||||
{
|
||||
return this->FindBase->Validate(path);
|
||||
}
|
||||
|
||||
cmFindBaseDebugState DebugSearches;
|
||||
|
||||
void DebugLibraryFailed(std::string const& name, std::string const& path)
|
||||
@@ -291,6 +297,7 @@ std::string const& get_suffixes(cmMakefile* mf)
|
||||
cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
|
||||
cmFindBase const* base)
|
||||
: Makefile(mf)
|
||||
, FindBase(base)
|
||||
, DebugMode(base->DebugModeEnabled())
|
||||
, DebugSearches(std::move(debugName), base)
|
||||
{
|
||||
@@ -416,10 +423,13 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
|
||||
if (!exists) {
|
||||
this->DebugLibraryFailed(name.Raw, path);
|
||||
} else {
|
||||
this->DebugLibraryFound(name.Raw, path);
|
||||
this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
|
||||
cmSystemTools::ConvertToUnixSlashes(this->BestPath);
|
||||
return true;
|
||||
auto testPath = cmSystemTools::CollapseFullPath(this->TestPath);
|
||||
if (this->Validate(testPath)) {
|
||||
this->DebugLibraryFound(name.Raw, path);
|
||||
this->BestPath = testPath;
|
||||
return true;
|
||||
}
|
||||
this->DebugLibraryFailed(name.Raw, path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,8 +453,11 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
|
||||
this->TestPath = cmStrCat(path, origName);
|
||||
// Make sure the path is readable and is not a directory.
|
||||
if (cmSystemTools::FileExists(this->TestPath, true)) {
|
||||
this->DebugLibraryFound(name.Raw, dir);
|
||||
if (!this->Validate(cmSystemTools::CollapseFullPath(this->TestPath))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->DebugLibraryFound(name.Raw, dir);
|
||||
// This is a matching file. Check if it is better than the
|
||||
// best name found so far. Earlier prefixes are preferred,
|
||||
// followed by earlier suffixes. For OpenBSD, shared library
|
||||
@@ -541,7 +554,10 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir()
|
||||
for (std::string const& n : this->Names) {
|
||||
fwPath = cmStrCat(d, n, ".framework");
|
||||
if (cmSystemTools::FileIsDirectory(fwPath)) {
|
||||
return cmSystemTools::CollapseFullPath(fwPath);
|
||||
auto finalPath = cmSystemTools::CollapseFullPath(fwPath);
|
||||
if (this->Validate(finalPath)) {
|
||||
return finalPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -558,7 +574,10 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName()
|
||||
for (std::string const& d : this->SearchPaths) {
|
||||
fwPath = cmStrCat(d, n, ".framework");
|
||||
if (cmSystemTools::FileIsDirectory(fwPath)) {
|
||||
return cmSystemTools::CollapseFullPath(fwPath);
|
||||
auto finalPath = cmSystemTools::CollapseFullPath(fwPath);
|
||||
if (this->Validate(finalPath)) {
|
||||
return finalPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,8 @@ std::string cmFindPathCommand::FindHeaderInFramework(
|
||||
if (!frameWorkName.empty()) {
|
||||
std::string fpath = cmStrCat(dir, frameWorkName, ".framework");
|
||||
std::string intPath = cmStrCat(fpath, "/Headers/", fileName);
|
||||
if (cmSystemTools::FileExists(intPath)) {
|
||||
if (cmSystemTools::FileExists(intPath) &&
|
||||
this->Validate(this->IncludeFileInPath ? intPath : fpath)) {
|
||||
debug.FoundAt(intPath);
|
||||
if (this->IncludeFileInPath) {
|
||||
return intPath;
|
||||
@@ -124,7 +125,8 @@ std::string cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState& debug)
|
||||
for (std::string const& n : this->Names) {
|
||||
for (std::string const& sp : this->SearchPaths) {
|
||||
tryPath = cmStrCat(sp, n);
|
||||
if (cmSystemTools::FileExists(tryPath)) {
|
||||
if (cmSystemTools::FileExists(tryPath) &&
|
||||
this->Validate(this->IncludeFileInPath ? tryPath : sp)) {
|
||||
debug.FoundAt(tryPath);
|
||||
if (this->IncludeFileInPath) {
|
||||
return tryPath;
|
||||
|
||||
@@ -27,6 +27,7 @@ struct cmFindProgramHelper
|
||||
cmFindBase const* base)
|
||||
: DebugSearches(std::move(debugName), base)
|
||||
, Makefile(makefile)
|
||||
, FindBase(base)
|
||||
, PolicyCMP0109(makefile->GetPolicyStatus(cmPolicies::CMP0109))
|
||||
{
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
|
||||
@@ -56,6 +57,7 @@ struct cmFindProgramHelper
|
||||
// Debug state
|
||||
cmFindBaseDebugState DebugSearches;
|
||||
cmMakefile* Makefile;
|
||||
cmFindBase const* FindBase;
|
||||
|
||||
cmPolicies::PolicyStatus PolicyCMP0109;
|
||||
|
||||
@@ -94,7 +96,7 @@ struct cmFindProgramHelper
|
||||
this->TestNameExt = cmStrCat(name, ext);
|
||||
this->TestPath = cmSystemTools::CollapseFullPath(
|
||||
this->TestNameExt, path);
|
||||
bool exists = this->FileIsExecutable(this->TestPath);
|
||||
bool exists = this->FileIsValid(this->TestPath);
|
||||
exists ? this->DebugSearches.FoundAt(this->TestPath)
|
||||
: this->DebugSearches.FailedAt(this->TestPath);
|
||||
if (exists) {
|
||||
@@ -104,12 +106,12 @@ struct cmFindProgramHelper
|
||||
return false;
|
||||
});
|
||||
}
|
||||
bool FileIsExecutable(std::string const& file) const
|
||||
bool FileIsValid(std::string const& file) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!this->FileIsExecutableCMP0109(file)) {
|
||||
return false;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
// Pretend the Windows "python" app installer alias does not exist.
|
||||
if (cmSystemTools::LowerCase(file).find("/windowsapps/python") !=
|
||||
std::string::npos) {
|
||||
@@ -119,10 +121,8 @@ struct cmFindProgramHelper
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return this->FileIsExecutableCMP0109(file);
|
||||
#endif
|
||||
return this->FindBase->Validate(file);
|
||||
}
|
||||
bool FileIsExecutableCMP0109(std::string const& file) const
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user