diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bb1099078..11e6511c53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,14 @@ project(Foundation LANGUAGES C Swift) enable_testing() +if(NOT SWIFT_SYSTEM_NAME) + if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(SWIFT_SYSTEM_NAME macosx) + else() + set(SWIFT_SYSTEM_NAME "$") + endif() +endif() + # NOTE(compnerd) default to /MD or /MDd by default based on the configuration. # Cache the variable to allow the user to alter the configuration. set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL" CACHE @@ -38,6 +46,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift) option(BUILD_SHARED_LIBS "build shared libraries" ON) +option(BUILD_FULLY_STATIC "build fully static" NO) option(HAS_LIBDISPATCH_API "has libdispatch API" ON) option(BUILD_NETWORKING "build FoundationNetworking module" ON) option(BUILD_TOOLS "build tools" ON) @@ -49,6 +58,12 @@ endif() find_package(ICU COMPONENTS uc i18n REQUIRED OPTIONAL_COMPONENTS data) +# This is needed if we're statically linking, otherwise we can't pull in Dispatch +# because we won't have RT::rt as a CMake target. +if(NOT CMAKE_SYSTEM_NAME STREQUAL Android) + find_package(LibRT) +endif() + include(SwiftSupport) include(GNUInstallDirs) include(XCTest) @@ -99,13 +114,13 @@ if(NOT BUILD_SHARED_LIBS) endif() install(TARGETS CoreFoundation CFXMLInterface - DESTINATION lib/swift_static/$) + DESTINATION lib/swift_static/${SWIFT_SYSTEM_NAME}) if(BUILD_NETWORKING) set_property(GLOBAL APPEND PROPERTY Foundation_EXPORTS CFURLSessionInterface) install(TARGETS CFURLSessionInterface - DESTINATION lib/swift_static/$) + DESTINATION lib/swift_static/${SWIFT_SYSTEM_NAME}) endif() endif() diff --git a/CoreFoundation/Base.subproj/CFUtilities.c b/CoreFoundation/Base.subproj/CFUtilities.c index 7c3fc9f8e7..e3fdd98c04 100644 --- a/CoreFoundation/Base.subproj/CFUtilities.c +++ b/CoreFoundation/Base.subproj/CFUtilities.c @@ -1675,7 +1675,7 @@ CFDictionaryRef __CFGetEnvironment() { extern char **environ; char **envp = environ; #elif TARGET_OS_LINUX -#if !defined(environ) && !TARGET_OS_ANDROID +#if !defined(environ) && !TARGET_OS_ANDROID && !defined(__musl__) #define environ __environ #endif char **envp = environ; diff --git a/CoreFoundation/Base.subproj/CoreFoundation_Prefix.h b/CoreFoundation/Base.subproj/CoreFoundation_Prefix.h index bf6f203b5f..928fef002f 100644 --- a/CoreFoundation/Base.subproj/CoreFoundation_Prefix.h +++ b/CoreFoundation/Base.subproj/CoreFoundation_Prefix.h @@ -189,7 +189,8 @@ static dispatch_queue_t __ ## PREFIX ## Queue(void) { \ #define CF_RETAIN_BALANCED_ELSEWHERE(obj, identified_location) do { } while (0) #endif -#if (TARGET_OS_LINUX && !TARGET_OS_ANDROID && !TARGET_OS_CYGWIN) || TARGET_OS_WIN32 +#if !TARGET_OS_MAC +#if !HAVE_STRLCPY CF_INLINE size_t strlcpy(char * dst, const char * src, size_t maxlen) { const size_t srclen = strlen(src); @@ -201,7 +202,9 @@ strlcpy(char * dst, const char * src, size_t maxlen) { } return srclen; } +#endif +#if !HAVE_STRLCAT CF_INLINE size_t strlcat(char * dst, const char * src, size_t maxlen) { const size_t srclen = strlen(src); @@ -216,6 +219,7 @@ strlcat(char * dst, const char * src, size_t maxlen) { return dstlen + srclen; } #endif +#endif // !TARGET_OS_MAC #if TARGET_OS_WIN32 // Compatibility with boolean.h @@ -300,7 +304,7 @@ typedef unsigned long fd_mask; #endif -#if !TARGET_OS_CYGWIN && !TARGET_OS_BSD +#if !TARGET_OS_MAC && !HAVE_ISSETUGID #define issetugid() 0 #endif diff --git a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h index 642151ab34..9dc7379c9d 100644 --- a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h +++ b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h @@ -69,6 +69,7 @@ #include #include +#ifdef __GLIBC_PREREQ #if __GLIBC_PREREQ(2, 28) == 0 // required for statx() system call, glibc >=2.28 wraps the kernel function #include @@ -78,7 +79,7 @@ #include #define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */ #endif //__GLIBC_PREREQ(2. 28) - +#endif // defined(__GLIBC_PREREQ) #ifndef __NR_statx #include #endif // not __NR_statx @@ -562,7 +563,7 @@ CF_CROSS_PLATFORM_EXPORT int _CFOpenFile(const char *path, int opts); static inline int _direntNameLength(struct dirent *entry) { #ifdef _D_EXACT_NAMLEN // defined on Linux return _D_EXACT_NAMLEN(entry); -#elif TARGET_OS_ANDROID +#elif TARGET_OS_LINUX || TARGET_OS_ANDROID return strlen(entry->d_name); #else return entry->d_namlen; diff --git a/CoreFoundation/CMakeLists.txt b/CoreFoundation/CMakeLists.txt index beb48d6c86..2e8afc2139 100644 --- a/CoreFoundation/CMakeLists.txt +++ b/CoreFoundation/CMakeLists.txt @@ -6,6 +6,9 @@ project(CoreFoundation VERSION 1338 LANGUAGES ASM C) +include(CheckSymbolExists) +include(CheckIncludeFile) + set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED YES) @@ -70,8 +73,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL Android) add_compile_definitions($<$:_GNU_SOURCE>) if(CMAKE_SYSTEM_NAME STREQUAL Linux) - include(CheckSymbolExists) - include(CheckIncludeFile) list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) check_include_file("sched.h" HAVE_SCHED_H) if(HAVE_SCHED_H) @@ -90,6 +91,21 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL Windows) endif() endif() +# Look for some functions that may not be present on all platforms +check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY) +check_symbol_exists(strlcat "string.h" HAVE_STRLCAT) +check_symbol_exists(issetugid "unistd.h" HAVE_ISSETUGID) + +if(HAVE_STRLCPY) + add_compile_definitions($<$:HAVE_STRLCPY>) +endif() +if(HAVE_STRLCAT) + add_compile_definitions($<$:HAVE_STRLCAT>) +endif() +if(HAVE_ISSETUGID) + add_compile_definitions($<$:HAVE_ISSETUGID>) +endif() + add_compile_definitions($<$:U_SHOW_DRAFT_API>) add_compile_definitions($<$:CF_BUILDING_CF>) diff --git a/Sources/BlocksRuntime/CMakeLists.txt b/Sources/BlocksRuntime/CMakeLists.txt index 057302dd43..671627e4ee 100644 --- a/Sources/BlocksRuntime/CMakeLists.txt +++ b/Sources/BlocksRuntime/CMakeLists.txt @@ -11,5 +11,5 @@ set_target_properties(BlocksRuntime PROPERTIES add_library(BlocksRuntime::BlocksRuntime ALIAS BlocksRuntime) install(TARGETS BlocksRuntime - ARCHIVE DESTINATION lib/swift$<$>:_static>/$ - LIBRARY DESTINATION lib/swift$<$>:_static>/$) + ARCHIVE DESTINATION lib/swift$<$>:_static>/${SWIFT_SYSTEM_NAME} + LIBRARY DESTINATION lib/swift$<$>:_static>/${SWIFT_SYSTEM_NAME}) diff --git a/Sources/Foundation/CMakeLists.txt b/Sources/Foundation/CMakeLists.txt index fc093ce0c8..7154092e29 100644 --- a/Sources/Foundation/CMakeLists.txt +++ b/Sources/Foundation/CMakeLists.txt @@ -164,6 +164,11 @@ target_link_libraries(Foundation uuid PUBLIC swiftDispatch) +if("${CMAKE_C_COMPILER_TARGET}" MATCHES ".*-musl[^-*]$") + target_link_libraries(Foundation + PUBLIC + fts) +endif() set_target_properties(Foundation PROPERTIES INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$" diff --git a/Sources/Foundation/Data.swift b/Sources/Foundation/Data.swift index 86585a3a86..23254e6b22 100644 --- a/Sources/Foundation/Data.swift +++ b/Sources/Foundation/Data.swift @@ -28,6 +28,13 @@ @usableFromInline let memset = Glibc.memset @usableFromInline let memcpy = Glibc.memcpy @usableFromInline let memcmp = Glibc.memcmp +#elseif canImport(Musl) +@usableFromInline let calloc = Musl.calloc +@usableFromInline let malloc = Musl.malloc +@usableFromInline let free = Musl.free +@usableFromInline let memset = Musl.memset +@usableFromInline let memcpy = Musl.memcpy +@usableFromInline let memcmp = Musl.memcmp #elseif canImport(WASILibc) @usableFromInline let calloc = WASILibc.calloc @usableFromInline let malloc = WASILibc.malloc @@ -48,6 +55,8 @@ internal func malloc_good_size(_ size: Int) -> Int { #if canImport(Glibc) import Glibc +#elseif canImport(Musl) +import Musl #elseif canImport(WASILibc) import WASILibc #endif diff --git a/Sources/Foundation/FileHandle.swift b/Sources/Foundation/FileHandle.swift index a538a2975e..285bed7059 100644 --- a/Sources/Foundation/FileHandle.swift +++ b/Sources/Foundation/FileHandle.swift @@ -22,6 +22,11 @@ import Glibc fileprivate let _read = Glibc.read(_:_:_:) fileprivate let _write = Glibc.write(_:_:_:) fileprivate let _close = Glibc.close(_:) +#elseif canImport(Musl) +import Musl +fileprivate let _read = Musl.read(_:_:_:) +fileprivate let _write = Musl.write(_:_:_:) +fileprivate let _close = Musl.close(_:) #endif #if canImport(WinSDK) diff --git a/Sources/Foundation/Host.swift b/Sources/Foundation/Host.swift index 5fe7b29c5b..5a72373c6d 100644 --- a/Sources/Foundation/Host.swift +++ b/Sources/Foundation/Host.swift @@ -281,7 +281,7 @@ open class Host: NSObject { } var hints = addrinfo() hints.ai_family = PF_UNSPEC -#if os(macOS) || os(iOS) || os(Android) || os(OpenBSD) +#if os(macOS) || os(iOS) || os(Android) || os(OpenBSD) || canImport(Musl) hints.ai_socktype = SOCK_STREAM #else hints.ai_socktype = Int32(SOCK_STREAM.rawValue) diff --git a/Sources/Foundation/NSData.swift b/Sources/Foundation/NSData.swift index ed9e7f0529..e004c9502a 100644 --- a/Sources/Foundation/NSData.swift +++ b/Sources/Foundation/NSData.swift @@ -494,8 +494,10 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding { let createMode = Int(ucrt.S_IREAD) | Int(ucrt.S_IWRITE) #elseif canImport(Darwin) let createMode = Int(S_IRUSR) | Int(S_IWUSR) | Int(S_IRGRP) | Int(S_IWGRP) | Int(S_IROTH) | Int(S_IWOTH) -#else +#elseif canImport(Glibc) let createMode = Int(Glibc.S_IRUSR) | Int(Glibc.S_IWUSR) | Int(Glibc.S_IRGRP) | Int(Glibc.S_IWGRP) | Int(Glibc.S_IROTH) | Int(Glibc.S_IWOTH) +#elseif canImport(Musl) + let createMode = Int(Musl.S_IRUSR) | Int(Musl.S_IWUSR) | Int(Musl.S_IRGRP) | Int(Musl.S_IWGRP) | Int(Musl.S_IROTH) | Int(Musl.S_IWOTH) #endif guard let fh = FileHandle(path: path, flags: flags, createMode: createMode) else { throw _NSErrorWithErrno(errno, reading: false, path: path) diff --git a/Sources/Foundation/NSSwiftRuntime.swift b/Sources/Foundation/NSSwiftRuntime.swift index 04958446d7..c079ed6259 100644 --- a/Sources/Foundation/NSSwiftRuntime.swift +++ b/Sources/Foundation/NSSwiftRuntime.swift @@ -14,8 +14,10 @@ // This mimics the behavior of the swift sdk overlay on Darwin #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) @_exported import Darwin -#elseif os(Linux) || os(Android) || CYGWIN || os(OpenBSD) +#elseif canImport(Glibc) @_exported import Glibc +#elseif canImport(Musl) +@_exported import Musl #elseif os(WASI) @_exported import WASILibc #elseif os(Windows) diff --git a/Sources/Foundation/NSURL.swift b/Sources/Foundation/NSURL.swift index 9b121d6681..4b6a2a5b98 100644 --- a/Sources/Foundation/NSURL.swift +++ b/Sources/Foundation/NSURL.swift @@ -20,6 +20,8 @@ internal let kCFURLWindowsPathStyle = CFURLPathStyle.cfurlWindowsPathStyle import Darwin #elseif canImport(Glibc) import Glibc +#elseif canImport(Musl) +import Musl #endif // NOTE: this represents PLATFORM_PATH_STYLE diff --git a/Sources/Foundation/Process.swift b/Sources/Foundation/Process.swift index 542cc94cf1..8d5ac46563 100644 --- a/Sources/Foundation/Process.swift +++ b/Sources/Foundation/Process.swift @@ -776,7 +776,7 @@ open class Process: NSObject { } var taskSocketPair : [Int32] = [0, 0] -#if os(macOS) || os(iOS) || os(Android) || os(OpenBSD) +#if os(macOS) || os(iOS) || os(Android) || os(OpenBSD) || canImport(Musl) socketpair(AF_UNIX, SOCK_STREAM, 0, &taskSocketPair) #else socketpair(AF_UNIX, Int32(SOCK_STREAM.rawValue), 0, &taskSocketPair) diff --git a/Sources/Foundation/Thread.swift b/Sources/Foundation/Thread.swift index 7734cf738d..7fbcbb522e 100644 --- a/Sources/Foundation/Thread.swift +++ b/Sources/Foundation/Thread.swift @@ -14,6 +14,8 @@ import WinSDK #if canImport(Glibc) import Glibc +#elseif canImport(Musl) +import Musl #endif // WORKAROUND_SR9811 @@ -356,13 +358,15 @@ open class Thread : NSObject { _cancelled = true } + // ###TODO: Switch these over to using the Swift runtime's backtracer + // once we have Windows support there. private class func backtraceAddresses(_ body: (UnsafeMutablePointer, Int) -> [T]) -> [T] { // Same as swift/stdlib/public/runtime/Errors.cpp backtrace let maxSupportedStackDepth = 128; let addrs = UnsafeMutablePointer.allocate(capacity: maxSupportedStackDepth) defer { addrs.deallocate() } -#if os(Android) || os(OpenBSD) +#if os(Android) || os(OpenBSD) || canImport(Musl) let count = 0 #elseif os(Windows) let count = RtlCaptureStackBackTrace(0, DWORD(maxSupportedStackDepth), @@ -383,7 +387,7 @@ open class Thread : NSObject { } open class var callStackSymbols: [String] { -#if os(Android) || os(OpenBSD) +#if os(Android) || os(OpenBSD) || canImport(Musl) return [] #elseif os(Windows) let hProcess: HANDLE = GetCurrentProcess() diff --git a/Sources/FoundationNetworking/CMakeLists.txt b/Sources/FoundationNetworking/CMakeLists.txt index 1a8f516e98..183013cc82 100644 --- a/Sources/FoundationNetworking/CMakeLists.txt +++ b/Sources/FoundationNetworking/CMakeLists.txt @@ -72,6 +72,14 @@ if(NOT BUILD_SHARED_LIBS) PRIVATE "SHELL:-Xfrontend -public-autolink-library -Xfrontend curl") + if(BUILD_FULLY_STATIC) + target_compile_options(FoundationNetworking + PRIVATE + "SHELL:-Xfrontend -public-autolink-library -Xfrontend crypto" + "SHELL:-Xfrontend -public-autolink-library -Xfrontend ssl" + "SHELL:-Xfrontend -public-autolink-library -Xfrontend z") + endif() + # Merge private dependencies into single static objects archive set_property(TARGET FoundationNetworking PROPERTY STATIC_LIBRARY_OPTIONS $) diff --git a/Sources/FoundationXML/CMakeLists.txt b/Sources/FoundationXML/CMakeLists.txt index 944ea25875..5a73f70f58 100644 --- a/Sources/FoundationXML/CMakeLists.txt +++ b/Sources/FoundationXML/CMakeLists.txt @@ -23,6 +23,12 @@ if(NOT BUILD_SHARED_LIBS) PRIVATE "SHELL:-Xfrontend -public-autolink-library -Xfrontend xml2") + if(BUILD_FULLY_STATIC) + target_compile_options(FoundationXML + PRIVATE + "SHELL:-Xfrontend -public-autolink-library -Xfrontend z") + endif() + # Merge private dependencies into single static objects archive set_property(TARGET FoundationXML PROPERTY STATIC_LIBRARY_OPTIONS $) diff --git a/Sources/Tools/plutil/CMakeLists.txt b/Sources/Tools/plutil/CMakeLists.txt index b1c843506a..30ff29bb0c 100644 --- a/Sources/Tools/plutil/CMakeLists.txt +++ b/Sources/Tools/plutil/CMakeLists.txt @@ -28,7 +28,7 @@ if(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin|Windows") endif() set_target_properties(plutil PROPERTIES - INSTALL_RPATH "$ORIGIN/../lib/swift/$") + INSTALL_RPATH "$ORIGIN/../lib/swift/${SWIFT_SYSTEM_NAME}") set_property(GLOBAL APPEND PROPERTY Foundation_EXPORTS plutil) diff --git a/Sources/Tools/plutil/main.swift b/Sources/Tools/plutil/main.swift index c9ee783f84..d71d9ba9a2 100644 --- a/Sources/Tools/plutil/main.swift +++ b/Sources/Tools/plutil/main.swift @@ -12,6 +12,9 @@ import SwiftFoundation #elseif canImport(Glibc) import Foundation import Glibc +#elseif canImport(Musl) +import Foundation +import Musl #elseif canImport(CRT) import Foundation import CRT diff --git a/Sources/UUID/CMakeLists.txt b/Sources/UUID/CMakeLists.txt index fea52c7396..bab43b0f01 100644 --- a/Sources/UUID/CMakeLists.txt +++ b/Sources/UUID/CMakeLists.txt @@ -28,7 +28,7 @@ if(NOT BUILD_SHARED_LIBS) # TODO(drexin): should be installed in architecture specific folder, once # the layout is fixed for non-Darwin platforms install(TARGETS uuid - ARCHIVE DESTINATION lib/swift_static/$ - LIBRARY DESTINATION lib/swift_static/$ + ARCHIVE DESTINATION lib/swift_static/${SWIFT_SYSTEM_NAME} + LIBRARY DESTINATION lib/swift_static/${SWIFT_SYSTEM_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/cmake/modules/FindLibRT.cmake b/cmake/modules/FindLibRT.cmake new file mode 100644 index 0000000000..0a9f0d80e5 --- /dev/null +++ b/cmake/modules/FindLibRT.cmake @@ -0,0 +1,39 @@ +#.rst: +# FindLibRT +# --------- +# +# Find librt library and headers. +# +# The mdoule defines the following variables: +# +# :: +# +# LibRT_FOUND - true if librt was found +# LibRT_INCLUDE_DIR - include search path +# LibRT_LIBRARIES - libraries to link + +if(UNIX) + find_path(LibRT_INCLUDE_DIR + NAMES + time.h) + find_library(LibRT_LIBRARIES rt) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(LibRT + REQUIRED_VARS + LibRT_LIBRARIES + LibRT_INCLUDE_DIR) + + if(LibRT_FOUND) + if(NOT TARGET RT::rt) + add_library(RT::rt UNKNOWN IMPORTED) + set_target_properties(RT::rt + PROPERTIES + IMPORTED_LOCATION ${LibRT_LIBRARIES} + INTERFACE_INCLUDE_DIRECTORIES ${LibRT_INCLUDE_DIR}) + endif() + endif() + + mark_as_advanced(LibRT_LIBRARIES LibRT_INCLUDE_DIR) +endif() + diff --git a/cmake/modules/SwiftSupport.cmake b/cmake/modules/SwiftSupport.cmake index ffb24527eb..ba22becab2 100644 --- a/cmake/modules/SwiftSupport.cmake +++ b/cmake/modules/SwiftSupport.cmake @@ -49,12 +49,7 @@ endfunction() # Sets ${result_var_name} with the converted OS name derived from # CMAKE_SYSTEM_NAME. function(get_swift_host_os result_var_name) - if(CMAKE_SYSTEM_NAME STREQUAL Darwin) - set(${result_var_name} macosx PARENT_SCOPE) - else() - string(TOLOWER ${CMAKE_SYSTEM_NAME} cmake_system_name_lc) - set(${result_var_name} ${cmake_system_name_lc} PARENT_SCOPE) - endif() + set(${result_var_name} ${SWIFT_SYSTEM_NAME} PARENT_SCOPE) endfunction() function(_install_target module)