add_test: Honor CROSSCOMPILING_EMULATOR only when cross-compiling

Add policy CMP0158 to provide compatibility for existing projects.

Fixes: #23672
stage/master/nightly/2023/12/20
Ralf Habacker 2023-11-02 17:48:15 +01:00 committed by Brad King
parent daf8da8c80
commit ca5a300d7f
13 changed files with 163 additions and 2 deletions

View File

@ -42,6 +42,12 @@ directory the test is created in.
<emulator> <command>
.. versionchanged:: 3.29
The emulator is used only when
:variable:`cross-compiling <CMAKE_CROSSCOMPILING>`.
See policy :policy:`CMP0158`.
* .. versionadded:: 3.29
The target's :prop_tgt:`TEST_LAUNCHER`, if set, will be

View File

@ -57,6 +57,7 @@ Policies Introduced by CMake 3.29
.. toctree::
:maxdepth: 1
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>

27
Help/policy/CMP0158.rst Normal file
View File

@ -0,0 +1,27 @@
CMP0158
-------
.. versionadded:: 3.29
:command:`add_test` honors :variable:`CMAKE_CROSSCOMPILING_EMULATOR` only
when :variable:`cross-compiling <CMAKE_CROSSCOMPILING>`.
In CMake 3.28 and below, :command:`add_test` unconditionally used the
:prop_tgt:`CROSSCOMPILING_EMULATOR` target property (initialized by the
:variable:`CMAKE_CROSSCOMPILING_EMULATOR` variable) to run test commands
naming executable targets. CMake 3.29 and above prefer to use the emulator
only when the :variable:`CMAKE_CROSSCOMPILING` variable is enabled. The
:variable:`CMAKE_TEST_LAUNCHER` variable may be used instead when not
cross-compiling. This policy provides compatibility for projects that
have not been updated.
The ``OLD`` behavior for this policy is for :command:`add_test` to use
the :prop_tgt:`CROSSCOMPILING_EMULATOR` target property unconditionally.
The ``NEW`` behavior for this policy is for :command:`add_test` to use
the :prop_tgt:`CROSSCOMPILING_EMULATOR` target property only when
:variable:`cross-compiling <CMAKE_CROSSCOMPILING>`.
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.

View File

@ -5,3 +5,7 @@ cmake-test-launcher
:prop_tgt:`TEST_LAUNCHER` target property were added to specify
a launcher to be used by executable targets when invoked by
tests added by the :command:`add_test` command.
* The :command:`add_test` command now honors
:variable:`CMAKE_CROSSCOMPILING_EMULATOR` only when cross-compiling.
See policy :policy:`CMP0158`.

View File

@ -480,7 +480,11 @@ class cmMakefile;
29, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0157, \
"Swift compilation mode selected by an abstraction.", 3, 29, 0, \
cmPolicies::WARN)
cmPolicies::WARN) \
SELECT(POLICY, CMP0158, \
"add_test() honors CMAKE_CROSSCOMPILING_EMULATOR only when " \
"cross-compiling.", \
3, 28, 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

@ -9,6 +9,7 @@
cmTest::cmTest(cmMakefile* mf)
: Backtrace(mf->GetBacktrace())
, PolicyStatusCMP0158(mf->GetPolicyStatus(cmPolicies::CMP0158))
{
this->Makefile = mf;
this->OldStyle = true;

View File

@ -9,6 +9,7 @@
#include <vector>
#include "cmListFileCache.h"
#include "cmPolicies.h"
#include "cmPropertyMap.h"
#include "cmValue.h"
@ -60,6 +61,12 @@ public:
bool GetOldStyle() const { return this->OldStyle; }
void SetOldStyle(bool b) { this->OldStyle = b; }
/** Get/Set if CMP0158 policy is NEW */
bool GetCMP0158IsNew() const
{
return this->PolicyStatusCMP0158 == cmPolicies::NEW;
}
/** Set/Get whether lists in command lines should be expanded. */
bool GetCommandExpandLists() const;
void SetCommandExpandLists(bool b);
@ -74,4 +81,5 @@ private:
cmMakefile* Makefile;
cmListFileBacktrace Backtrace;
cmPolicies::PolicyStatus PolicyStatusCMP0158;
};

View File

@ -167,6 +167,8 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
if (target && target->GetType() == cmStateEnums::EXECUTABLE) {
// Use the target file on disk.
exe = target->GetFullPath(config);
auto useEmulator = !this->GetTest()->GetCMP0158IsNew() ||
this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING");
// Prepend with the test launcher if specified.
cmValue launcher = target->GetProperty("TEST_LAUNCHER");
@ -182,7 +184,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
// Prepend with the emulator when cross compiling if required.
cmValue emulator = target->GetProperty("CROSSCOMPILING_EMULATOR");
if (cmNonempty(emulator)) {
if (cmNonempty(emulator) && useEmulator) {
cmList emulatorWithArgs{ *emulator };
std::string emulatorExe(emulatorWithArgs[0]);
cmSystemTools::ConvertToUnixSlashes(emulatorExe);

View File

@ -0,0 +1,28 @@
set(testfile "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake")
if(EXISTS "${testfile}")
file(READ "${testfile}" testfile_contents)
else()
message(FATAL_ERROR "Could not find expected CTestTestfile.cmake.")
endif()
set(error_details "There is a problem with generated test file: ${testfile}")
if(testfile_contents MATCHES "add_test[(]DoesNotUseEmulator [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Used emulator when it should not be used. ${error_details}")
endif()
if(testfile_contents MATCHES "add_test[(]ShouldNotUseEmulator [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Used emulator when it should be used. ${error_details}")
endif()
if(testfile_contents MATCHES "add_test[(]DoesNotUseEmulatorWithGenex [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Used emulator when it should not be used. ${error_details}")
endif()
if(testfile_contents MATCHES "add_test[(]ShouldNotUseEmulatorWithExecTargetFromSubdirAddedWithoutGenex [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Used emulator when it should be used. ${error_details}")
endif()
if(testfile_contents MATCHES "add_test[(]DoesNotUseEmulatorWithExecTargetFromSubdirAddedWithGenex [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Used emulator when it should not be used. ${error_details}")
endif()

View File

@ -0,0 +1,25 @@
if(CMAKE_CROSSCOMPILING)
message(FATAL_ERROR "cross compiling")
endif()
cmake_policy(SET CMP0158 NEW)
enable_testing()
add_test(NAME DoesNotUseEmulator
COMMAND ${CMAKE_COMMAND} -E echo "Hi")
add_executable(generated_exe simple_src_exiterror.cxx)
add_test(NAME ShouldNotUseEmulator
COMMAND generated_exe)
add_test(NAME DoesNotUseEmulatorWithGenex
COMMAND $<TARGET_FILE:generated_exe>)
add_subdirectory(AddTest)
add_test(NAME ShouldNotUseEmulatorWithExecTargetFromSubdirAddedWithoutGenex
COMMAND generated_exe_in_subdir_added_to_test_without_genex)
add_test(NAME DoesNotUseEmulatorWithExecTargetFromSubdirAddedWithGenex
COMMAND $<TARGET_FILE:generated_exe_in_subdir_added_to_test_with_genex>)

View File

@ -0,0 +1,28 @@
set(testfile "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake")
if(EXISTS "${testfile}")
file(READ "${testfile}" testfile_contents)
else()
message(FATAL_ERROR "Could not find expected CTestTestfile.cmake.")
endif()
set(error_details "There is a problem with generated test file: ${testfile}")
if(testfile_contents MATCHES "add_test[(]DoesNotUseEmulator [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Used emulator when it should not be used. ${error_details}")
endif()
if(NOT testfile_contents MATCHES "add_test[(]UsesEmulator [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Did not use emulator when it should be used. ${error_details}")
endif()
if(testfile_contents MATCHES "add_test[(]DoesNotUseEmulatorWithGenex [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Used emulator when it should not be used. ${error_details}")
endif()
if(NOT testfile_contents MATCHES "add_test[(]UsesEmulatorWithExecTargetFromSubdirAddedWithoutGenex [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Did not use emulator when it should be used. ${error_details}")
endif()
if(testfile_contents MATCHES "add_test[(]DoesNotUseEmulatorWithExecTargetFromSubdirAddedWithGenex [^\n]+pseudo_emulator[^\n]+\n")
message(SEND_ERROR "Used emulator when it should not be used. ${error_details}")
endif()

View File

@ -0,0 +1,25 @@
if(CMAKE_CROSSCOMPILING)
message(FATAL_ERROR "cross compiling")
endif()
cmake_policy(SET CMP0158 OLD)
enable_testing()
add_test(NAME DoesNotUseEmulator
COMMAND ${CMAKE_COMMAND} -E echo "Hi")
add_executable(generated_exe simple_src_exiterror.cxx)
add_test(NAME UsesEmulator
COMMAND generated_exe)
add_test(NAME DoesNotUseEmulatorWithGenex
COMMAND $<TARGET_FILE:generated_exe>)
add_subdirectory(AddTest)
add_test(NAME UsesEmulatorWithExecTargetFromSubdirAddedWithoutGenex
COMMAND generated_exe_in_subdir_added_to_test_without_genex)
add_test(NAME DoesNotUseEmulatorWithExecTargetFromSubdirAddedWithGenex
COMMAND $<TARGET_FILE:generated_exe_in_subdir_added_to_test_with_genex>)

View File

@ -6,6 +6,8 @@ set(RunCMake_TEST_OPTIONS
run_cmake(CrosscompilingEmulatorProperty)
run_cmake(TryRun)
run_cmake(AddTest)
run_cmake(AddTest-CMP0158-OLD)
run_cmake(AddTest-CMP0158-NEW)
function(CustomCommandGenerator_run_and_build case)
# Use a single build tree for a few tests without cleaning.