diff --git a/.gitlab/ci/ctest_exclusions.cmake b/.gitlab/ci/ctest_exclusions.cmake index f151bf6782..89a5ace956 100644 --- a/.gitlab/ci/ctest_exclusions.cmake +++ b/.gitlab/ci/ctest_exclusions.cmake @@ -13,13 +13,6 @@ if (CTEST_CMAKE_GENERATOR MATCHES "Visual Studio") "^ExternalProjectUpdateSetup$") endif () -if (CTEST_CMAKE_GENERATOR MATCHES "Xcode") - list(APPEND test_exclusions - # FIXME(#26301): The XCTest fails with Xcode 16.0. - "^XCTest$" - ) -endif () - if ("$ENV{CMAKE_CONFIGURATION}" MATCHES "_asan") list(APPEND test_exclusions CTestTest2 # crashes on purpose diff --git a/Modules/FindXCTest.cmake b/Modules/FindXCTest.cmake index 05ef36cb62..e6c846bd17 100644 --- a/Modules/FindXCTest.cmake +++ b/Modules/FindXCTest.cmake @@ -158,18 +158,13 @@ function(xctest_add_bundle target testee) set_target_properties(${target} PROPERTIES XCODE_ATTRIBUTE_BUNDLE_LOADER "$(TEST_HOST)" XCODE_ATTRIBUTE_TEST_HOST "$") - if(XCODE_VERSION VERSION_GREATER_EQUAL 7.3) - # The Xcode "new build system" used a different path until Xcode 12.5. - if(CMAKE_XCODE_BUILD_SYSTEM EQUAL 12 AND - XCODE_VERSION VERSION_LESS 12.5 AND - NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") - set(_output_directory "$") - else() - set(_output_directory "$/PlugIns") - endif() - set_target_properties(${target} PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${_output_directory}") - endif() + # TEST_HOST overrides ${target}'s artifact path, but the relative + # path from TEST_HOST to ${testee}'s PlugIns folder must not leave + # ${target}'s TARGET_BUILD_DIR. If the project sets an explicit + # RUNTIME_OUTPUT_DIRECTORY for ${testee}, put ${target} there too. + # If not, just suppress the project's CMAKE_LIBRARY_OUTPUT_DIRECTORY. + get_property(testee_RUNTIME_OUTPUT_DIRECTORY TARGET ${testee} PROPERTY RUNTIME_OUTPUT_DIRECTORY) + set_property(TARGET ${target} PROPERTY LIBRARY_OUTPUT_DIRECTORY ${testee_RUNTIME_OUTPUT_DIRECTORY}) else() target_link_options(${target} PRIVATE "SHELL:-bundle_loader \"$\"") @@ -210,6 +205,24 @@ function(xctest_add_test name bundle) get_property(_testee_type TARGET ${_testee} PROPERTY TYPE) get_property(_testee_framework TARGET ${_testee} PROPERTY FRAMEWORK) + get_property(_testee_macosx_bundle TARGET ${_testee} PROPERTY MACOSX_BUNDLE) + + # Determine the path to the test module artifact on disk. + set(_test_bundle_dir "$") + if(XCODE AND _testee_type STREQUAL "EXECUTABLE" AND _testee_macosx_bundle) + # Xcode's TEST_HOST setting places the test module inside the testee bundle. + if(XCODE_VERSION VERSION_GREATER_EQUAL 7.3) + # The Xcode "new build system" used a different path until Xcode 12.5. + if(CMAKE_XCODE_BUILD_SYSTEM EQUAL 12 AND + XCODE_VERSION VERSION_LESS 12.5 AND + NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(_test_bundle_dir "$") + else() + set(_test_bundle_dir "$/PlugIns") + endif() + string(APPEND _test_bundle_dir "/$") + endif() + endif() # register test @@ -217,7 +230,7 @@ function(xctest_add_test name bundle) # here for CMP0178. add_test( NAME ${name} - COMMAND ${XCTest_EXECUTABLE} $) + COMMAND ${XCTest_EXECUTABLE} ${_test_bundle_dir}) # point loader to testee in case rpath is disabled diff --git a/Tests/RunCMake/XcodeProject-Device/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject-Device/RunCMakeTest.cmake index b61b7fc07f..64abfb55fa 100644 --- a/Tests/RunCMake/XcodeProject-Device/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject-Device/RunCMakeTest.cmake @@ -307,6 +307,7 @@ if (XCODE_VERSION VERSION_GREATER_EQUAL 7.3) if(BuildSystemVersion) set(RunCMake_GENERATOR_TOOLSET "buildsystem=${BuildSystemVersion}") endif() + set(RunCMake_TEST_VARIANT_DESCRIPTION "-${SystemName}-${SDK}") run_cmake(XCTestAddBundle) endfunction() diff --git a/Tests/RunCMake/XcodeProject-Device/XCTestAddBundle.cmake b/Tests/RunCMake/XcodeProject-Device/XCTestAddBundle.cmake index 9114feea53..519dbe548c 100644 --- a/Tests/RunCMake/XcodeProject-Device/XCTestAddBundle.cmake +++ b/Tests/RunCMake/XcodeProject-Device/XCTestAddBundle.cmake @@ -10,13 +10,20 @@ add_executable(TestedApp MACOSX_BUNDLE dummy_main.swift) xctest_add_bundle(TestingAppBundle TestedApp dummy_main.swift) -get_target_property(_lib_output_dir TestingAppBundle LIBRARY_OUTPUT_DIRECTORY) +macro(add_test NAME name COMMAND xctest arg) + set(actual_arg "${arg}" PARENT_SCOPE) +endmacro() -if (NOT DEFINED TEST_EXPECTED_OUTPUT_DIR) - message(FATAL_ERROR "Testing variable TEST_EXPECTED_OUTPUT_DIR is not set") -endif() +xctest_add_test(TestedApp.TestingAppBundle TestingAppBundle) -if (NOT _lib_output_dir STREQUAL TEST_EXPECTED_OUTPUT_DIR) - message(SEND_ERROR "Property LIBRARY_OUTPUT_DIRECTORY is expected to be ${TEST_EXPECTED_OUTPUT_DIR} " - "but was ${_lib_output_dir}") +if(NOT DEFINED TEST_EXPECTED_OUTPUT_DIR) + message(FATAL_ERROR "Testing variable TEST_EXPECTED_OUTPUT_DIR is not set") +endif() +set(expect_arg "${TEST_EXPECTED_OUTPUT_DIR}/$") +if(NOT "${actual_arg}" STREQUAL "${expect_arg}") + message(FATAL_ERROR "xctest argument expected to be:\n" + " ${expect_arg}\n" + "but was:\n" + " ${actual_arg}\n" + ) endif() diff --git a/Tests/XCTest/CMakeLists.txt b/Tests/XCTest/CMakeLists.txt index e028108079..fdda826a0b 100644 --- a/Tests/XCTest/CMakeLists.txt +++ b/Tests/XCTest/CMakeLists.txt @@ -60,6 +60,21 @@ xctest_add_bundle(CocoaExampleTests CocoaExample xctest_add_test(XCTest.CocoaExample CocoaExampleTests) +# Cocoa App Bundle with explicit artifact location. +block() + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") + add_executable(CocoaExample2 MACOSX_BUNDLE + CocoaExample/main.m + CocoaExample/AppDelegate.m + CocoaExample/AppDelegate.h + CocoaExample/MainMenu.xib + ) + target_link_libraries(CocoaExample2 PRIVATE "-framework Foundation" "-framework AppKit") + xctest_add_bundle(CocoaExample2Tests CocoaExample2 CocoaExampleTests/CocoaExampleTests.m) + xctest_add_test(XCTest.CocoaExample2 CocoaExample2Tests) +endblock() + # Static lib add_library(StaticLibExample STATIC