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