blob: a54a6120b7674117e3eda5b800bdcec2a9acec26 [file]
# 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} AND EXISTS "${${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 ()
# One entry per SDK the Cocoa port builds for, matching SUPPORTED_PLATFORMS in the
# Xcode configurations. The fields, in order: the platform name Info.plists carry,
# the CMAKE_SYSTEM_NAME to cross-compile with, the OS as a target triple spells it,
# the OS as a Swift module triple spells it, and the clang deployment-target flag
# wtf/Platform.h is evaluated against. macOS is the one platform whose two triple
# spellings differ, and visionOS the one with no -m<os>-version-min flag.
set(_wk_sdk_macosx "MacOSX" "Darwin" "macosx" "macos" "-mmacosx-version-min=@VERSION@")
set(_wk_sdk_iphoneos "iPhoneOS" "iOS" "ios" "ios" "-miphoneos-version-min=@VERSION@")
set(_wk_sdk_iphonesimulator "iPhoneSimulator" "iOS" "ios" "ios" "-mios-simulator-version-min=@VERSION@")
set(_wk_sdk_appletvos "AppleTVOS" "tvOS" "tvos" "tvos" "-mtvos-version-min=@VERSION@")
set(_wk_sdk_appletvsimulator "AppleTVSimulator" "tvOS" "tvos" "tvos" "-mtvos-simulator-version-min=@VERSION@")
set(_wk_sdk_watchos "WatchOS" "watchOS" "watchos" "watchos" "-mwatchos-version-min=@VERSION@")
set(_wk_sdk_watchsimulator "WatchSimulator" "watchOS" "watchos" "watchos" "-mwatchos-simulator-version-min=@VERSION@")
set(_wk_sdk_xros "XROS" "visionOS" "xros" "xros" "-mtargetos=xros@VERSION@")
set(_wk_sdk_xrsimulator "XRSimulator" "visionOS" "xros" "xros" "-mtargetos=xros@VERSION@-simulator")
# 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.
if (NOT DEFINED _wk_sdk_${WEBKIT_SDK_NAME})
message(FATAL_ERROR "Unsupported Apple SDK '${WEBKIT_SDK_NAME}'. Add a row for it to "
"the SDK table in WebKitXcodeSDK.cmake so the platform name, the system name, the "
"triple spellings, and the deployment-target flag that wtf/Platform.h is evaluated "
"against are all derived for it.")
endif ()
set(_wk_sdk_entry ${_wk_sdk_${WEBKIT_SDK_NAME}})
list(GET _wk_sdk_entry 0 WEBKIT_PLATFORM_NAME)
list(GET _wk_sdk_entry 1 WEBKIT_SDK_SYSTEM_NAME)
list(GET _wk_sdk_entry 2 WEBKIT_SDK_TARGET_OS)
list(GET _wk_sdk_entry 3 WEBKIT_SDK_MODULE_OS)
list(GET _wk_sdk_entry 4 _wk_sdk_min_version_flag)
unset(_wk_sdk_entry)
# Cocoa is macOS plus the iOS family, the same split wtf/PlatformLegacy.h makes
# between PLATFORM(MAC) and PLATFORM(IOS_FAMILY), so every SDK above that isn't
# macOS belongs to the family.
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)
else ()
set(WEBKIT_SDK_IS_IOS_FAMILY ON)
endif ()
if (WEBKIT_SDK_NAME MATCHES "simulator$")
set(WEBKIT_SDK_IS_SIMULATOR ON)
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 ()
if (CMAKE_OSX_DEPLOYMENT_TARGET)
string(REPLACE "@VERSION@" "${CMAKE_OSX_DEPLOYMENT_TARGET}"
WEBKIT_SDK_MIN_VERSION_FLAG "${_wk_sdk_min_version_flag}")
endif ()
unset(_wk_sdk_min_version_flag)
# 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 ${WEBKIT_SDK_SYSTEM_NAME})
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")