diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2022-11-01 18:16:34 +0100 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2022-12-02 20:53:01 +0100 |
commit | 9b2c82cc8424f65a00ec6d5842103181e27604ee (patch) | |
tree | c6661d42fd579a71cee3792de1beb21a473fef28 /tests/auto/cmake | |
parent | 919664b29a874e8cdc3d74427654cbaa2b61be29 (diff) |
CMake: Add auto test for qt_add_resources dependency rebuilding
Make sure that touching any file that is part of a qrc resource
actually rebuilds the resource and the target that depends on the
resource.
Pick-to: 6.4
Task-number: QTBUG-107687
Task-number: QTBUG-108113
Change-Id: I1153dc13fee44ffe59d2685a8cb33303538b026c
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Diffstat (limited to 'tests/auto/cmake')
4 files changed, 170 insertions, 0 deletions
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index 99d36c3d56..61cd6d588e 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -185,6 +185,7 @@ endif() _qt_internal_test_expect_pass(test_multiple_find_package) _qt_internal_test_expect_pass(test_add_resources_delayed_file) _qt_internal_test_expect_pass(test_add_binary_resources_delayed_file BINARY test_add_binary_resources_delayed_file) +_qt_internal_test_expect_pass(test_qt_add_resources_rebuild) if(NOT NO_GUI) _qt_internal_test_expect_pass(test_private_includes) diff --git a/tests/auto/cmake/test_qt_add_resources_rebuild/CMakeLists.txt b/tests/auto/cmake/test_qt_add_resources_rebuild/CMakeLists.txt new file mode 100644 index 0000000000..e7b35b332f --- /dev/null +++ b/tests/auto/cmake/test_qt_add_resources_rebuild/CMakeLists.txt @@ -0,0 +1,123 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) + +project(test_qt_add_resources_rebuild) + +set(test_project_source_dir "${CMAKE_CURRENT_SOURCE_DIR}/sample") +set(test_project_build_dir "${CMAKE_CURRENT_BINARY_DIR}/build_sample") + +# Make sure that file paths are 'real' paths +get_filename_component(test_project_source_dir "${test_project_source_dir}" REALPATH) +get_filename_component(test_project_build_dir "${test_project_build_dir}" REALPATH) + +file(REMOVE_RECURSE "${test_project_build_dir}") +file(MAKE_DIRECTORY "${test_project_build_dir}") + +# For access to _qt_internal_get_cmake_test_configure_options +find_package(Qt6 COMPONENTS Core REQUIRED) +include("${_Qt6CTestMacros}") + +set(indent " ") +list(APPEND CMAKE_MESSAGE_INDENT "${indent}") + +function(configure_project) + message(STATUS "Configuring build") + _qt_internal_get_cmake_test_configure_options(option_list) + execute_process(COMMAND + "${CMAKE_COMMAND}" + "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" + "-G${CMAKE_GENERATOR}" + ${option_list} + -B "${test_project_build_dir}" + -S "${test_project_source_dir}" + RESULT_VARIABLE result + ) + if(NOT result EQUAL 0) + message(FATAL_ERROR "Unable to configure sample project") + endif() +endfunction() + +function(try_build) + message(STATUS "Building project") + execute_process(COMMAND + "${CMAKE_COMMAND}" + --build "${test_project_build_dir}" + RESULT_VARIABLE result + ) + if(NOT result EQUAL 0) + message(FATAL_ERROR "Unable to build test project") + endif() +endfunction() + +function(get_target_path out_var) + file(STRINGS "${test_project_build_dir}/targets.txt" targets) + list(GET targets 0 first_target_path) + message(STATUS "Built target is at '${first_target_path}'") + set(${out_var} "${first_target_path}" PARENT_SCOPE) +endfunction() + +function(get_timestamp file_path out_var) + message(STATUS "Getting timestamp of built target.") + file(TIMESTAMP "${file_path}" value "%s") + set(${out_var} "${value}" PARENT_SCOPE) +endfunction() + +function(sleep) + # Avoids issues with low resolution modification times (like HFS on macOS). + set(seconds 2) + message(STATUS "Sleeping for ${seconds} seconds.") + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep ${seconds}) +endfunction() + +function(touch_file) + set(input "input.ts") + set(input_path "${test_project_source_dir}/${input}") + message(STATUS "Touching ${input_path}") + file(TOUCH "${input_path}") +endfunction() + +function(assert_timestamp_is_equal before after) + set(timestamps "\n${indent}Before TS: ${before}\n${indent} After TS: ${after}") + if("${after}" EQUAL "${before}") + message(STATUS "Target was not rebuilt. ${timestamps}") + else() + message(FATAL_ERROR "Target WAS rebuilt. ${timestamps}") + endif() +endfunction() + +function(assert_timestamp_is_greater before after) + set(timestamps "\n${indent}Before TS: ${before}\n${indent} After TS: ${after}") + if("${after}" GREATER "${before}") + message(STATUS "Target was correctly rebuilt. ${timestamps}") + else() + message(FATAL_ERROR "Target was NOT rebuilt. ${timestamps}") + endif() +endfunction() + +configure_project() +try_build() +get_target_path(target_path) + +# Make sure that a second build without changes doesn't rebuild the executable. +get_timestamp("${target_path}" ts_1) +sleep() +try_build() +get_timestamp("${target_path}" ts_2) +assert_timestamp_is_equal("${ts_1}" "${ts_2}") + +# Touching the input file should cause rcc to rerun, then the compiler, then the linker, +# and thus the executable timestamp should be updated. +touch_file() +try_build() +get_timestamp("${target_path}" ts_3) +assert_timestamp_is_greater("${ts_2}" "${ts_3}") + +# Check that building again doesn't rebuild the executable. +sleep() +try_build() +get_timestamp("${target_path}" ts_4) +assert_timestamp_is_equal("${ts_3}" "${ts_4}") + +list(POP_BACK CMAKE_MESSAGE_INDENT) diff --git a/tests/auto/cmake/test_qt_add_resources_rebuild/sample/CMakeLists.txt b/tests/auto/cmake/test_qt_add_resources_rebuild/sample/CMakeLists.txt new file mode 100644 index 0000000000..0a40a948c6 --- /dev/null +++ b/tests/auto/cmake/test_qt_add_resources_rebuild/sample/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.16) +project(sample LANGUAGES CXX) + +find_package(Qt6 REQUIRED COMPONENTS Core) + +set(source "${CMAKE_BINARY_DIR}/main.cpp") +file(GENERATE OUTPUT "${source}" CONTENT "int main() { return 0; }") + +qt_add_executable(${PROJECT_NAME} ${source}) + +# This is a poor man's implementation of qt_add_lupdate. +set(input "${CMAKE_SOURCE_DIR}/input.ts") +set(output "${CMAKE_BINARY_DIR}/output.qm") +add_custom_command( + OUTPUT "${output}" + COMMAND ${CMAKE_COMMAND} -E copy "${input}" "${output}" + DEPENDS "${input}" + VERBATIM +) + +# This is where the bug happened before. Adding the target dependency properties used the target +# as an order-only dependency, instead of depending on the actual dependency file. +set_source_files_properties("${output}" + PROPERTIES _qt_resource_target_dependency "output_target") + +add_custom_target(output_target + DEPENDS "${output}" +) + +qt_add_resources(${PROJECT_NAME} "res" + PREFIX "/" + BASE "${CMAKE_CURRENT_BINARY_DIR}" + FILES "${output}" +) + +# Write out the location of the binary so its timestamp can be checked by the driving parent +# project. +set(target_file_out "${CMAKE_BINARY_DIR}/targets.txt") +add_custom_target(all_built ALL + COMMAND + ${CMAKE_COMMAND} -E echo "$<TARGET_FILE:${PROJECT_NAME}>" > "${target_file_out}" + VERBATIM +) +# Make sure the file path is written out after the executable is linked. +add_dependencies(all_built ${PROJECT_NAME}) diff --git a/tests/auto/cmake/test_qt_add_resources_rebuild/sample/input.ts b/tests/auto/cmake/test_qt_add_resources_rebuild/sample/input.ts new file mode 100644 index 0000000000..20a96e90c4 --- /dev/null +++ b/tests/auto/cmake/test_qt_add_resources_rebuild/sample/input.ts @@ -0,0 +1 @@ +bonk |