mirror of
https://github.com/Kitware/CMake.git
synced 2026-08-10 17:14:10 +00:00
GoogleTest: Avoid generation error on duplicate target test discovery
The discovery script created by commit 3748ca9f (GoogleTest: generate
single discovery script, 2026-04-08, v4.4.0-rc1~302^2~1) creates
generate-time collisions if gtest_discover_tests() is called on the
same target in the same directory with the same arguments multiple
times. Handle the case with a warning to preserve compatibility with
existing projects.
Fixes: #27940
This commit is contained in:
@@ -673,43 +673,64 @@ function(gtest_discover_tests target)
|
||||
list(JOIN arg_PROPERTIES "]==] [==[" arg_PROPERTIES)
|
||||
list(JOIN arg_DISCOVERY_EXTRA_ARGS "]==] [==[" arg_DISCOVERY_EXTRA_ARGS)
|
||||
|
||||
# Make sure that TEST_LAUNCHER and CROSSCOMPILING_EMULATOR appear on the
|
||||
# command line, so that CMake can add them as implicit dependencies in the
|
||||
# case where they are executable targets.
|
||||
add_custom_command(
|
||||
TARGET ${target} POST_BUILD
|
||||
BYPRODUCTS "${ctest_tests_file}"
|
||||
COMMAND "${CMAKE_COMMAND}" -P "${discovery_file}" -- "${test_executor}"
|
||||
)
|
||||
# Resolve alias to support custom target properties.
|
||||
get_target_property(_gt_real_target ${target} ALIASED_TARGET)
|
||||
if(NOT _gt_real_target)
|
||||
set(_gt_real_target ${target})
|
||||
endif()
|
||||
|
||||
string(CONCAT discovery_content
|
||||
"include(\"${CMAKE_ROOT}/Modules/GoogleTestAddTests.cmake\")" "\n"
|
||||
"gtest_discover_tests_impl(" "\n"
|
||||
" TEST_TARGET" " [==[${target}]==]" "\n"
|
||||
" TEST_EXECUTABLE" " [==[$<TARGET_FILE:${target}>]==]" "\n"
|
||||
" TEST_EXECUTOR" " [==[${test_executor}]==]" "\n"
|
||||
" TEST_WORKING_DIR" " [==[${arg_WORKING_DIRECTORY}]==]" "\n"
|
||||
" TEST_EXTRA_ARGS" " [==[${arg_EXTRA_ARGS}]==]" "\n"
|
||||
" TEST_PROPERTIES" " [==[${arg_PROPERTIES}]==]" "\n"
|
||||
" TEST_PREFIX" " [==[${arg_TEST_PREFIX}]==]" "\n"
|
||||
" TEST_SUFFIX" " [==[${arg_TEST_SUFFIX}]==]" "\n"
|
||||
" TEST_FILTER" " [==[${arg_TEST_FILTER}]==]" "\n"
|
||||
" NO_PRETTY_TYPES" " [==[${arg_NO_PRETTY_TYPES}]==]" "\n"
|
||||
" NO_PRETTY_VALUES" " [==[${arg_NO_PRETTY_VALUES}]==]" "\n"
|
||||
" TEST_LIST" " [==[${arg_TEST_LIST}]==]" "\n"
|
||||
" CTEST_FILE" " [==[${ctest_tests_file}]==]" "\n"
|
||||
" TEST_DISCOVERY_TIMEOUT" " [==[${arg_DISCOVERY_TIMEOUT}]==]" "\n"
|
||||
" TEST_DISCOVERY_EXTRA_ARGS [==[${arg_DISCOVERY_EXTRA_ARGS}]==]" "\n"
|
||||
" TEST_XML_OUTPUT_DIR" " [==[${arg_XML_OUTPUT_DIR}]==]" "\n"
|
||||
" TEST_JSON_OUTPUT_DIR" " [==[${CMAKE_CURRENT_BINARY_DIR}]==]" "\n"
|
||||
")" "\n"
|
||||
get_target_property(
|
||||
_current_gt_post_build_discovery ${_gt_real_target} _GT_POST_BUILD_DISCOVERY
|
||||
)
|
||||
file(GENERATE OUTPUT "${discovery_file}" CONTENT "${discovery_content}")
|
||||
if("${discovery_file}" IN_LIST _current_gt_post_build_discovery)
|
||||
message(AUTHOR_WARNING
|
||||
"gtest_discover_tests() invoked multiple times with the same arguments "
|
||||
"for the same target '${target}'. This invocation will be ignored."
|
||||
)
|
||||
return()
|
||||
else()
|
||||
set_property(
|
||||
TARGET ${_gt_real_target}
|
||||
APPEND PROPERTY _GT_POST_BUILD_DISCOVERY "${discovery_file}"
|
||||
)
|
||||
# Make sure that TEST_LAUNCHER and CROSSCOMPILING_EMULATOR appear on the
|
||||
# command line, so that CMake can add them as implicit dependencies in the
|
||||
# case where they are executable targets.
|
||||
add_custom_command(
|
||||
TARGET ${target} POST_BUILD
|
||||
BYPRODUCTS "${ctest_tests_file}"
|
||||
COMMAND "${CMAKE_COMMAND}" -P "${discovery_file}" -- "${test_executor}"
|
||||
)
|
||||
|
||||
string(CONCAT ctest_include_content
|
||||
"if(EXISTS \"${ctest_tests_file}\")" "\n"
|
||||
" include(\"${ctest_tests_file}\")" "\n"
|
||||
)
|
||||
string(CONCAT discovery_content
|
||||
"include(\"${CMAKE_ROOT}/Modules/GoogleTestAddTests.cmake\")" "\n"
|
||||
"gtest_discover_tests_impl(" "\n"
|
||||
" TEST_TARGET" " [==[${target}]==]" "\n"
|
||||
" TEST_EXECUTABLE" " [==[$<TARGET_FILE:${target}>]==]" "\n"
|
||||
" TEST_EXECUTOR" " [==[${test_executor}]==]" "\n"
|
||||
" TEST_WORKING_DIR" " [==[${arg_WORKING_DIRECTORY}]==]" "\n"
|
||||
" TEST_EXTRA_ARGS" " [==[${arg_EXTRA_ARGS}]==]" "\n"
|
||||
" TEST_PROPERTIES" " [==[${arg_PROPERTIES}]==]" "\n"
|
||||
" TEST_PREFIX" " [==[${arg_TEST_PREFIX}]==]" "\n"
|
||||
" TEST_SUFFIX" " [==[${arg_TEST_SUFFIX}]==]" "\n"
|
||||
" TEST_FILTER" " [==[${arg_TEST_FILTER}]==]" "\n"
|
||||
" NO_PRETTY_TYPES" " [==[${arg_NO_PRETTY_TYPES}]==]" "\n"
|
||||
" NO_PRETTY_VALUES" " [==[${arg_NO_PRETTY_VALUES}]==]" "\n"
|
||||
" TEST_LIST" " [==[${arg_TEST_LIST}]==]" "\n"
|
||||
" CTEST_FILE" " [==[${ctest_tests_file}]==]" "\n"
|
||||
" TEST_DISCOVERY_TIMEOUT" " [==[${arg_DISCOVERY_TIMEOUT}]==]" "\n"
|
||||
" TEST_DISCOVERY_EXTRA_ARGS [==[${arg_DISCOVERY_EXTRA_ARGS}]==]" "\n"
|
||||
" TEST_XML_OUTPUT_DIR" " [==[${arg_XML_OUTPUT_DIR}]==]" "\n"
|
||||
" TEST_JSON_OUTPUT_DIR" " [==[${CMAKE_CURRENT_BINARY_DIR}]==]" "\n"
|
||||
")" "\n"
|
||||
)
|
||||
file(GENERATE OUTPUT "${discovery_file}" CONTENT "${discovery_content}")
|
||||
|
||||
string(CONCAT ctest_include_content
|
||||
"if(EXISTS \"${ctest_tests_file}\")" "\n"
|
||||
" include(\"${ctest_tests_file}\")" "\n"
|
||||
)
|
||||
endif()
|
||||
|
||||
elseif(arg_DISCOVERY_MODE STREQUAL "PRE_TEST")
|
||||
set(test_xml_output "")
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
CMake Warning \(author\) at [^
|
||||
]*/Modules/GoogleTest\.cmake:[0-9]+ \(message\):
|
||||
gtest_discover_tests\(\) invoked multiple times with the same arguments for
|
||||
the same target 'fake_gtest'\. This invocation will be ignored\.
|
||||
Call Stack \(most recent call first\):
|
||||
GoogleTestDiscoveryDuplicate\.cmake:[0-9]+ \(gtest_discover_tests\)
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.
|
||||
20
Tests/RunCMake/GoogleTest/GoogleTestDiscoveryDuplicate.cmake
Normal file
20
Tests/RunCMake/GoogleTest/GoogleTestDiscoveryDuplicate.cmake
Normal file
@@ -0,0 +1,20 @@
|
||||
enable_language(CXX)
|
||||
include(GoogleTest)
|
||||
|
||||
enable_testing()
|
||||
|
||||
include(xcode_sign_adhoc.cmake)
|
||||
|
||||
add_executable(fake_gtest fake_gtest.cpp)
|
||||
xcode_sign_adhoc(fake_gtest)
|
||||
|
||||
gtest_discover_tests(fake_gtest
|
||||
DISCOVERY_MODE POST_BUILD
|
||||
TEST_PREFIX DUPLICATE:
|
||||
PROPERTIES LABELS DUPLICATE
|
||||
)
|
||||
gtest_discover_tests(fake_gtest
|
||||
DISCOVERY_MODE POST_BUILD
|
||||
TEST_PREFIX DUPLICATE:
|
||||
PROPERTIES LABELS DUPLICATE
|
||||
)
|
||||
@@ -487,6 +487,26 @@ function(run_GoogleTest_DEF_SOURCE_LINE)
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(run_GoogleTest_discovery_duplicate)
|
||||
# Use a single build tree for a few tests without cleaning.
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-discovery-duplicate-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
|
||||
endif()
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
|
||||
run_cmake(GoogleTestDiscoveryDuplicate)
|
||||
|
||||
run_cmake_command(GoogleTest-discovery-duplicate-build
|
||||
${CMAKE_COMMAND}
|
||||
--build .
|
||||
--config Debug
|
||||
--target fake_gtest
|
||||
)
|
||||
endfunction()
|
||||
|
||||
foreach(DISCOVERY_MODE POST_BUILD PRE_TEST)
|
||||
message(STATUS "Testing ${DISCOVERY_MODE} discovery mode via CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE global override...")
|
||||
run_GoogleTest(${DISCOVERY_MODE})
|
||||
@@ -542,3 +562,5 @@ run_GoogleTest_DEF_SOURCE_LINE()
|
||||
if (NOT RunCMake_GENERATOR MATCHES "(Borland|NMake|Watcom)")
|
||||
run_GoogleTest_discovery_post_build_race()
|
||||
endif()
|
||||
|
||||
run_GoogleTest_discovery_duplicate()
|
||||
|
||||
Reference in New Issue
Block a user