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. Task-number: QTBUG-107687 Task-number: QTBUG-108113 Change-Id: I1153dc13fee44ffe59d2685a8cb33303538b026c Reviewed-by: Alexey Edelev <alexey.edelev@qt.io> (cherry picked from commit 9b2c82cc8424f65a00ec6d5842103181e27604ee) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
5d7ea8de1f
commit
6453d17a0a
@ -174,6 +174,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)
|
||||
|
123
tests/auto/cmake/test_qt_add_resources_rebuild/CMakeLists.txt
Normal file
123
tests/auto/cmake/test_qt_add_resources_rebuild/CMakeLists.txt
Normal file
@ -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)
|
@ -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})
|
@ -0,0 +1 @@
|
||||
bonk
|
Loading…
x
Reference in New Issue
Block a user