mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 10:50:16 -06:00
find_program: Find programs that are executable but not readable
This fix was first made by commit 86e6349ef7 (find_program: Find
programs that are executable but not readable, 2020-04-04,
v3.18.0-rc1~372^2) but was reverted for compatibility. Re-introduce it
with a policy for compatibility.
Fixes: #10468
This commit is contained in:
@@ -54,6 +54,14 @@ functions.
|
||||
Policies Introduced by CMake 3.18
|
||||
=================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
CMP0109: find_program() requires permission to execute but not to read. </policy/CMP0109>
|
||||
|
||||
Policies Introduced by CMake 3.18
|
||||
=================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
|
||||
22
Help/policy/CMP0109.rst
Normal file
22
Help/policy/CMP0109.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
CMP0109
|
||||
-------
|
||||
|
||||
:command:`find_program` requires permission to execute but not to read.
|
||||
|
||||
In CMake 3.18 and below, the :command:`find_program` command on UNIX
|
||||
would find files that are readable without requiring execute permission,
|
||||
and would not find files that are executable without read permission.
|
||||
In CMake 3.19 and above, ``find_program`` now prefers to require execute
|
||||
permission but not read permission. This policy provides compatibility
|
||||
with projects that have not been updated to expect the new behavior.
|
||||
|
||||
The ``OLD`` behavior for this policy is for ``find_program`` to require
|
||||
read permission but not execute permission.
|
||||
The ``NEW`` behavior for this policy is for ``find_program`` to require
|
||||
execute permission but not read permission.
|
||||
|
||||
This policy was introduced in CMake version 3.19. CMake version |release|
|
||||
warns when the policy is not set and uses ``OLD`` behavior. Use the
|
||||
:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
|
||||
|
||||
.. include:: DEPRECATED.txt
|
||||
5
Help/release/dev/find_program-exe-no-read.rst
Normal file
5
Help/release/dev/find_program-exe-no-read.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
find_program-exe-no-read
|
||||
------------------------
|
||||
|
||||
* The :command:`find_program` command now requires permission to execute
|
||||
but not to read the file found. See policy :policy:`CMP0109`.
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
@@ -19,6 +20,7 @@ struct cmFindProgramHelper
|
||||
cmFindProgramHelper(cmMakefile* makefile, cmFindBase const* base)
|
||||
: DebugSearches("find_program", base)
|
||||
, Makefile(makefile)
|
||||
, PolicyCMP0109(makefile->GetPolicyStatus(cmPolicies::CMP0109))
|
||||
{
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
|
||||
// Consider platform-specific extensions.
|
||||
@@ -48,6 +50,8 @@ struct cmFindProgramHelper
|
||||
cmFindBaseDebugState DebugSearches;
|
||||
cmMakefile* Makefile;
|
||||
|
||||
cmPolicies::PolicyStatus PolicyCMP0109;
|
||||
|
||||
void AddName(std::string const& name) { this->Names.push_back(name); }
|
||||
void SetName(std::string const& name)
|
||||
{
|
||||
@@ -85,7 +89,7 @@ struct cmFindProgramHelper
|
||||
this->TestNameExt = cmStrCat(name, ext);
|
||||
this->TestPath =
|
||||
cmSystemTools::CollapseFullPath(this->TestNameExt, path);
|
||||
bool exists = cmSystemTools::FileExists(this->TestPath, true);
|
||||
bool exists = this->FileIsExecutable(this->TestPath);
|
||||
exists ? this->DebugSearches.FoundAt(this->TestPath)
|
||||
: this->DebugSearches.FailedAt(this->TestPath);
|
||||
if (exists) {
|
||||
@@ -95,6 +99,48 @@ struct cmFindProgramHelper
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool FileIsExecutable(std::string const& file) const
|
||||
{
|
||||
switch (this->PolicyCMP0109) {
|
||||
case cmPolicies::OLD:
|
||||
return cmSystemTools::FileExists(file, true);
|
||||
case cmPolicies::NEW:
|
||||
case cmPolicies::REQUIRED_ALWAYS:
|
||||
case cmPolicies::REQUIRED_IF_USED:
|
||||
return cmSystemTools::FileIsExecutable(file);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
bool const isExeOld = cmSystemTools::FileExists(file, true);
|
||||
bool const isExeNew = cmSystemTools::FileIsExecutable(file);
|
||||
if (isExeNew == isExeOld) {
|
||||
return isExeNew;
|
||||
}
|
||||
if (isExeNew) {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::AUTHOR_WARNING,
|
||||
cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0109),
|
||||
"\n"
|
||||
"The file\n"
|
||||
" ",
|
||||
file,
|
||||
"\n"
|
||||
"is executable but not readable. "
|
||||
"CMake is ignoring it for compatibility."));
|
||||
} else {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::AUTHOR_WARNING,
|
||||
cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0109),
|
||||
"\n"
|
||||
"The file\n"
|
||||
" ",
|
||||
file,
|
||||
"\n"
|
||||
"is readable but not executable. "
|
||||
"CMake is using it for compatibility."));
|
||||
}
|
||||
return isExeOld;
|
||||
}
|
||||
};
|
||||
|
||||
cmFindProgramCommand::cmFindProgramCommand(cmExecutionStatus& status)
|
||||
|
||||
@@ -320,7 +320,10 @@ class cmMakefile;
|
||||
SELECT(POLICY, CMP0107, "An ALIAS target cannot overwrite another target.", \
|
||||
3, 18, 0, cmPolicies::WARN) \
|
||||
SELECT(POLICY, CMP0108, "A target cannot link to itself through an alias.", \
|
||||
3, 18, 0, cmPolicies::WARN)
|
||||
3, 18, 0, cmPolicies::WARN) \
|
||||
SELECT(POLICY, CMP0109, \
|
||||
"find_program() requires permission to execute but not to read.", 3, \
|
||||
19, 0, cmPolicies::WARN)
|
||||
|
||||
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
|
||||
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ExeNoRead" "#!/bin/sh\n")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ReadNoExe" "#ReadNoExe")
|
||||
execute_process(COMMAND chmod -r+x "${CMAKE_CURRENT_BINARY_DIR}/ExeNoRead")
|
||||
find_program(ExeNoRead_EXECUTABLE NAMES ExeNoRead NO_DEFAULT_PATH PATHS "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
message(STATUS "ExeNoRead_EXECUTABLE='${ExeNoRead_EXECUTABLE}'")
|
||||
find_program(ReadNoExe_EXECUTABLE NAMES ReadNoExe NO_DEFAULT_PATH PATHS "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
message(STATUS "ReadNoExe_EXECUTABLE='${ReadNoExe_EXECUTABLE}'")
|
||||
2
Tests/RunCMake/find_program/CMP0109-NEW-stdout.txt
Normal file
2
Tests/RunCMake/find_program/CMP0109-NEW-stdout.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
-- ExeNoRead_EXECUTABLE='.*/Tests/RunCMake/find_program/CMP0109-NEW-build/ExeNoRead'
|
||||
-- ReadNoExe_EXECUTABLE='ReadNoExe_EXECUTABLE-NOTFOUND'
|
||||
2
Tests/RunCMake/find_program/CMP0109-NEW.cmake
Normal file
2
Tests/RunCMake/find_program/CMP0109-NEW.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0109 NEW)
|
||||
include(CMP0109-Common.cmake)
|
||||
2
Tests/RunCMake/find_program/CMP0109-OLD-stdout.txt
Normal file
2
Tests/RunCMake/find_program/CMP0109-OLD-stdout.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
-- ExeNoRead_EXECUTABLE='ExeNoRead_EXECUTABLE-NOTFOUND'
|
||||
-- ReadNoExe_EXECUTABLE='.*/Tests/RunCMake/find_program/CMP0109-OLD-build/ReadNoExe'
|
||||
2
Tests/RunCMake/find_program/CMP0109-OLD.cmake
Normal file
2
Tests/RunCMake/find_program/CMP0109-OLD.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0109 OLD)
|
||||
include(CMP0109-Common.cmake)
|
||||
29
Tests/RunCMake/find_program/CMP0109-WARN-stderr.txt
Normal file
29
Tests/RunCMake/find_program/CMP0109-WARN-stderr.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
^CMake Warning \(dev\) at CMP0109-Common.cmake:4 \(find_program\):
|
||||
Policy CMP0109 is not set: find_program\(\) requires permission to execute
|
||||
but not to read. Run "cmake --help-policy CMP0109" for policy details.
|
||||
Use the cmake_policy command to set the policy and suppress this warning.
|
||||
|
||||
The file
|
||||
|
||||
.*/Tests/RunCMake/find_program/CMP0109-WARN-build/ExeNoRead
|
||||
|
||||
is executable but not readable. CMake is ignoring it for compatibility.
|
||||
Call Stack \(most recent call first\):
|
||||
CMP0109-WARN.cmake:1 \(include\)
|
||||
CMakeLists.txt:3 \(include\)
|
||||
This warning is for project developers. Use -Wno-dev to suppress it.
|
||||
+
|
||||
CMake Warning \(dev\) at CMP0109-Common.cmake:6 \(find_program\):
|
||||
Policy CMP0109 is not set: find_program\(\) requires permission to execute
|
||||
but not to read. Run "cmake --help-policy CMP0109" for policy details.
|
||||
Use the cmake_policy command to set the policy and suppress this warning.
|
||||
|
||||
The file
|
||||
|
||||
.*/Tests/RunCMake/find_program/CMP0109-WARN-build/ReadNoExe
|
||||
|
||||
is readable but not executable. CMake is using it for compatibility.
|
||||
Call Stack \(most recent call first\):
|
||||
CMP0109-WARN.cmake:1 \(include\)
|
||||
CMakeLists.txt:3 \(include\)
|
||||
This warning is for project developers. Use -Wno-dev to suppress it.$
|
||||
2
Tests/RunCMake/find_program/CMP0109-WARN-stdout.txt
Normal file
2
Tests/RunCMake/find_program/CMP0109-WARN-stdout.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
-- ExeNoRead_EXECUTABLE='ExeNoRead_EXECUTABLE-NOTFOUND'
|
||||
-- ReadNoExe_EXECUTABLE='.*/Tests/RunCMake/find_program/CMP0109-WARN-build/ReadNoExe'
|
||||
1
Tests/RunCMake/find_program/CMP0109-WARN.cmake
Normal file
1
Tests/RunCMake/find_program/CMP0109-WARN.cmake
Normal file
@@ -0,0 +1 @@
|
||||
include(CMP0109-Common.cmake)
|
||||
@@ -1 +0,0 @@
|
||||
-- ExeNoRead_EXECUTABLE='ExeNoRead_EXECUTABLE-NOTFOUND'
|
||||
@@ -17,7 +17,9 @@ else()
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(NOT "${uid}" STREQUAL "0")
|
||||
run_cmake(ExeNoRead)
|
||||
run_cmake(CMP0109-WARN)
|
||||
run_cmake(CMP0109-OLD)
|
||||
run_cmake(CMP0109-NEW)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user