file: STRINGS + REGEX store match results

Signed-off-by: Cristian Le <cristian.le@mpsd.mpg.de>
This commit is contained in:
Cristian Le
2024-01-03 20:34:56 +01:00
committed by Brad King
parent ff0085cf74
commit fa00928bcd
18 changed files with 133 additions and 1 deletions

View File

@@ -113,6 +113,11 @@ Reading
Consider only strings that match the given regular expression,
as described under :ref:`string(REGEX) <Regex Specification>`.
.. versionchanged:: 3.29
Capture groups from the last match in the file are stored in
:variable:`CMAKE_MATCH_<n>`, similar to
:command:`string(REGEX MATCHALL)`. See policy :policy:`CMP0159`.
``ENCODING <encoding-type>``
.. versionadded:: 3.1

View File

@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.29
.. toctree::
:maxdepth: 1
CMP0159: file(STRINGS) with REGEX updates CMAKE_MATCH_<n>. </policy/CMP0159>
CMP0158: add_test() honors CMAKE_CROSSCOMPILING_EMULATOR only when cross-compiling. </policy/CMP0158>
CMP0157: Swift compilation mode is selected by an abstraction. </policy/CMP0157>
CMP0156: De-duplicate libraries on link lines based on linker capabilities. </policy/CMP0156>

24
Help/policy/CMP0159.rst Normal file
View File

@@ -0,0 +1,24 @@
CMP0159
-------
.. versionadded:: 3.29
:command:`file(STRINGS)` with ``REGEX`` updates :variable:`CMAKE_MATCH_<n>`.
In CMake 3.28 and below the :command:`file(STRINGS)` command's ``REGEX``
option does not affect :variable:`CMAKE_MATCH_<n>` variables. CMake 3.29
and above prefer to update the :variable:`CMAKE_MATCH_<n>` variables using
captures from the last match in the file, similar to the
:command:`string(REGEX MATCHALL)` command. This policy provides
compatibility for projects that have not been updated to expect the behavior.
The ``OLD`` behavior for this policy is for :command:`file(STRINGS)` with
``REGEX`` to not store capture groups in :variable:`CMAKE_MATCH_<n>`
variables. The ``NEW`` behavior is to store the capture groups.
This policy was introduced in CMake version 3.29. Use the
:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
Unlike many policies, CMake version |release| does *not* warn
when this policy is not set and simply uses ``OLD`` behavior.
.. include:: DEPRECATED.txt

View File

@@ -315,6 +315,7 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
unsigned int limit_count = 0;
cmsys::RegularExpression regex;
bool have_regex = false;
bool store_regex = true;
bool newline_consume = false;
bool hex_conversion_enabled = true;
enum
@@ -399,6 +400,26 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
return false;
}
have_regex = true;
switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0159)) {
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
// store_regex = true
break;
case cmPolicies::WARN:
if (status.GetMakefile().PolicyOptionalWarningEnabled(
"CMAKE_POLICY_WARNING_CMP0159")) {
status.GetMakefile().IssueMessage(
MessageType::AUTHOR_WARNING,
cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0159), '\n',
"For compatibility, CMake is leaving CMAKE_MATCH_<n> "
"unchanged."));
}
CM_FALLTHROUGH;
case cmPolicies::OLD:
store_regex = false;
break;
}
arg_mode = arg_none;
} else if (arg_mode == arg_encoding) {
if (args[i] == "UTF-8") {
@@ -539,6 +560,10 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
// string matches the requirements. The length may now be as
// low as zero since blank lines are allowed.
if (s.length() >= minlen && (!have_regex || regex.find(s))) {
if (store_regex) {
status.GetMakefile().ClearMatches();
status.GetMakefile().StoreMatches(regex);
}
output_size += static_cast<int>(s.size()) + 1;
if (limit_output >= 0 && output_size >= limit_output) {
s.clear();
@@ -555,6 +580,10 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
// be at least one no matter what the user specified.
if (s.length() >= minlen && !s.empty() &&
(!have_regex || regex.find(s))) {
if (store_regex) {
status.GetMakefile().ClearMatches();
status.GetMakefile().StoreMatches(regex);
}
output_size += static_cast<int>(s.size()) + 1;
if (limit_output >= 0 && output_size >= limit_output) {
s.clear();
@@ -572,6 +601,10 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
if (maxlen > 0 && s.size() == maxlen) {
// Terminate a string if the maximum length is reached.
if (s.length() >= minlen && (!have_regex || regex.find(s))) {
if (store_regex) {
status.GetMakefile().ClearMatches();
status.GetMakefile().StoreMatches(regex);
}
output_size += static_cast<int>(s.size()) + 1;
if (limit_output >= 0 && output_size >= limit_output) {
s.clear();
@@ -588,6 +621,10 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
// matches the requirements.
if ((!limit_count || strings.size() < limit_count) && !s.empty() &&
s.length() >= minlen && (!have_regex || regex.find(s))) {
if (store_regex) {
status.GetMakefile().ClearMatches();
status.GetMakefile().StoreMatches(regex);
}
output_size += static_cast<int>(s.size()) + 1;
if (limit_output < 0 || output_size < limit_output) {
strings.push_back(s);

View File

@@ -484,7 +484,10 @@ class cmMakefile;
SELECT(POLICY, CMP0158, \
"add_test() honors CMAKE_CROSSCOMPILING_EMULATOR only when " \
"cross-compiling.", \
3, 29, 0, cmPolicies::WARN)
3, 29, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0159, \
"file(STRINGS) with REGEX updates CMAKE_MATCH_<n>.", 3, 29, 0, \
cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \

View File

@@ -538,6 +538,7 @@ foreach(var
endforeach()
add_RunCMake_test(file-DOWNLOAD)
add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
add_RunCMake_test(file-STRINGS)
add_RunCMake_test(find_file -DMINGW=${MINGW})
add_RunCMake_test(find_library -DMINGW=${MINGW} -DCYGWIN=${CYGWIN} -DMSYS=${MSYS} -DMSVC=${MSVC})
add_RunCMake_test(find_package -DMINGW=${MINGW} -DMSYS=${MSYS})

View File

@@ -1,2 +1,3 @@
cmake_policy(VERSION 3.24)
cmake_policy(SET CMP0159 NEW)
enable_language(C)

View File

@@ -0,0 +1,12 @@
function (output_results msg)
message(STATUS "results from: ${msg}")
message(STATUS "CMAKE_MATCH_0: -->${CMAKE_MATCH_0}<--")
message(STATUS "CMAKE_MATCH_1: -->${CMAKE_MATCH_1}<--")
message(STATUS "CMAKE_MATCH_2: -->${CMAKE_MATCH_2}<--")
message(STATUS "CMAKE_MATCH_COUNT: -->${CMAKE_MATCH_COUNT}<--")
endfunction ()
# Populate `CMAKE_MATCH_<n>` with some initial value
string(REGEX MATCH "(.*):" _ "Initial-value:")
file(STRINGS CMP0159.txt _ REGEX "(.*): (.*)")
output_results(CMP0159)

View File

@@ -0,0 +1,5 @@
-- results from: CMP0159
-- CMAKE_MATCH_0: -->real-value: 1<--
-- CMAKE_MATCH_1: -->real-value<--
-- CMAKE_MATCH_2: -->1<--
-- CMAKE_MATCH_COUNT: -->2<--

View File

@@ -0,0 +1,4 @@
cmake_policy(SET CMP0159 NEW)
include(CMP0159-Common.cmake)

View File

@@ -0,0 +1,5 @@
-- results from: CMP0159
-- CMAKE_MATCH_0: -->Initial-value:<--
-- CMAKE_MATCH_1: -->Initial-value<--
-- CMAKE_MATCH_2: --><--
-- CMAKE_MATCH_COUNT: -->1<--

View File

@@ -0,0 +1,4 @@
cmake_policy(SET CMP0159 OLD)
include(CMP0159-Common.cmake)

View File

@@ -0,0 +1,10 @@
CMake Warning \(dev\) at CMP0159-Common.cmake:[0-9]+ \(file\):
Policy CMP0159 is not set: file\(STRINGS\) with REGEX updates
CMAKE_MATCH_<n>\. Run "cmake --help-policy CMP0159" for policy details\.
Use the cmake_policy command to set the policy and suppress this warning\.
For compatibility, CMake is leaving CMAKE_MATCH_<n> unchanged\.
Call Stack \(most recent call first\):
CMP0159-WARN.cmake:[0-9]+ \(include\)
CMakeLists.txt:[0-9]+ \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.

View File

@@ -0,0 +1,5 @@
-- results from: CMP0159
-- CMAKE_MATCH_0: -->Initial-value:<--
-- CMAKE_MATCH_1: -->Initial-value<--
-- CMAKE_MATCH_2: --><--
-- CMAKE_MATCH_COUNT: -->1<--

View File

@@ -0,0 +1,4 @@
set(CMAKE_POLICY_WARNING_CMP0159 TRUE)
include(CMP0159-Common.cmake)

View File

@@ -0,0 +1,3 @@
overwritten-value: -1
real-value: 1
ignored = -2

View File

@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.13)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@@ -0,0 +1,5 @@
include(RunCMake)
run_cmake(CMP0159-WARN)
run_cmake(CMP0159-OLD)
run_cmake(CMP0159-NEW)