diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 2be88f8b615be..ed5e164144f87 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -1,3 +1,4 @@ +include(macCatalystUtils) include(SwiftList) include(SwiftXcodeSupport) include(SwiftWindowsSupport) @@ -30,7 +31,7 @@ endfunction() # Compute the library subdirectory to use for the given sdk and # architecture, placing the result in 'result_var_name'. function(compute_library_subdir result_var_name sdk arch) - if(sdk IN_LIST SWIFT_APPLE_PLATFORMS) + if(sdk IN_LIST SWIFT_APPLE_PLATFORMS OR sdk STREQUAL "MACCATALYST") set("${result_var_name}" "${SWIFT_SDK_${sdk}_LIB_SUBDIR}" PARENT_SCOPE) else() set("${result_var_name}" "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}" PARENT_SCOPE) @@ -89,6 +90,7 @@ endfunction() # ANALYZE_CODE_COVERAGE analyze_code_coverage # RESULT_VAR_NAME result_var_name # DEPLOYMENT_VERSION_OSX version # If provided, overrides the default value of the OSX deployment target set by the Swift project for this compilation only. +# DEPLOYMENT_VERSION_MACCATALYST version # DEPLOYMENT_VERSION_IOS version # DEPLOYMENT_VERSION_TVOS version # DEPLOYMENT_VERSION_WATCHOS version @@ -96,20 +98,29 @@ endfunction() # ) function(_add_variant_c_compile_link_flags) set(oneValueArgs SDK ARCH BUILD_TYPE RESULT_VAR_NAME ENABLE_LTO ANALYZE_CODE_COVERAGE - DEPLOYMENT_VERSION_OSX DEPLOYMENT_VERSION_IOS DEPLOYMENT_VERSION_TVOS DEPLOYMENT_VERSION_WATCHOS) + DEPLOYMENT_VERSION_OSX DEPLOYMENT_VERSION_MACCATALYST DEPLOYMENT_VERSION_IOS DEPLOYMENT_VERSION_TVOS DEPLOYMENT_VERSION_WATCHOS + MACCATALYST_BUILD_FLAVOR + ) cmake_parse_arguments(CFLAGS "" "${oneValueArgs}" "" ${ARGN}) + get_maccatalyst_build_flavor(maccatalyst_build_flavor + "${CFLAGS_SDK}" "${CFLAGS_MACCATALYST_BUILD_FLAVOR}") + set(result ${${CFLAGS_RESULT_VAR_NAME}}) is_darwin_based_sdk("${CFLAGS_SDK}" IS_DARWIN) if(IS_DARWIN) # Check if there's a specific OS deployment version needed for this invocation if("${CFLAGS_SDK}" STREQUAL "OSX") - set(DEPLOYMENT_VERSION ${CFLAGS_DEPLOYMENT_VERSION_OSX}) + if(DEFINED maccatalyst_build_flavor) + set(DEPLOYMENT_VERSION ${CFLAGS_DEPLOYMENT_VERSION_MACCATALYST}) + else() + set(DEPLOYMENT_VERSION ${CFLAGS_DEPLOYMENT_VERSION_OSX}) + endif() elseif("${CFLAGS_SDK}" STREQUAL "IOS" OR "${CFLAGS_SDK}" STREQUAL "IOS_SIMULATOR") set(DEPLOYMENT_VERSION ${CFLAGS_DEPLOYMENT_VERSION_IOS}) elseif("${CFLAGS_SDK}" STREQUAL "TVOS" OR "${CFLAGS_SDK}" STREQUAL "TVOS_SIMULATOR") @@ -126,7 +137,13 @@ function(_add_variant_c_compile_link_flags) # MSVC, clang-cl, gcc don't understand -target. if(CMAKE_C_COMPILER_ID MATCHES "^Clang|AppleClang$" AND NOT SWIFT_COMPILER_IS_MSVC_LIKE) - list(APPEND result "-target" "${SWIFT_SDK_${CFLAGS_SDK}_ARCH_${CFLAGS_ARCH}_TRIPLE}${DEPLOYMENT_VERSION}") + get_target_triple(target target_variant "${CFLAGS_SDK}" "${CFLAGS_ARCH}" + MACCATALYST_BUILD_FLAVOR "${maccatalyst_build_flavor}" + DEPLOYMENT_VERSION "${DEPLOYMENT_VERSION}") + list(APPEND result "-target" "${target}") + if(target_variant) + list(APPEND result "-target-variant" "${target_variant}") + endif() endif() set(_sysroot "${SWIFT_SDK_${CFLAGS_SDK}_ARCH_${CFLAGS_ARCH}_PATH}") @@ -148,8 +165,21 @@ function(_add_variant_c_compile_link_flags) if(IS_DARWIN) list(APPEND result "-arch" "${CFLAGS_ARCH}" - "-F" "${SWIFT_SDK_${CFLAGS_SDK}_PATH}/../../../Developer/Library/Frameworks" - "-m${SWIFT_SDK_${CFLAGS_SDK}_VERSION_MIN_NAME}-version-min=${DEPLOYMENT_VERSION}") + "-F" "${SWIFT_SDK_${CFLAGS_SDK}_PATH}/../../../Developer/Library/Frameworks") + + set(add_explicit_version TRUE) + + # iOS-like and zippered libraries get their deployment version from the + # target triple + if(maccatalyst_build_flavor STREQUAL "ios-like" OR + maccatalyst_build_flavor STREQUAL "zippered") + set(add_explicit_version FALSE) + endif() + + if(add_explicit_version) + list(APPEND result + "-m${SWIFT_SDK_${CFLAGS_SDK}_VERSION_MIN_NAME}-version-min=${DEPLOYMENT_VERSION}") + endif() endif() if(CFLAGS_ANALYZE_CODE_COVERAGE) @@ -165,10 +195,12 @@ function(_add_variant_c_compile_link_flags) set("${CFLAGS_RESULT_VAR_NAME}" "${result}" PARENT_SCOPE) endfunction() + function(_add_variant_c_compile_flags) set(oneValueArgs SDK ARCH BUILD_TYPE ENABLE_ASSERTIONS ANALYZE_CODE_COVERAGE - DEPLOYMENT_VERSION_OSX DEPLOYMENT_VERSION_IOS DEPLOYMENT_VERSION_TVOS DEPLOYMENT_VERSION_WATCHOS - RESULT_VAR_NAME ENABLE_LTO) + DEPLOYMENT_VERSION_OSX DEPLOYMENT_VERSION_MACCATALYST DEPLOYMENT_VERSION_IOS DEPLOYMENT_VERSION_TVOS DEPLOYMENT_VERSION_WATCHOS + RESULT_VAR_NAME ENABLE_LTO + MACCATALYST_BUILD_FLAVOR) cmake_parse_arguments(CFLAGS "FORCE_BUILD_OPTIMIZED" "${oneValueArgs}" @@ -185,10 +217,12 @@ function(_add_variant_c_compile_flags) ENABLE_LTO "${CFLAGS_ENABLE_LTO}" ANALYZE_CODE_COVERAGE FALSE DEPLOYMENT_VERSION_OSX "${CFLAGS_DEPLOYMENT_VERSION_OSX}" + DEPLOYMENT_VERSION_MACCATALYST "${CFLAGS_DEPLOYMENT_VERSION_MACCATALYST}" DEPLOYMENT_VERSION_IOS "${CFLAGS_DEPLOYMENT_VERSION_IOS}" DEPLOYMENT_VERSION_TVOS "${CFLAGS_DEPLOYMENT_VERSION_TVOS}" DEPLOYMENT_VERSION_WATCHOS "${CFLAGS_DEPLOYMENT_VERSION_WATCHOS}" - RESULT_VAR_NAME result) + RESULT_VAR_NAME result + MACCATALYST_BUILD_FLAVOR "${CFLAGS_MACCATALYST_BUILD_FLAVOR}") is_build_type_optimized("${CFLAGS_BUILD_TYPE}" optimized) if(optimized OR CFLAGS_FORCE_BUILD_OPTIMIZED) @@ -370,6 +404,13 @@ function(_add_variant_swift_compile_flags sdk arch build_type enable_assertions result_var_name) set(result ${${result_var_name}}) + cmake_parse_arguments( + VARIANT # prefix + "" # options + "MACCATALYST_BUILD_FLAVOR" # single-value args + "" # multi-value args + ${ARGN}) + # On Windows, we don't set SWIFT_SDK_WINDOWS_PATH_ARCH_{ARCH}_PATH, so don't include it. # On Android the sdk is split to two different paths for includes and libs, so these # need to be set manually. @@ -379,8 +420,15 @@ function(_add_variant_swift_compile_flags is_darwin_based_sdk("${sdk}" IS_DARWIN) if(IS_DARWIN) - list(APPEND result - "-target" "${SWIFT_SDK_${sdk}_ARCH_${arch}_TRIPLE}${SWIFT_SDK_${sdk}_DEPLOYMENT_VERSION}") + set(sdk_deployment_version "${SWIFT_SDK_${sdk}_DEPLOYMENT_VERSION}") + get_target_triple(target target_variant "${sdk}" "${arch}" + MACCATALYST_BUILD_FLAVOR "${VARIANT_MACCATALYST_BUILD_FLAVOR}" + DEPLOYMENT_VERSION "${sdk_deployment_version}") + + list(APPEND result "-target" "${target}") + if(target_variant) + list(APPEND result "-target-variant" "${target_variant}") + endif() else() list(APPEND result "-target" "${SWIFT_SDK_${sdk}_ARCH_${arch}_TRIPLE}") @@ -431,8 +479,10 @@ endfunction() function(_add_variant_link_flags) set(oneValueArgs SDK ARCH BUILD_TYPE ENABLE_ASSERTIONS ANALYZE_CODE_COVERAGE - DEPLOYMENT_VERSION_OSX DEPLOYMENT_VERSION_IOS DEPLOYMENT_VERSION_TVOS DEPLOYMENT_VERSION_WATCHOS - RESULT_VAR_NAME ENABLE_LTO LTO_OBJECT_NAME LINK_LIBRARIES_VAR_NAME LIBRARY_SEARCH_DIRECTORIES_VAR_NAME) + DEPLOYMENT_VERSION_OSX DEPLOYMENT_VERSION_MACCATALYST DEPLOYMENT_VERSION_IOS DEPLOYMENT_VERSION_TVOS DEPLOYMENT_VERSION_WATCHOS + RESULT_VAR_NAME ENABLE_LTO LTO_OBJECT_NAME LINK_LIBRARIES_VAR_NAME LIBRARY_SEARCH_DIRECTORIES_VAR_NAME + MACCATALYST_BUILD_FLAVOR + ) cmake_parse_arguments(LFLAGS "" "${oneValueArgs}" @@ -454,11 +504,12 @@ function(_add_variant_link_flags) ENABLE_LTO "${LFLAGS_ENABLE_LTO}" ANALYZE_CODE_COVERAGE "${LFLAGS_ANALYZE_CODE_COVERAGE}" DEPLOYMENT_VERSION_OSX "${LFLAGS_DEPLOYMENT_VERSION_OSX}" + DEPLOYMENT_VERSION_MACCATALYST "${LFLAGS_DEPLOYMENT_VERSION_MACCATALYST}" DEPLOYMENT_VERSION_IOS "${LFLAGS_DEPLOYMENT_VERSION_IOS}" DEPLOYMENT_VERSION_TVOS "${LFLAGS_DEPLOYMENT_VERSION_TVOS}" DEPLOYMENT_VERSION_WATCHOS "${LFLAGS_DEPLOYMENT_VERSION_WATCHOS}" - RESULT_VAR_NAME result) - + RESULT_VAR_NAME result + MACCATALYST_BUILD_FLAVOR "${LFLAGS_MACCATALYST_BUILD_FLAVOR}") if("${LFLAGS_SDK}" STREQUAL "LINUX") list(APPEND link_libraries "pthread" "atomic" "dl") elseif("${LFLAGS_SDK}" STREQUAL "FREEBSD") @@ -557,6 +608,9 @@ function(_add_variant_link_flags) endif() endif() + get_maccatalyst_build_flavor(maccatalyst_build_flavor + "${LFLAGS_SDK}" "${LFLAGS_MACCATALYST_BUILD_FLAVOR}") + set("${LFLAGS_RESULT_VAR_NAME}" "${result}" PARENT_SCOPE) set("${LFLAGS_LINK_LIBRARIES_VAR_NAME}" "${link_libraries}" PARENT_SCOPE) set("${LFLAGS_LIBRARY_SEARCH_DIRECTORIES_VAR_NAME}" "${library_search_directories}" PARENT_SCOPE) @@ -662,7 +716,7 @@ endfunction() # _add_swift_library_single( # target # name -# [MODULE_TARGET] +# [MODULE_TARGETS] # [SHARED] # [STATIC] # [SDK sdk] @@ -682,6 +736,7 @@ endfunction() # [IS_STDLIB_CORE] # [IS_SDK_OVERLAY] # INSTALL_IN_COMPONENT comp +# MACCATALYST_BUILD_FLAVOR flavor # source1 [source2 source3 ...]) # # target @@ -690,8 +745,8 @@ endfunction() # name # Name of the library (e.g., swiftParse). # -# MODULE_TARGET -# Name of the module target (e.g., swiftParse-swiftmodule-IOS-armv7). +# MODULE_TARGETS +# Names of the module target (e.g., swiftParse-swiftmodule-IOS-armv7). # # SHARED # Build a shared library. @@ -747,6 +802,9 @@ endfunction() # INSTALL_IN_COMPONENT comp # The Swift installation component that this library belongs to. # +# MACCATALYST_BUILD_FLAVOR +# Possible values are 'ios-like', 'macos-like', 'zippered', 'unzippered-twin' +# # source1 ... # Sources to add into this library function(_add_swift_library_single target name) @@ -770,8 +828,9 @@ function(_add_swift_library_single target name) DEPLOYMENT_VERSION_WATCHOS INSTALL_IN_COMPONENT DARWIN_INSTALL_NAME_DIR - MODULE_TARGET - SDK) + SDK + DEPLOYMENT_VERSION_MACCATALYST + MACCATALYST_BUILD_FLAVOR) set(SWIFTLIB_SINGLE_multiple_parameter_options C_COMPILE_FLAGS DEPENDS @@ -785,13 +844,19 @@ function(_add_swift_library_single target name) LINK_LIBRARIES LLVM_LINK_COMPONENTS PRIVATE_LINK_LIBRARIES - SWIFT_COMPILE_FLAGS) + SWIFT_COMPILE_FLAGS + MODULE_TARGETS) cmake_parse_arguments(SWIFTLIB_SINGLE "${SWIFTLIB_SINGLE_options}" "${SWIFTLIB_SINGLE_single_parameter_options}" "${SWIFTLIB_SINGLE_multiple_parameter_options}" ${ARGN}) + + # Determine macCatalyst build flavor + get_maccatalyst_build_flavor(maccatalyst_build_flavor + "${SWIFTLIB_SINGLE_SDK}" "${SWIFTLIB_SINGLE_MACCATALYST_BUILD_FLAVOR}") + set(SWIFTLIB_SINGLE_SOURCES ${SWIFTLIB_SINGLE_UNPARSED_ARGUMENTS}) translate_flags(SWIFTLIB_SINGLE "${SWIFTLIB_SINGLE_options}") @@ -812,6 +877,12 @@ function(_add_swift_library_single target name) set(SWIFTLIB_SINGLE_SUBDIR "${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_LIB_SUBDIR}/${SWIFTLIB_SINGLE_ARCHITECTURE}") + # macCatalyst ios-like builds are installed in the maccatalyst/x86_64 directory + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(SWIFTLIB_SINGLE_SUBDIR + "${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}/${SWIFTLIB_SINGLE_ARCHITECTURE}") + endif() + # Include LLVM Bitcode slices for iOS, Watch OS, and Apple TV OS device libraries. set(embed_bitcode_arg) if(SWIFT_EMBED_BITCODE_SECTION AND NOT SWIFTLIB_SINGLE_DONT_EMBED_BITCODE) @@ -925,17 +996,24 @@ function(_add_swift_library_single target name) ${SWIFTLIB_SINGLE_IS_STDLIB_CORE_keyword} ${SWIFTLIB_SINGLE_IS_SDK_OVERLAY_keyword} ${embed_bitcode_arg} - INSTALL_IN_COMPONENT "${SWIFTLIB_SINGLE_INSTALL_IN_COMPONENT}") + INSTALL_IN_COMPONENT "${SWIFTLIB_SINGLE_INSTALL_IN_COMPONENT}" + MACCATALYST_BUILD_FLAVOR "${SWIFTLIB_SINGLE_MACCATALYST_BUILD_FLAVOR}") add_swift_source_group("${SWIFTLIB_SINGLE_EXTERNAL_SOURCES}") # If there were any swift sources, then a .swiftmodule may have been created. # If that is the case, then add a target which is an alias of the module files. set(VARIANT_SUFFIX "-${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_LIB_SUBDIR}-${SWIFTLIB_SINGLE_ARCHITECTURE}") - if(NOT "${SWIFTLIB_SINGLE_MODULE_TARGET}" STREQUAL "" AND NOT "${swift_module_dependency_target}" STREQUAL "") - add_custom_target("${SWIFTLIB_SINGLE_MODULE_TARGET}" - DEPENDS ${swift_module_dependency_target}) - set_target_properties("${SWIFTLIB_SINGLE_MODULE_TARGET}" PROPERTIES - FOLDER "Swift libraries/Modules") + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(VARIANT_SUFFIX "-${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}-${SWIFTLIB_SINGLE_ARCHITECTURE}") + endif() + + if(NOT "${SWIFTLIB_SINGLE_MODULE_TARGETS}" STREQUAL "" AND NOT "${swift_module_dependency_target}" STREQUAL "") + foreach(module_target ${SWIFTLIB_SINGLE_MODULE_TARGETS}) + add_custom_target("${module_target}" + DEPENDS ${swift_module_dependency_target}) + set_target_properties("${module_target}" PROPERTIES + FOLDER "Swift libraries/Modules") + endforeach() endif() # For standalone overlay builds to work @@ -1082,6 +1160,13 @@ function(_add_swift_library_single target name) if(SWIFTLIB_SINGLE_IS_STDLIB) set(install_name_dir "${SWIFT_DARWIN_STDLIB_INSTALL_NAME_DIR}") + + # iOS-like overlays are installed in a separate directory so that + # unzippered twins do not conflict. + if(maccatalyst_build_flavor STREQUAL "ios-like" + AND DEFINED SWIFT_DARWIN_MACCATALYST_STDLIB_INSTALL_NAME_DIR) + set(install_name_dir "${SWIFT_DARWIN_MACCATALYST_STDLIB_INSTALL_NAME_DIR}") + endif() endif() # Always use @rpath for XCTest @@ -1295,11 +1380,13 @@ function(_add_swift_library_single target name) ANALYZE_CODE_COVERAGE "${analyze_code_coverage}" ENABLE_LTO "${lto_type}" DEPLOYMENT_VERSION_OSX "${SWIFTLIB_DEPLOYMENT_VERSION_OSX}" + DEPLOYMENT_VERSION_MACCATALYST "${SWIFTLIB_DEPLOYMENT_VERSION_MACCATALYST}" DEPLOYMENT_VERSION_IOS "${SWIFTLIB_DEPLOYMENT_VERSION_IOS}" DEPLOYMENT_VERSION_TVOS "${SWIFTLIB_DEPLOYMENT_VERSION_TVOS}" DEPLOYMENT_VERSION_WATCHOS "${SWIFTLIB_DEPLOYMENT_VERSION_WATCHOS}" "${SWIFTLIB_SINGLE_FORCE_BUILD_OPTIMIZED_keyword}" RESULT_VAR_NAME c_compile_flags + MACCATALYST_BUILD_FLAVOR "${SWIFTLIB_SINGLE_MACCATALYST_BUILD_FLAVOR}" ) if(SWIFTLIB_IS_STDLIB) @@ -1324,12 +1411,14 @@ function(_add_swift_library_single target name) ENABLE_LTO "${lto_type}" LTO_OBJECT_NAME "${target}-${SWIFTLIB_SINGLE_SDK}-${SWIFTLIB_SINGLE_ARCHITECTURE}" DEPLOYMENT_VERSION_OSX "${SWIFTLIB_DEPLOYMENT_VERSION_OSX}" + DEPLOYMENT_VERSION_MACCATALYST "${SWIFTLIB_DEPLOYMENT_VERSION_MACCATALYST}" DEPLOYMENT_VERSION_IOS "${SWIFTLIB_DEPLOYMENT_VERSION_IOS}" DEPLOYMENT_VERSION_TVOS "${SWIFTLIB_DEPLOYMENT_VERSION_TVOS}" DEPLOYMENT_VERSION_WATCHOS "${SWIFTLIB_DEPLOYMENT_VERSION_WATCHOS}" RESULT_VAR_NAME link_flags LINK_LIBRARIES_VAR_NAME link_libraries LIBRARY_SEARCH_DIRECTORIES_VAR_NAME library_search_directories + MACCATALYST_BUILD_FLAVOR "${SWIFTLIB_SINGLE_MACCATALYST_BUILD_FLAVOR}" ) # Configure plist creation for OS X. @@ -1565,9 +1654,11 @@ endfunction() # [INSTALL_WITH_SHARED] # INSTALL_IN_COMPONENT comp # DEPLOYMENT_VERSION_OSX version +# DEPLOYMENT_VERSION_MACCATALYST version # DEPLOYMENT_VERSION_IOS version # DEPLOYMENT_VERSION_TVOS version # DEPLOYMENT_VERSION_WATCHOS version +# MACCATALYST_BUILD_FLAVOR flavor # source1 [source2 source3 ...]) # # name @@ -1591,6 +1682,14 @@ endfunction() # SWIFT_MODULE_DEPENDS_OSX # Swift modules this library depends on when built for OS X. # +# SWIFT_MODULE_DEPENDS_MACCATALYST +# Zippered Swift modules this library depends on when built for macCatalyst. +# For example, Foundation. +# +# SWIFT_MODULE_DEPENDS_MACCATALYST_UNZIPPERED +# Unzippered Swift modules this library depends on when built for macCatalyst. +# For example, UIKit +# # SWIFT_MODULE_DEPENDS_IOS # Swift modules this library depends on when built for iOS. # @@ -1648,7 +1747,6 @@ endfunction() # # IS_SDK_OVERLAY # Treat the library as a part of the Swift SDK overlay. -# IS_SDK_OVERLAY implies IS_STDLIB. # # INSTALL_IN_COMPONENT comp # The Swift installation component that this library belongs to. @@ -1656,6 +1754,9 @@ endfunction() # DEPLOYMENT_VERSION_OSX # The minimum deployment version to build for if this is an OSX library. # +# DEPLOYMENT_VERSION_MACCATALYST +# The minimum deployment version to build for if this is an macCatalyst library. +# # DEPLOYMENT_VERSION_IOS # The minimum deployment version to build for if this is an iOS library. # @@ -1668,6 +1769,11 @@ endfunction() # INSTALL_WITH_SHARED # Install a static library target alongside shared libraries # +# MACCATALYST_BUILD_FLAVOR +# Possible values are 'ios-like', 'macos-like', 'zippered', 'unzippered-twin' +# Presence of a build flavor requires SWIFT_MODULE_DEPENDS_MACCATALYST to be +# defined and have values. +# # source1 ... # Sources to add into this library. function(add_swift_target_library name) @@ -1689,7 +1795,9 @@ function(add_swift_target_library name) DEPLOYMENT_VERSION_TVOS DEPLOYMENT_VERSION_WATCHOS INSTALL_IN_COMPONENT - DARWIN_INSTALL_NAME_DIR) + DARWIN_INSTALL_NAME_DIR + DEPLOYMENT_VERSION_MACCATALYST + MACCATALYST_BUILD_FLAVOR) set(SWIFTLIB_multiple_parameter_options C_COMPILE_FLAGS DEPENDS @@ -1722,7 +1830,10 @@ function(add_swift_target_library name) SWIFT_MODULE_DEPENDS_WATCHOS SWIFT_MODULE_DEPENDS_WINDOWS SWIFT_MODULE_DEPENDS_FROM_SDK - TARGET_SDKS) + TARGET_SDKS + SWIFT_COMPILE_FLAGS_MACCATALYST + SWIFT_MODULE_DEPENDS_MACCATALYST + SWIFT_MODULE_DEPENDS_MACCATALYST_UNZIPPERED) cmake_parse_arguments(SWIFTLIB "${SWIFTLIB_options}" @@ -1731,6 +1842,15 @@ function(add_swift_target_library name) ${ARGN}) set(SWIFTLIB_SOURCES ${SWIFTLIB_UNPARSED_ARGUMENTS}) + # Ensure it's impossible to build for macCatalyst without module dependencies + if(SWIFT_ENABLE_MACCATALYST AND SWIFTLIB_MACCATALYST_BUILD_FLAVOR) + if((NOT SWIFTLIB_MACCATALYST_BUILD_FLAVOR STREQUAL "zippered") OR + SWIFTLIB_SWIFT_MODULE_DEPENDS_OSX) + precondition(SWIFTLIB_SWIFT_MODULE_DEPENDS_MACCATALYST + MESSAGE "SWIFT_MODULE_DEPENDS_MACCATALYST is required when building for macCatalyst") + endif() + endif() + # Infer arguments. if(SWIFTLIB_IS_SDK_OVERLAY) @@ -1802,11 +1922,50 @@ function(add_swift_target_library name) continue() endif() + # Skip building library for macOS if macCatalyst support is not enabled and the + # library only builds for macOS when macCatalyst is enabled. + if(NOT SWIFT_ENABLE_MACCATALYST AND + sdk STREQUAL "OSX" AND + SWIFTLIB_MACCATALYST_BUILD_FLAVOR STREQUAL "ios-like") + message(STATUS "Skipping OSX SDK for module ${name}") + continue() + endif() + + # Determine if/what macCatalyst build flavor we are + get_maccatalyst_build_flavor(maccatalyst_build_flavor + "${sdk}" "${SWIFTLIB_MACCATALYST_BUILD_FLAVOR}") + + set(maccatalyst_build_flavors) + if(NOT DEFINED maccatalyst_build_flavor) + list(APPEND maccatalyst_build_flavors "none") + elseif(maccatalyst_build_flavor STREQUAL "unzippered-twin") + list(APPEND maccatalyst_build_flavors "macos-like" "ios-like") + else() + list(APPEND maccatalyst_build_flavors "${maccatalyst_build_flavor}") + endif() + + # Loop over the build flavors for the this library. If it is an unzippered + # twin we'll build it twice: once for "macos-like" and once for "ios-like" + # flavors. + foreach(maccatalyst_build_flavor ${maccatalyst_build_flavors}) + if(maccatalyst_build_flavor STREQUAL "none") + unset(maccatalyst_build_flavor) + endif() + set(THIN_INPUT_TARGETS) # Collect architecture agnostic SDK module dependencies set(swiftlib_module_depends_flattened ${SWIFTLIB_SWIFT_MODULE_DEPENDS}) if(${sdk} STREQUAL OSX) + if(DEFINED maccatalyst_build_flavor AND NOT maccatalyst_build_flavor STREQUAL "macos-like") + list(APPEND swiftlib_module_depends_flattened + ${SWIFTLIB_SWIFT_MODULE_DEPENDS_MACCATALYST}) + list(APPEND swiftlib_module_depends_flattened + ${SWIFTLIB_SWIFT_MODULE_DEPENDS_MACCATALYST_UNZIPPERED}) + else() + list(APPEND swiftlib_module_depends_flattened + ${SWIFTLIB_SWIFT_MODULE_DEPENDS_OSX}) + endif() list(APPEND swiftlib_module_depends_flattened ${SWIFTLIB_SWIFT_MODULE_DEPENDS_OSX}) elseif(${sdk} STREQUAL IOS OR ${sdk} STREQUAL IOS_SIMULATOR) @@ -1923,6 +2082,15 @@ function(add_swift_target_library name) set(MODULE_VARIANT_SUFFIX "-swiftmodule${VARIANT_SUFFIX}") set(MODULE_VARIANT_NAME "${name}${MODULE_VARIANT_SUFFIX}") + # Configure macCatalyst flavor variables + if(DEFINED maccatalyst_build_flavor) + set(maccatalyst_variant_suffix "-${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}-${arch}") + set(maccatalyst_variant_name "${name}${maccatalyst_variant_suffix}") + + set(maccatalyst_module_variant_suffix "-swiftmodule${maccatalyst_variant_suffix}") + set(maccatalyst_module_variant_name "${name}${maccatalyst_module_variant_suffix}") + endif() + # Map dependencies over to the appropriate variants. set(swiftlib_link_libraries) foreach(lib ${SWIFTLIB_LINK_LIBRARIES}) @@ -1940,6 +2108,44 @@ function(add_swift_target_library name) if(NOT BUILD_STANDALONE) foreach(mod ${swiftlib_module_depends_flattened}) + if(DEFINED maccatalyst_build_flavor) + if(maccatalyst_build_flavor STREQUAL "zippered") + # Zippered libraries are dependent on both the macCatalyst and normal macOS + # modules of their dependencies (which themselves must be zippered). + list(APPEND swiftlib_module_dependency_targets + "swift${mod}${maccatalyst_module_variant_suffix}") + list(APPEND swiftlib_module_dependency_targets + "swift${mod}${MODULE_VARIANT_SUFFIX}") + + # Zippered libraries link against their zippered library targets, which + # live (and are built in) the same location as normal macOS libraries. + list(APPEND swiftlib_private_link_libraries_targets + "swift${mod}${VARIANT_SUFFIX}") + elseif(maccatalyst_build_flavor STREQUAL "ios-like") + # iOS-like libraries depend on the macCatalyst modules of their dependencies + # regardless of whether the target is zippered or macCatalyst only. + list(APPEND swiftlib_module_dependency_targets + "swift${mod}${maccatalyst_module_variant_suffix}") + + # iOS-like libraries can link against either iOS-like library targets + # or zippered targets. + if(mod IN_LIST SWIFTLIB_SWIFT_MODULE_DEPENDS_MACCATALYST_UNZIPPERED) + list(APPEND swiftlib_private_link_libraries_targets + "swift${mod}${maccatalyst_variant_suffix}") + else() + list(APPEND swiftlib_private_link_libraries_targets + "swift${mod}${VARIANT_SUFFIX}") + endif() + else() + list(APPEND swiftlib_module_dependency_targets + "swift${mod}${MODULE_VARIANT_SUFFIX}") + + list(APPEND swiftlib_private_link_libraries_targets + "swift${mod}${VARIANT_SUFFIX}") + endif() + continue() + endif() + list(APPEND swiftlib_module_dependency_targets "swift${mod}${MODULE_VARIANT_SUFFIX}") @@ -1959,6 +2165,25 @@ function(add_swift_target_library name) # Add PrivateFrameworks, rdar://28466433 set(swiftlib_c_compile_flags_all ${SWIFTLIB_C_COMPILE_FLAGS}) + set(swiftlib_link_flags_all ${SWIFTLIB_LINK_FLAGS}) + + # Add flags to prepend framework search paths for the parallel framework + # hierarchy rooted at /System/iOSSupport/... + # These paths must come before their normal counterparts so that when compiling + # macCatalyst-only or unzippered-twin overlays the macCatalyst version + # of a framework is found and not the Mac version. + if(maccatalyst_build_flavor STREQUAL "ios-like" + OR (name STREQUAL "swiftXCTest" + AND maccatalyst_build_flavor STREQUAL "zippered")) + + # The path to find iOS-only frameworks (such as UIKit) under macCatalyst. + set(ios_support_frameworks_path "${SWIFT_SDK_${sdk}_PATH}/System/iOSSupport/System/Library/Frameworks/") + + list(APPEND swiftlib_swift_compile_flags_all "-Fsystem" "${ios_support_frameworks_path}") + list(APPEND swiftlib_c_compile_flags_all "-iframework" "${ios_support_frameworks_path}") + list(APPEND swiftlib_link_flags_all "-F" "${ios_support_frameworks_path}") + endif() + if(sdk IN_LIST SWIFT_APPLE_PLATFORMS AND SWIFTLIB_IS_SDK_OVERLAY) set(swiftlib_swift_compile_private_frameworks_flag "-Fsystem" "${SWIFT_SDK_${sdk}_ARCH_${arch}_PATH}/System/Library/PrivateFrameworks/") foreach(tbd_lib ${SWIFTLIB_SWIFT_MODULE_DEPENDS_FROM_SDK}) @@ -1966,11 +2191,22 @@ function(add_swift_target_library name) endforeach() endif() - list(APPEND swiftlib_c_compile_flags_all "-DSWIFT_TARGET_LIBRARY_NAME=${name}") + set(variant_name "${VARIANT_NAME}") + set(module_variant_names "${MODULE_VARIANT_NAME}") + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(variant_name "${maccatalyst_variant_name}") + set(module_variant_names "${maccatalyst_module_variant_name}") + elseif(maccatalyst_build_flavor STREQUAL "zippered") + # Zippered libraries produce two modules: one for macCatalyst and one for macOS + # and so need two module targets. + list(APPEND module_variant_names "${maccatalyst_module_variant_name}") + endif() + + list(APPEND swiftlib_c_compile_flags_all "-DSWIFT_TARGET_LIBRARY_NAME=${name}") # Add this library variant. _add_swift_library_single( - ${VARIANT_NAME} + ${variant_name} ${name} ${SWIFTLIB_SHARED_keyword} ${SWIFTLIB_STATIC_keyword} @@ -1978,7 +2214,7 @@ function(add_swift_target_library name) ${SWIFTLIB_INSTALL_WITH_SHARED_keyword} ${SWIFTLIB_SOURCES} TARGET_LIBRARY - MODULE_TARGET ${MODULE_VARIANT_NAME} + MODULE_TARGETS ${module_variant_names} SDK ${sdk} ARCHITECTURE ${arch} DEPENDS ${SWIFTLIB_DEPENDS} @@ -2002,9 +2238,12 @@ function(add_swift_target_library name) DARWIN_INSTALL_NAME_DIR "${SWIFTLIB_DARWIN_INSTALL_NAME_DIR}" INSTALL_IN_COMPONENT "${SWIFTLIB_INSTALL_IN_COMPONENT}" DEPLOYMENT_VERSION_OSX "${SWIFTLIB_DEPLOYMENT_VERSION_OSX}" + DEPLOYMENT_VERSION_MACCATALYST "${SWIFTLIB_DEPLOYMENT_VERSION_MACCATALYST}" DEPLOYMENT_VERSION_IOS "${SWIFTLIB_DEPLOYMENT_VERSION_IOS}" DEPLOYMENT_VERSION_TVOS "${SWIFTLIB_DEPLOYMENT_VERSION_TVOS}" DEPLOYMENT_VERSION_WATCHOS "${SWIFTLIB_DEPLOYMENT_VERSION_WATCHOS}" + MACCATALYST_BUILD_FLAVOR "${maccatalyst_build_flavor}" + GYB_SOURCES ${SWIFTLIB_GYB_SOURCES} ) if(NOT SWIFT_BUILT_STANDALONE AND NOT "${CMAKE_C_COMPILER_ID}" MATCHES "Clang") @@ -2076,27 +2315,32 @@ function(add_swift_target_library name) return() endif() + set(library_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}") + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(library_subdir "${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}") + endif() + if(NOT SWIFTLIB_OBJECT_LIBRARY) # Determine the name of the universal library. if(SWIFTLIB_SHARED) if("${sdk}" STREQUAL "WINDOWS") set(UNIVERSAL_LIBRARY_NAME - "${SWIFTLIB_DIR}/${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${name}.dll") + "${SWIFTLIB_DIR}/${library_subdir}/${name}.dll") else() set(UNIVERSAL_LIBRARY_NAME - "${SWIFTLIB_DIR}/${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}${name}${CMAKE_SHARED_LIBRARY_SUFFIX}") + "${SWIFTLIB_DIR}/${library_subdir}/${CMAKE_SHARED_LIBRARY_PREFIX}${name}${CMAKE_SHARED_LIBRARY_SUFFIX}") endif() else() if("${sdk}" STREQUAL "WINDOWS") set(UNIVERSAL_LIBRARY_NAME - "${SWIFTLIB_DIR}/${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${name}.lib") + "${SWIFTLIB_DIR}/${library_subdir}/${name}.lib") else() set(UNIVERSAL_LIBRARY_NAME - "${SWIFTLIB_DIR}/${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") + "${SWIFTLIB_DIR}/${library_subdir}/${CMAKE_STATIC_LIBRARY_PREFIX}${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") endif() endif() - set(lipo_target "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}") + set(lipo_target "${name}-${library_subdir}") if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin" AND SWIFTLIB_SHARED) set(codesign_arg CODESIGN) endif() @@ -2111,13 +2355,17 @@ function(add_swift_target_library name) ${THIN_INPUT_TARGETS}) # Cache universal libraries for dependency purposes - set(UNIVERSAL_LIBRARY_NAMES_${SWIFT_SDK_${sdk}_LIB_SUBDIR} - ${UNIVERSAL_LIBRARY_NAMES_${SWIFT_SDK_${sdk}_LIB_SUBDIR}} + set(UNIVERSAL_LIBRARY_NAMES_${library_subdir} + ${UNIVERSAL_LIBRARY_NAMES_${library_subdir}} ${lipo_target} - CACHE INTERNAL "UNIVERSAL_LIBRARY_NAMES_${SWIFT_SDK_${sdk}_LIB_SUBDIR}") + CACHE INTERNAL "UNIVERSAL_LIBRARY_NAMES_${library_subdir}") # Determine the subdirectory where this library will be installed. set(resource_dir_sdk_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}") + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(resource_dir_sdk_subdir "${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}") + endif() + precondition(resource_dir_sdk_subdir) if(SWIFTLIB_SHARED OR SWIFTLIB_INSTALL_WITH_SHARED) @@ -2183,6 +2431,10 @@ function(add_swift_target_library name) # Add the arch-specific library targets to the global exports. foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES}) set(_variant_name "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(_variant_name "${name}-${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}-${arch}") + endif() + if(NOT TARGET "${_variant_name}") continue() endif() @@ -2199,6 +2451,10 @@ function(add_swift_target_library name) # Add the swiftmodule-only targets to the lipo target depdencies. foreach(arch ${SWIFT_SDK_${sdk}_MODULE_ARCHITECTURES}) set(_variant_name "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(_variant_name "${name}-${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}-${arch}") + endif() + if(NOT TARGET "${_variant_name}") continue() endif() @@ -2224,9 +2480,9 @@ function(add_swift_target_library name) endif() set(lipo_target_static - "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-static") + "${name}-${library_subdir}-static") set(UNIVERSAL_LIBRARY_NAME - "${universal_subdir}/${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") + "${universal_subdir}/${library_subdir}/${CMAKE_STATIC_LIBRARY_PREFIX}${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") _add_swift_lipo_target(SDK ${sdk} TARGET @@ -2266,6 +2522,7 @@ function(add_swift_target_library name) endif() endforeach() endif() + endforeach() # maccatalyst_build_flavors endforeach() endfunction() diff --git a/cmake/modules/StandaloneOverlay.cmake b/cmake/modules/StandaloneOverlay.cmake index 5a886c931e94e..ed089097b8d19 100644 --- a/cmake/modules/StandaloneOverlay.cmake +++ b/cmake/modules/StandaloneOverlay.cmake @@ -93,6 +93,12 @@ set(SWIFT_BUILD_STANDALONE_OVERLAY TRUE) set(SWIFT_STDLIB_LIBRARY_BUILD_TYPES "SHARED") set(SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES "SHARED") +option(SWIFT_ENABLE_MACCATALYST + "Build the overlays with macCatalyst support" + FALSE) + +set(SWIFT_DARWIN_DEPLOYMENT_VERSION_MACCATALYST "13.0" CACHE STRING + "Minimum deployment target version for macCatalyst") # ----------------------------------------------------------------------------- diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake index 3a87bfcd80bb2..52a3a4f3aeb0c 100644 --- a/cmake/modules/SwiftConfigureSDK.cmake +++ b/cmake/modules/SwiftConfigureSDK.cmake @@ -133,7 +133,7 @@ macro(configure_sdk_darwin endif() if(NOT EXISTS "${SWIFT_SDK_${prefix}_PATH}/System/Library/Frameworks/module.map") - message(FATAL_ERROR "${name} SDK not found at ${SWIFT_SDK_${prefix}_PATH}.") + message(FATAL_ERROR "${name} SDK not found at SWIFT_SDK_${prefix}_PATH.") endif() # Determine the SDK version we found. @@ -183,6 +183,20 @@ macro(configure_sdk_darwin set(SWIFT_SDK_${prefix}_ARCH_${arch}_TRIPLE "${arch}-apple-${SWIFT_SDK_${prefix}_TRIPLE_NAME}") + + if(SWIFT_ENABLE_MACCATALYST AND "${prefix}" STREQUAL "OSX") + # For macCatalyst append the '-macabi' environment to the target triple. + set(SWIFT_SDK_MACCATALYST_ARCH_${arch}_TRIPLE + "${SWIFT_SDK_${prefix}_ARCH_${arch}_TRIPLE}-macabi") + + # macCatalyst triple + set(SWIFT_MACCATALYST_TRIPLE + "x86_64-apple-ios${SWIFT_DARWIN_DEPLOYMENT_VERSION_MACCATALYST}-macabi") + + # For macCatalyst, the xcrun_name is "macosx" since it uses that sdk. + # Hard code the library subdirectory to "maccatalyst" in that case. + set(SWIFT_SDK_MACCATALYST_LIB_SUBDIR "maccatalyst") + endif() endforeach() # Add this to the list of known SDKs. diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake index 25314d3e627d3..818a03c1e46cc 100644 --- a/cmake/modules/SwiftSource.cmake +++ b/cmake/modules/SwiftSource.cmake @@ -1,3 +1,4 @@ +include(macCatalystUtils) include(SwiftUtils) # Process the sources within the given variable, pulling out any Swift @@ -7,6 +8,9 @@ include(SwiftUtils) # # Usage: # handle_swift_sources(sourcesvar externalvar) +# +# MACCATALYST_BUILD_FLAVOR +# Possible values are 'ios-like', 'macos-like', 'zippered', 'unzippered-twin' function(handle_swift_sources dependency_target_out_var_name dependency_module_target_out_var_name @@ -16,7 +20,7 @@ function(handle_swift_sources sourcesvar externalvar name) cmake_parse_arguments(SWIFTSOURCES "IS_MAIN;IS_STDLIB;IS_STDLIB_CORE;IS_SDK_OVERLAY;EMBED_BITCODE" - "SDK;ARCHITECTURE;INSTALL_IN_COMPONENT" + "SDK;ARCHITECTURE;INSTALL_IN_COMPONENT;MACCATALYST_BUILD_FLAVOR" "DEPENDS;COMPILE_FLAGS;MODULE_NAME" ${ARGN}) translate_flag(${SWIFTSOURCES_IS_MAIN} "IS_MAIN" IS_MAIN_arg) @@ -63,6 +67,12 @@ function(handle_swift_sources if(swift_sources) set(objsubdir "/${SWIFTSOURCES_SDK}/${SWIFTSOURCES_ARCHITECTURE}") + get_maccatalyst_build_flavor(maccatalyst_build_flavor + "${SWIFTSOURCES_SDK}" "${SWIFTSOURCES_MACCATALYST_BUILD_FLAVOR}") + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(objsubdir "/MACCATALYST/${SWIFTSOURCES_ARCHITECTURE}") + endif() + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}${objsubdir}") set(swift_obj @@ -91,7 +101,8 @@ function(handle_swift_sources ${IS_SDK_OVERLAY_arg} ${EMBED_BITCODE_arg} ${STATIC_arg} - INSTALL_IN_COMPONENT "${SWIFTSOURCES_INSTALL_IN_COMPONENT}") + INSTALL_IN_COMPONENT "${SWIFTSOURCES_INSTALL_IN_COMPONENT}" + MACCATALYST_BUILD_FLAVOR "${SWIFTSOURCES_MACCATALYST_BUILD_FLAVOR}") set("${dependency_target_out_var_name}" "${dependency_target}" PARENT_SCOPE) set("${dependency_module_target_out_var_name}" "${module_dependency_target}" PARENT_SCOPE) set("${dependency_sib_target_out_var_name}" "${sib_dependency_target}" PARENT_SCOPE) @@ -131,6 +142,7 @@ endfunction() # OUTPUT objfile # Name of the resulting object file # SOURCES swift_src [swift_src...] # Swift source files to compile # FLAGS -module-name foo # Flags to add to the compilation +# MACCATALYST_BUILD_FLAVOR flavor # macCatalyst flavor # [SDK sdk] # SDK to build for # [ARCHITECTURE architecture] # Architecture to build for # [DEPENDS cmake_target...] # CMake targets on which the object @@ -151,7 +163,7 @@ function(_compile_swift_files dependency_sibgen_target_out_var_name) cmake_parse_arguments(SWIFTFILE "IS_MAIN;IS_STDLIB;IS_STDLIB_CORE;IS_SDK_OVERLAY;EMBED_BITCODE" - "OUTPUT;MODULE_NAME;INSTALL_IN_COMPONENT" + "OUTPUT;MODULE_NAME;INSTALL_IN_COMPONENT;MACCATALYST_BUILD_FLAVOR" "SOURCES;FLAGS;DEPENDS;SDK;ARCHITECTURE;OPT_FLAGS;MODULE_DIR" ${ARGN}) @@ -175,6 +187,27 @@ function(_compile_swift_files precondition(SWIFTFILE_ARCHITECTURE MESSAGE "Should specify an architecture") precondition(SWIFTFILE_INSTALL_IN_COMPONENT MESSAGE "INSTALL_IN_COMPONENT is required") + # Determine if/what macCatalyst build variant we are + get_maccatalyst_build_flavor(maccatalyst_build_flavor + "${SWIFTFILE_SDK}" "${SWIFTFILE_MACCATALYST_BUILD_FLAVOR}") + + # Determine target triples + get_target_triple(target_triple ignored_target_variant_triple + "${SWIFTFILE_SDK}" + "${SWIFTFILE_ARCHITECTURE}" + DEPLOYMENT_VERSION "${SWIFT_SDK_${SWIFTFILE_SDK}_DEPLOYMENT_VERSION}") + + get_target_triple(maccatalyst_target_triple ignored_target_variant_triple + "${SWIFTFILE_SDK}" + "${SWIFTFILE_ARCHITECTURE}" + DEPLOYMENT_VERSION "${SWIFT_SDK_${SWIFTFILE_SDK}_DEPLOYMENT_VERSION}" + MACCATALYST_BUILD_FLAVOR "${maccatalyst_build_flavor}") + + # macCatalyst ios-like target triple + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(target_triple "${maccatalyst_target_triple}") + endif() + if ("${SWIFTFILE_MODULE_NAME}" STREQUAL "") get_filename_component(SWIFTFILE_MODULE_NAME "${first_output}" NAME_WE) message(SEND_ERROR @@ -202,17 +235,18 @@ function(_compile_swift_files "${SWIFTFILE_ARCHITECTURE}" "${SWIFT_STDLIB_BUILD_TYPE}" "${SWIFT_STDLIB_ASSERTIONS}" - swift_flags) + swift_flags + MACCATALYST_BUILD_FLAVOR "${maccatalyst_build_flavor}" + ) # Determine the subdirectory where the binary should be placed. compute_library_subdir(library_subdir "${SWIFTFILE_SDK}" "${SWIFTFILE_ARCHITECTURE}") - # Allow import of other Swift modules we just built. - list(APPEND swift_flags - "-I" "${SWIFTLIB_DIR}/${library_subdir}") - # FIXME: should we use '-resource-dir' here? Seems like it has no advantage - # over '-I' in this case. + if(maccatalyst_build_flavor STREQUAL "ios-like") + compute_library_subdir(library_subdir + "MACCATALYST" "${SWIFTFILE_ARCHITECTURE}") + endif() # If we have a custom module cache path, use it. if (SWIFT_MODULE_CACHE_PATH) @@ -308,7 +342,8 @@ function(_compile_swift_files list(APPEND swift_flags "-parse-as-library") set(module_base "${module_dir}/${SWIFTFILE_MODULE_NAME}") - if(SWIFTFILE_SDK IN_LIST SWIFT_APPLE_PLATFORMS) + if(SWIFTFILE_SDK IN_LIST SWIFT_APPLE_PLATFORMS OR + SWIFTFILE_SDK STREQUAL "MACCATALYST") set(specific_module_dir "${module_base}.swiftmodule") set(specific_module_project_dir "${specific_module_dir}/Project") set(source_info_file "${specific_module_project_dir}/${SWIFTFILE_ARCHITECTURE}.swiftsourceinfo") @@ -338,6 +373,57 @@ function(_compile_swift_files "-Xfrontend" "-experimental-skip-non-inlinable-function-bodies") endif() + set(module_outputs "${module_file}" "${module_doc_file}") + + if(interface_file) + list(APPEND module_outputs "${interface_file}") + endif() + + set(optional_arg) + if(SWIFTFILE_SDK IN_LIST SWIFT_APPLE_PLATFORMS OR + SWIFTFILE_SDK STREQUAL "MACCATALYST") + # Allow installation of stdlib without building all variants on Darwin. + set(optional_arg "OPTIONAL") + endif() + + if(SWIFTFILE_SDK IN_LIST SWIFT_APPLE_PLATFORMS OR + SWIFTFILE_SDK STREQUAL "MACCATALYST") + swift_install_in_component(DIRECTORY "${specific_module_dir}" + DESTINATION "lib${LLVM_LIBDIR_SUFFIX}/swift/${library_subdir}" + COMPONENT "${SWIFTFILE_INSTALL_IN_COMPONENT}") + else() + swift_install_in_component(FILES ${module_outputs} + DESTINATION "lib${LLVM_LIBDIR_SUFFIX}/swift/${library_subdir}" + COMPONENT "${SWIFTFILE_INSTALL_IN_COMPONENT}") + endif() + + # macCatalyst zippered module setup + if(maccatalyst_build_flavor STREQUAL "zippered") + compute_library_subdir(maccatalyst_library_subdir + "MACCATALYST" "${SWIFTFILE_ARCHITECTURE}") + + if(SWIFTFILE_MODULE_DIR) + set(maccatalyst_module_dir "${SWIFTFILE_MODULE_DIR}") + elseif(SWIFTFILE_IS_STDLIB) + set(maccatalyst_module_dir "${SWIFTLIB_DIR}/${maccatalyst_library_subdir}") + else() + message(FATAL_ERROR "Don't know where to put the module files") + endif() + + set(maccatalyst_specific_module_dir + "${maccatalyst_module_dir}/${SWIFTFILE_MODULE_NAME}.swiftmodule") + set(maccatalyst_module_base "${maccatalyst_specific_module_dir}/${SWIFTFILE_ARCHITECTURE}") + set(maccatalyst_module_file "${maccatalyst_module_base}.swiftmodule") + set(maccatalyst_module_doc_file "${maccatalyst_module_base}.swiftdoc") + + set(maccatalyst_module_outputs "${maccatalyst_module_file}" "${maccatalyst_module_doc_file}") + + swift_install_in_component(DIRECTORY ${maccatalyst_specific_module_dir} + DESTINATION "lib${LLVM_LIBDIR_SUFFIX}/swift/${maccatalyst_library_subdir}" + COMPONENT "${SWIFTFILE_INSTALL_IN_COMPONENT}" + "${optional_arg}") + endif() + # If we have extra regexp flags, check if we match any of the regexps. If so # add the relevant flags to our swift_flags. if (SWIFT_EXPERIMENTAL_EXTRA_REGEXP_FLAGS OR SWIFT_EXPERIMENTAL_EXTRA_NEGATIVE_REGEXP_FLAGS) @@ -401,6 +487,26 @@ function(_compile_swift_files set(sibopt_outputs "${sibopt_file}") set(sibgen_outputs "${sibgen_file}") + # macCatalyst zippered swiftmodule + if(maccatalyst_build_flavor STREQUAL "zippered") + set(maccatalyst_swift_flags "${swift_flags}") + list(APPEND maccatalyst_swift_flags + "-I" "${SWIFTLIB_DIR}/${maccatalyst_library_subdir}") + set(maccatalyst_swift_module_flags ${swift_module_flags}) + elseif(maccatalyst_build_flavor STREQUAL "ios-like") + compute_library_subdir(maccatalyst_library_subdir + "MACCATALYST" "${SWIFTFILE_ARCHITECTURE}") + list(APPEND swift_flags + "-I" "${SWIFTLIB_DIR}/${maccatalyst_library_subdir}") + else() + # Allow import of other Swift modules we just built. + list(APPEND swift_flags + "-I" "${SWIFTLIB_DIR}/${library_subdir}") + + # FIXME: should we use '-resource-dir' here? Seems like it has no advantage + # over '-I' in this case. + endif() + if(XCODE) # HACK: work around an issue with CMake Xcode generator and the Swift # driver. @@ -424,6 +530,12 @@ function(_compile_swift_files COMMAND "${CMAKE_COMMAND}" -E touch ${sibopt_outputs}) set(command_touch_sibgen_outputs COMMAND "${CMAKE_COMMAND}" -E touch ${sibgen_outputs}) + + # macCatalyst zippered outputs + if(maccatalyst_build_flavor STREQUAL "zippered") + set(command_touch_maccatalyst_module_outputs + COMMAND "${CMAKE_COMMAND}" -E touch ${maccatalyst_module_outputs}) + endif() endif() # First generate the obj dirs @@ -516,6 +628,49 @@ function(_compile_swift_files COMMENT "Generating ${module_file}") set("${dependency_module_target_out_var_name}" "${module_dependency_target}" PARENT_SCOPE) + # macCatalyst zippered swiftmodule + if(maccatalyst_build_flavor STREQUAL "zippered") + get_target_triple(ios_like_target_triple ignored_target_variant + "${SWIFTFILE_SDK}" + "${SWIFTFILE_ARCHITECTURE}" + MACCATALYST_BUILD_FLAVOR "ios-like") + + # Remove previous -target and -target-variant flags from + # the zippered Swift flags and add an ios-like target. + remove_given_flag(maccatalyst_swift_flags "target") + remove_given_flag(maccatalyst_swift_flags "target-variant") + list(APPEND maccatalyst_swift_flags + "-target" "${ios_like_target_triple}") + + add_custom_command_target( + maccatalyst_module_dependency_target + COMMAND + "${CMAKE_COMMAND}" "-E" "remove" "-f" ${maccatalyst_module_outputs} + COMMAND + "${CMAKE_COMMAND}" "-E" "make_directory" ${maccatalyst_specific_module_dir} + COMMAND + "${PYTHON_EXECUTABLE}" "${line_directive_tool}" "@${file_path}" -- + "${swift_compiler_tool}" "-emit-module" "-o" "${maccatalyst_module_file}" + ${maccatalyst_swift_flags} ${maccatalyst_swift_module_flags} "@${file_path}" + ${command_touch_maccatalyst_module_outputs} + OUTPUT + ${maccatalyst_module_outputs} + DEPENDS + ${swift_compiler_tool_dep} + ${source_files} + ${SWIFTFILE_DEPENDS} + ${swift_ide_test_dependency} + ${obj_dirs_dependency_target} + COMMENT + "Generating ${maccatalyst_module_file}") + + # Piggy-back on the same out-var as the regular swiftmodule + set("${dependency_module_target_out_var_name}" + "${module_dependency_target}" + "${maccatalyst_module_dependency_target}" + PARENT_SCOPE) + endif() + # This is the target to generate the .sib files. It is not built by default. add_custom_command_target( sib_dependency_target diff --git a/cmake/modules/macCatalystUtils.cmake b/cmake/modules/macCatalystUtils.cmake new file mode 100644 index 0000000000000..d30177bc8682d --- /dev/null +++ b/cmake/modules/macCatalystUtils.cmake @@ -0,0 +1,100 @@ +# macCatalystUtils.cmake +# +# Utility functions for macCatalyst support in Swift. + + +# Include guard +if(MACCATALYST_UTILS_INCLUDED) + return() +endif() + +set(MACCATALYST_UTILS_INCLUDED TRUE) + + +# ----------------------------------------------------------------------------- + +# List of all valid macCatalyst build flavors +set(MACCATALYST_BUILD_FLAVORS "ios-like" "macos-like" "zippered" "unzippered-twin") + + +# Sets out_var with the macCatalyst build flavor if macCatalyst is enabled and building +# for the OSX sdk. +function(get_maccatalyst_build_flavor out_var sdk flavor) + if(SWIFT_ENABLE_MACCATALYST AND sdk STREQUAL "OSX") + if(flavor IN_LIST MACCATALYST_BUILD_FLAVORS) + set("${out_var}" "${flavor}" PARENT_SCOPE) + elseif(NOT flavor STREQUAL "") + message(FATAL_ERROR "Invalid MACCATALYST_BUILD_FLAVOR: ${flavor}") + else() + # Unset the variable to indicate the absence of a build flavor + unset("${out_var}" PARENT_SCOPE) + endif() + else() + # Unset the variable to indicate macCatalyst is not enabled + unset("${out_var}" PARENT_SCOPE) + endif() +endfunction() + + +# Sets target_out_var to the target triple for the given SDK and maccatalyst flavor. +# For zippered flavors also sets the target_variant_out_var. For other +# flavors the target_variant_out_var is unset, causing it to be undefined. +function(get_target_triple target_out_var target_variant_out_var sdk arch) + # parse args + set(option_args) + set(single_value_args MACCATALYST_BUILD_FLAVOR DEPLOYMENT_VERSION) + set(multi_value_args) + cmake_parse_arguments(TARGET + "${option_args}" + "${single_value_args}" + "${multi_value_args}" + ${ARGN}) + + set(deployment_version "${TARGET_DEPLOYMENT_VERSION}") + + # Default target triple + set(target "${SWIFT_SDK_${sdk}_ARCH_${arch}_TRIPLE}${deployment_version}") + set(target_variant) + + get_maccatalyst_build_flavor(maccatalyst_build_flavor + "${sdk}" "${TARGET_MACCATALYST_BUILD_FLAVOR}") + + if(maccatalyst_build_flavor STREQUAL "ios-like") + set(target "${arch}-apple-ios${SWIFT_DARWIN_DEPLOYMENT_VERSION_MACCATALYST}-macabi") + elseif(maccatalyst_build_flavor STREQUAL "macos-like") + # Use the default macOS triple. + elseif(maccatalyst_build_flavor STREQUAL "zippered") + set(target "${arch}-apple-macosx${SWIFT_DARWIN_DEPLOYMENT_VERSION_OSX}") + set(target_variant "${arch}-apple-ios${SWIFT_DARWIN_DEPLOYMENT_VERSION_MACCATALYST}-macabi") + elseif(maccatalyst_build_flavor STREQUAL "unzippered-twin") + # Use the default triple for now + endif() + + set(${target_out_var} "${target}" PARENT_SCOPE) + set(${target_variant_out_var} "${target_variant}" PARENT_SCOPE) +endfunction() + + +# Removes all instances of `-${flag} ` from an input list of flags +function(remove_given_flag flags_var flag_name) + set(output_flags) + + set(seen_flag FALSE) + foreach(flag ${${flags_var}}) + # Skip flag argument + if(seen_flag) + set(seen_flag FALSE) + continue() + endif() + + # Skip flag + if(flag STREQUAL "-${flag_name}") + set(seen_flag TRUE) + continue() + endif() + + list(APPEND output_flags "${flag}") + endforeach() + + set("${flags_var}" "${output_flags}" PARENT_SCOPE) +endfunction() diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index 146404a438fa6..476b46e6a1483 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -1997,6 +1997,11 @@ class DeclAttributes { bool isUnavailableInSwiftVersion(const version::Version &effectiveVersion) const; + /// Finds the most-specific platform-specific attribute that is + /// active for the current platform. + const AvailableAttr * + findMostSpecificActivePlatform(const ASTContext &ctx) const; + /// Returns the first @available attribute that indicates /// a declaration is unavailable, or the first one that indicates it's /// potentially unavailable, or null otherwise. diff --git a/include/swift/AST/DiagnosticsDriver.def b/include/swift/AST/DiagnosticsDriver.def index e301e51f09daf..2246c54348a2e 100644 --- a/include/swift/AST/DiagnosticsDriver.def +++ b/include/swift/AST/DiagnosticsDriver.def @@ -117,6 +117,10 @@ ERROR(error_sdk_too_old,none, ERROR(error_ios_maximum_deployment_32,none, "iOS %0 does not support 32-bit programs", (unsigned)) +ERROR(error_unsupported_target_variant,none, + "unsupported '%select{-target|-target-variant}1' value '%0'; use 'ios-macabi' instead", + (StringRef, bool)) + WARNING(warn_arclite_not_found_when_link_objc_runtime,none, "unable to find Objective-C runtime support library 'arclite'; " "pass '-no-link-objc-runtime' to silence this warning", ()) diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index afda5761bce67..1cbb3766c86ee 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -1651,6 +1651,8 @@ ERROR(empty_version_string,none, WARNING(unknown_platform_condition_argument,none, "unknown %0 for build configuration '%1'", (StringRef, StringRef)) +WARNING(renamed_platform_condition_argument,none, + "'%0' has been renamed to '%1'", (StringRef, StringRef)) WARNING(likely_simulator_platform_condition,none, "platform condition appears to be testing for simulator environment; " "use 'targetEnvironment(simulator)' instead", diff --git a/include/swift/AST/PlatformKind.h b/include/swift/AST/PlatformKind.h index 37e171ef41652..b4bc373bd68cb 100644 --- a/include/swift/AST/PlatformKind.h +++ b/include/swift/AST/PlatformKind.h @@ -51,11 +51,20 @@ StringRef prettyPlatformString(PlatformKind platform); /// restrictions are enabled, but OSXApplicationExtension is not considered /// active when the target platform is OS X and app extension restrictions are /// disabled. PlatformKind::none is always considered active. -bool isPlatformActive(PlatformKind Platform, LangOptions &LangOpts); - +/// If ForTargetVariant is true then for zippered builds the target-variant +/// triple will be used rather than the target to determine whether the +/// platform is active. +bool isPlatformActive(PlatformKind Platform, LangOptions &LangOpts, + bool ForTargetVariant = false); + /// Returns the target platform for the given language options. PlatformKind targetPlatform(LangOptions &LangOpts); - + +/// Returns true when availability attributes from the "parent" platform +/// should also apply to the "child" platform for declarations without +/// an explicit attribute for the child. +bool inheritsAvailabilityFromPlatform(PlatformKind Child, PlatformKind Parent); + } // end namespace swift #endif diff --git a/include/swift/AST/PlatformKinds.def b/include/swift/AST/PlatformKinds.def index 9192450f15236..cc9b9ede0eae8 100644 --- a/include/swift/AST/PlatformKinds.def +++ b/include/swift/AST/PlatformKinds.def @@ -30,5 +30,7 @@ AVAILABILITY_PLATFORM(iOSApplicationExtension, "application extensions for iOS") AVAILABILITY_PLATFORM(tvOSApplicationExtension, "application extensions for tvOS") AVAILABILITY_PLATFORM(watchOSApplicationExtension, "application extensions for watchOS") AVAILABILITY_PLATFORM(OSXApplicationExtension, "application extensions for macOS") +AVAILABILITY_PLATFORM(macCatalyst, "Mac Catalyst") +AVAILABILITY_PLATFORM(macCatalystApplicationExtension, "application extensions for Mac Catalyst") #undef AVAILABILITY_PLATFORM diff --git a/include/swift/AST/Stmt.h b/include/swift/AST/Stmt.h index 9a762df4f6de2..6b6f7164fc22a 100644 --- a/include/swift/AST/Stmt.h +++ b/include/swift/AST/Stmt.h @@ -329,11 +329,20 @@ class alignas(8) PoundAvailableInfo final : /// The version range when this query will return true. This value is /// filled in by Sema. VersionRange AvailableRange; - + + /// For zippered builds, this is the version range for the target variant + /// that must hold for the query to return true. For example, when + /// compiling with target x86_64-macosx10.15 and target-variant + /// x86_64-ios13.0 a query of #available(macOS 10.22, iOS 20.0, *) will + /// have a variant range of [20.0, +inf). + /// This is filled in by Sema. + VersionRange VariantAvailableRange; + PoundAvailableInfo(SourceLoc PoundLoc, ArrayRef queries, SourceLoc RParenLoc) : PoundLoc(PoundLoc), RParenLoc(RParenLoc), NumQueries(queries.size()), - AvailableRange(VersionRange::empty()) { + AvailableRange(VersionRange::empty()), + VariantAvailableRange(VersionRange::empty()) { std::uninitialized_copy(queries.begin(), queries.end(), getTrailingObjects()); } @@ -356,6 +365,13 @@ class alignas(8) PoundAvailableInfo final : const VersionRange &getAvailableRange() const { return AvailableRange; } void setAvailableRange(const VersionRange &Range) { AvailableRange = Range; } + + const VersionRange &getVariantAvailableRange() const { + return VariantAvailableRange; + } + void setVariantAvailableRange(const VersionRange &Range) { + VariantAvailableRange = Range; + } }; diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 3d54ece63ff4f..28602e9b3890c 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -64,6 +64,17 @@ namespace swift { /// This represents the minimum deployment target. llvm::Triple Target; + /// \brief The second target for a zippered build + /// + /// This represents the target and minimum deployment version for the + /// second ('variant') target when performing a zippered build. + /// For example, if the target is x86_64-apple-macosx10.14 then + /// a target-variant of x86_64-apple-ios12.0-macabi will produce + /// a zippered binary that can be loaded into both macCatalyst and + /// macOS processes. A value of 'None' means no zippering will be + /// performed. + llvm::Optional TargetVariant; + /// /// Language features /// @@ -402,7 +413,8 @@ namespace swift { /// /// \param suggestedKind Populated with suggested replacement platform condition /// \param suggestedValues Populated with suggested replacement values - /// if a match is not found. + /// if a match is not found, or if the value has been deprecated + /// in favor of a newer one. static bool checkPlatformConditionSupported( PlatformConditionKind Kind, StringRef Value, PlatformConditionKind &suggestedKind, diff --git a/include/swift/Basic/Platform.h b/include/swift/Basic/Platform.h index cfd9abebd4a00..eb21ea7a29714 100644 --- a/include/swift/Basic/Platform.h +++ b/include/swift/Basic/Platform.h @@ -46,6 +46,14 @@ namespace swift { /// Return true if the given triple represents any simulator. bool tripleIsAnySimulator(const llvm::Triple &triple); + /// Returns true if the given triple represents a macCatalyst environment. + bool tripleIsMacCatalystEnvironment(const llvm::Triple &triple); + + /// Returns true if the given -target triple and -target-variant triple + /// can be zippered. + bool triplesAreValidForZippering(const llvm::Triple &target, + const llvm::Triple &targetVariant); + /// Returns true if the given triple represents an OS that ships with /// ABI-stable swift libraries (eg. in /usr/lib/swift). bool tripleRequiresRPathForSwiftInOS(const llvm::Triple &triple); diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h index 921b9fb04defc..12c1b802e0716 100644 --- a/include/swift/Driver/ToolChain.h +++ b/include/swift/Driver/ToolChain.h @@ -201,6 +201,11 @@ class ToolChain { void getResourceDirPath(SmallVectorImpl &runtimeLibPath, const llvm::opt::ArgList &args, bool shared) const; + /// Get the secondary runtime library link path given the primary path. + void getSecondaryResourceDirPath( + SmallVectorImpl &secondaryResourceDirPath, + StringRef primaryPath) const; + /// Get the runtime library link paths, which typically include the resource /// dir path and the SDK. void getRuntimeLibraryPaths(SmallVectorImpl &runtimeLibPaths, @@ -310,7 +315,8 @@ class ToolChain { /// An override point for platform-specific subclasses to customize the /// validations that should be performed. virtual void validateArguments(DiagnosticEngine &diags, - const llvm::opt::ArgList &args) const {} + const llvm::opt::ArgList &args, + StringRef defaultTarget) const {} }; } // end namespace driver } // end namespace swift diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index a5a7813b4f17c..b5de606ec416c 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -919,6 +919,11 @@ def print_target_info : Flag<["-"], "print-target-info">, def target_cpu : Separate<["-"], "target-cpu">, Flags<[FrontendOption, ModuleInterfaceOption]>, HelpText<"Generate code for a particular CPU variant">; +def target_variant : Separate<["-"], "target-variant">, + Flags<[FrontendOption]>, + HelpText<"Generate 'zippered' code for macCatalyst that can run on the specified" + " variant target triple in addition to the main -target triple">; + def profile_generate : Flag<["-"], "profile-generate">, Flags<[FrontendOption, NoInteractiveOption]>, HelpText<"Generate instrumented code to collect execution counts">; diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index 7e09cc69accb3..bf2ec20779d8d 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -172,6 +172,35 @@ DeclAttributes::isUnavailableInSwiftVersion( return false; } +const AvailableAttr * +DeclAttributes::findMostSpecificActivePlatform(const ASTContext &ctx) const{ + const AvailableAttr *bestAttr = nullptr; + + for (auto attr : *this) { + auto *avAttr = dyn_cast(attr); + if (!avAttr) + continue; + + if (avAttr->isInvalid()) + continue; + + if (!avAttr->hasPlatform()) + continue; + + if (!avAttr->isActivePlatform(ctx)) + continue; + + // We have an attribute that is active for the platform, but + // is it more specific than our curent best? + if (!bestAttr || inheritsAvailabilityFromPlatform(avAttr->Platform, + bestAttr->Platform)) { + bestAttr = avAttr; + } + } + + return bestAttr; +} + const AvailableAttr * DeclAttributes::getPotentiallyUnavailable(const ASTContext &ctx) const { const AvailableAttr *potential = nullptr; @@ -217,12 +246,19 @@ DeclAttributes::getPotentiallyUnavailable(const ASTContext &ctx) const { const AvailableAttr *DeclAttributes::getUnavailable( const ASTContext &ctx) const { const AvailableAttr *conditional = nullptr; + const AvailableAttr *bestActive = findMostSpecificActivePlatform(ctx); for (auto Attr : *this) if (auto AvAttr = dyn_cast(Attr)) { if (AvAttr->isInvalid()) continue; + // If this is a platform-specific attribute and it isn't the most + // specific attribute for the current platform, we're done. + if (AvAttr->hasPlatform() && + (!bestActive || AvAttr != bestActive)) + continue; + // If this attribute doesn't apply to the active platform, we're done. if (!AvAttr->isActivePlatform(ctx) && !AvAttr->isLanguageVersionSpecific() && @@ -250,11 +286,16 @@ const AvailableAttr *DeclAttributes::getUnavailable( const AvailableAttr * DeclAttributes::getDeprecated(const ASTContext &ctx) const { const AvailableAttr *conditional = nullptr; + const AvailableAttr *bestActive = findMostSpecificActivePlatform(ctx); for (auto Attr : *this) { if (auto AvAttr = dyn_cast(Attr)) { if (AvAttr->isInvalid()) continue; + if (AvAttr->hasPlatform() && + (!bestActive || AvAttr != bestActive)) + continue; + if (!AvAttr->isActivePlatform(ctx) && !AvAttr->isLanguageVersionSpecific() && !AvAttr->isPackageDescriptionVersionSpecific()) @@ -329,6 +370,30 @@ static bool isShortAvailable(const DeclAttribute *DA) { return true; } +/// Return true when another availability attribute implies the same availability as this +/// attribute and so printing the attribute can be skipped to de-clutter the declaration +/// when printing the short form. +/// For example, iOS availability implies macCatalyst availability so if attributes for +/// both are present and they have the same 'introduced' version, we can skip printing an +/// explicit availability for macCatalyst. +static bool isShortFormAvailabilityImpliedByOther(const AvailableAttr *Attr, + ArrayRef Others) { + assert(isShortAvailable(Attr)); + + for (auto *DA : Others) { + auto *Other = cast(DA); + if (Attr->Platform == Other->Platform) + continue; + + if (!inheritsAvailabilityFromPlatform(Attr->Platform, Other->Platform)) + continue; + + if (Attr->Introduced == Other->Introduced) + return true; + } + return false; +} + /// Print the short-form @available() attribute for an array of long-form /// AvailableAttrs that can be represented in the short form. /// For example, for: @@ -359,6 +424,8 @@ static void printShortFormAvailable(ArrayRef Attrs, for (auto *DA : Attrs) { auto *AvailAttr = cast(DA); assert(AvailAttr->Introduced.hasValue()); + if (isShortFormAvailabilityImpliedByOther(AvailAttr, Attrs)) + continue; Printer << platformString(AvailAttr->Platform) << " " << AvailAttr->Introduced.getValue().getAsString() << ", "; } diff --git a/lib/AST/PlatformKind.cpp b/lib/AST/PlatformKind.cpp index c62460b05b97a..1119601d458c1 100644 --- a/lib/AST/PlatformKind.cpp +++ b/lib/AST/PlatformKind.cpp @@ -16,6 +16,7 @@ #include "swift/AST/PlatformKind.h" #include "swift/Basic/LangOptions.h" +#include "swift/Basic/Platform.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" @@ -63,7 +64,8 @@ static bool isPlatformActiveForTarget(PlatformKind Platform, return true; if (Platform == PlatformKind::OSXApplicationExtension || - Platform == PlatformKind::iOSApplicationExtension) + Platform == PlatformKind::iOSApplicationExtension || + Platform == PlatformKind::macCatalystApplicationExtension) if (!EnableAppExtensionRestrictions) return false; @@ -75,6 +77,9 @@ static bool isPlatformActiveForTarget(PlatformKind Platform, case PlatformKind::iOS: case PlatformKind::iOSApplicationExtension: return Target.isiOS() && !Target.isTvOS(); + case PlatformKind::macCatalyst: + case PlatformKind::macCatalystApplicationExtension: + return tripleIsMacCatalystEnvironment(Target); case PlatformKind::tvOS: case PlatformKind::tvOSApplicationExtension: return Target.isTvOS(); @@ -87,8 +92,15 @@ static bool isPlatformActiveForTarget(PlatformKind Platform, llvm_unreachable("bad PlatformKind"); } -bool swift::isPlatformActive(PlatformKind Platform, LangOptions &LangOpts) { +bool swift::isPlatformActive(PlatformKind Platform, LangOptions &LangOpts, + bool ForTargetVariant) { llvm::Triple TT = LangOpts.Target; + + if (ForTargetVariant) { + assert(LangOpts.TargetVariant && "Must have target variant triple"); + TT = *LangOpts.TargetVariant; + } + return isPlatformActiveForTarget(Platform, TT, LangOpts.EnableAppExtensionRestrictions); } @@ -113,6 +125,10 @@ PlatformKind swift::targetPlatform(LangOptions &LangOpts) { } if (LangOpts.Target.isiOS()) { + if (tripleIsMacCatalystEnvironment(LangOpts.Target)) + return (LangOpts.EnableAppExtensionRestrictions + ? PlatformKind::macCatalystApplicationExtension + : PlatformKind::macCatalyst); return (LangOpts.EnableAppExtensionRestrictions ? PlatformKind::iOSApplicationExtension : PlatformKind::iOS); @@ -120,3 +136,22 @@ PlatformKind swift::targetPlatform(LangOptions &LangOpts) { return PlatformKind::none; } + +bool swift::inheritsAvailabilityFromPlatform(PlatformKind Child, + PlatformKind Parent) { + if (Child == PlatformKind::macCatalyst && Parent == PlatformKind::iOS) + return true; + + if (Child == PlatformKind::macCatalystApplicationExtension) { + if (Parent == PlatformKind::iOS || + Parent == PlatformKind::iOSApplicationExtension || + Parent == PlatformKind::macCatalyst) { + return true; + } + } + + // Ideally we would have all ApplicationExtension platforms + // inherit from their non-extension platform. + + return false; +} diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index 95c937cbd2f43..def6143af764f 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -26,7 +26,18 @@ using namespace swift; -static const StringRef SupportedConditionalCompilationOSs[] = { +struct SupportedConditionalValue { + StringRef value; + + /// If the value has been deprecated, the new value to replace it with. + StringRef replacement = ""; + + SupportedConditionalValue(const char *value) : value(value) {} + SupportedConditionalValue(const char *value, const char *replacement) + : value(value), replacement(replacement) {} +}; + +static const SupportedConditionalValue SupportedConditionalCompilationOSs[] = { "OSX", "macOS", "tvOS", @@ -42,7 +53,7 @@ static const StringRef SupportedConditionalCompilationOSs[] = { "WASI", }; -static const StringRef SupportedConditionalCompilationArches[] = { +static const SupportedConditionalValue SupportedConditionalCompilationArches[] = { "arm", "arm64", "i386", @@ -53,18 +64,20 @@ static const StringRef SupportedConditionalCompilationArches[] = { "wasm32", }; -static const StringRef SupportedConditionalCompilationEndianness[] = { +static const SupportedConditionalValue SupportedConditionalCompilationEndianness[] = { "little", "big" }; -static const StringRef SupportedConditionalCompilationRuntimes[] = { +static const SupportedConditionalValue SupportedConditionalCompilationRuntimes[] = { "_ObjC", "_Native", }; -static const StringRef SupportedConditionalCompilationTargetEnvironments[] = { +static const SupportedConditionalValue SupportedConditionalCompilationTargetEnvironments[] = { "simulator", + { "macabi", "macCatalyst" }, + "macCatalyst", // A synonym for "macabi" when compiling for iOS }; static const PlatformConditionKind AllPublicPlatformConditionKinds[] = { @@ -73,7 +86,7 @@ static const PlatformConditionKind AllPublicPlatformConditionKinds[] = { #include "swift/AST/PlatformConditionKinds.def" }; -ArrayRef getSupportedConditionalCompilationValues(const PlatformConditionKind &Kind) { +ArrayRef getSupportedConditionalCompilationValues(const PlatformConditionKind &Kind) { switch (Kind) { case PlatformConditionKind::OS: return SupportedConditionalCompilationOSs; @@ -97,11 +110,11 @@ PlatformConditionKind suggestedPlatformConditionKind(PlatformConditionKind Kind, for (const PlatformConditionKind& candidateKind : AllPublicPlatformConditionKinds) { if (candidateKind != Kind) { auto supportedValues = getSupportedConditionalCompilationValues(candidateKind); - for (const StringRef& candidateValue : supportedValues) { - if (candidateValue.lower() == lower) { + for (const SupportedConditionalValue& candidateValue : supportedValues) { + if (candidateValue.value.lower() == lower) { suggestedValues.clear(); - if (candidateValue != V) { - suggestedValues.emplace_back(candidateValue); + if (candidateValue.value != V) { + suggestedValues.emplace_back(candidateValue.value); } return candidateKind; } @@ -118,19 +131,21 @@ bool isMatching(PlatformConditionKind Kind, const StringRef &V, unsigned minDistance = std::numeric_limits::max(); std::string lower = V.lower(); auto supportedValues = getSupportedConditionalCompilationValues(Kind); - for (const StringRef& candidate : supportedValues) { - if (candidate == V) { + for (const SupportedConditionalValue& candidate : supportedValues) { + if (candidate.value == V) { suggestedKind = Kind; suggestions.clear(); + if (!candidate.replacement.empty()) + suggestions.push_back(candidate.replacement); return true; } - unsigned distance = StringRef(lower).edit_distance(candidate.lower()); + unsigned distance = StringRef(lower).edit_distance(candidate.value.lower()); if (distance < minDistance) { suggestions.clear(); minDistance = distance; } if (distance == minDistance) - suggestions.emplace_back(candidate); + suggestions.emplace_back(candidate.value); } suggestedKind = suggestedPlatformConditionKind(Kind, V, suggestions); return false; @@ -171,6 +186,16 @@ checkPlatformCondition(PlatformConditionKind Kind, StringRef Value) const { if (Kind == PlatformConditionKind::OS && Value == "macOS") return checkPlatformCondition(Kind, "OSX"); + // When compiling for iOS we consider "macCatalyst" to be a + // synonym of "macabi". This enables the use of + // #if targetEnvironment(macCatalyst) as a compilation + // condition for macCatalyst. + + if (Kind == PlatformConditionKind::TargetEnvironment && + Value == "macCatalyst" && Target.isiOS()) { + return checkPlatformCondition(Kind, "macabi"); + } + for (auto &Opt : llvm::reverse(PlatformConditionValues)) { if (Opt.first == Kind) if (Opt.second == Value) @@ -321,6 +346,10 @@ std::pair LangOptions::setTarget(llvm::Triple triple) { addPlatformConditionValue(PlatformConditionKind::TargetEnvironment, "simulator"); + if (tripleIsMacCatalystEnvironment(Target)) + addPlatformConditionValue(PlatformConditionKind::TargetEnvironment, + "macabi"); + // If you add anything to this list, change the default size of // PlatformConditionValues to not require an extra allocation // in the common case. diff --git a/lib/Basic/Platform.cpp b/lib/Basic/Platform.cpp index 85abc0ee97e43..9581df610fab2 100644 --- a/lib/Basic/Platform.cpp +++ b/lib/Basic/Platform.cpp @@ -21,6 +21,7 @@ using namespace swift; bool swift::tripleIsiOSSimulator(const llvm::Triple &triple) { llvm::Triple::ArchType arch = triple.getArch(); return (triple.isiOS() && + !tripleIsMacCatalystEnvironment(triple) && // FIXME: transitional, this should eventually stop testing arch, and // switch to only checking the -environment field. (triple.isSimulatorEnvironment() || @@ -54,6 +55,38 @@ bool swift::tripleIsAnySimulator(const llvm::Triple &triple) { tripleIsAppleTVSimulator(triple); } +bool swift::tripleIsMacCatalystEnvironment(const llvm::Triple &triple) { + return triple.isiOS() && !triple.isTvOS() && + triple.getEnvironment() == llvm::Triple::MacABI; +} + +bool swift::triplesAreValidForZippering(const llvm::Triple &target, + const llvm::Triple &targetVariant) { + // The arch and vendor must match. + if (target.getArchName() != targetVariant.getArchName() || + target.getArch() != targetVariant.getArch() || + target.getSubArch() != targetVariant.getSubArch() || + target.getVendor() != targetVariant.getVendor()) { + return false; + } + + // Allow a macOS target and an iOS-macabi target variant + // This is typically the case when zippering a library originally + // developed for macOS. + if (target.isMacOSX() && tripleIsMacCatalystEnvironment(targetVariant)) { + return true; + } + + // Allow an iOS-macabi target and a macOS target variant. This would + // be the case when zippering a library originally developed for + // iOS. + if (targetVariant.isMacOSX() && tripleIsMacCatalystEnvironment(target)) { + return true; + } + + return false; +} + bool swift::tripleRequiresRPathForSwiftInOS(const llvm::Triple &triple) { if (triple.isMacOSX()) { // macOS 10.14.4 contains a copy of Swift, but the linker will still use an @@ -304,6 +337,7 @@ getEnvironmentForAppleTargetSpecificModuleTriple(const llvm::Triple &triple) { .Cases("unknown", "", None) // These values are also supported, but are handled by the default case below: // .Case ("simulator", StringRef("simulator")) + // .Case ("macabi", StringRef("macabi")) .Default(tripleEnvironment); } diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index f36a626a7debd..e60015f6530df 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1859,6 +1859,8 @@ PlatformAvailability::PlatformAvailability(LangOptions &langOpts) switch (platformKind) { case PlatformKind::iOS: case PlatformKind::iOSApplicationExtension: + case PlatformKind::macCatalyst: + case PlatformKind::macCatalystApplicationExtension: case PlatformKind::tvOS: case PlatformKind::tvOSApplicationExtension: deprecatedAsUnavailableMessage = @@ -1893,6 +1895,11 @@ bool PlatformAvailability::isPlatformRelevant(StringRef name) const { case PlatformKind::iOSApplicationExtension: return name == "ios" || name == "ios_app_extension"; + case PlatformKind::macCatalyst: + case PlatformKind::macCatalystApplicationExtension: + // ClangImporter does not yet support macCatalyst. + return false; + case PlatformKind::tvOS: return name == "tvos"; case PlatformKind::tvOSApplicationExtension: @@ -1933,6 +1940,11 @@ bool PlatformAvailability::treatDeprecatedAsUnavailable( // Anything deprecated in iOS 7.x and earlier is unavailable in Swift. return major <= 7; + case PlatformKind::macCatalyst: + case PlatformKind::macCatalystApplicationExtension: + // ClangImporter does not yet support macCatalyst. + return false; + case PlatformKind::watchOS: case PlatformKind::watchOSApplicationExtension: // No deprecation filter on watchOS diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 9a8974b67e82a..71656e2fa8073 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -96,6 +96,11 @@ getDarwinLibraryNameSuffixForTriple(const llvm::Triple &triple, case DarwinPlatformKind::MacOS: return "osx"; case DarwinPlatformKind::IPhoneOS: + // Here we return "osx" under the assumption that all the + // darwin runtime libraries are zippered and so the "osx" variants + // should be used for macCatalyst targets. + if (tripleIsMacCatalystEnvironment(triple)) + return "osx"; return "ios"; case DarwinPlatformKind::IPhoneOSSimulator: return "iossim"; @@ -431,6 +436,9 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments, // package isn't installed. Arguments.push_back("-rpath"); Arguments.push_back(context.Args.MakeArgString("/usr/lib/swift")); + // We don't need an rpath for /System/iOSSupport/usr/lib/swift because... + assert(!tripleIsMacCatalystEnvironment(getTriple()) + && "macCatalyst not supported without Swift-in-the-OS"); } } @@ -489,12 +497,23 @@ toolchains::Darwin::addDeploymentTargetArgs(ArgStringList &Arguments, } else { if (isiOSSimulator) Arguments.push_back("-ios_simulator_version_min"); + else if (tripleIsMacCatalystEnvironment(Triple)) + Arguments.push_back("-maccatalyst_version_min"); else Arguments.push_back("-iphoneos_version_min"); } unsigned major, minor, micro; Triple.getiOSVersion(major, minor, micro); addVersionString(context.Args, Arguments, major, minor, micro); + + if (TargetVariant) { + assert(triplesAreValidForZippering(Triple, *TargetVariant)); + assert(TargetVariant->isMacOSX()); + Arguments.push_back("-macosx_version_min"); + unsigned major, minor, micro; + TargetVariant->getMacOSXVersion(major, minor, micro); + addVersionString(context.Args, Arguments, major, minor, micro); + } } else if (Triple.isWatchOS()) { if (tripleIsWatchSimulator(Triple)) Arguments.push_back("-watchos_simulator_version_min"); @@ -508,6 +527,15 @@ toolchains::Darwin::addDeploymentTargetArgs(ArgStringList &Arguments, unsigned major, minor, micro; Triple.getMacOSXVersion(major, minor, micro); addVersionString(context.Args, Arguments, major, minor, micro); + + if (TargetVariant) { + assert(triplesAreValidForZippering(Triple, *TargetVariant)); + assert(tripleIsMacCatalystEnvironment(*TargetVariant)); + Arguments.push_back("-maccatalyst_version_min"); + unsigned major, minor, micro; + TargetVariant->getiOSVersion(major, minor, micro); + addVersionString(context.Args, Arguments, major, minor, micro); + } } } @@ -718,15 +746,33 @@ static void validateDeploymentTarget(const toolchains::Darwin &TC, } } +static void validateTargetVariant(const toolchains::Darwin &TC, + DiagnosticEngine &diags, + const llvm::opt::ArgList &args, + StringRef defaultTarget) { + if (TC.getTargetVariant().hasValue()) { + auto target = TC.getTriple(); + auto variant = *TC.getTargetVariant(); + + if (!triplesAreValidForZippering(target, variant)) { + diags.diagnose(SourceLoc(), diag::error_unsupported_target_variant, + variant.str(), + variant.isiOS()); + } + } +} + void toolchains::Darwin::validateArguments(DiagnosticEngine &diags, - const llvm::opt::ArgList &args) const { + const llvm::opt::ArgList &args, + StringRef defaultTarget) const { // Validating arclite library path when link-objc-runtime. validateLinkObjcRuntimeARCLiteLib(*this, diags, args); // Validating apple platforms deployment targets. validateDeploymentTarget(*this, diags, args); - + validateTargetVariant(*this, diags, args, defaultTarget); + // Validating darwin unsupported -static-stdlib argument. if (args.hasArg(options::OPT_static_stdlib)) { diags.diagnose(SourceLoc(), diag::error_darwin_static_stdlib_not_supported); diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 4cba95dffecbe..24aa389685474 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -22,6 +22,7 @@ #include "swift/AST/DiagnosticsFrontend.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/OutputFileMap.h" +#include "swift/Basic/Platform.h" #include "swift/Basic/Range.h" #include "swift/Basic/Statistic.h" #include "swift/Basic/TaskQueue.h" @@ -252,8 +253,13 @@ Driver::buildToolChain(const llvm::opt::InputArgList &ArgList) { case llvm::Triple::MacOSX: case llvm::Triple::IOS: case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - return llvm::make_unique(*this, target); + case llvm::Triple::WatchOS: { + Optional targetVariant; + if (const Arg *A = ArgList.getLastArg(options::OPT_target_variant)) + targetVariant = llvm::Triple(llvm::Triple::normalize(A->getValue())); + + return llvm::make_unique(*this, target, targetVariant); + } case llvm::Triple::Linux: if (target.isAndroid()) return llvm::make_unique(*this, target); @@ -824,7 +830,7 @@ Driver::buildCompilation(const ToolChain &TC, validateArgs(Diags, *TranslatedArgList, TC.getTriple()); // Perform toolchain specific args validation. - TC.validateArguments(Diags, *TranslatedArgList); + TC.validateArguments(Diags, *TranslatedArgList, DefaultTargetTriple); if (Diags.hadAnyError()) return nullptr; diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 092921b03a6b5..9e65bf4f28a07 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -151,6 +151,12 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI, break; } + if (const Arg *variant = inputArgs.getLastArg(options::OPT_target_variant)) { + arguments.push_back("-target-variant"); + std::string normalized = llvm::Triple::normalize(variant->getValue()); + arguments.push_back(inputArgs.MakeArgString(normalized)); + } + // Enable address top-byte ignored in the ARM64 backend. if (Triple.getArch() == llvm::Triple::aarch64) { arguments.push_back("-Xllvm"); @@ -1223,8 +1229,28 @@ void ToolChain::getResourceDirPath(SmallVectorImpl &resourceDirPath, llvm::sys::path::append(resourceDirPath, "lib", shared ? "swift" : "swift_static"); } - llvm::sys::path::append(resourceDirPath, - getPlatformNameForTriple(getTriple())); + + StringRef libSubDir = getPlatformNameForTriple(getTriple()); + if (tripleIsMacCatalystEnvironment(getTriple())) + libSubDir = "maccatalyst"; + llvm::sys::path::append(resourceDirPath, libSubDir); +} + +// Get the secondary runtime library link path given the primary path. +// The compiler will look for runtime libraries in the secondary path if they +// can't be found in the primary path. +void ToolChain::getSecondaryResourceDirPath( + SmallVectorImpl &secondaryResourceDirPath, + StringRef primaryPath) const { + if (!tripleIsMacCatalystEnvironment(getTriple())) + return; + + // For macCatalyst, the secondary runtime library path is the macOS library + // path. The compiler will find zippered libraries here. + secondaryResourceDirPath.append(primaryPath.begin(), primaryPath.end()); + // Remove '/maccatalyst' and replace with 'macosx'. + llvm::sys::path::remove_filename(secondaryResourceDirPath); + llvm::sys::path::append(secondaryResourceDirPath, "macosx"); } void ToolChain::getRuntimeLibraryPaths(SmallVectorImpl &runtimeLibPaths, @@ -1234,7 +1260,22 @@ void ToolChain::getRuntimeLibraryPaths(SmallVectorImpl &runtimeLibP getResourceDirPath(scratchPath, args, shared); runtimeLibPaths.push_back(scratchPath.str()); + // If there's a secondary resource dir, add it too. + scratchPath.clear(); + getSecondaryResourceDirPath(scratchPath, runtimeLibPaths[0]); + if (!scratchPath.empty()) + runtimeLibPaths.push_back(scratchPath.str()); + if (!SDKPath.empty()) { + if (!scratchPath.empty()) { + // If we added the secondary resource dir, we also need the iOSSupport + // directory. + scratchPath = SDKPath; + llvm::sys::path::append(scratchPath, "System", "iOSSupport"); + llvm::sys::path::append(scratchPath, "usr", "lib", "swift"); + runtimeLibPaths.push_back(scratchPath.str()); + } + scratchPath = SDKPath; llvm::sys::path::append(scratchPath, "usr", "lib", "swift"); runtimeLibPaths.push_back(scratchPath.str()); diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index 936599c4cf36d..addeeba50f52c 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -55,17 +55,27 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { const JobContext &context) const override; void validateArguments(DiagnosticEngine &diags, - const llvm::opt::ArgList &args) const override; + const llvm::opt::ArgList &args, + StringRef defaultTarget) const override; std::string findProgramRelativeToSwiftImpl(StringRef name) const override; bool shouldStoreInvocationInDebugInfo() const override; + const Optional TargetVariant; + public: - Darwin(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {} + Darwin(const Driver &D, const llvm::Triple &Triple, + const Optional &TargetVariant) : + ToolChain(D, Triple), TargetVariant(TargetVariant) {} + ~Darwin() = default; std::string sanitizerRuntimeLibName(StringRef Sanitizer, bool shared = true) const override; + + Optional getTargetVariant() const { + return TargetVariant; + } }; class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index dbe9733e670ab..6d2c5636cf797 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -73,7 +73,14 @@ static void setDefaultPrebuiltCacheIfNecessary( return; SmallString<64> defaultPrebuiltPath{searchPathOpts.RuntimeResourcePath}; - StringRef platform = getPlatformNameForTriple(triple); + StringRef platform; + if (tripleIsMacCatalystEnvironment(triple)) { + // The prebuilt cache for macCatalyst is the same as the one for macOS, not iOS + // or a separate location of its own. + platform = "macosx"; + } else { + platform = getPlatformNameForTriple(triple); + } llvm::sys::path::append(defaultPrebuiltPath, platform, "prebuilt-modules"); frontendOpts.PrebuiltModuleCachePath = defaultPrebuiltPath.str(); } @@ -82,7 +89,11 @@ static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts, llvm::Triple &Triple) { llvm::SmallString<128> LibPath(SearchPathOpts.RuntimeResourcePath); - llvm::sys::path::append(LibPath, getPlatformNameForTriple(Triple)); + StringRef LibSubDir = getPlatformNameForTriple(Triple); + if (tripleIsMacCatalystEnvironment(Triple)) + LibSubDir = "maccatalyst"; + + llvm::sys::path::append(LibPath, LibSubDir); SearchPathOpts.RuntimeLibraryPaths.clear(); SearchPathOpts.RuntimeLibraryPaths.push_back(LibPath.str()); if (Triple.isOSDarwin()) @@ -101,6 +112,13 @@ static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts, SearchPathOpts.RuntimeLibraryImportPaths.push_back(LibPath.str()); if (!SearchPathOpts.SDKPath.empty()) { + if (tripleIsMacCatalystEnvironment(Triple)) { + LibPath = SearchPathOpts.SDKPath; + llvm::sys::path::append(LibPath, "System", "iOSSupport"); + llvm::sys::path::append(LibPath, "usr", "lib", "swift"); + SearchPathOpts.RuntimeLibraryImportPaths.push_back(LibPath.str()); + } + LibPath = SearchPathOpts.SDKPath; llvm::sys::path::append(LibPath, "usr", "lib", "swift"); if (!Triple.isOSDarwin()) { @@ -520,6 +538,10 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, TargetArg = A->getValue(); } + if (const Arg *A = Args.getLastArg(OPT_target_variant)) { + Opts.TargetVariant = llvm::Triple(A->getValue()); + } + Opts.EnableCXXInterop |= Args.hasArg(OPT_enable_cxx_interop); Opts.EnableObjCInterop = Args.hasFlag(OPT_enable_objc_interop, OPT_disable_objc_interop, diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp index 2b5d67bb2e4e1..aa7acdbfbadea 100644 --- a/lib/Parse/ParseIfConfig.cpp +++ b/lib/Parse/ParseIfConfig.cpp @@ -311,6 +311,16 @@ class ValidateIfConfigCondition : D.diagnose(Loc, diag::note_typo_candidate, suggestion) .fixItReplace(Arg->getSourceRange(), suggestion); } + else if (!suggestedValues.empty()) { + // The value the user gave has been replaced by something newer. + assert(suggestedValues.size() == 1 && "only support one replacement"); + auto replacement = suggestedValues.front(); + + auto Loc = Arg->getLoc(); + D.diagnose(Loc, diag::renamed_platform_condition_argument, + *ArgStr, replacement) + .fixItReplace(Arg->getSourceRange(), replacement); + } return E; } diff --git a/lib/PrintAsObjC/DeclAndTypePrinter.cpp b/lib/PrintAsObjC/DeclAndTypePrinter.cpp index 0ed1c2c1999c5..0b609510f66c7 100644 --- a/lib/PrintAsObjC/DeclAndTypePrinter.cpp +++ b/lib/PrintAsObjC/DeclAndTypePrinter.cpp @@ -827,6 +827,9 @@ class DeclAndTypePrinter::Implementation case PlatformKind::iOS: plat = "ios"; break; + case PlatformKind::macCatalyst: + plat = "maccatalyst"; + break; case PlatformKind::tvOS: plat = "tvos"; break; @@ -839,6 +842,9 @@ class DeclAndTypePrinter::Implementation case PlatformKind::iOSApplicationExtension: plat = "ios_app_extension"; break; + case PlatformKind::macCatalystApplicationExtension: + plat = "maccatalyst_app_extension"; + break; case PlatformKind::tvOSApplicationExtension: plat = "tvos_app_extension"; break; diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 537723f19c71b..24c68f8b68d0e 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1351,6 +1351,16 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) { return; } + // Make sure there isn't a more specific attribute we should be using instead. + // findMostSpecificActivePlatform() is O(N), so only do this if we're checking + // an iOS attribute while building for macCatalyst. + if (attr->Platform == PlatformKind::iOS && + isPlatformActive(PlatformKind::macCatalyst, Ctx.LangOpts)) { + if (attr != D->getAttrs().findMostSpecificActivePlatform(Ctx)) { + return; + } + } + SourceLoc attrLoc = attr->getLocation(); Optional> MaybeNotAllowed = diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 0f6812903c459..ecbebda7e831a 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -456,6 +456,18 @@ class TypeRefinementContextBuilder : private ASTWalker { AvailabilityContext NewConstraint = contextForSpec(Spec); Query->setAvailableRange(NewConstraint.getOSVersion()); + // When compiling zippered for macCatalyst, we need to collect both + // a macOS version (the target version) and an iOS/macCatalyst version + // (the target-variant). These versions will both be passed to a runtime + // entrypoint that will check either the macOS version or the iOS + // version depending on the kind of process this code is loaded into. + if (Context.LangOpts.TargetVariant) { + AvailabilitySpec *VariantSpec = + bestActiveSpecForQuery(Query, /*ForTargetVariant*/ true); + VersionRange VariantRange = contextForSpec(VariantSpec).getOSVersion(); + Query->setVariantAvailableRange(VariantRange); + } + if (Spec->getKind() == AvailabilitySpecKind::OtherPlatform) { // The wildcard spec '*' represents the minimum deployment target, so // there is no need to create a refinement context for this query. @@ -480,9 +492,18 @@ class TypeRefinementContextBuilder : private ASTWalker { // required compatibility version is different than the deployment // target). if (CurrentTRC->getReason() != TypeRefinementContext::Reason::Root) { + PlatformKind BestPlatform = targetPlatform(Context.LangOpts); + auto *PlatformSpec = + dyn_cast(Spec); + // If possible, try to report the diagnostic in terms for the + // platform the user uttered in the '#available()'. For a platform + // that inherits availability from another platform it may be + // different from the platform specified in the target triple. + if (PlatformSpec) + BestPlatform = PlatformSpec->getPlatform(); Diags.diagnose(Query->getLoc(), diag::availability_query_useless_enclosing_scope, - platformString(targetPlatform(Context.LangOpts))); + platformString(BestPlatform)); Diags.diagnose(CurrentTRC->getIntroductionLoc(), diag::availability_query_useless_enclosing_scope_here); } @@ -535,8 +556,11 @@ class TypeRefinementContextBuilder : private ASTWalker { /// Return the best active spec for the target platform or nullptr if no /// such spec exists. - AvailabilitySpec *bestActiveSpecForQuery(PoundAvailableInfo *available) { + AvailabilitySpec *bestActiveSpecForQuery(PoundAvailableInfo *available, + bool forTargetVariant = false) { OtherPlatformAvailabilitySpec *FoundOtherSpec = nullptr; + PlatformVersionConstraintAvailabilitySpec *BestSpec = nullptr; + for (auto *Spec : available->getQueries()) { if (auto *OtherSpec = dyn_cast(Spec)) { FoundOtherSpec = OtherSpec; @@ -551,11 +575,19 @@ class TypeRefinementContextBuilder : private ASTWalker { // properly. For example, on the OSXApplicationExtension platform // we want to chose the OS X spec unless there is an explicit // OSXApplicationExtension spec. - if (isPlatformActive(VersionSpec->getPlatform(), Context.LangOpts)) { - return VersionSpec; + if (isPlatformActive(VersionSpec->getPlatform(), Context.LangOpts, + forTargetVariant)) { + if (!BestSpec || + inheritsAvailabilityFromPlatform(VersionSpec->getPlatform(), + BestSpec->getPlatform())) { + BestSpec = VersionSpec; + } } } + if (BestSpec) + return BestSpec; + // If we have reached this point, we found no spec for our target, so // we return the other spec ('*'), if we found it, or nullptr, if not. return FoundOtherSpec; diff --git a/lib/SymbolGraphGen/Symbol.cpp b/lib/SymbolGraphGen/Symbol.cpp index 441a636454051..c30210d75a1e1 100644 --- a/lib/SymbolGraphGen/Symbol.cpp +++ b/lib/SymbolGraphGen/Symbol.cpp @@ -292,6 +292,8 @@ Symbol::getDomain(PlatformAgnosticAvailabilityKind AgnosticKind, switch (Kind) { case swift::PlatformKind::iOS: return { "iOS" }; + case swift::PlatformKind::macCatalyst: + return { "macCatalyst" }; case swift::PlatformKind::OSX: return { "macOS" }; case swift::PlatformKind::tvOS: @@ -300,6 +302,8 @@ Symbol::getDomain(PlatformAgnosticAvailabilityKind AgnosticKind, return { "watchOS" }; case swift::PlatformKind::iOSApplicationExtension: return { "iOSAppExtension" }; + case swift::PlatformKind::macCatalystApplicationExtension: + return { "macCatalystAppExtension" }; case swift::PlatformKind::OSXApplicationExtension: return { "macOSAppExtension" }; case swift::PlatformKind::tvOSApplicationExtension: diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp index 8f351d4ee1dff..675c9d2a3faea 100644 --- a/lib/TBDGen/TBDGen.cpp +++ b/lib/TBDGen/TBDGen.cpp @@ -253,6 +253,9 @@ getLinkerPlatformId(OriginallyDefinedInAttr::ActiveVersion Ver) { case swift::PlatformKind::OSX: case swift::PlatformKind::OSXApplicationExtension: return LinkerPlatformId::macOS; + case swift::PlatformKind::macCatalyst: + case swift::PlatformKind::macCatalystApplicationExtension: + return LinkerPlatformId::macCatalyst; } } diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index 958bbd290a18d..7b0c16cc9245e 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -187,6 +187,7 @@ foreach(sdk ${SWIFT_CONFIGURED_SDKS}) endif() endforeach() + add_swift_target_library(swiftImageRegistrationObjectELF OBJECT_LIBRARY IS_STDLIB IS_STDLIB_CORE SwiftRT-ELF.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a6a06dfea4e24..796b9bf1da4cb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -163,10 +163,28 @@ endif() foreach(SDK ${SWIFT_SDKS}) foreach(ARCH ${SWIFT_SDK_${SDK}_ARCHITECTURES}) + # macCatalyst needs to run two sets of tests: one with the normal macosx target triple + # and one with the the macCatalyst ios-macabi triple. The build_flavors list will + # have have only the "default" flavor for all SDKs and architectures except + # OSX when macCatalyst support is enabled. + set(build_flavors "default") + if(SWIFT_ENABLE_MACCATALYST AND "${SDK}" STREQUAL "OSX") + list(APPEND build_flavors "ios-like" ) + endif() + + foreach(BUILD_FLAVOR ${build_flavors}) # Configure variables for this subdirectory. set(VARIANT_SUFFIX "-${SWIFT_SDK_${SDK}_LIB_SUBDIR}-${ARCH}") set(VARIANT_TRIPLE "${SWIFT_SDK_${SDK}_ARCH_${ARCH}_TRIPLE}${SWIFT_SDK_${SDK}_DEPLOYMENT_VERSION}") set(VARIANT_SDK "${SWIFT_SDK_${SDK}_ARCH_${ARCH}_PATH}") + set(DEFAULT_OSX_VARIANT_SUFFIX "") + + if(BUILD_FLAVOR STREQUAL "ios-like") + set(DEFAULT_OSX_VARIANT_SUFFIX "${VARIANT_SUFFIX}") + # Use the macCatalyst target triple and compiler resources for the iOS-like build flavor. + set(VARIANT_SUFFIX "-${SWIFT_SDK_${SDK}_LIB_SUBDIR}-maccatalyst-${ARCH}") + set(VARIANT_TRIPLE "${ARCH}-apple-ios13.0-macabi") + endif() # A directory where to put the xUnit-style XML test results. set(SWIFT_TEST_RESULTS_DIR @@ -232,8 +250,17 @@ _Block_release(void) { }\n") if(SWIFT_BUILD_STDLIB AND SWIFT_INCLUDE_TESTS) list(APPEND test_dependencies "swift-test-stdlib-${SWIFT_SDK_${SDK}_LIB_SUBDIR}") - list(APPEND test_dependencies - "swift-reflection-test${VARIANT_SUFFIX}_signed") + + if(BUILD_FLAVOR STREQUAL "ios-like") + # When testing the iOS-like build flavor, use the the normal macOS + # swift-reflection-test-tool. That tool runs out of process so it + # doesn't need to be build for macCatalyst. + list(APPEND test_dependencies + "swift-reflection-test${DEFAULT_OSX_VARIANT_SUFFIX}") + else() + list(APPEND test_dependencies + "swift-reflection-test${VARIANT_SUFFIX}_signed") + endif() endif() if(NOT "${COVERAGE_DB}" STREQUAL "") @@ -391,6 +418,7 @@ _Block_release(void) { }\n") endforeach() endforeach() endforeach() + endforeach() endforeach() # Add shortcuts for the default variant. diff --git a/test/Driver/linker-clang_rt.swift b/test/Driver/linker-clang_rt.swift index 6e1a37e03f6d2..7c8ad36805a54 100644 --- a/test/Driver/linker-clang_rt.swift +++ b/test/Driver/linker-clang_rt.swift @@ -14,6 +14,7 @@ // RUN: touch %t/lib/swift/clang/lib/darwin/libclang_rt.osx.a %t/lib/swift/clang/lib/darwin/libclang_rt.ios.a %t/lib/swift/clang/lib/darwin/libclang_rt.tvos.a %t/lib/swift/clang/lib/darwin/libclang_rt.watchos.a // RUN: %t/bin/swiftc -driver-print-jobs -target x86_64-apple-macosx10.9 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix CHECK-MACOS %s +// RUN: %t/bin/swiftc -driver-print-jobs -target x86_64-apple-ios13.0-macabi %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix CHECK-MACCATALYST %s // RUN: %t/bin/swiftc -driver-print-jobs -target i386-apple-ios7 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix CHECK-IOS %s // RUN: %t/bin/swiftc -driver-print-jobs -target x86_64-apple-ios7 %S/../Inputs/empty.swift | %FileCheck -check-prefix CHECK -check-prefix CHECK-IOS %s @@ -31,6 +32,7 @@ // CHECK: {{(bin/)?}}ld{{(.exe)?"? }} // CHECK-NO-RUNTIME-NOT: libclang_rt +// CHECK-MACCATALYST-SAME: {{[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)clang(/|\\\\)lib(/|\\\\)darwin(/|\\\\)libclang_rt.osx.a}} // CHECK-MACOS-SAME: {{[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)clang(/|\\\\)lib(/|\\\\)darwin(/|\\\\)libclang_rt.osx.a}} // CHECK-IOS-SAME: {{[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)clang(/|\\\\)lib(/|\\\\)darwin(/|\\\\)libclang_rt.ios.a}} // CHECK-TVOS-SAME: {{[^ ]+(/|\\\\)lib(/|\\\\)swift(/|\\\\)clang(/|\\\\)lib(/|\\\\)darwin(/|\\\\)libclang_rt.tvos.a}} diff --git a/test/Driver/macabi-environment.swift b/test/Driver/macabi-environment.swift new file mode 100644 index 0000000000000..516d90fba6140 --- /dev/null +++ b/test/Driver/macabi-environment.swift @@ -0,0 +1,83 @@ +// Tests to check that the driver finds standard library in the macabi environment. + +// UNSUPPORTED: windows + +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios13.0-macabi -sdk %S/../Inputs/clang-importer-sdk %s | %FileCheck -check-prefix=IOS13-MACABI %s +// IOS13-MACABI: bin/swift +// IOS13-MACABI: -target x86_64-apple-ios13.0-macabi + +// IOS13-MACABI: bin/ld +// IOS13-MACABI-DAG: -L [[MACCATALYST_STDLIB_PATH:[^ ]+/lib/swift/maccatalyst]] +// IOS13-MACABI-DAG: -L [[MACOSX_STDLIB_PATH:[^ ]+/lib/swift/macosx]] +// IOS13-MACABI-DAG: -L [[MACCATALYST_SDK_STDLIB_PATH:[^ ]+/clang-importer-sdk/System/iOSSupport/usr/lib/swift]] +// IOS13-MACABI-DAG: -L [[MACOSX_SDK_STDLIB_PATH:[^ ]+/clang-importer-sdk/usr/lib/swift]] +// IOS13-MACABI-DAG: -rpath [[MACCATALYST_STDLIB_PATH]] +// IOS13-MACABI-DAG: -rpath [[MACOSX_STDLIB_PATH]] +// IOS13-MACABI-DAG: -rpath [[MACCATALYST_SDK_STDLIB_PATH]] +// IOS13-MACABI-DAG: -rpath [[MACOSX_SDK_STDLIB_PATH]] +// IOS13-MACABI-DAG: -maccatalyst_version_min 13.0.0 + + +// Test using target-variant to build zippered outputs + +// RUN: %swiftc_driver -driver-print-jobs -c -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0-macabi %s | %FileCheck -check-prefix=ZIPPERED-VARIANT-OBJECT %s +// ZIPPERED-VARIANT-OBJECT: bin/swift +// ZIPPERED-VARIANT-OBJECT: -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0-macabi + +// RUN: %swiftc_driver -driver-print-jobs -emit-library -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0-macabi -module-name foo %s | %FileCheck -check-prefix=ZIPPERED-VARIANT-LIBRARY %s +// ZIPPERED-VARIANT-LIBRARY: bin/swift +// ZIPPERED-VARIANT-LIBRARY: -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0-macabi + +// ZIPPERED-VARIANT-LIBRARY: bin/ld +// ZIPPERED-VARIANT-LIBRARY: -macosx_version_min 10.14.0 -maccatalyst_version_min 13.0.0 + +// Make sure we pass the -target-variant when creating the pre-compiled header. +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0-macabi -enable-bridging-pch -import-objc-header %S/Inputs/bridging-header.h %s | %FileCheck -check-prefix=ZIPPERED-VARIANT-PCH %s +// ZIPPERED-VARIANT-PCH: bin/swift +// ZIPPERED-VARIANT-PCH: -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0-macabi +// ZIPPERED_VARIANT-PCH -emit-pch +// ZIPPERED-VARIANT-PCH: bin/swift +// ZIPPERED-VARIANT-PCH: -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0-macabi +// ZIPPERED-VARIANT-PCH: bin/ld +// ZIPPERED-VARIANT-PCH: -macosx_version_min 10.14.0 -maccatalyst_version_min 13.0.0 + +// Test using 'reverse' target-variant to build zippered outputs when the primary +// target is ios-macabi + +// RUN: %swiftc_driver -driver-print-jobs -c -target x86_64-apple-ios13.0-macabi -target-variant x86_64-apple-macosx10.14 %s | %FileCheck -check-prefix=REVERSE-ZIPPERED-VARIANT-OBJECT %s +// REVERSE-ZIPPERED-VARIANT-OBJECT: bin/swift +// REVERSE-ZIPPERED-VARIANT-OBJECT: -target x86_64-apple-ios13.0-macabi -target-variant x86_64-apple-macosx10.14 + +// RUN: %swiftc_driver -driver-print-jobs -emit-library -target x86_64-apple-ios13.0-macabi -target-variant x86_64-apple-macosx10.14 -module-name foo %s | %FileCheck -check-prefix=REVERSE-ZIPPERED-VARIANT-LIBRARY %s +// REVERSE-ZIPPERED-VARIANT-LIBRARY: bin/swift +// REVERSE-ZIPPERED-VARIANT-LIBRARY: -target x86_64-apple-ios13.0-macabi -target-variant x86_64-apple-macosx10.14 + +// REVERSE-ZIPPERED-VARIANT-LIBRARY: bin/ld +// REVERSE-ZIPPERED-VARIANT-LIBRARY: -maccatalyst_version_min 13.0.0 -macosx_version_min 10.14.0 + +// Make sure we pass the -target-variant when creating the pre-compiled header. +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios13.0-macabi -target-variant x86_64-apple-macosx10.14 -enable-bridging-pch -import-objc-header %S/Inputs/bridging-header.h %s | %FileCheck -check-prefix=REVERSE-ZIPPERED-VARIANT-PCH %s +// REVERSE-ZIPPERED-VARIANT-PCH: bin/swift +// REVERSE-ZIPPERED-VARIANT-PCH: -target x86_64-apple-ios13.0-macabi -target-variant x86_64-apple-macosx10.14 +// REVERSE-ZIPPERED_VARIANT-PCH -emit-pch +// REVERSE-ZIPPERED-VARIANT-PCH: bin/swift +// REVERSE-ZIPPERED-VARIANT-PCH: -target x86_64-apple-ios13.0-macabi -target-variant x86_64-apple-macosx10.14 +// REVERSE-ZIPPERED-VARIANT-PCH: bin/ld +// REVERSE-ZIPPERED-VARIANT-PCH: -maccatalyst_version_min 13.0.0 -macosx_version_min 10.14.0 + +// RUN: not %swiftc_driver -target x86_64-apple-macosx10.14 -target-variant x86_64-apple-ios13.0 %s 2>&1 | %FileCheck --check-prefix=UNSUPPORTED-TARGET-VARIANT %s +// RUN: not %swiftc_driver -target x86_64-apple-ios13.0 -target-variant x86_64-apple-macosx10.14 %s 2>&1 | %FileCheck --check-prefix=UNSUPPORTED-TARGET %s + +// UNSUPPORTED-TARGET-VARIANT: error: unsupported '-target-variant' value {{.*}}; use 'ios-macabi' instead +// UNSUPPORTED-TARGET: error: unsupported '-target' value {{.*}}; use 'ios-macabi' instead + +// When compiling for iOS, pass iphoneos_version_min to the linker, not maccatalyst_version_min. + +// RUN: %swiftc_driver -driver-print-jobs -target arm64-apple-ios13.0 -sdk %S/../Inputs/clang-importer-sdk %s | %FileCheck -check-prefix=IOS13-NO-MACABI -implicit-check-not=maccatalyst_version_min %s +// IOS13-NO-MACABI: bin/swift +// IOS13-NO-MACABI: -target arm64-apple-ios13.0 + +// IOS13-NO-MACABI: bin/ld +// IOS13-NO-MACABI-DAG: -L {{[^ ]+/lib/swift/iphoneos}} +// IOS13-NO-MACABI-DAG: -L {{[^ ]+/clang-importer-sdk/usr/lib/swift}} +// IOS13-NO-MACABI-DAG: -iphoneos_version_min 13.0.0 diff --git a/test/IDE/complete_decl_attribute.swift b/test/IDE/complete_decl_attribute.swift index e6528dbb15489..9ab5063a1707b 100644 --- a/test/IDE/complete_decl_attribute.swift +++ b/test/IDE/complete_decl_attribute.swift @@ -37,6 +37,8 @@ struct MyStruct {} // AVAILABILITY1-NEXT: Keyword/None: tvOSApplicationExtension[#Platform#]; name=tvOSApplicationExtension{{$}} // AVAILABILITY1-NEXT: Keyword/None: watchOSApplicationExtension[#Platform#]; name=watchOSApplicationExtension{{$}} // AVAILABILITY1-NEXT: Keyword/None: OSXApplicationExtension[#Platform#]; name=OSXApplicationExtension{{$}} +// AVAILABILITY1-NEXT: Keyword/None: macCatalyst[#Platform#]; name=macCatalyst +// AVAILABILITY1-NEXT: Keyword/None: macCatalystApplicationExtension[#Platform#]; name=macCatalystApplicationExtension // AVAILABILITY1-NEXT: End completions @available(*, #^AVAILABILITY2^#) diff --git a/test/Parse/ConditionalCompilation/basicParseErrors.swift b/test/Parse/ConditionalCompilation/basicParseErrors.swift index f68a7c9849d65..9d0616bb0b925 100644 --- a/test/Parse/ConditionalCompilation/basicParseErrors.swift +++ b/test/Parse/ConditionalCompilation/basicParseErrors.swift @@ -148,7 +148,7 @@ undefinedFunc() // expected-error {{use of unresolved identifier 'undefinedFunc' #if _endian(arm64) // expected-warning {{unknown endianness for build configuration '_endian'}} expected-note {{did you mean 'arch'}} {{5-12=arch}} #endif -#if targetEnvironment(_ObjC) // expected-warning {{unknown target environment for build configuration 'targetEnvironment'}} expected-note {{did you mean 'simulator'}} {{23-28=simulator}} +#if targetEnvironment(_ObjC) // expected-warning {{unknown target environment for build configuration 'targetEnvironment'}} expected-note {{did you mean 'macabi'}} {{23-28=macabi}} #endif #if os(iOS) || os(simulator) // expected-warning {{unknown operating system for build configuration 'os'}} expected-note {{did you mean 'targetEnvironment'}} {{16-18=targetEnvironment}} diff --git a/test/Parse/ConditionalCompilation/macabiTargetEnv.swift b/test/Parse/ConditionalCompilation/macabiTargetEnv.swift new file mode 100644 index 0000000000000..f1990b3eb633f --- /dev/null +++ b/test/Parse/ConditionalCompilation/macabiTargetEnv.swift @@ -0,0 +1,36 @@ +// RUN: %swift -swift-version 4 -typecheck %s -verify -target x86_64-apple-ios12.0-macabi -parse-stdlib +// RUN: %swift-ide-test -swift-version 4 -test-input-complete -source-filename=%s -target x86_64-apple-ios12.0-macabi + +// REQUIRES: OS=maccatalyst + +#if targetEnvironment(macabi) // expected-warning {{'macabi' has been renamed to 'macCatalyst'}} {{23-29=macCatalyst}} +func underMacABI() { + foo() // expected-error {{use of unresolved identifier 'foo'}} +} +#endif + +#if !targetEnvironment(macabi) // expected-warning {{'macabi' has been renamed to 'macCatalyst'}} {{24-30=macCatalyst}} +// This block does not typecheck but the #if prevents it from +// from being a compiler error. +let i: SomeType = "SomeString" // no-error +#endif + +#if targetEnvironment(macCatalyst) +func underTargetEnvironmentMacCatalyst() { + foo() // expected-error {{use of unresolved identifier 'foo'}} +} +#endif + +// Make sure we don't treat the macabi environment as a simulator. +#if targetEnvironment(simulator) +// This block does not typecheck but the #if prevents it from +// from being a compiler error. +let i: SomeType = "SomeString" // no-error +#endif + +#if os(macCatalyst) +// expected-warning@-1 {{unknown operating system for build configuration 'os'}} +// expected-note@-2 *{{did you mean}} +func underOSMacCatalyst() { +} +#endif diff --git a/test/attr/attr_availability_maccatalyst.swift b/test/attr/attr_availability_maccatalyst.swift new file mode 100644 index 0000000000000..3c3bf676f1c8b --- /dev/null +++ b/test/attr/attr_availability_maccatalyst.swift @@ -0,0 +1,125 @@ +// RUN: %swift -typecheck -verify -parse-stdlib -target x86_64-apple-ios51.0-macabi %s + +// REQUIRES: OS=maccatalyst + +@available(macCatalyst, introduced: 1.0, deprecated: 2.0, obsoleted: 9.0, + message: "you don't want to do that anyway") +func obsoletedOnMacCatalyst() { } +// expected-note @-1{{'obsoletedOnMacCatalyst()' was obsoleted in Mac Catalyst 9.0}} + +obsoletedOnMacCatalyst() // expected-error{{'obsoletedOnMacCatalyst()' is unavailable in Mac Catalyst: you don't want to do that anyway}} + +@available(iOS, introduced: 1.0, deprecated: 2.0, obsoleted: 9.0, + message: "you don't want to do that anyway") +func obsoletedOnIOS() { } +// expected-note @-1{{'obsoletedOnIOS()' was obsoleted in iOS 9.0}} + +obsoletedOnIOS() // expected-error{{'obsoletedOnIOS()' is unavailable in iOS: you don't want to do that anyway}} + + +@available(iOS, introduced: 1.0) +@available(macCatalyst, introduced: 1.0, obsoleted: 12.0) +func obsoletedOnMacCatalystButNotIOS() { } +// expected-note @-1{{'obsoletedOnMacCatalystButNotIOS()' was obsoleted in Mac Catalyst 12.0}} + +obsoletedOnMacCatalystButNotIOS() // expected-error {{'obsoletedOnMacCatalystButNotIOS()' is unavailable}} + + +@available(iOS, introduced: 12.0, obsoleted: 12.0) +@available(macCatalyst, introduced: 12.0) +func obsoletedOnIOSButNotMacCatalyst() { } +obsoletedOnIOSButNotMacCatalyst() // no-error + + + +@available(iOS, introduced: 1.0) +@available(macCatalyst, introduced: 1.0, deprecated: 12.0) +func deprecatedOnMacCatalystButNotIOS() { } + +deprecatedOnMacCatalystButNotIOS() // expected-warning {{deprecatedOnMacCatalystButNotIOS()' was deprecated in Mac Catalyst 12.0}} + +@available(iOS, introduced: 12.0, deprecated: 13.0) +@available(macCatalyst, introduced: 12.0) +func deprecatedOnIOSButNotMacCatalyst() { } +deprecatedOnIOSButNotMacCatalyst() // no-warning + + +@available(iOS 55.0, macCatalyst 56.0, *) +func introducedLaterOnMacCatalyst() { +} + +// expected-note@+1 *{{add @available attribute to enclosing global function}} +func testPoundAvailable() { + + if #available(macCatalyst 55.0, *) { + introducedLaterOnMacCatalyst() // expected-error {{'introducedLaterOnMacCatalyst()' is only available in Mac Catalyst 56.0 or newer}} + // expected-note@-1 {{add 'if #available' version check}} + } + + // macCatalyst should win over iOS when present + + if #available(iOS 56.0, macCatalyst 55.0, *) { + introducedLaterOnMacCatalyst() // expected-error {{'introducedLaterOnMacCatalyst()' is only available in Mac Catalyst 56.0 or newer}} + // expected-note@-1 {{add 'if #available' version check}} + } + + if #available(iOS 55.0, macCatalyst 56.0, *) { + introducedLaterOnMacCatalyst() // no-warning + } + + // iOS availability should be inherited when macCatalyst is not present + + if #available(iOS 55.0, *) { + introducedLaterOnMacCatalyst() // expected-error {{'introducedLaterOnMacCatalyst()' is only available in Mac Catalyst 56.0 or newer}} + // expected-note@-1 {{add 'if #available' version check}} + } + + if #available(iOS 56.0, *) { + introducedLaterOnMacCatalyst() // no-warning + } + + // macOS availability doesn't count on macCatalyst for Swift. + if #available(macOS 9999.0, *) { + introducedLaterOnMacCatalyst() // expected-error {{'introducedLaterOnMacCatalyst()' is only available in Mac Catalyst 56.0 or newer}} + // expected-note@-1 {{add 'if #available' version check}} + } +} + +@available(iOS 55.0, *) +func testUnnecessaryPoundAvailable() { // expected-note*{{enclosing scope here}} + + // Even though we're compiling for macCatalyst, the #available is expressed in terms of + // 'iOS', so we should use that to report to the user in the diagnostic. + if #available(iOS 54.0, *) { + // expected-warning@-1 {{unnecessary check for 'iOS'; enclosing scope ensures guard will always be true}} + } + + if #available(macCatalyst 54.0, *) { + // expected-warning@-1 {{unnecessary check for 'macCatalyst'; enclosing scope ensures guard will always be true}} + } + + if #available(macCatalyst 54.0, iOS 53.0, *) { + // expected-warning@-1 {{unnecessary check for 'macCatalyst'; enclosing scope ensures guard will always be true}} + } + + if #available(iOS 53.0, macCatalyst 54.0, *) { + // expected-warning@-1 {{unnecessary check for 'macCatalyst'; enclosing scope ensures guard will always be true}} + } +} + +// Test that we don't accidentally try to validate @available(iOS, ...) attrs +// on accessors against the property's @available(macCatalyst, ...) attr. +// (rdar://problem/50067784) +class X { + @available(iOS 3.2, macCatalyst 13, *) + var x: X { + get { return self } + set { } + } +} + +protocol P: Builtin.AnyObject { + var x: X { get set } +} + +extension X: P {} diff --git a/test/lit.cfg b/test/lit.cfg index 4ee12fa1e9f31..94394c3ba1830 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -319,6 +319,10 @@ lit_config.note('Using resource dir: ' + test_resource_dir) # Parse the variant triple. (run_cpu, run_vendor, run_os, run_vers) = re.match('([^-]+)-([^-]+)-([^0-9]+)(.*)', config.variant_triple).groups() +if run_os == 'ios' and run_vers.endswith('-macabi'): + run_vers = run_vers[0:-len('-macabi')] + run_os = 'maccatalyst' + run_ptrsize = '64' if ('64' in run_cpu or run_cpu == "s390x") else '32' run_endian = 'little' if run_cpu != 's390x' else 'big' @@ -602,7 +606,12 @@ if config.benchmark_o != 'Benchmark_O': config.substitutions.append(('%target-triple', config.variant_triple)) if run_vendor == 'apple': - if True: + if run_os == 'maccatalyst': + config.stable_abi_triple = '%s-%s-ios13.0-macabi' % (run_cpu, run_vendor) + config.pre_stable_abi_triple = config.stable_abi_triple + config.next_stable_abi_triple = config.stable_abi_triple + config.available_features.add('swift_stable_abi') + else: # iOS 12.2 does not support 32-bit targets, so we cannot run tests that # want to deploy to an iOS that has Swift in the OS. if run_os == 'ios' and run_ptrsize == '32': @@ -612,6 +621,7 @@ if run_vendor == 'apple': PRE_STABLE_VERSION = { 'macosx': '10.14.3', 'ios': '12.1', + 'maccatalyst': '12.1', 'tvos': '12.1', 'watchos': '5.1' } @@ -622,6 +632,7 @@ if run_vendor == 'apple': STABLE_VERSION = { 'macosx': '10.14.4', 'ios': '12.2', + 'maccatalyst': '12.2', 'tvos': '12.2', 'watchos': '5.2' } @@ -632,6 +643,7 @@ if run_vendor == 'apple': NEXT_STABLE_VERSION = { 'macosx': '10.15', 'ios': '13', + 'maccatalyst': '13', 'tvos': '13', 'watchos': '6' } @@ -668,6 +680,17 @@ config.substitutions.append(('%sanitizers-target-triple', config.variant_triple.replace("ios7", "ios8"))) config.substitutions.append(('%target-cpu', run_cpu)) + +target_os_abi = run_os +target_os_is_maccatalyst = "FALSE" +if (run_os == 'maccatalyst'): + # For purposes of ABI, treat maccatalyst as macosx since the maccatalyst ABI + # must match the macosx ABI. + target_os_abi = 'macosx' + target_os_is_maccatalyst = "TRUE" + config.available_features.add("OS=ios") +config.substitutions.append(('%target-os-abi', target_os_abi)) +config.substitutions.append(('%target-os-is-maccatalyst', target_os_is_maccatalyst)) config.substitutions.append(('%target-endian', run_endian)) config.substitutions.append(('%target-os', run_os)) config.substitutions.append(('%target-ptrsize', run_ptrsize)) @@ -703,7 +726,12 @@ if 'swift_interpreter' in config.available_features: config.target_runtime = "unknown" -swift_reflection_test_name = 'swift-reflection-test' + config.variant_suffix +if (getattr(config, 'darwin_enable_maccatalyst', False) and + config.darwin_maccatalyst_build_flavor == "ios-like"): + variant_suffix = config.darwin_osx_variant_suffix +else: + variant_suffix = config.variant_suffix +swift_reflection_test_name = 'swift-reflection-test' + variant_suffix def use_interpreter_for_simple_runs(): def make_simple_target_run(gyb=False, stdlib=False, parameterized=False): @@ -858,25 +886,49 @@ if run_vendor == 'apple': lit_config.fatal('Could not get or decode sw_vers output. ' + 'Perhaps the simulator is not working.') - elif run_os == 'macosx': + elif run_os == 'macosx' or run_os == 'maccatalyst': # OS X lit_config.note("Testing OS X " + config.variant_triple) xcrun_sdk_name = "macosx" - config.target_cc_options = ( - "-arch %s -m%s-version-min=%s %s" % - (run_cpu, run_os, run_vers, clang_mcp_opt)) + + if run_os == 'maccatalyst': + # For maccatalyst, pass the target triple to clang + # rather than arch and version separately. + config.target_cc_options = ( + "-target %s %s" % + (config.variant_triple, clang_mcp_opt)) + else: + config.target_cc_options = ( + "-arch %s -m%s-version-min=%s %s" % + (run_cpu, run_os, run_vers, clang_mcp_opt)) + + maccatalyst_frameworks_component = "" + if run_os == 'maccatalyst': + # Additional framework search paths for macCatalyst. + # These have to come before other search paths so that for + # unzippered twin frameworks the unzippered twin version + # is favored under macCatalyst. + maccatalyst_frameworks_dir = make_path(config.variant_sdk, + "System", "iOSSupport", "System", "Library", "Frameworks") + maccatalyst_frameworks_component = ( "-F %r" % maccatalyst_frameworks_dir ) + # Module triples end in ios-macabi. + target_specific_module_triple = '{}-apple-ios-macabi'.format( + { 'aarch64': 'arm64', 'amd64': 'x86_64' }.get(run_cpu, run_cpu) + ) config.target_build_swift = ( - ("%s %s %s -F %r -toolchain-stdlib-rpath " + ("%s %s %s %s -F %r -toolchain-stdlib-rpath " + "-Xlinker -rpath -Xlinker %r %s %s %s %s " + "-F %r -Xlinker -rpath -Xlinker %r") % (xcrun_prefix, config.swiftc, target_options, + maccatalyst_frameworks_component, extra_frameworks_dir, extra_frameworks_dir, sdk_overlay_linker_opt, config.swift_test_options, config.swift_driver_test_options, swift_execution_tests_extra_flags, sourcekitd_framework_dir, sourcekitd_framework_dir)) + config.target_run = "" target_future_version = "10.99" @@ -896,9 +948,13 @@ if run_vendor == 'apple': config.target_sdk_name = xcrun_sdk_name config.target_ld = "%s ld -L%r" % (xcrun_prefix, make_path(test_resource_dir, config.target_sdk_name)) + + maccatalyst_extra_frameworks = "" + if run_os == 'maccatalyst': + maccatalyst_extra_frameworks = "-F {}/System/iOSSupport/System/Library/Frameworks".format(config.variant_sdk) config.target_swift_frontend = ( - "%s -frontend %s -sdk %r %s %s" % - (config.swiftc, target_options, config.variant_sdk, + "%s -frontend %s -sdk %r %s %s %s" % + (config.swiftc, target_options, config.variant_sdk, maccatalyst_extra_frameworks, config.swift_test_options, config.swift_frontend_test_options)) subst_target_swift_frontend_mock_sdk = ( "%s -frontend %s -sdk %r %s %s" % @@ -940,6 +996,7 @@ if run_vendor == 'apple': config.target_add_rpath = r'-Xlinker -rpath -Xlinker \1' target_future = format('%s-apple-%s%s' % (run_cpu, run_os, target_future_version)) + config.otool_classic = ("%s otool-classic" % (xcrun_prefix)) elif run_os in ['windows-msvc']: lit_config.note('Testing Windows ' + config.variant_triple) @@ -1480,6 +1537,13 @@ if platform.system() != 'Darwin' or swift_test_mode == 'optimize_none_with_impli platform_module_dir = make_path(test_resource_dir, config.target_sdk_name) if run_vendor != 'apple': platform_module_dir = make_path(platform_module_dir, run_cpu) + +platform_dylib_dir = platform_module_dir +if run_os == 'maccatalyst' and config.darwin_maccatalyst_build_flavor == "ios-like": + # When using the ios-macabi triple, look for module files + # in the 'maccatalyst' compiler resource directory. + platform_module_dir = make_path(test_resource_dir, 'maccatalyst') + lit_config.note('Using platform module dir: ' + platform_module_dir) if test_sdk_overlay_dir: platform_sdk_overlay_dir = test_sdk_overlay_dir @@ -1496,10 +1560,15 @@ if os.path.exists(static_libswiftCore_path): # Set up testing with the standard libraries coming from the OS / just-built libraries # default Swift tests to use the just-built libraries -target_stdlib_path = platform_module_dir +target_stdlib_path = platform_dylib_dir if not kIsWindows: libdispatch_path = getattr(config, 'libdispatch_artifact_dir', '') if 'use_os_stdlib' not in lit_config.params: + if run_os == 'maccatalyst': + # Under macCatalyst we need to have the unzippered twin dylib dir come before + # the zippered/macosx dylib dir so that unzippered twins are picked upload_dylibs + # before the macOS variant. + target_stdlib_path = "{0}:{1}".format(platform_module_dir, target_stdlib_path) lit_config.note('Testing with the just-built libraries at ' + target_stdlib_path) config.target_run = ( "/usr/bin/env " @@ -1513,6 +1582,8 @@ if not kIsWindows: if run_vendor == 'apple': #If we get swift-in-the-OS for non-Apple platforms, add a condition here os_stdlib_path = "/usr/lib/swift" + if run_os == 'maccatalyst': + os_stdlib_path = "/System/iOSSupport/usr/lib/swift:/usr/lib/swift" all_stdlib_path = os.path.pathsep.join((os_stdlib_path, target_stdlib_path)) lit_config.note('Testing with the standard libraries coming from the OS ' + all_stdlib_path) config.target_run = ( @@ -1667,6 +1738,8 @@ config.substitutions.append(('%target-swift-emit-pcm', config.substitutions.insert(0, ('%platform-module-dir', platform_module_dir)) config.substitutions.insert(0, ('%platform-sdk-overlay-dir', platform_sdk_overlay_dir)) +config.substitutions.insert(0, ('%platform-dylib-dir', platform_dylib_dir)) +config.substitutions.insert(0, ('%test-resource-dir', test_resource_dir)) if run_vendor != 'apple': extra_frameworks_dir = '' @@ -1690,6 +1763,9 @@ config.substitutions.append(('%target-resilience-test', config.target_resilience config.substitutions.append(('%llvm-profdata', config.llvm_profdata)) config.substitutions.append(('%llvm-cov', config.llvm_cov)) +if hasattr(config, 'otool_classic'): + config.substitutions.append(('%otool-classic', config.otool_classic)) + config.substitutions.append(('%FileCheck', '%r %r --sanitize BUILD_DIR=%r --sanitize SOURCE_DIR=%r --use-filecheck %r %s' % ( sys.executable, diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 69a41da6cc847..69107930747b0 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -51,6 +51,10 @@ msvc_runtime_flags = { config.swift_stdlib_msvc_runtime = \ msvc_runtime_flags["@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@"] +config.darwin_enable_maccatalyst = "@SWIFT_ENABLE_MACCATALYST@" == "TRUE" +config.darwin_maccatalyst_build_flavor = "@BUILD_FLAVOR@" +config.darwin_osx_variant_suffix = "@DEFAULT_OSX_VARIANT_SUFFIX@" + # Please remember to handle empty strings and/or unset variables correctly. if "@SWIFT_ASAN_BUILD@" == "TRUE": @@ -103,6 +107,9 @@ if "@CMAKE_GENERATOR@" == "Xcode": config.available_features.add("CMAKE_GENERATOR=@CMAKE_GENERATOR@") +if "@SWIFT_ENABLE_MACCATALYST@" == "TRUE": + config.available_features.add('maccatalyst_support') + if "@SWIFT_BUILD_SYNTAXPARSERLIB@" == "TRUE": config.available_features.add('syntax_parser_lib') diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp index 9ed275a1d1a87..9e7616216ddab 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp @@ -584,10 +584,12 @@ static void reportAttributes(ASTContext &Ctx, DocInfoConsumer &Consumer) { static UIdent AvailableAttrKind("source.lang.swift.attribute.availability"); static UIdent PlatformIOS("source.availability.platform.ios"); + static UIdent PlatformMacCatalyst("source.availability.platform.maccatalyst"); static UIdent PlatformOSX("source.availability.platform.osx"); static UIdent PlatformtvOS("source.availability.platform.tvos"); static UIdent PlatformWatchOS("source.availability.platform.watchos"); static UIdent PlatformIOSAppExt("source.availability.platform.ios_app_extension"); + static UIdent PlatformMacCatalystAppExt("source.availability.platform.maccatalyst_app_extension"); static UIdent PlatformOSXAppExt("source.availability.platform.osx_app_extension"); static UIdent PlatformtvOSAppExt("source.availability.platform.tvos_app_extension"); static UIdent PlatformWatchOSAppExt("source.availability.platform.watchos_app_extension"); @@ -601,6 +603,8 @@ static void reportAttributes(ASTContext &Ctx, PlatformUID = UIdent(); break; case PlatformKind::iOS: PlatformUID = PlatformIOS; break; + case PlatformKind::macCatalyst: + PlatformUID = PlatformIOS; break; case PlatformKind::OSX: PlatformUID = PlatformOSX; break; case PlatformKind::tvOS: @@ -609,6 +613,8 @@ static void reportAttributes(ASTContext &Ctx, PlatformUID = PlatformWatchOS; break; case PlatformKind::iOSApplicationExtension: PlatformUID = PlatformIOSAppExt; break; + case PlatformKind::macCatalystApplicationExtension: + PlatformUID = PlatformMacCatalystAppExt; break; case PlatformKind::OSXApplicationExtension: PlatformUID = PlatformOSXAppExt; break; case PlatformKind::tvOSApplicationExtension: diff --git a/utils/build-script b/utils/build-script index 689355d07171d..1ee9d8c455d09 100755 --- a/utils/build-script +++ b/utils/build-script @@ -596,6 +596,13 @@ class BuildScriptInvocation(object): "--extra-swift-args=%s" % ';'.join(args.extra_swift_args) ] + # Enable macCatalyst + if args.maccatalyst: + (args.extra_cmake_options + .append('-DSWIFT_ENABLE_MACCATALYST:BOOL=TRUE')) + if args.maccatalyst_ios_tests: + impl_args += ["--darwin-test-maccatalyst-ios-like=1"] + # If we have extra_cmake_options, combine all of them together and then # add them as one command. if args.extra_cmake_options: diff --git a/utils/build-script-impl b/utils/build-script-impl index c54e470557ebf..bf7d597106d4a 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -147,6 +147,7 @@ KNOWN_SETTINGS=( skip-build-llbuild "" "set to skip building llbuild" skip-build-lldb "" "set to skip building LLDB" skip-build-llvm "" "set to skip building LLVM/Clang" + skip-build-maccatalyst "" "set to skip building Swift stdlibs for macCatalyst" skip-build-osx "" "set to skip building Swift stdlibs for OS X" skip-build-playgroundsupport "" "set to skip building PlaygroundSupport" skip-build-static-foundation "" "set to skip building static Foundation" @@ -174,6 +175,7 @@ KNOWN_SETTINGS=( skip-test-linux "" "set to skip testing Swift stdlibs for Linux" skip-test-llbuild "" "set to skip testing llbuild" skip-test-lldb "" "set to skip testing lldb" + skip-test-maccatalyst "" "set to skip testing Swift stdlibs for macCatalyst" skip-test-osx "" "set to skip testing Swift stdlibs for OS X" skip-test-playgroundsupport "" "set to skip testing PlaygroundSupport" skip-test-swift "" "set to skip testing Swift" diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py index e6cb284d27187..1f1587c5b20d0 100644 --- a/utils/build_swift/build_swift/driver_arguments.py +++ b/utils/build_swift/build_swift/driver_arguments.py @@ -335,6 +335,13 @@ def create_argument_parser(): option('--skip-watchos', store_false('watchos'), help='set to skip everything watchOS-related') + option('--maccatalyst', toggle_true, + help='Enable building Swift with macCatalyst support') + + option('--maccatalyst-ios-tests', toggle_true, + help='When building for macCatalyst run tests with iOS-like ' + 'target triple') + option('--android', toggle_true, help='also build for Android') diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py index cb7f87f061d75..f91a9c21a13da 100644 --- a/utils/build_swift/tests/expected_options.py +++ b/utils/build_swift/tests/expected_options.py @@ -172,6 +172,8 @@ 'tsan_libdispatch_test': False, 'long_test': False, 'lto_type': None, + 'maccatalyst': False, + 'maccatalyst_ios_tests': False, 'dump_config': False, 'show_sdks': False, 'skip_build': False, @@ -441,6 +443,8 @@ class BuildScriptImplOption(_BaseOption): SetTrueOption('--llbuild', dest='build_llbuild'), SetTrueOption('--lldb', dest='build_lldb'), SetTrueOption('--libcxx', dest='build_libcxx'), + SetTrueOption('--maccatalyst', dest='maccatalyst'), + SetTrueOption('--maccatalyst-ios-tests', dest='maccatalyst_ios_tests'), SetTrueOption('--playgroundsupport', dest='build_playgroundsupport'), SetTrueOption('--skip-build'), SetTrueOption('--swiftpm', dest='build_swiftpm'), diff --git a/utils/swift_build_support/swift_build_support/host_specific_configuration.py b/utils/swift_build_support/swift_build_support/host_specific_configuration.py index e5316b043eff8..ecdb437113321 100644 --- a/utils/swift_build_support/swift_build_support/host_specific_configuration.py +++ b/utils/swift_build_support/swift_build_support/host_specific_configuration.py @@ -149,8 +149,18 @@ def __init__(self, host_target, args): subset_suffix = "-only_stress" else: subset_suffix = "" - self.swift_test_run_targets.append("check-swift{}{}-{}".format( - subset_suffix, suffix, name)) + + # Support for running the macCatalyst tests with + # the iOS-like target triple. + if name == "macosx-x86_64" and args.maccatalyst \ + and args.maccatalyst_ios_tests: + (self.swift_test_run_targets + .append("check-swift{}{}-{}".format( + subset_suffix, suffix, "macosx-maccatalyst-x86_64"))) + else: + (self.swift_test_run_targets + .append("check-swift{}{}-{}".format( + subset_suffix, suffix, name))) if args.test_optimized and not test_host_only: self.swift_test_run_targets.append( "check-swift{}-optimize-{}".format( diff --git a/utils/swift_build_support/tests/test_host_specific_configuration.py b/utils/swift_build_support/tests/test_host_specific_configuration.py index 136b8cc8a4fdc..5b8a6dd5f9e8c 100644 --- a/utils/swift_build_support/tests/test_host_specific_configuration.py +++ b/utils/swift_build_support/tests/test_host_specific_configuration.py @@ -616,6 +616,8 @@ def default_args(self): build_tvos_simulator=False, build_watchos_device=False, build_watchos_simulator=False, + maccatalyst=False, + maccatalyst_ios_tests=False, long_test=False, only_executable_test=False, stress_test=False,