Skip to content

Commit cb4a7bd

Browse files
committed
Merge pull request #2560 from karwa/cmake-crosscompiling
Refactored CMake host/target SDK detection to support cross-compiling
2 parents 1ca76b2 + 8c7da8d commit cb4a7bd

File tree

2 files changed

+134
-100
lines changed

2 files changed

+134
-100
lines changed

CMakeLists.txt

Lines changed: 132 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -390,29 +390,78 @@ function(check_working_std_regex result_var_name)
390390
# Apple operating systems use libc++, which has a working std::regex.
391391
set("${result_var_name}" TRUE PARENT_SCOPE)
392392
else()
393-
# libstdc++ 4.8 has an incomplete std::regex implementation, and crashes
394-
# on many regexes.
395-
# libstdc++ 4.9 works.
396-
set(std_regex_test_source
397-
"
398-
#include <regex>
399-
const std::regex broken_regex{
400-
\"([a]+)\",
401-
std::regex::ECMAScript | std::regex::nosubs};
402-
403-
int main() {}
404-
")
405-
406-
check_cxx_source_runs("${std_regex_test_source}" "${result_var_name}_TEST")
407-
if ("${${result_var_name}_TEST}")
408-
set("${result_var_name}" TRUE PARENT_SCOPE)
409-
else()
393+
if(CMAKE_CROSSCOMPILING)
394+
# Can't run C source when cross-compiling; assume false until we have a static check.
410395
set("${result_var_name}" FALSE PARENT_SCOPE)
396+
else()
397+
# libstdc++ 4.8 has an incomplete std::regex implementation, and crashes
398+
# on many regexes.
399+
# libstdc++ 4.9 works.
400+
set(std_regex_test_source
401+
"
402+
#include <regex>
403+
const std::regex broken_regex{
404+
\"([a]+)\",
405+
std::regex::ECMAScript | std::regex::nosubs};
406+
407+
int main() {}
408+
")
409+
410+
check_cxx_source_runs("${std_regex_test_source}" "${result_var_name}_TEST")
411+
if ("${${result_var_name}_TEST}")
412+
set("${result_var_name}" TRUE PARENT_SCOPE)
413+
else()
414+
set("${result_var_name}" FALSE PARENT_SCOPE)
415+
endif()
411416
endif()
412417
endif()
413418
endfunction()
414419
check_working_std_regex(SWIFT_HAVE_WORKING_STD_REGEX)
415420

421+
# If SWIFT_HOST_VARIANT_SDK not given, try to detect from the CMAKE_SYSTEM_NAME.
422+
if(SWIFT_HOST_VARIANT_SDK)
423+
set(SWIFT_HOST_VARIANT_SDK_default "${SWIFT_HOST_VARIANT_SDK}")
424+
else()
425+
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
426+
set(SWIFT_HOST_VARIANT_SDK_default "LINUX")
427+
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
428+
set(SWIFT_HOST_VARIANT_SDK_default "FREEBSD")
429+
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
430+
set(SWIFT_HOST_VARIANT_SDK_default "CYGWIN")
431+
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
432+
set(SWIFT_HOST_VARIANT_SDK_default "OSX")
433+
else()
434+
message(FATAL_ERROR "Unable to detect SDK for host system: ${CMAKE_SYSTEM_NAME}")
435+
endif()
436+
endif()
437+
438+
# If SWIFT_HOST_VARIANT_ARCH not given, try to detect from the CMAKE_SYSTEM_PROCESSOR.
439+
if(SWIFT_HOST_VARIANT_ARCH)
440+
set(SWIFT_HOST_VARIANT_ARCH_default, "${SWIFT_HOST_VARIANT_ARCH}")
441+
else()
442+
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
443+
set(SWIFT_HOST_VARIANT_ARCH_default "x86_64")
444+
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")
445+
set(SWIFT_HOST_VARIANT_ARCH_default "aarch64")
446+
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ppc64")
447+
set(SWIFT_HOST_VARIANT_ARCH_default "powerpc64")
448+
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ppc64le")
449+
set(SWIFT_HOST_VARIANT_ARCH_default "powerpc64le")
450+
# FIXME: Only matches v6l/v7l - by far the most common variants
451+
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv6l")
452+
set(SWIFT_HOST_VARIANT_ARCH_default "armv6")
453+
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7l")
454+
set(SWIFT_HOST_VARIANT_ARCH_default "armv7")
455+
else()
456+
message(FATAL_ERROR "Unrecognized architecture on host system: ${CMAKE_SYSTEM_PROCESSOR}")
457+
endif()
458+
endif()
459+
460+
set(SWIFT_HOST_VARIANT_SDK "${SWIFT_HOST_VARIANT_SDK_default}" CACHE STRING
461+
"Deployment sdk for Swift host tools (the compiler).")
462+
set(SWIFT_HOST_VARIANT_ARCH "${SWIFT_HOST_VARIANT_ARCH_default}" CACHE STRING
463+
"Deployment arch for Swift host tools (the compiler).")
464+
416465
#
417466
# Enable additional warnings.
418467
#
@@ -439,114 +488,95 @@ function(is_sdk_requested name result_var_name)
439488
endif()
440489
endfunction()
441490

442-
# FIXME: separate the notions of SDKs used for compiler tools and target
443-
# binaries.
444-
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
491+
# FIXME: the parameters we specify in SWIFT_SDKS are lacking architecture specifics,
492+
# so we need to hard-code it. For example, the SDK for Android is just 'ANDROID',
493+
# which we assume below to be armv7.
494+
# The iOS SDKs all have their architectures hardcoded because they are just specified by name (e.g. 'IOS' or 'WATCHOS').
495+
# We can't cross-compile the standard library for another linux architecture,
496+
# because the SDK list would just be 'LINUX' and we couldn't disambiguate it from the host.
497+
#
498+
# To fix it, we would need to append the architecture to the SDKs,
499+
# for example: 'OSX-x86_64;IOS-armv7;...etc'.
500+
# We could easily do that - we have all of that information in build-script-impl.
501+
# Also, we would need to be provided with the sysroot for each SDK (see SWIFT_ANDROID_SDK_PATH/SWIFT_SDK_ANDROID_PATH).
502+
# Darwin targets cheat and use `xcrun`.
503+
504+
if("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "LINUX")
505+
445506
set(CMAKE_EXECUTABLE_FORMAT "ELF")
446-
447507
set(SWIFT_HOST_VARIANT "linux" CACHE STRING
448508
"Deployment OS for Swift host tools (the compiler) [linux].")
449509

450-
set(SWIFT_HOST_VARIANT_SDK "LINUX")
451-
set(SWIFT_PRIMARY_VARIANT_SDK_default "LINUX")
452-
453-
# FIXME: This will not work while trying to cross-compile.
454-
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
455-
set(SWIFT_HOST_VARIANT_ARCH "x86_64")
456-
set(SWIFT_PRIMARY_VARIANT_ARCH_default "x86_64")
457-
458-
if("${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
459-
set(swift_can_crosscompile_stdlib FALSE)
510+
# Calculate the host triple
511+
if("${SWIFT_HOST_TRIPLE}" STREQUAL "")
512+
if("${SWIFT_HOST_VARIANT_ARCH}" STREQUAL "x86_64")
513+
set(SWIFT_HOST_TRIPLE "x86_64-unknown-linux-gnu")
514+
elseif("${SWIFT_HOST_VARIANT_ARCH}" STREQUAL "aarch64")
515+
set(SWIFT_HOST_TRIPLE "aarch64-unknown-linux-gnu")
516+
elseif("${SWIFT_HOST_VARIANT_ARCH}" MATCHES "(powerpc64|powerpc64le)")
517+
set(SWIFT_HOST_TRIPLE "${SWIFT_HOST_VARIANT_ARCH}-unknown-linux-gnu")
518+
elseif("${SWIFT_HOST_VARIANT_ARCH}" MATCHES "(armv6|armv7)")
519+
set(SWIFT_HOST_TRIPLE "${SWIFT_HOST_VARIANT_ARCH}-unknown-linux-gnueabihf")
460520
else()
461-
set(swift_can_crosscompile_stdlib TRUE)
521+
message(FATAL_ERROR "Unable to calculate triple for linux host on ${SWIFT_HOST_VARIANT_ARCH}")
462522
endif()
523+
endif()
463524

464-
is_sdk_requested(LINUX swift_build_linux)
465-
if(swift_build_linux)
466-
configure_sdk_unix(LINUX "Linux" "linux" "linux" "x86_64" "x86_64-unknown-linux-gnu")
467-
set(SWIFT_PRIMARY_VARIANT_SDK_default "LINUX")
468-
set(SWIFT_PRIMARY_VARIANT_ARCH_default "x86_64")
469-
endif()
525+
# Should we build the standard library for the host?
526+
is_sdk_requested(LINUX swift_build_linux)
527+
if(swift_build_linux)
528+
configure_sdk_unix(LINUX "Linux" "linux" "${SWIFT_HOST_VARIANT}" "${SWIFT_HOST_VARIANT_ARCH}" "${SWIFT_HOST_TRIPLE}" "/")
529+
set(SWIFT_PRIMARY_VARIANT_SDK_default "${SWIFT_HOST_VARIANT_SDK}")
530+
set(SWIFT_PRIMARY_VARIANT_ARCH_default "${SWIFT_HOST_VARIANT_ARCH}")
531+
endif()
470532

471-
is_sdk_requested(ANDROID swift_build_android)
472-
if(swift_build_android AND ${swift_can_crosscompile_stdlib})
473-
configure_sdk_unix(ANDROID "Android" "android" "android" "armv7" "armv7-none-linux-androideabi")
474-
# This must be set, as variables such as "${SWIFT_SDK_${sdk}_PATH}" are
475-
# referenced in several other locations.
476-
set(SWIFT_SDK_ANDROID_PATH "${SWIFT_ANDROID_SDK_PATH}")
533+
# Compatible cross-compile SDKS for LINUX: ANDROID (arch always armv7)
534+
is_sdk_requested(ANDROID swift_build_android)
535+
if("${SWIFT_ANDROID_NDK_PATH}" STREQUAL "")
536+
set(swift_can_crosscompile_stdlib_android FALSE)
537+
else()
538+
set(swift_can_crosscompile_stdlib_android TRUE)
539+
endif()
477540

541+
if(swift_build_android AND ${swift_can_crosscompile_stdlib_android})
542+
configure_sdk_unix(ANDROID "Android" "android" "android" "armv7" "armv7-none-linux-androideabi" "${SWIFT_ANDROID_SDK_PATH}")
543+
# If we're not building for the host, the cross-compiled target should be the 'primary variant'.
544+
if("${swift_build_linux}" STREQUAL "FALSE")
478545
set(SWIFT_PRIMARY_VARIANT_SDK_default "ANDROID")
479546
set(SWIFT_PRIMARY_VARIANT_ARCH_default "armv7")
480547
endif()
481-
482-
# FIXME: This only matches ARMv6l (by far the most common variant).
483-
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv6l")
484-
configure_sdk_unix(LINUX "Linux" "linux" "linux" "armv6" "armv6-unknown-linux-gnueabihf")
485-
set(SWIFT_HOST_VARIANT_ARCH "armv6")
486-
set(SWIFT_PRIMARY_VARIANT_ARCH_default "armv6")
487-
# FIXME: This only matches ARMv7l (by far the most common variant).
488-
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7l")
489-
configure_sdk_unix(LINUX "Linux" "linux" "linux" "armv7" "armv7-unknown-linux-gnueabihf")
490-
set(SWIFT_HOST_VARIANT_ARCH "armv7")
491-
set(SWIFT_PRIMARY_VARIANT_ARCH_default "armv7")
492-
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")
493-
configure_sdk_unix(LINUX "Linux" "linux" "linux" "aarch64" "aarch64-unknown-linux-gnu")
494-
set(SWIFT_HOST_VARIANT_ARCH "aarch64")
495-
set(SWIFT_PRIMARY_VARIANT_ARCH_default "aarch64")
496-
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ppc64")
497-
configure_sdk_unix(LINUX "Linux" "linux" "linux" "powerpc64" "powerpc64-unknown-linux-gnu")
498-
set(SWIFT_HOST_VARIANT_ARCH "powerpc64")
499-
set(SWIFT_PRIMARY_VARIANT_ARCH_default "powerpc64")
500-
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ppc64le")
501-
configure_sdk_unix(LINUX "Linux" "linux" "linux" "powerpc64le" "powerpc64le-unknown-linux-gnu")
502-
set(SWIFT_HOST_VARIANT_ARCH "powerpc64le")
503-
set(SWIFT_PRIMARY_VARIANT_ARCH_default "powerpc64le")
504-
else()
505-
message(FATAL_ERROR "Unknown or unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}")
506548
endif()
507549

508-
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
550+
elseif("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "FREEBSD")
551+
552+
set(CMAKE_EXECUTABLE_FORMAT "ELF")
553+
set(SWIFT_HOST_VARIANT "freebsd" CACHE STRING
554+
"Deployment OS for Swift host tools (the compiler) [freebsd].")
555+
509556
# FIXME: Using the host OS version won't produce correct results for
510557
# cross-compilation.
511558
string(REPLACE "[-].*" "" FREEBSD_SYSTEM_VERSION ${CMAKE_SYSTEM_VERSION})
512559
message(STATUS "FreeBSD Version: ${FREEBSD_SYSTEM_VERSION}")
513560
configure_sdk_unix(FREEBSD "FreeBSD" "freebsd" "freebsd" "x86_64"
514-
"x86_64-unknown-freebsd${FREEBSD_SYSTEM_VERSION}")
515-
516-
set(CMAKE_EXECUTABLE_FORMAT "ELF")
517-
518-
set(SWIFT_HOST_VARIANT "freebsd" CACHE STRING
519-
"Deployment OS for Swift host tools (the compiler) [freebsd].")
520-
521-
set(SWIFT_HOST_VARIANT_SDK "FREEBSD")
522-
set(SWIFT_HOST_VARIANT_ARCH "x86_64")
523-
524-
set(SWIFT_PRIMARY_VARIANT_SDK_default "FREEBSD")
561+
"x86_64-unknown-freebsd${FREEBSD_SYSTEM_VERSION}" "/")
562+
set(SWIFT_PRIMARY_VARIANT_SDK_default "${SWIFT_HOST_VARIANT_SDK}")
525563
set(SWIFT_PRIMARY_VARIANT_ARCH_default "x86_64")
526-
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
527-
configure_sdk_unix(CYGWIN "Cygwin" "windows" "cygwin" "x86_64" "x86_64-unknown-windows-cygnus")
528-
529-
# set(CMAKE_EXECUTABLE_FORMAT "ELF")
530-
564+
565+
elseif("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "CYGWIN")
566+
567+
# set(CMAKE_EXECUTABLE_FORMAT "ELF")
531568
set(SWIFT_HOST_VARIANT "windows" CACHE STRING
532569
"Deployment OS for Swift host tools (the compiler) [windows].")
533-
534-
set(SWIFT_HOST_VARIANT_SDK "CYGWIN")
535-
set(SWIFT_HOST_VARIANT_ARCH "x86_64")
536570

537-
set(SWIFT_PRIMARY_VARIANT_SDK_default "CYGWIN")
571+
configure_sdk_unix(CYGWIN "Cygwin" "windows" "cygwin" "windows" "x86_64-unknown-windows-cygnus" "/")
572+
set(SWIFT_PRIMARY_VARIANT_SDK_default "${SWIFT_HOST_VARIANT_SDK}")
538573
set(SWIFT_PRIMARY_VARIANT_ARCH_default "x86_64")
539-
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
540-
# Set defaults.
574+
575+
elseif("${SWIFT_HOST_VARIANT_SDK}" MATCHES "(OSX|IOS*|TVOS*|WATCHOS*)")
541576

542577
set(SWIFT_HOST_VARIANT "macosx" CACHE STRING
543578
"Deployment OS for Swift host tools (the compiler) [macosx, iphoneos].")
544579

545-
set(SWIFT_HOST_VARIANT_SDK "OSX" CACHE STRING
546-
"Deployment sdk for Swift host tools (the compiler).")
547-
set(SWIFT_HOST_VARIANT_ARCH "x86_64" CACHE STRING
548-
"Deployment arch for Swift host tools (the compiler).")
549-
550580
# Display Xcode toolchain version.
551581
# The SDK configuration below prints each SDK version.
552582
execute_process(
@@ -567,6 +597,9 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
567597
configure_target_variant(OSX-R "OS X Release" OSX R "Release")
568598
endif()
569599

600+
# Compatible cross-compile SDKS for Darwin OSes: IOS, IOS_SIMULATOR, TVOS,
601+
# TVOS_SIMULATOR, WATCHOS, WATCHOS_SIMULATOR (archs hardcoded below).
602+
570603
if(XCODE)
571604
# FIXME: Cannot cross-compile stdlib using Xcode. Xcode insists on
572605
# passing -mmacosx-version-min to the compiler, and we want to pass
@@ -654,9 +687,10 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
654687
# set(SWIFT_PRIMARY_VARIANT ${SWIFT_PRIMARY_VARIANT_GUESS} CACHE STRING
655688
# "[OSX-DA, OSX-RA, OSX-R, IOS-DA, IOS-RA, IOS-R, IOS_SIMULATOR-DA, IOS_SIMULATOR-RA, IOS_SIMULATOR-R]")
656689
#
657-
# FIXME: hardcode OS X as the default variant for now.
690+
# Primary variant is always OSX; even on iOS hosts.
658691
set(SWIFT_PRIMARY_VARIANT_SDK_default "OSX")
659692
set(SWIFT_PRIMARY_VARIANT_ARCH_default "x86_64")
693+
660694
endif()
661695

662696
if("${SWIFT_PRIMARY_VARIANT_SDK}" STREQUAL "")

cmake/modules/SwiftConfigureSDK.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ macro(configure_sdk_darwin
109109
endmacro()
110110

111111
macro(configure_sdk_unix
112-
prefix name lib_subdir triple_name arch triple)
112+
prefix name lib_subdir triple_name arch triple sdkpath)
113113
# Note: this has to be implemented as a macro because it sets global
114114
# variables.
115115

116116
set(SWIFT_SDK_${prefix}_NAME "${name}")
117-
set(SWIFT_SDK_${prefix}_PATH "/")
117+
set(SWIFT_SDK_${prefix}_PATH "${sdkpath}")
118118
set(SWIFT_SDK_${prefix}_VERSION "don't use")
119119
set(SWIFT_SDK_${prefix}_BUILD_NUMBER "don't use")
120120
set(SWIFT_SDK_${prefix}_DEPLOYMENT_VERSION "don't use")

0 commit comments

Comments
 (0)