1# Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2# file Copyright.txt or https://cmake.org/licensing for details. 3 4#[=======================================================================[.rst: 5FindXCTest 6---------- 7 8.. versionadded:: 3.3 9 10Functions to help creating and executing XCTest bundles. 11 12An XCTest bundle is a CFBundle with a special product-type 13and bundle extension. The Mac Developer Library provides more 14information in the `Testing with Xcode`_ document. 15 16.. _Testing with Xcode: http://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/testing_with_xcode/ 17 18Module Functions 19^^^^^^^^^^^^^^^^ 20 21.. command:: xctest_add_bundle 22 23 The ``xctest_add_bundle`` function creates a XCTest bundle named 24 <target> which will test the target <testee>. Supported target types 25 for testee are Frameworks and App Bundles:: 26 27 xctest_add_bundle( 28 <target> # Name of the XCTest bundle 29 <testee> # Target name of the testee 30 ) 31 32.. command:: xctest_add_test 33 34 The ``xctest_add_test`` function adds an XCTest bundle to the 35 project to be run by :manual:`ctest(1)`. The test will be named 36 <name> and tests <bundle>:: 37 38 xctest_add_test( 39 <name> # Test name 40 <bundle> # Target name of XCTest bundle 41 ) 42 43Module Variables 44^^^^^^^^^^^^^^^^ 45 46The following variables are set by including this module: 47 48.. variable:: XCTest_FOUND 49 50 True if the XCTest Framework and executable were found. 51 52.. variable:: XCTest_EXECUTABLE 53 54 The path to the xctest command line tool used to execute XCTest bundles. 55 56.. variable:: XCTest_INCLUDE_DIRS 57 58 The directory containing the XCTest Framework headers. 59 60.. variable:: XCTest_LIBRARIES 61 62 The location of the XCTest Framework. 63 64#]=======================================================================] 65 66set(_PRESERVED_CMAKE_FIND_ROOT_PATH "${CMAKE_FIND_ROOT_PATH}") 67 68if(CMAKE_EFFECTIVE_SYSTEM_NAME STREQUAL "Apple" 69 AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") 70 # Non-macos systems set the CMAKE_FIND_ROOT_PATH_MODE to "ONLY" which 71 # restricts the search paths too much to find XCTest.framework. In 72 # contrast to the regular system frameworks which reside within the 73 # SDK direectory the XCTest framework is located in the respective 74 # platform directory which is not added to the CMAKE_FIND_ROOT_PATH 75 # (only to CMAKE_SYSTEM_FRAMEWORK_PATH) and therefore not searched. 76 # 77 # Until this is properly addressed, temporaily add the platform 78 # directory to CMAKE_FIND_ROOT_PATH. 79 list(APPEND CMAKE_FIND_ROOT_PATH "${_CMAKE_OSX_SYSROOT_PATH}/../..") 80endif() 81 82find_path(XCTest_INCLUDE_DIR 83 NAMES "XCTest/XCTest.h" 84 DOC "XCTest include directory") 85mark_as_advanced(XCTest_INCLUDE_DIR) 86 87find_library(XCTest_LIBRARY 88 NAMES XCTest 89 DOC "XCTest Framework library") 90mark_as_advanced(XCTest_LIBRARY) 91 92set(CMAKE_FIND_ROOT_PATH "${_PRESERVED_CMAKE_FIND_ROOT_PATH}") 93unset(_PRESERVED_CMAKE_FIND_ROOT_PATH) 94 95execute_process( 96 COMMAND xcrun --find xctest 97 OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE 98 ERROR_VARIABLE _xcrun_err) 99if(_xcrun_out) 100 set(XCTest_EXECUTABLE "${_xcrun_out}" CACHE FILEPATH "XCTest executable") 101 mark_as_advanced(XCTest_EXECUTABLE) 102endif() 103 104include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) 105find_package_handle_standard_args(XCTest 106 FOUND_VAR XCTest_FOUND 107 REQUIRED_VARS XCTest_LIBRARY XCTest_INCLUDE_DIR XCTest_EXECUTABLE) 108 109if(XCTest_FOUND) 110 set(XCTest_INCLUDE_DIRS "${XCTest_INCLUDE_DIR}") 111 set(XCTest_LIBRARIES "${XCTest_LIBRARY}") 112endif(XCTest_FOUND) 113 114 115function(xctest_add_bundle target testee) 116 if(NOT XCTest_FOUND) 117 message(FATAL_ERROR "XCTest is required to create a XCTest Bundle.") 118 endif(NOT XCTest_FOUND) 119 120 if(NOT CMAKE_OSX_SYSROOT) 121 message(FATAL_ERROR "Adding XCTest bundles requires CMAKE_OSX_SYSROOT to be set.") 122 endif() 123 124 add_library(${target} MODULE ${ARGN}) 125 126 set_target_properties(${target} PROPERTIES 127 BUNDLE TRUE 128 XCTEST TRUE 129 XCTEST_TESTEE ${testee}) 130 131 target_link_libraries(${target} PRIVATE "-framework Foundation") 132 target_link_libraries(${target} PRIVATE ${XCTest_LIBRARIES}) 133 target_include_directories(${target} PRIVATE ${XCTest_INCLUDE_DIRS}) 134 135 # retrieve testee target type 136 if(NOT TARGET ${testee}) 137 message(FATAL_ERROR "${testee} is not a target.") 138 endif() 139 get_property(_testee_type TARGET ${testee} PROPERTY TYPE) 140 get_property(_testee_framework TARGET ${testee} PROPERTY FRAMEWORK) 141 get_property(_testee_macosx_bundle TARGET ${testee} PROPERTY MACOSX_BUNDLE) 142 143 if(_testee_type STREQUAL "SHARED_LIBRARY" AND _testee_framework) 144 # testee is a Framework 145 target_link_libraries(${target} PRIVATE ${testee}) 146 147 elseif(_testee_type STREQUAL "STATIC_LIBRARY") 148 # testee is a static library 149 target_link_libraries(${target} PRIVATE ${testee}) 150 151 elseif(_testee_type STREQUAL "EXECUTABLE" AND _testee_macosx_bundle) 152 # testee is an App Bundle 153 add_dependencies(${target} ${testee}) 154 if(XCODE) 155 set_target_properties(${target} PROPERTIES 156 XCODE_ATTRIBUTE_BUNDLE_LOADER "$(TEST_HOST)" 157 XCODE_ATTRIBUTE_TEST_HOST "$<TARGET_FILE:${testee}>") 158 if(XCODE_VERSION VERSION_GREATER_EQUAL 7.3) 159 # The Xcode "new build system" used a different path until Xcode 12.5. 160 if(CMAKE_XCODE_BUILD_SYSTEM EQUAL 12 AND 161 XCODE_VERSION VERSION_LESS 12.5 AND 162 NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") 163 set(_output_directory "$<TARGET_BUNDLE_CONTENT_DIR:${testee}>") 164 else() 165 set(_output_directory "$<TARGET_BUNDLE_CONTENT_DIR:${testee}>/PlugIns") 166 endif() 167 set_target_properties(${target} PROPERTIES 168 LIBRARY_OUTPUT_DIRECTORY "${_output_directory}") 169 endif() 170 else(XCODE) 171 target_link_libraries(${target} 172 PRIVATE -bundle_loader $<TARGET_FILE:${testee}>) 173 endif(XCODE) 174 175 else() 176 message(FATAL_ERROR "Testee ${testee} is of unsupported type.") 177 endif() 178endfunction(xctest_add_bundle) 179 180 181function(xctest_add_test name bundle) 182 if(NOT XCTest_EXECUTABLE) 183 message(FATAL_ERROR "XCTest executable is required to register a test.") 184 endif() 185 186 # check that bundle is a XCTest Bundle 187 188 if(NOT TARGET ${bundle}) 189 message(FATAL_ERROR "${bundle} is not a target.") 190 endif(NOT TARGET ${bundle}) 191 192 get_property(_test_type TARGET ${bundle} PROPERTY TYPE) 193 get_property(_test_bundle TARGET ${bundle} PROPERTY BUNDLE) 194 get_property(_test_xctest TARGET ${bundle} PROPERTY XCTEST) 195 196 if(NOT _test_type STREQUAL "MODULE_LIBRARY" 197 OR NOT _test_xctest OR NOT _test_bundle) 198 message(FATAL_ERROR "Test ${bundle} is not an XCTest Bundle") 199 endif() 200 201 # get and check testee properties 202 203 get_property(_testee TARGET ${bundle} PROPERTY XCTEST_TESTEE) 204 if(NOT TARGET ${_testee}) 205 message(FATAL_ERROR "${_testee} is not a target.") 206 endif() 207 208 get_property(_testee_type TARGET ${_testee} PROPERTY TYPE) 209 get_property(_testee_framework TARGET ${_testee} PROPERTY FRAMEWORK) 210 211 # register test 212 213 add_test( 214 NAME ${name} 215 COMMAND ${XCTest_EXECUTABLE} $<TARGET_BUNDLE_DIR:${bundle}>) 216 217 # point loader to testee in case rpath is disabled 218 219 if(_testee_type STREQUAL "SHARED_LIBRARY" AND _testee_framework) 220 set_property(TEST ${name} APPEND PROPERTY 221 ENVIRONMENT DYLD_FRAMEWORK_PATH=$<TARGET_LINKER_FILE_DIR:${_testee}>/..) 222 endif() 223endfunction(xctest_add_test) 224