00729bc273f3a014e69f3cd7b2fc30f3155b1084
[platform/upstream/cmake.git] / Modules / FindXCTest.cmake
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:
5 FindXCTest
6 ----------
7
8 .. versionadded:: 3.3
9
10 Functions to help creating and executing XCTest bundles.
11
12 An XCTest bundle is a CFBundle with a special product-type
13 and bundle extension. The Mac Developer Library provides more
14 information in the `Testing with Xcode`_ document.
15
16 .. _Testing with Xcode: http://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/testing_with_xcode/
17
18 Module 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
43 Module Variables
44 ^^^^^^^^^^^^^^^^
45
46 The 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
66 set(_PRESERVED_CMAKE_FIND_ROOT_PATH "${CMAKE_FIND_ROOT_PATH}")
67
68 if(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}/../..")
80 endif()
81
82 find_path(XCTest_INCLUDE_DIR
83   NAMES "XCTest/XCTest.h"
84   DOC "XCTest include directory")
85 mark_as_advanced(XCTest_INCLUDE_DIR)
86
87 find_library(XCTest_LIBRARY
88   NAMES XCTest
89   DOC "XCTest Framework library")
90 mark_as_advanced(XCTest_LIBRARY)
91
92 set(CMAKE_FIND_ROOT_PATH "${_PRESERVED_CMAKE_FIND_ROOT_PATH}")
93 unset(_PRESERVED_CMAKE_FIND_ROOT_PATH)
94
95 execute_process(
96   COMMAND xcrun --find xctest
97   OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE
98   ERROR_VARIABLE _xcrun_err)
99 if(_xcrun_out)
100   set(XCTest_EXECUTABLE "${_xcrun_out}" CACHE FILEPATH "XCTest executable")
101   mark_as_advanced(XCTest_EXECUTABLE)
102 endif()
103
104 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
105 find_package_handle_standard_args(XCTest
106   FOUND_VAR XCTest_FOUND
107   REQUIRED_VARS XCTest_LIBRARY XCTest_INCLUDE_DIR XCTest_EXECUTABLE)
108
109 if(XCTest_FOUND)
110   set(XCTest_INCLUDE_DIRS "${XCTest_INCLUDE_DIR}")
111   set(XCTest_LIBRARIES "${XCTest_LIBRARY}")
112 endif(XCTest_FOUND)
113
114
115 function(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()
178 endfunction(xctest_add_bundle)
179
180
181 function(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()
223 endfunction(xctest_add_test)