blob: 7b3f6149311c10edd918fb6c0303736214911d6f [file] [edit]
# Helpers and initialization logic for building with Apple SDKs.
#
# Always pass --sdk to xcrun explicitly -- otherwise, toolchain and SDK
# are not guaranteed to match.
# Sets CMAKE_OSX_SYSROOT, WEBKIT_SDK_NAME, and WEBKIT_SDK_VERSION in the caller's scope.
function(WEBKIT_RESOLVE_SDK)
foreach (_sdk IN LISTS ARGN)
execute_process(COMMAND xcrun --sdk ${_sdk} --show-sdk-path
OUTPUT_VARIABLE _sdk_path
RESULT_VARIABLE _sdk_result
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
if (_sdk_result EQUAL 0 AND _sdk_path)
file(READ "${_sdk_path}/SDKSettings.json" _sdk_settings)
string(JSON _sdk_version GET ${_sdk_settings} Version)
string(JSON _sdk_canonical_name GET ${_sdk_settings} CanonicalName)
string(JSON _platform_name GET ${_sdk_settings} DefaultProperties PLATFORM_NAME)
message(STATUS "Xcode SDK: ${_sdk_canonical_name} at ${_sdk_path}")
set(WEBKIT_SDK_VERSION "${_sdk_version}" PARENT_SCOPE)
set(WEBKIT_SDK_NAME "${_platform_name}" PARENT_SCOPE)
set(CMAKE_OSX_SYSROOT "${_sdk_path}" CACHE PATH "" FORCE)
if (_sdk_path MATCHES "\\.[Ii]nternal.sdk$")
set(USE_APPLE_INTERNAL_SDK ON CACHE BOOL "" FORCE)
else ()
set(USE_APPLE_INTERNAL_SDK OFF CACHE BOOL "" FORCE)
endif ()
if (NOT CMAKE_OSX_ARCHITECTURES)
# Build the supported-archs list from SDKSettings.json's
# SupportedTargets.<platform>.Archs. Order works out
# to match our preferred build defaults.
string(JSON _archs_length LENGTH ${_sdk_settings}
SupportedTargets ${_platform_name} Archs)
set(_supported_archs "")
math(EXPR _archs_last "${_archs_length} - 1")
foreach (_i RANGE 0 ${_archs_last})
string(JSON _arch_i GET ${_sdk_settings}
SupportedTargets ${_platform_name} Archs ${_i})
list(APPEND _supported_archs "${_arch_i}")
endforeach ()
# FIXME: This is different from what we do in the xcodebuild. For devices,
# we default to building for all architectures supported by the device
# (for iOS devices, just arm64e). For simulators, we query the system for
# created simulator targets and match their architecture (usually arm64).
if (_platform_name STREQUAL "macosx")
# When building for the host machine CMAKE_HOST_SYSTEM_PROCESSOR
# isn't populated until `project()` is called, so consult `uname -m`.
# Only set _arch if SDK supports arm64e otherwise let `project()`
# configure.
execute_process(COMMAND uname -m
OUTPUT_VARIABLE _host_arch
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (_host_arch STREQUAL "arm64" AND USE_APPLE_INTERNAL_SDK
AND "arm64e" IN_LIST _supported_archs)
set(_arch "arm64e")
set(_arch_reason "internal SDK + arm64 host")
endif ()
else ()
# When Cross-compiling, just trust the SDKSettings's ordering.
list(GET _supported_archs 0 _arch)
set(_arch_reason "first SDK-supported arch")
endif ()
if (DEFINED _arch)
set(CMAKE_OSX_ARCHITECTURES "${_arch}"
CACHE STRING "Target architecture" FORCE)
message(STATUS "Architecture: ${_arch} (${_arch_reason})")
endif ()
endif ()
return()
endif ()
endforeach ()
message(FATAL_ERROR "xcrun could not locate any SDK in: ${ARGN}")
endfunction()
# Runs `xcrun and capture stdout in OUTPUT_VAR
# (in the caller's scope).
function(WEBKIT_XCRUN OUTPUT_VAR)
if (NOT CMAKE_OSX_SYSROOT)
message(FATAL_ERROR "WEBKIT_XCRUN called before WEBKIT_RESOLVE_SDK")
endif ()
execute_process(COMMAND xcrun ${ARGN}
OUTPUT_VARIABLE _out
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
set(${OUTPUT_VAR} "${_out}" PARENT_SCOPE)
endfunction()
function(WEBKIT_RESOLVE_TOOL OUTPUT_VAR _tool)
if (DEFINED ${OUTPUT_VAR})
return()
endif ()
WEBKIT_XCRUN(_path -f ${_tool})
if (NOT EXISTS "${_path}")
message(SEND_ERROR "Cannot find ${_tool} in the active SDK and "
"toolchain (${CMAKE_OSX_SYSROOT})")
else ()
set(${OUTPUT_VAR} "${_path}" CACHE STRING "" FORCE)
endif ()
endfunction()
# ----------------------------------------------------------------------------
# Initialization logic. Sets CMAKE_OSX_SYSROOT if needed, and pins compiler
# tools from the SDK.
# ----------------------------------------------------------------------------
if (CMAKE_OSX_SYSROOT)
WEBKIT_RESOLVE_SDK(${CMAKE_OSX_SYSROOT})
elseif (PORT STREQUAL "Mac" OR PORT STREQUAL "Cocoa" OR PORT STREQUAL "JSCOnly" OR NOT PORT)
WEBKIT_RESOLVE_SDK(macosx.internal macosx)
elseif (PORT STREQUAL "IOS" AND CMAKE_IOS_SIMULATOR)
WEBKIT_RESOLVE_SDK(iphonesimulator.internal iphonesimulator)
elseif (PORT STREQUAL "IOS")
WEBKIT_RESOLVE_SDK(iphoneos.internal iphoneos)
else ()
message(FATAL_ERROR "Building for an Apple platform without an SDK "
"directory (CMAKE_OSX_SYSROOT) or supported PORT variable.")
endif ()
# Platform detection, derived once from the resolved SDK's PLATFORM_NAME. All
# downstream CMake branches on these booleans instead of on PORT or an ad-hoc
# CMAKE_IOS_SIMULATOR flag, so the platform is chosen purely by the selected SDK.
set(WEBKIT_SDK_IS_MACOS OFF)
set(WEBKIT_SDK_IS_IOS_FAMILY OFF)
set(WEBKIT_SDK_IS_SIMULATOR OFF)
if (WEBKIT_SDK_NAME STREQUAL "macosx")
set(WEBKIT_SDK_IS_MACOS ON)
set(WEBKIT_PLATFORM_NAME "MacOSX")
elseif (WEBKIT_SDK_NAME STREQUAL "iphoneos")
set(WEBKIT_SDK_IS_IOS_FAMILY ON)
set(WEBKIT_PLATFORM_NAME "iPhoneOS")
elseif (WEBKIT_SDK_NAME STREQUAL "iphonesimulator")
set(WEBKIT_SDK_IS_IOS_FAMILY ON)
set(WEBKIT_SDK_IS_SIMULATOR ON)
set(WEBKIT_PLATFORM_NAME "iPhoneSimulator")
endif ()
# Building for macOS defaults uses the host system's deployment target. Other
# platforms deploy to the SDK version.
# FIXME: macOS should use the host version OR SDK version, whichever is
# smaller.
if (NOT CMAKE_OSX_DEPLOYMENT_TARGET)
if (WEBKIT_SDK_IS_MACOS)
execute_process(COMMAND sw_vers -productVersion
OUTPUT_VARIABLE _host_os_version
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _host_os_result)
if (_host_os_result EQUAL 0)
string(REGEX MATCH "^[0-9]+\\.[0-9]+" _deployment_target "${_host_os_version}")
endif ()
unset(_host_os_version)
unset(_host_os_result)
else ()
string(REGEX MATCH "^[0-9]+\\.[0-9]+" _deployment_target "${WEBKIT_SDK_VERSION}")
endif ()
if (_deployment_target)
set(CMAKE_OSX_DEPLOYMENT_TARGET "${_deployment_target}" CACHE STRING "Deployment target" FORCE)
endif ()
unset(_deployment_target)
endif ()
# Cross-compile setup for the iOS family (device or simulator). CMake doesn't
# infer CMAKE_SYSTEM_PROCESSOR once CMAKE_SYSTEM_NAME is set, so it has to be
# supplied explicitly. Both must be in place before project() runs. Device vs.
# simulator is inferred by CMake from the sysroot path, so only the system name
# differs from a macOS build here.
if (WEBKIT_SDK_IS_IOS_FAMILY)
set(CMAKE_SYSTEM_NAME iOS)
if (NOT CMAKE_SYSTEM_PROCESSOR)
set(CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE STRING "Target processor" FORCE)
endif ()
endif ()
# Subsequent use of `xcrun` or any of the system Xcode and BSD tools will
# use the selected SDK and toolchain.
set(ENV{SDKROOT} ${CMAKE_OSX_SYSROOT})
WEBKIT_RESOLVE_TOOL(CMAKE_C_COMPILER "clang")
WEBKIT_RESOLVE_TOOL(CMAKE_ASM_COMPILER "clang")
WEBKIT_RESOLVE_TOOL(CMAKE_CXX_COMPILER "clang++")
WEBKIT_RESOLVE_TOOL(CMAKE_OBJC_COMPILER "clang")
WEBKIT_RESOLVE_TOOL(CMAKE_OBJCXX_COMPILER "clang++")
WEBKIT_RESOLVE_TOOL(CMAKE_Swift_COMPILER "swiftc")
WEBKIT_RESOLVE_TOOL(CMAKE_INSTALL_NAME_TOOL "install_name_tool")
WEBKIT_RESOLVE_TOOL(CMAKE_LINKER "ld")
# FIXME: Move these to proper find modules, as they are not part of any CMake
# language.
WEBKIT_RESOLVE_TOOL(GPERF_EXECUTABLE "gperf")
WEBKIT_RESOLVE_TOOL(Mig_EXECUTABLE "mig")