diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f96e7122..02cd9422 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -120,6 +120,30 @@ jobs: - run: ./Vendor/checkout-dependency - run: ./build-exec swift test + build-musl: + runs-on: ubuntu-22.04 + strategy: + matrix: + include: + - swift: 6.0.1-jammy + musl-swift-sdk-download: "https://download.swift.org/swift-6.0.1-release/static-sdk/swift-6.0.1-RELEASE/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz" + musl-swift-sdk-checksum: "d4f46ba40e11e697387468e18987ee622908bc350310d8af54eb5e17c2ff5481" + steps: + - uses: actions/checkout@v4 + - name: Configure container + run: | + docker run -dit --name build-container -v $PWD:/workspace -w /workspace swift:${{ matrix.swift }} + echo 'docker exec -i build-container "$@"' > ./build-exec + chmod +x ./build-exec + + - name: Install Static Linux SDK + run: ./build-exec swift sdk install "${{ matrix.musl-swift-sdk-download }}" --checksum "${{ matrix.musl-swift-sdk-checksum }}" + + - name: Build (x86_64-swift-linux-musl) + run: ./build-exec swift build --swift-sdk x86_64-swift-linux-musl + - name: Build (aarch64-swift-linux-musl) + run: ./build-exec swift build --swift-sdk aarch64-swift-linux-musl + build-windows: runs-on: windows-latest steps: diff --git a/Sources/SystemExtras/Clock.swift b/Sources/SystemExtras/Clock.swift index 0d491fc2..64cefc5e 100644 --- a/Sources/SystemExtras/Clock.swift +++ b/Sources/SystemExtras/Clock.swift @@ -1,8 +1,11 @@ #if SYSTEM_PACKAGE_DARWIN import Darwin -#elseif os(Linux) || os(FreeBSD) || os(Android) +#elseif canImport(Glibc) import CSystem import Glibc +#elseif canImport(Musl) +import CSystem +import Musl #elseif os(Windows) import CSystem import ucrt diff --git a/Sources/SystemExtras/Constants.swift b/Sources/SystemExtras/Constants.swift index 0d7aad86..1a32cc06 100644 --- a/Sources/SystemExtras/Constants.swift +++ b/Sources/SystemExtras/Constants.swift @@ -1,8 +1,11 @@ #if SYSTEM_PACKAGE_DARWIN import Darwin -#elseif os(Linux) || os(FreeBSD) || os(Android) +#elseif canImport(Glibc) import CSystem import Glibc +#elseif canImport(Musl) +import CSystem +import Musl #elseif os(Windows) import CSystem import ucrt diff --git a/Sources/SystemExtras/FileAtOperations.swift b/Sources/SystemExtras/FileAtOperations.swift index e0690103..dc2ff8a2 100644 --- a/Sources/SystemExtras/FileAtOperations.swift +++ b/Sources/SystemExtras/FileAtOperations.swift @@ -1,7 +1,11 @@ #if SYSTEM_PACKAGE_DARWIN import Darwin -#elseif os(Linux) || os(FreeBSD) || os(Android) +#elseif canImport(Glibc) +import CSystem import Glibc +#elseif canImport(Musl) +import CSystem +import Musl #elseif os(Windows) import ucrt import WinSDK diff --git a/Sources/SystemExtras/FileOperations.swift b/Sources/SystemExtras/FileOperations.swift index dad6a7c2..a3b9dada 100644 --- a/Sources/SystemExtras/FileOperations.swift +++ b/Sources/SystemExtras/FileOperations.swift @@ -1,7 +1,11 @@ #if SYSTEM_PACKAGE_DARWIN import Darwin -#elseif os(Linux) || os(FreeBSD) || os(Android) +#elseif canImport(Glibc) +import CSystem import Glibc +#elseif canImport(Musl) +import CSystem +import Musl #elseif os(Windows) import ucrt import WinSDK diff --git a/Sources/SystemExtras/Syscalls.swift b/Sources/SystemExtras/Syscalls.swift index 913edf5c..ddc37839 100644 --- a/Sources/SystemExtras/Syscalls.swift +++ b/Sources/SystemExtras/Syscalls.swift @@ -1,7 +1,11 @@ #if SYSTEM_PACKAGE_DARWIN import Darwin -#elseif os(Linux) || os(FreeBSD) || os(Android) +#elseif canImport(Glibc) +import CSystem import Glibc +#elseif canImport(Musl) +import CSystem +import Musl #elseif os(Windows) import ucrt import WinSDK diff --git a/Sources/SystemExtras/Vendor/Exports.swift b/Sources/SystemExtras/Vendor/Exports.swift index fcfbb807..1714316e 100644 --- a/Sources/SystemExtras/Vendor/Exports.swift +++ b/Sources/SystemExtras/Vendor/Exports.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift System open source project - Copyright (c) 2020 Apple Inc. and the Swift System project authors + Copyright (c) 2020 - 2024 Apple Inc. and the Swift System project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -14,12 +14,20 @@ #if SYSTEM_PACKAGE_DARWIN import Darwin -#elseif os(Linux) || os(FreeBSD) || os(Android) -import CSystem -import Glibc #elseif os(Windows) import CSystem import ucrt +#elseif canImport(Glibc) +import CSystem +import Glibc +#elseif canImport(Musl) +import CSystem +import Musl +#elseif canImport(WASILibc) +import WASILibc +#elseif canImport(Android) +import CSystem +import Android #else #error("Unsupported Platform") #endif @@ -47,11 +55,26 @@ internal var system_errno: CInt { _ = ucrt._set_errno(newValue) } } -#else +#elseif canImport(Glibc) internal var system_errno: CInt { get { Glibc.errno } set { Glibc.errno = newValue } } +#elseif canImport(Musl) +internal var system_errno: CInt { + get { Musl.errno } + set { Musl.errno = newValue } +} +#elseif canImport(WASILibc) +internal var system_errno: CInt { + get { WASILibc.errno } + set { WASILibc.errno = newValue } +} +#elseif canImport(Android) +internal var system_errno: CInt { + get { Android.errno } + set { Android.errno = newValue } +} #endif // MARK: C stdlib decls @@ -62,7 +85,10 @@ internal func system_strerror(_ __errnum: Int32) -> UnsafeMutablePointer! strerror(__errnum) } -internal func system_strlen(_ s: UnsafePointer) -> Int { +internal func system_strlen(_ s: UnsafePointer) -> Int { + strlen(s) +} +internal func system_strlen(_ s: UnsafeMutablePointer) -> Int { strlen(s) } @@ -80,7 +106,17 @@ internal func system_platform_strlen(_ s: UnsafePointer) #endif } -// Interop between String and platform string +// memset for raw buffers +// FIXME: Do we really not have something like this in the stdlib already? +internal func system_memset( + _ buffer: UnsafeMutableRawBufferPointer, + to byte: UInt8 +) { + guard buffer.count > 0 else { return } + memset(buffer.baseAddress!, CInt(byte), buffer.count) +} + +// Interop between String and platfrom string extension String { internal func _withPlatformString( _ body: (UnsafePointer) throws -> Result @@ -130,6 +166,24 @@ extension String { // TLS #if os(Windows) internal typealias _PlatformTLSKey = DWORD +#elseif os(WASI) && (swift(<6.1) || !_runtime(_multithreaded)) +// Mock TLS storage for single-threaded WASI +internal final class _PlatformTLSKey { + fileprivate init() {} +} +private final class TLSStorage: @unchecked Sendable { + var storage = [ObjectIdentifier: UnsafeMutableRawPointer]() +} +private let sharedTLSStorage = TLSStorage() + +func pthread_setspecific(_ key: _PlatformTLSKey, _ p: UnsafeMutableRawPointer?) -> Int { + sharedTLSStorage.storage[ObjectIdentifier(key)] = p + return 0 +} + +func pthread_getspecific(_ key: _PlatformTLSKey) -> UnsafeMutableRawPointer? { + sharedTLSStorage.storage[ObjectIdentifier(key)] +} #else internal typealias _PlatformTLSKey = pthread_key_t #endif @@ -141,6 +195,8 @@ internal func makeTLSKey() -> _PlatformTLSKey { fatalError("Unable to create key") } return raw + #elseif os(WASI) && (swift(<6.1) || !_runtime(_multithreaded)) + return _PlatformTLSKey() #else var raw = pthread_key_t() guard 0 == pthread_key_create(&raw, nil) else { diff --git a/Sources/WASI/WASI.swift b/Sources/WASI/WASI.swift index ada0e53e..57297871 100644 --- a/Sources/WASI/WASI.swift +++ b/Sources/WASI/WASI.swift @@ -4,8 +4,10 @@ import WasmTypes #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || os(visionOS) import Darwin -#elseif os(Linux) || os(FreeBSD) || os(Android) +#elseif canImport(Glibc) import Glibc +#elseif canImport(Musl) + import Musl #elseif os(Windows) import ucrt #else