@@ -38,6 +38,7 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
3838 [OUTPUT_PREFIX prefix]
3939 [OUTPUT_SUFFIX suffix]
4040 [DISCOVERY_MODE <POST_BUILD|PRE_TEST>]
41+ [USE_RELATIVE_PATHS]
4142 [SKIP_IS_FAILURE]
4243 [ADD_TAGS_AS_LABELS]
4344 )
@@ -146,6 +147,12 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
146147 calling ``catch_discover_tests``. This provides a mechanism for globally selecting
147148 a preferred test discovery behavior without having to modify each call site.
148149
150+ ``USE_RELATIVE_PATHS``
151+ Makes the files generated for ``PRE_TEST`` discovery use paths relative to
152+ the generated CTest include file. This allows a build tree to be relocated
153+ with its test executable before test discovery runs. This option requires
154+ CMake 3.24 or newer.
155+
149156 ``SKIP_IS_FAILURE``
150157 Disables skipped test detection.
151158
@@ -159,7 +166,7 @@ function(catch_discover_tests TARGET)
159166
160167 cmake_parse_arguments (
161168 ""
162- "SKIP_IS_FAILURE;ADD_TAGS_AS_LABELS"
169+ "SKIP_IS_FAILURE;ADD_TAGS_AS_LABELS;USE_RELATIVE_PATHS "
163170 "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX;DISCOVERY_MODE"
164171 "TEST_SPEC;EXTRA_ARGS;PROPERTIES;DL_PATHS;DL_FRAMEWORK_PATHS"
165172 ${ARGN}
@@ -190,6 +197,12 @@ function(catch_discover_tests TARGET)
190197 if (NOT _DISCOVERY_MODE MATCHES "^(POST_BUILD|PRE_TEST)$" )
191198 message (FATAL_ERROR "Unknown DISCOVERY_MODE: ${_DISCOVERY_MODE} " )
192199 endif ()
200+ if (_USE_RELATIVE_PATHS AND NOT _DISCOVERY_MODE STREQUAL "PRE_TEST" )
201+ message (FATAL_ERROR "USE_RELATIVE_PATHS requires DISCOVERY_MODE PRE_TEST" )
202+ endif ()
203+ if (_USE_RELATIVE_PATHS AND CMAKE_VERSION VERSION_LESS "3.24" )
204+ message (FATAL_ERROR "USE_RELATIVE_PATHS requires CMake 3.24 or newer" )
205+ endif ()
193206
194207 ## Generate a unique name based on the extra arguments
195208 string (SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS} ${_REPORTER} ${_OUTPUT_DIR} ${_OUTPUT_PREFIX} ${_OUTPUT_SUFFIX} " )
@@ -199,6 +212,7 @@ function(catch_discover_tests TARGET)
199212 set (ctest_file_base "${CMAKE_CURRENT_BINARY_DIR } /${TARGET} -${args_hash} " )
200213 set (ctest_include_file "${ctest_file_base} _include.cmake" )
201214 set (ctest_tests_file "${ctest_file_base} _tests.cmake" )
215+ set (ctest_include_file_for_property "${ctest_include_file} " )
202216
203217 get_property (crosscompiling_emulator
204218 TARGET ${TARGET}
@@ -253,16 +267,69 @@ function(catch_discover_tests TARGET)
253267 set (ctest_tests_file "${ctest_file_base} _tests-$<CONFIG >.cmake" )
254268 endif ()
255269
270+ set (test_executable_for_script "$<TARGET_FILE :${TARGET} >" )
271+ set (test_working_dir_for_script "${_WORKING_DIRECTORY} " )
272+ set (discover_tests_script_for_script "${_CATCH_DISCOVER_TESTS_SCRIPT} " )
273+ set (ctest_tests_file_for_script "${ctest_tests_file} " )
274+ set (test_executable_argument "[==[${test_executable_for_script} ]==]" )
275+ set (test_working_dir_argument "[==[${test_working_dir_for_script} ]==]" )
276+ set (ctest_file_argument "[==[${ctest_tests_file_for_script} ]==]" )
277+ set (ctest_path_setup)
278+ set (ctest_config_include_file
279+ "${ctest_file_base} _include-\$ {CTEST_CONFIGURATION_TYPE}.cmake"
280+ )
281+
282+ if (_USE_RELATIVE_PATHS)
283+ get_filename_component (ctest_file_base_name "${ctest_file_base} " NAME )
284+ get_filename_component (ctest_tests_file_name "${ctest_tests_file} " NAME )
285+ get_filename_component (ctest_include_file_name "${ctest_include_file} " NAME )
286+
287+ set (test_executable_relative
288+ "$<PATH :RELATIVE_PATH ,$<TARGET_FILE :${TARGET} >,${CMAKE_CURRENT_BINARY_DIR } >"
289+ )
290+ set (test_working_dir_relative
291+ "$<PATH :RELATIVE_PATH ,$<PATH :ABSOLUTE_PATH ,${_WORKING_DIRECTORY} ,${CMAKE_CURRENT_BINARY_DIR } >,${CMAKE_CURRENT_BINARY_DIR } >"
292+ )
293+ set (discover_tests_script_name
294+ "${ctest_file_base_name} _CatchAddTests.cmake"
295+ )
296+ configure_file (
297+ "${_CATCH_DISCOVER_TESTS_SCRIPT} "
298+ "${CMAKE_CURRENT_BINARY_DIR } /${discover_tests_script_name} "
299+ COPYONLY
300+ )
301+
302+ set (ctest_config_include_file
303+ "${ctest_file_base_name} _include-\$ {CTEST_CONFIGURATION_TYPE}.cmake"
304+ )
305+ string (CONCAT ctest_path_setup
306+ "get_filename_component(_catch_discover_tests_script \" ${discover_tests_script_name} \" REALPATH)" "\n "
307+ "get_filename_component(_catch_discovery_dir \"\$ {_catch_discover_tests_script}\" DIRECTORY)" "\n "
308+ "set(_catch_test_executable \"\$ {_catch_discovery_dir}/${test_executable_relative} \" )" "\n "
309+ "set(_catch_test_working_dir \"\$ {_catch_discovery_dir}/${test_working_dir_relative} \" )" "\n "
310+ "set(_catch_tests_file \"\$ {_catch_discovery_dir}/${ctest_tests_file_name} \" )" "\n "
311+ )
312+ set (test_executable_for_script "\$ {_catch_test_executable}" )
313+ set (test_working_dir_for_script "\$ {_catch_test_working_dir}" )
314+ set (discover_tests_script_for_script "\$ {_catch_discover_tests_script}" )
315+ set (ctest_tests_file_for_script "\$ {_catch_tests_file}" )
316+ set (test_executable_argument "\"\$ {_catch_test_executable}\" " )
317+ set (test_working_dir_argument "\"\$ {_catch_test_working_dir}\" " )
318+ set (ctest_file_argument "\"\$ {_catch_tests_file}\" " )
319+ set (ctest_include_file_for_property "${ctest_include_file_name} " )
320+ endif ()
321+
256322 string (CONCAT ctest_include_content
257- "if(EXISTS \" $<TARGET_FILE :${TARGET} >\" )" "\n "
258- " if(NOT EXISTS \" ${ctest_tests_file} \" OR" "\n "
259- " NOT \" ${ctest_tests_file} \" IS_NEWER_THAN \" $<TARGET_FILE :${TARGET} >\" OR\n "
260- " NOT \" ${ctest_tests_file} \" IS_NEWER_THAN \"\$ {CMAKE_CURRENT_LIST_FILE}\" )\n "
261- " include(\" ${_CATCH_DISCOVER_TESTS_SCRIPT} \" )" "\n "
323+ "${ctest_path_setup} "
324+ "if(EXISTS \" ${test_executable_for_script} \" )" "\n "
325+ " if(NOT EXISTS \" ${ctest_tests_file_for_script} \" OR" "\n "
326+ " NOT \" ${ctest_tests_file_for_script} \" IS_NEWER_THAN \" ${test_executable_for_script} \" OR\n "
327+ " NOT \" ${ctest_tests_file_for_script} \" IS_NEWER_THAN \"\$ {CMAKE_CURRENT_LIST_FILE}\" )\n "
328+ " include(\" ${discover_tests_script_for_script} \" )" "\n "
262329 " catch_discover_tests_impl(" "\n "
263- " TEST_EXECUTABLE" " [==[" "$< TARGET_FILE : ${TARGET} > " "]==]" "\n "
330+ " TEST_EXECUTABLE" " ${test_executable_argument} " "\n "
264331 " TEST_EXECUTOR" " [==[" "${crosscompiling_emulator} " "]==]" "\n "
265- " TEST_WORKING_DIR" " [==[" " ${_WORKING_DIRECTORY } " "]==]" "\n "
332+ " TEST_WORKING_DIR" " ${test_working_dir_argument } " "\n "
266333 " TEST_SPEC" " [==[" "${_TEST_SPEC} " "]==]" "\n "
267334 " TEST_EXTRA_ARGS" " [==[" "${_EXTRA_ARGS} " "]==]" "\n "
268335 " TEST_PROPERTIES" " [==[" "${_PROPERTIES} " "]==]" "\n "
@@ -273,13 +340,13 @@ function(catch_discover_tests TARGET)
273340 " TEST_OUTPUT_DIR" " [==[" "${_OUTPUT_DIR} " "]==]" "\n "
274341 " TEST_OUTPUT_PREFIX" " [==[" "${_OUTPUT_PREFIX} " "]==]" "\n "
275342 " TEST_OUTPUT_SUFFIX" " [==[" "${_OUTPUT_SUFFIX} " "]==]" "\n "
276- " CTEST_FILE" " [==[" " ${ctest_tests_file } " "]==]" "\n "
343+ " CTEST_FILE" " ${ctest_file_argument } " "\n "
277344 " TEST_DL_PATHS" " [==[" "${_DL_PATHS} " "]==]" "\n "
278345 " TEST_DL_FRAMEWORK_PATHS" " [==[" "${_DL_FRAMEWORK_PATHS} " "]==]" "\n "
279346 " ADD_TAGS_AS_LABELS" " [==[" "${_ADD_TAGS_AS_LABELS} " "]==]" "\n "
280347 " )" "\n "
281348 " endif()" "\n "
282- " include(\" ${ctest_tests_file } \" )" "\n "
349+ " include(\" ${ctest_tests_file_for_script } \" )" "\n "
283350 "else()" "\n "
284351 " add_test(${TARGET} _NOT_BUILT ${TARGET} _NOT_BUILT)" "\n "
285352 "endif()" "\n "
@@ -293,7 +360,7 @@ function(catch_discover_tests TARGET)
293360 "if(NOT CTEST_CONFIGURATION_TYPE)" "\n "
294361 " message(\" No configuration for testing specified, use '-C <cfg>'.\" )" "\n "
295362 "else()" "\n "
296- " include(\" ${ctest_file_base} _include- \$ {CTEST_CONFIGURATION_TYPE}.cmake \ " )" "\n "
363+ " include(\" ${ctest_config_include_file} \ " )" "\n "
297364 "endif()" "\n "
298365 )
299366 file (GENERATE OUTPUT "${ctest_include_file} " CONTENT "${ctest_include_multi_content} " )
@@ -305,7 +372,7 @@ function(catch_discover_tests TARGET)
305372
306373 # Add discovered tests to directory TEST_INCLUDE_FILES
307374 set_property (DIRECTORY
308- APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file } "
375+ APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file_for_property } "
309376 )
310377
311378endfunction ()
0 commit comments