Darwin-Initialize.cmake 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. set(APPLE 1)
  2. set(UNIX 1)
  3. # Ask xcode-select where to find /Developer or fall back to ancient location.
  4. execute_process(COMMAND xcode-select -print-path
  5. OUTPUT_VARIABLE _stdout
  6. OUTPUT_STRIP_TRAILING_WHITESPACE
  7. ERROR_VARIABLE _stderr
  8. RESULT_VARIABLE _failed)
  9. if(NOT _failed AND IS_DIRECTORY ${_stdout})
  10. set(OSX_DEVELOPER_ROOT ${_stdout})
  11. elseif(IS_DIRECTORY "/Developer")
  12. set(OSX_DEVELOPER_ROOT "/Developer")
  13. else()
  14. set(OSX_DEVELOPER_ROOT "")
  15. endif()
  16. execute_process(COMMAND sw_vers -productVersion
  17. OUTPUT_VARIABLE CURRENT_OSX_VERSION
  18. OUTPUT_STRIP_TRAILING_WHITESPACE)
  19. # Save CMAKE_OSX_ARCHITECTURES from the environment.
  20. set(CMAKE_OSX_ARCHITECTURES "$ENV{CMAKE_OSX_ARCHITECTURES}" CACHE STRING
  21. "Build architectures for OSX")
  22. if(NOT CMAKE_CROSSCOMPILING AND
  23. CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND
  24. CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^(arm64|x86_64)$")
  25. execute_process(COMMAND sysctl -q hw.optional.arm64
  26. OUTPUT_VARIABLE _sysctl_stdout
  27. ERROR_VARIABLE _sysctl_stderr
  28. RESULT_VARIABLE _sysctl_result
  29. )
  30. # When building on an Apple Silicon host, we need to explicitly specify
  31. # the architecture to the toolchain since it will otherwise guess the
  32. # architecture based on that of the build system tool.
  33. # Set an *internal variable* to tell the generators to do this.
  34. if(_sysctl_result EQUAL 0 AND _sysctl_stdout MATCHES "hw.optional.arm64: 1")
  35. set(_CMAKE_APPLE_ARCHS_DEFAULT "${CMAKE_HOST_SYSTEM_PROCESSOR}")
  36. endif()
  37. unset(_sysctl_result)
  38. unset(_sysctl_stderr)
  39. unset(_sysctl_stdout)
  40. endif()
  41. # macOS, iOS, tvOS, visionOS, and watchOS should lookup compilers from
  42. # Platform/Apple-${CMAKE_CXX_COMPILER_ID}-<LANG>
  43. set(CMAKE_EFFECTIVE_SYSTEM_NAME "Apple")
  44. #----------------------------------------------------------------------------
  45. # _CURRENT_OSX_VERSION - as a two-component string: 10.5, 10.6, ...
  46. #
  47. string(REGEX REPLACE "^([0-9]+\\.[0-9]+).*$" "\\1"
  48. _CURRENT_OSX_VERSION "${CURRENT_OSX_VERSION}")
  49. #----------------------------------------------------------------------------
  50. # CMAKE_OSX_DEPLOYMENT_TARGET
  51. # Set cache variable - end user may change this during ccmake or cmake-gui configure.
  52. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND _CURRENT_OSX_VERSION VERSION_GREATER 10.3)
  53. set(CMAKE_OSX_DEPLOYMENT_TARGET "$ENV{MACOSX_DEPLOYMENT_TARGET}" CACHE STRING
  54. "Minimum OS X version to target for deployment (at runtime); newer APIs weak linked. Set to empty string for default value.")
  55. endif()
  56. #----------------------------------------------------------------------------
  57. # CMAKE_OSX_SYSROOT
  58. if(CMAKE_OSX_SYSROOT)
  59. # Use the existing value without further computation to choose a default.
  60. set(_CMAKE_OSX_SYSROOT_DEFAULT "${CMAKE_OSX_SYSROOT}")
  61. elseif(NOT "x$ENV{SDKROOT}" STREQUAL "x" AND
  62. (NOT "x$ENV{SDKROOT}" MATCHES "/" OR IS_DIRECTORY "$ENV{SDKROOT}"))
  63. # Use the value of SDKROOT from the environment.
  64. set(_CMAKE_OSX_SYSROOT_DEFAULT "$ENV{SDKROOT}")
  65. elseif(CMAKE_SYSTEM_NAME STREQUAL iOS)
  66. set(_CMAKE_OSX_SYSROOT_DEFAULT "iphoneos")
  67. elseif(CMAKE_SYSTEM_NAME STREQUAL tvOS)
  68. set(_CMAKE_OSX_SYSROOT_DEFAULT "appletvos")
  69. elseif(CMAKE_SYSTEM_NAME STREQUAL visionOS)
  70. set(_CMAKE_OSX_SYSROOT_DEFAULT "xros")
  71. elseif(CMAKE_SYSTEM_NAME STREQUAL watchOS)
  72. set(_CMAKE_OSX_SYSROOT_DEFAULT "watchos")
  73. elseif("${CMAKE_GENERATOR}" MATCHES Xcode
  74. OR CMAKE_OSX_DEPLOYMENT_TARGET
  75. OR CMAKE_OSX_ARCHITECTURES MATCHES "[^;]"
  76. OR NOT EXISTS "/usr/include/sys/types.h")
  77. # Find installed SDKs in either Xcode-4.3+ or pre-4.3 SDKs directory.
  78. set(_CMAKE_OSX_SDKS_DIR "")
  79. if(OSX_DEVELOPER_ROOT)
  80. foreach(_d Platforms/MacOSX.platform/Developer/SDKs SDKs)
  81. file(GLOB _CMAKE_OSX_SDKS ${OSX_DEVELOPER_ROOT}/${_d}/*)
  82. if(_CMAKE_OSX_SDKS)
  83. set(_CMAKE_OSX_SDKS_DIR ${OSX_DEVELOPER_ROOT}/${_d})
  84. break()
  85. endif()
  86. endforeach()
  87. endif()
  88. if(_CMAKE_OSX_SDKS_DIR)
  89. # Find the latest SDK as recommended by Apple (Technical Q&A QA1806)
  90. set(_CMAKE_OSX_LATEST_SDK_VERSION "0.0")
  91. file(GLOB _CMAKE_OSX_SDKS RELATIVE "${_CMAKE_OSX_SDKS_DIR}" "${_CMAKE_OSX_SDKS_DIR}/MacOSX*.sdk")
  92. foreach(_SDK ${_CMAKE_OSX_SDKS})
  93. if(IS_DIRECTORY "${_CMAKE_OSX_SDKS_DIR}/${_SDK}"
  94. AND _SDK MATCHES "MacOSX([0-9]+\\.[0-9]+)[^/]*\\.sdk"
  95. AND CMAKE_MATCH_1 VERSION_GREATER ${_CMAKE_OSX_LATEST_SDK_VERSION})
  96. set(_CMAKE_OSX_LATEST_SDK_VERSION "${CMAKE_MATCH_1}")
  97. endif()
  98. endforeach()
  99. if(NOT _CMAKE_OSX_LATEST_SDK_VERSION STREQUAL "0.0")
  100. set(_CMAKE_OSX_SYSROOT_DEFAULT "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CMAKE_OSX_LATEST_SDK_VERSION}.sdk")
  101. else()
  102. message(WARNING "Could not find any valid SDKs in ${_CMAKE_OSX_SDKS_DIR}")
  103. endif()
  104. if(NOT CMAKE_CROSSCOMPILING AND NOT CMAKE_OSX_DEPLOYMENT_TARGET
  105. AND (_CURRENT_OSX_VERSION VERSION_LESS _CMAKE_OSX_LATEST_SDK_VERSION
  106. OR _CMAKE_OSX_LATEST_SDK_VERSION STREQUAL "0.0"))
  107. set(CMAKE_OSX_DEPLOYMENT_TARGET ${_CURRENT_OSX_VERSION} CACHE STRING
  108. "Minimum OS X version to target for deployment (at runtime); newer APIs weak linked. Set to empty string for default value." FORCE)
  109. endif()
  110. else()
  111. # Assume developer files are in root (such as Xcode 4.5 command-line tools).
  112. set(_CMAKE_OSX_SYSROOT_DEFAULT "")
  113. endif()
  114. endif()
  115. # Set cache variable - end user may change this during ccmake or cmake-gui configure.
  116. # Choose the type based on the current value.
  117. set(_CMAKE_OSX_SYSROOT_TYPE STRING)
  118. foreach(_v CMAKE_OSX_SYSROOT _CMAKE_OSX_SYSROOT_DEFAULT)
  119. if("x${${_v}}" MATCHES "/")
  120. set(_CMAKE_OSX_SYSROOT_TYPE PATH)
  121. break()
  122. endif()
  123. endforeach()
  124. set(CMAKE_OSX_SYSROOT "${_CMAKE_OSX_SYSROOT_DEFAULT}" CACHE ${_CMAKE_OSX_SYSROOT_TYPE}
  125. "The product will be built against the headers and libraries located inside the indicated SDK.")
  126. # Resolves the SDK name into a path
  127. function(_apple_resolve_sdk_path sdk_name ret)
  128. execute_process(
  129. COMMAND xcrun -sdk ${sdk_name} --show-sdk-path
  130. OUTPUT_VARIABLE _stdout
  131. OUTPUT_STRIP_TRAILING_WHITESPACE
  132. ERROR_VARIABLE _stderr
  133. RESULT_VARIABLE _failed
  134. )
  135. set(${ret} "${_stdout}" PARENT_SCOPE)
  136. endfunction()
  137. function(_apple_resolve_supported_archs_for_sdk_from_system_lib sdk_path ret ret_failed)
  138. # Detect the supported SDK architectures by inspecting the main libSystem library.
  139. set(common_lib_prefix "${sdk_path}/usr/lib/libSystem")
  140. set(system_lib_dylib_path "${common_lib_prefix}.dylib")
  141. set(system_lib_tbd_path "${common_lib_prefix}.tbd")
  142. # Newer SDKs ship text based dylib stub files which contain the architectures supported by the
  143. # library in text form.
  144. if(EXISTS "${system_lib_tbd_path}")
  145. cmake_policy(PUSH)
  146. cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
  147. file(STRINGS "${system_lib_tbd_path}" tbd_lines REGEX "^(archs|targets): +\\[.+\\]")
  148. cmake_policy(POP)
  149. if(NOT tbd_lines)
  150. set(${ret_failed} TRUE PARENT_SCOPE)
  151. return()
  152. endif()
  153. # The tbd architectures line looks like the following:
  154. # archs: [ armv7, armv7s, arm64, arm64e ]
  155. # or for version 4 TBD files:
  156. # targets: [ armv7-ios, armv7s-ios, arm64-ios, arm64e-ios ]
  157. list(GET tbd_lines 0 first_arch_line)
  158. string(REGEX REPLACE
  159. "(archs|targets): +\\[ (.+) \\]" "\\2" arches_comma_separated "${first_arch_line}")
  160. string(STRIP "${arches_comma_separated}" arches_comma_separated)
  161. string(REPLACE "," ";" arch_list "${arches_comma_separated}")
  162. string(REPLACE " " "" arch_list "${arch_list}")
  163. # Remove -platform suffix from target (version 4 only)
  164. string(REGEX REPLACE "-[a-z-]+" "" arch_list "${arch_list}")
  165. if(NOT arch_list)
  166. set(${ret_failed} TRUE PARENT_SCOPE)
  167. return()
  168. endif()
  169. set(${ret} "${arch_list}" PARENT_SCOPE)
  170. elseif(EXISTS "${system_lib_dylib_path}")
  171. # Old SDKs (Xcode < 7) ship dylib files, use lipo to inspect the supported architectures.
  172. # Can't use -archs because the option is not available in older Xcode versions.
  173. execute_process(
  174. COMMAND lipo -info ${system_lib_dylib_path}
  175. OUTPUT_VARIABLE lipo_output
  176. OUTPUT_STRIP_TRAILING_WHITESPACE
  177. ERROR_VARIABLE _stderr
  178. RESULT_VARIABLE _failed
  179. )
  180. if(_failed OR NOT lipo_output OR NOT lipo_output MATCHES "(Non-fat file:|Architectures in the fat file:)")
  181. set(${ret_failed} TRUE PARENT_SCOPE)
  182. return()
  183. endif()
  184. # The lipo output looks like the following:
  185. # Non-fat file: <path> is architecture: i386
  186. # Architectures in the fat file: <path> are: i386 x86_64
  187. string(REGEX REPLACE
  188. "^(.+)is architecture:(.+)" "\\2" arches_space_separated "${lipo_output}")
  189. string(REGEX REPLACE
  190. "^(.+)are:(.+)" "\\2" arches_space_separated "${arches_space_separated}")
  191. # Need to clean up the arches, with Xcode 4.6.3 the output of lipo -info contains some
  192. # additional info, e.g.
  193. # Architectures in the fat file: <path> are: armv7 (cputype (12) cpusubtype (11))
  194. string(REGEX REPLACE
  195. "\\(.+\\)" "" arches_space_separated "${arches_space_separated}")
  196. # The output is space separated.
  197. string(STRIP "${arches_space_separated}" arches_space_separated)
  198. string(REPLACE " " ";" arch_list "${arches_space_separated}")
  199. if(NOT arch_list)
  200. set(${ret_failed} TRUE PARENT_SCOPE)
  201. return()
  202. endif()
  203. set(${ret} "${arch_list}" PARENT_SCOPE)
  204. else()
  205. # This shouldn't happen, but keep it for safety.
  206. message(WARNING "No way to find architectures for given sdk_path '${sdk_path}'")
  207. set(${ret_failed} TRUE PARENT_SCOPE)
  208. endif()
  209. endfunction()
  210. # Handle multi-arch sysroots. Do this before CMAKE_OSX_SYSROOT is
  211. # transformed into a path, so that we know the sysroot name.
  212. function(_apple_resolve_multi_arch_sysroots)
  213. if(DEFINED CMAKE_APPLE_ARCH_SYSROOTS)
  214. return() # Already cached
  215. endif()
  216. list(LENGTH CMAKE_OSX_ARCHITECTURES _num_archs)
  217. if(NOT (_num_archs GREATER 1))
  218. return() # Only apply to multi-arch
  219. endif()
  220. if(CMAKE_OSX_SYSROOT STREQUAL "macosx")
  221. # macOS doesn't have a simulator sdk / sysroot, so there is no need to handle per-sdk arches.
  222. return()
  223. endif()
  224. if(IS_DIRECTORY "${CMAKE_OSX_SYSROOT}")
  225. if(NOT CMAKE_OSX_SYSROOT STREQUAL _CMAKE_OSX_SYSROOT_DEFAULT)
  226. message(WARNING "Can not resolve multi-arch sysroots with CMAKE_OSX_SYSROOT set to path (${CMAKE_OSX_SYSROOT})")
  227. endif()
  228. return()
  229. endif()
  230. string(REPLACE "os" "simulator" _simulator_sdk ${CMAKE_OSX_SYSROOT})
  231. set(_sdks "${CMAKE_OSX_SYSROOT};${_simulator_sdk}")
  232. foreach(sdk ${_sdks})
  233. _apple_resolve_sdk_path(${sdk} _sdk_path)
  234. if(NOT IS_DIRECTORY "${_sdk_path}")
  235. message(WARNING "Failed to resolve SDK path for '${sdk}'")
  236. continue()
  237. endif()
  238. _apple_resolve_supported_archs_for_sdk_from_system_lib(${_sdk_path} _sdk_archs _failed)
  239. if(_failed)
  240. # Failure to extract supported architectures for an SDK means that the installed SDK is old
  241. # and does not provide such information (SDKs that come with Xcode >= 10.x started providing
  242. # the information). In such a case, return early, and handle multi-arch builds the old way
  243. # (no per-sdk arches).
  244. return()
  245. endif()
  246. set(_sdk_archs_${sdk} ${_sdk_archs})
  247. set(_sdk_path_${sdk} ${_sdk_path})
  248. endforeach()
  249. foreach(arch ${CMAKE_OSX_ARCHITECTURES})
  250. set(_arch_sysroot "")
  251. foreach(sdk ${_sdks})
  252. list(FIND _sdk_archs_${sdk} ${arch} arch_index)
  253. if(NOT arch_index EQUAL -1)
  254. set(_arch_sysroot ${_sdk_path_${sdk}})
  255. break()
  256. endif()
  257. endforeach()
  258. if(_arch_sysroot)
  259. list(APPEND _arch_sysroots ${_arch_sysroot})
  260. else()
  261. message(WARNING "No SDK found for architecture '${arch}'")
  262. list(APPEND _arch_sysroots "${arch}-SDK-NOTFOUND")
  263. endif()
  264. endforeach()
  265. set(CMAKE_APPLE_ARCH_SYSROOTS "${_arch_sysroots}" CACHE INTERNAL
  266. "Architecture dependent sysroots, one per CMAKE_OSX_ARCHITECTURES")
  267. endfunction()
  268. _apple_resolve_multi_arch_sysroots()
  269. # Transform CMAKE_OSX_SYSROOT to absolute path
  270. set(_CMAKE_OSX_SYSROOT_PATH "")
  271. if(CMAKE_OSX_SYSROOT)
  272. if("x${CMAKE_OSX_SYSROOT}" MATCHES "/")
  273. # This is a path to the SDK. Make sure it exists.
  274. if(NOT IS_DIRECTORY "${CMAKE_OSX_SYSROOT}")
  275. message(WARNING "Ignoring CMAKE_OSX_SYSROOT value:\n ${CMAKE_OSX_SYSROOT}\n"
  276. "because the directory does not exist.")
  277. set(CMAKE_OSX_SYSROOT "")
  278. endif()
  279. set(_CMAKE_OSX_SYSROOT_PATH "${CMAKE_OSX_SYSROOT}")
  280. else()
  281. _apple_resolve_sdk_path(${CMAKE_OSX_SYSROOT} _sdk_path)
  282. if(IS_DIRECTORY "${_sdk_path}")
  283. set(_CMAKE_OSX_SYSROOT_PATH "${_sdk_path}")
  284. # For non-Xcode generators use the path.
  285. if(NOT "${CMAKE_GENERATOR}" MATCHES "Xcode")
  286. set(CMAKE_OSX_SYSROOT "${_CMAKE_OSX_SYSROOT_PATH}")
  287. endif()
  288. endif()
  289. endif()
  290. endif()