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