FindXCTest.cmake 6.8 KB

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