diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2022-08-15 14:12:08 +0200 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2022-08-17 21:21:57 +0200 |
commit | edb88a3b2914bcce4a0a99b17ef14e3d4db0a220 (patch) | |
tree | 29a24e863a3cdb6d6467da16bd607eb37a1d02ad /cmake | |
parent | 5145d3899d338fbb82a2d314c58eb60a4a5205f8 (diff) |
CMake: Move _qt_internal_create_command_script to a public file
It's needed for creating qmake build tests.
CMake / CTest has a limitation of not allowing to create single-config
tests when using a multi-config generator using the add_test(NAME)
signature.
Using add_test(NAME) forcefully creates per-config tests, which means
that it's not possible to just run ctest to execute tests, without
specifying a -C parameter, which we do in the CI.
qmake tests need to use the add_test(NAME) signature
to specify the WORKING_DIRECTORY option.
Because of the above limitation, a work around is to not use the
add_test(NAME) signature, but instead delegate the working directory
assignment to a generated cmake script, which
_qt_internal_create_command_script can already do.
Pick-to: 6.4
Task-number: QTBUG-96058
Change-Id: I6f439165994671724157f0edb7a71e351271e329
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Diffstat (limited to 'cmake')
-rw-r--r-- | cmake/QtBaseGlobalTargets.cmake | 1 | ||||
-rw-r--r-- | cmake/QtBuild.cmake | 1 | ||||
-rw-r--r-- | cmake/QtConfig.cmake.in | 1 | ||||
-rw-r--r-- | cmake/QtPublicTestHelpers.cmake | 96 | ||||
-rw-r--r-- | cmake/QtTestHelpers.cmake | 98 |
5 files changed, 102 insertions, 95 deletions
diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index 16a6ac9273..8552137de7 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -332,6 +332,7 @@ set(__public_cmake_helpers cmake/QtPublicFinalizerHelpers.cmake cmake/QtPublicPluginHelpers.cmake cmake/QtPublicTargetHelpers.cmake + cmake/QtPublicTestHelpers.cmake cmake/QtPublicToolHelpers.cmake cmake/QtPublicWalkLibsHelpers.cmake cmake/QtPublicFindPackageHelpers.cmake diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 40c7080584..4c3654ba50 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -557,6 +557,7 @@ include(QtPublicTargetHelpers) include(QtPublicWalkLibsHelpers) include(QtPublicFindPackageHelpers) include(QtPublicDependencyHelpers) +include(QtPublicTestHelpers) include(QtPublicToolHelpers) if(CMAKE_CROSSCOMPILING) diff --git a/cmake/QtConfig.cmake.in b/cmake/QtConfig.cmake.in index cd7fdf7c02..ea92d180b5 100644 --- a/cmake/QtConfig.cmake.in +++ b/cmake/QtConfig.cmake.in @@ -115,6 +115,7 @@ include("${CMAKE_CURRENT_LIST_DIR}/QtPublicTargetHelpers.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicWalkLibsHelpers.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicFindPackageHelpers.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicDependencyHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicTestHelpers.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicToolHelpers.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicCMakeHelpers.cmake") diff --git a/cmake/QtPublicTestHelpers.cmake b/cmake/QtPublicTestHelpers.cmake new file mode 100644 index 0000000000..17ab6f5c97 --- /dev/null +++ b/cmake/QtPublicTestHelpers.cmake @@ -0,0 +1,96 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +# This function wraps COMMAND with cmake script, that makes possible standalone run with external +# arguments. +# +# Generated wrapper will be written to OUTPUT_FILE. +# If WORKING_DIRECTORY is not set COMMAND will be executed in CMAKE_CURRENT_BINARY_DIR. +# Variables from ENVIRONMENT will be set before COMMAND execution. +# PRE_RUN and POST_RUN arguments may contain extra cmake code that supposed to be executed before +# and after COMMAND, respectively. Both arguments accept a list of cmake script language +# constructions. Each item of the list will be concantinated into single string with '\n' separator. +function(_qt_internal_create_command_script) + #This style of parsing keeps ';' in ENVIRONMENT variables + cmake_parse_arguments(PARSE_ARGV 0 arg + "" + "OUTPUT_FILE;WORKING_DIRECTORY" + "COMMAND;ENVIRONMENT;PRE_RUN;POST_RUN" + ) + + if(NOT arg_COMMAND) + message(FATAL_ERROR "qt_internal_create_command_script: COMMAND is not specified") + endif() + + if(NOT arg_OUTPUT_FILE) + message(FATAL_ERROR "qt_internal_create_command_script: Wrapper OUTPUT_FILE\ +is not specified") + endif() + + if(NOT arg_WORKING_DIRECTORY AND NOT QNX) + set(arg_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + + set(environment_extras) + set(skipNext false) + if(arg_ENVIRONMENT) + list(LENGTH arg_ENVIRONMENT length) + math(EXPR length "${length} - 1") + foreach(envIdx RANGE ${length}) + if(skipNext) + set(skipNext FALSE) + continue() + endif() + + set(envVariable "") + set(envValue "") + + list(GET arg_ENVIRONMENT ${envIdx} envVariable) + math(EXPR envIdx "${envIdx} + 1") + if (envIdx LESS_EQUAL ${length}) + list(GET arg_ENVIRONMENT ${envIdx} envValue) + endif() + + if(NOT "${envVariable}" STREQUAL "") + set(environment_extras "${environment_extras}\nset(ENV{${envVariable}} \ +\"${envValue}\")") + endif() + set(skipNext TRUE) + endforeach() + endif() + + #Escaping environment variables before expand them by file GENERATE + string(REPLACE "\\" "\\\\" environment_extras "${environment_extras}") + + if(WIN32) + # It's necessary to call actual test inside 'cmd.exe', because 'execute_process' uses + # SW_HIDE to avoid showing a console window, it affects other GUI as well. + # See https://gitlab.kitware.com/cmake/cmake/-/issues/17690 for details. + set(extra_runner "cmd /c") + endif() + + if(arg_PRE_RUN) + string(JOIN "\n" pre_run ${arg_PRE_RUN}) + endif() + + if(arg_POST_RUN) + string(JOIN "\n" post_run ${arg_POST_RUN}) + endif() + + file(GENERATE OUTPUT "${arg_OUTPUT_FILE}" CONTENT +"#!${CMAKE_COMMAND} -P +# Qt generated command wrapper + +${environment_extras} +${pre_run} +execute_process(COMMAND ${extra_runner} ${arg_COMMAND} + WORKING_DIRECTORY \"${arg_WORKING_DIRECTORY}\" + RESULT_VARIABLE result +) +${post_run} +if(NOT result EQUAL 0) + string(JOIN \" \" full_command ${arg_COMMAND}) + message(FATAL_ERROR \"\${full_command} execution failed with exit code \${result}.\") +endif()" + ) +endfunction() diff --git a/cmake/QtTestHelpers.cmake b/cmake/QtTestHelpers.cmake index 1bf87c3870..78f50a0a06 100644 --- a/cmake/QtTestHelpers.cmake +++ b/cmake/QtTestHelpers.cmake @@ -50,7 +50,7 @@ function(qt_internal_add_benchmark target) # Add a ${target}_benchmark generator target, to run single benchmark more easily. set(benchmark_wrapper_file "${arg_OUTPUT_DIRECTORY}/${target}Wrapper$<CONFIG>.cmake") - qt_internal_create_command_script(COMMAND "$<TARGET_FILE:${target}>" + _qt_internal_create_command_script(COMMAND "$<TARGET_FILE:${target}>" OUTPUT_FILE "${benchmark_wrapper_file}" ENVIRONMENT "PATH" "${benchmark_env_path}" "QT_PLUGIN_PATH" "${benchmark_env_plugin_path}" @@ -507,7 +507,7 @@ endfunction() # directly by 'cmake -P path/to/scriptWrapper.cmake', COMMAND will be executed in specified # WORKING_DIRECTORY with arguments specified in ARGS. # -# See also qt_internal_create_command_script for details. +# See also _qt_internal_create_command_script for details. function(qt_internal_create_test_script) #This style of parsing keeps ';' in ENVIRONMENT variables cmake_parse_arguments(PARSE_ARGV 0 arg @@ -568,7 +568,7 @@ for this function. Will be ignored") endif() endif() - qt_internal_create_command_script(COMMAND "${crosscompiling_emulator} \${env_test_runner} \ + _qt_internal_create_command_script(COMMAND "${crosscompiling_emulator} \${env_test_runner} \ \"${executable_file}\" \${env_test_args} ${command_args}" OUTPUT_FILE "${arg_OUTPUT_FILE}" WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}" @@ -580,99 +580,7 @@ for this function. Will be ignored") ) endfunction() -# This function wraps COMMAND with cmake script, that makes possible standalone run with external -# arguments. -# -# Generated wrapper will be written to OUTPUT_FILE. -# If WORKING_DIRECTORY is not set COMMAND will be executed in CMAKE_CURRENT_BINARY_DIR. -# Variables from ENVIRONMENT will be set before COMMAND execution. -# PRE_RUN and POST_RUN arguments may contain extra cmake code that supposed to be executed before -# and after COMMAND, respectively. Both arguments accept a list of cmake script language -# constructions. Each item of the list will be concantinated into single string with '\n' sepatator. -function(qt_internal_create_command_script) - #This style of parsing keeps ';' in ENVIRONMENT variables - cmake_parse_arguments(PARSE_ARGV 0 arg - "" - "OUTPUT_FILE;WORKING_DIRECTORY" - "COMMAND;ENVIRONMENT;PRE_RUN;POST_RUN" - ) - - if(NOT arg_COMMAND) - message(FATAL_ERROR "qt_internal_create_command_script: COMMAND is not specified") - endif() - - if(NOT arg_OUTPUT_FILE) - message(FATAL_ERROR "qt_internal_create_command_script: Wrapper OUTPUT_FILE\ -is not specified") - endif() - - if(NOT arg_WORKING_DIRECTORY AND NOT QNX) - set(arg_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - endif() - - set(environment_extras) - set(skipNext false) - if(arg_ENVIRONMENT) - list(LENGTH arg_ENVIRONMENT length) - math(EXPR length "${length} - 1") - foreach(envIdx RANGE ${length}) - if(skipNext) - set(skipNext FALSE) - continue() - endif() - set(envVariable "") - set(envValue "") - - list(GET arg_ENVIRONMENT ${envIdx} envVariable) - math(EXPR envIdx "${envIdx} + 1") - if (envIdx LESS_EQUAL ${length}) - list(GET arg_ENVIRONMENT ${envIdx} envValue) - endif() - - if(NOT "${envVariable}" STREQUAL "") - set(environment_extras "${environment_extras}\nset(ENV{${envVariable}} \ -\"${envValue}\")") - endif() - set(skipNext TRUE) - endforeach() - endif() - - #Escaping environment variables before expand them by file GENERATE - string(REPLACE "\\" "\\\\" environment_extras "${environment_extras}") - - if(WIN32) - # It's necessary to call actual test inside 'cmd.exe', because 'execute_process' uses - # SW_HIDE to avoid showing a console window, it affects other GUI as well. - # See https://gitlab.kitware.com/cmake/cmake/-/issues/17690 for details. - set(extra_runner "cmd /c") - endif() - - if(arg_PRE_RUN) - string(JOIN "\n" pre_run ${arg_PRE_RUN}) - endif() - - if(arg_POST_RUN) - string(JOIN "\n" post_run ${arg_POST_RUN}) - endif() - - file(GENERATE OUTPUT "${arg_OUTPUT_FILE}" CONTENT -"#!${CMAKE_COMMAND} -P -# Qt generated command wrapper - -${environment_extras} -${pre_run} -execute_process(COMMAND ${extra_runner} ${arg_COMMAND} - WORKING_DIRECTORY \"${arg_WORKING_DIRECTORY}\" - RESULT_VARIABLE result -) -${post_run} -if(NOT result EQUAL 0) - string(JOIN \" \" full_command ${arg_COMMAND}) - message(FATAL_ERROR \"\${full_command} execution failed with exit code \${result}.\") -endif()" - ) -endfunction() # This function creates an executable for use as a helper program with tests. Some # tests launch separate programs to test certain input/output behavior. |