Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,17 @@ let package = Package(
.target(
name: "SystemExtras",
dependencies: [
.product(name: "SystemPackage", package: "swift-system")
.product(name: "SystemPackage", package: "swift-system"),
.target(name: "CSystemExtras", condition: .when(platforms: [.wasi])),
],
exclude: ["CMakeLists.txt"],
swiftSettings: [
.define("SYSTEM_PACKAGE_DARWIN", .when(platforms: DarwinPlatforms))
]
),

.target(name: "CSystemExtras"),

.executableTarget(
name: "WITTool",
dependencies: [
Expand All @@ -121,7 +124,7 @@ let package = Package(
if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
package.dependencies += [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.2.2"),
.package(url: "https://github.com/apple/swift-system", .upToNextMajor(from: "1.3.0")),
.package(url: "https://github.com/apple/swift-system", from: "1.5.0"),
]
} else {
package.dependencies += [
Expand Down
8 changes: 6 additions & 2 deletions Sources/CLI/Commands/Run.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,16 @@ struct Run: ParsableCommand {
var directories: [String] = []

enum ThreadingModel: String, ExpressibleByArgument, CaseIterable {
case direct
#if !os(WASI)
case direct
#endif
case token

func resolve() -> EngineConfiguration.ThreadingModel {
switch self {
case .direct: return .direct
#if !os(WASI)
case .direct: return .direct
#endif
case .token: return .token
}
}
Expand Down
Empty file.
5 changes: 5 additions & 0 deletions Sources/CSystemExtras/include/clock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <time.h>

inline static clockid_t csystemextras_monotonic_clockid() {
return CLOCK_MONOTONIC;
}
26 changes: 21 additions & 5 deletions Sources/SystemExtras/Clock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import Android
#elseif os(Windows)
import CSystem
import ucrt
#elseif os(WASI)
import CSystemExtras
import WASILibc
#else
#error("Unsupported Platform")
#endif
Expand Down Expand Up @@ -41,12 +44,17 @@ extension Clock {
public static var rawMonotonic: Clock { Clock(rawValue: _CLOCK_MONOTONIC_RAW) }
#endif

#if SYSTEM_PACKAGE_DARWIN || os(Linux) || os(Android) || os(OpenBSD) || os(FreeBSD) || os(WASI)
#if SYSTEM_PACKAGE_DARWIN || os(Linux) || os(Android) || os(OpenBSD) || os(FreeBSD)
@_alwaysEmitIntoClient
public static var monotonic: Clock { Clock(rawValue: _CLOCK_MONOTONIC) }
#endif

#if os(OpenBSD) || os(FreeBSD) || os(WASI)
#if os(WASI)
@_alwaysEmitIntoClient
public static var monotonic: Clock { Clock(rawValue: csystemextras_monotonic_clockid()) }
#endif

#if os(OpenBSD) || os(FreeBSD)
@_alwaysEmitIntoClient
public static var uptime: Clock { Clock(rawValue: _CLOCK_UPTIME) }
#endif
Expand Down Expand Up @@ -92,10 +100,10 @@ extension Clock {
public var rawValue: CInterop.TimeSpec

@_alwaysEmitIntoClient
public var seconds: Int { rawValue.tv_sec }
public var seconds: Int64 { .init(rawValue.tv_sec) }

@_alwaysEmitIntoClient
public var nanoseconds: Int { rawValue.tv_nsec }
public var nanoseconds: Int64 { .init(rawValue.tv_nsec) }

@_alwaysEmitIntoClient
public init(rawValue: CInterop.TimeSpec) {
Expand All @@ -104,17 +112,25 @@ extension Clock {

@_alwaysEmitIntoClient
public init(seconds: Int, nanoseconds: Int) {
self.init(rawValue: CInterop.TimeSpec(tv_sec: seconds, tv_nsec: nanoseconds))
self.init(rawValue: CInterop.TimeSpec(tv_sec: .init(seconds), tv_nsec: nanoseconds))
}

@_alwaysEmitIntoClient
public static var now: TimeSpec {
#if os(WASI)
return TimeSpec(rawValue: CInterop.TimeSpec(tv_sec: 0, tv_nsec: Int(UTIME_NOW)))
#else
return TimeSpec(rawValue: CInterop.TimeSpec(tv_sec: 0, tv_nsec: Int(_UTIME_NOW)))
#endif
}

@_alwaysEmitIntoClient
public static var omit: TimeSpec {
#if os(WASI)
return TimeSpec(rawValue: CInterop.TimeSpec(tv_sec: 0, tv_nsec: Int(UTIME_OMIT)))
#else
return TimeSpec(rawValue: CInterop.TimeSpec(tv_sec: 0, tv_nsec: Int(_UTIME_OMIT)))
#endif
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions Sources/SystemExtras/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import Android
#elseif os(Windows)
import CSystem
import ucrt
#elseif os(WASI)
import WASILibc
#else
#error("Unsupported Platform")
#endif
Expand Down Expand Up @@ -43,7 +45,7 @@ internal var _AT_NO_AUTOMOUNT: CInt { AT_NO_AUTOMOUNT }
#endif
*/

#if !os(Windows)
#if !os(Windows) && !os(WASI)
@_alwaysEmitIntoClient
internal var _F_GETFL: CInt { F_GETFL }
@_alwaysEmitIntoClient
Expand All @@ -61,7 +63,7 @@ internal var _O_SYNC: CInt { O_SYNC }
internal var _O_RSYNC: CInt { O_RSYNC }
#endif

#if !os(Windows)
#if !os(Windows) && !os(WASI)
@_alwaysEmitIntoClient
internal var _UTIME_NOW: CInt {
#if os(Linux) || os(Android)
Expand Down Expand Up @@ -132,16 +134,15 @@ internal var _CLOCK_BOOTTIME: CInterop.ClockId { CLOCK_BOOTTIME }
@_alwaysEmitIntoClient
internal var _CLOCK_MONOTONIC_RAW: CInterop.ClockId { CLOCK_MONOTONIC_RAW }
#endif
#if SYSTEM_PACKAGE_DARWIN || os(Linux) || os(Android) || os(OpenBSD) || os(FreeBSD) || os(WASI)
#if SYSTEM_PACKAGE_DARWIN || os(Linux) || os(Android) || os(OpenBSD) || os(FreeBSD)
@_alwaysEmitIntoClient
internal var _CLOCK_MONOTONIC: CInterop.ClockId { CLOCK_MONOTONIC }
#endif

#if SYSTEM_PACKAGE_DARWIN
@_alwaysEmitIntoClient
internal var _CLOCK_UPTIME_RAW: CInterop.ClockId { CLOCK_UPTIME_RAW }
#endif
#if os(OpenBSD) || os(FreeBSD) || os(WASI)
#if os(OpenBSD) || os(FreeBSD)
@_alwaysEmitIntoClient
internal var _CLOCK_UPTIME: CInterop.ClockId { CLOCK_UPTIME }
#endif
2 changes: 2 additions & 0 deletions Sources/SystemExtras/FileAtOperations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import Android
#elseif os(Windows)
import ucrt
import WinSDK
#elseif os(WASI)
import WASILibc
#else
#error("Unsupported Platform")
#endif
Expand Down
23 changes: 22 additions & 1 deletion Sources/SystemExtras/FileOperations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import Android
#elseif os(Windows)
import ucrt
import WinSDK
#elseif os(WASI)
import WASILibc
#else
#error("Unsupported Platform")
#endif
Expand Down Expand Up @@ -344,6 +346,8 @@ extension FileDescriptor {
#if os(Windows)
// FIXME: Need to query by `NtQueryInformationFile`?
return .success(OpenOptions(rawValue: 0))
#elseif os(WASI)
return .failure(Errno.notSupported)
#else
valueOrErrno(retryOnInterrupt: false) {
system_fcntl(self.rawValue, _F_GETFL)
Expand Down Expand Up @@ -511,15 +515,31 @@ extension FileDescriptor {

@_alwaysEmitIntoClient
public var name: String {
#if os(WASI)
// ClangImporter can't handle `char d_name[]`, but it's right after `unsigned char d_type`.
withUnsafePointer(to: &rawValue.pointee.d_type) { dType in
let dName = dType + 1
return dName.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: dName)) {
// String initializer copies the given buffer contents, so it's safe.
return String(cString: $0)
}
}
#else
withUnsafePointer(to: &rawValue.pointee.d_name) { dName in
dName.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout.size(ofValue: dName)) {
// String initializer copies the given buffer contents, so it's safe.
return String(cString: $0)
}
}
#endif
}

public var fileType: FileType {
#if os(WASI)
// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#-filetype-variant
// https://github.com/WebAssembly/wasi-libc/blob/6b45da5b05bc0edda355a6de46101d4b21631985/libc-bottom-half/headers/public/wasi/api.h#L780C9-L780C32
FileType(rawValue: .init(rawValue.pointee.d_type))
#else
switch CInt(rawValue.pointee.d_type) {
case _DT_REG: return .file
case _DT_BLK: return .blockDevice
Expand All @@ -529,6 +549,7 @@ extension FileDescriptor {
case _DT_SOCK: return .socket
default: return .unknown
}
#endif
}
}

Expand Down Expand Up @@ -657,7 +678,7 @@ public enum FileTime {
public typealias FileTime = Clock.TimeSpec
#endif

#if !os(Windows)
#if !os(Windows) && !os(WASI)

// MARK: - Synchronized Input and Output

Expand Down
4 changes: 3 additions & 1 deletion Sources/SystemExtras/Syscalls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import Android
#elseif os(Windows)
import ucrt
import WinSDK
#elseif os(WASI)
import WASILibc
#else
#error("Unsupported Platform")
#endif
Expand Down Expand Up @@ -127,7 +129,7 @@ internal func system_symlinkat(
extension CInterop {
#if SYSTEM_PACKAGE_DARWIN
public typealias DirP = UnsafeMutablePointer<DIR>
#elseif os(Linux) || os(Android)
#elseif os(Linux) || os(Android) || os(WASI)
public typealias DirP = OpaquePointer
#else
#error("Unsupported Platform")
Expand Down
4 changes: 1 addition & 3 deletions Sources/WASI/Clock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,10 @@ public protocol MonotonicClock {
/// A monotonic clock that uses the system's monotonic clock.
public struct SystemMonotonicClock: MonotonicClock {
private var underlying: SystemExtras.Clock {
#if os(Linux) || os(Android)
#if os(Linux) || os(Android) || os(WASI)
return .monotonic
#elseif os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
return .rawUptime
#elseif os(WASI)
return .monotonic
#elseif os(OpenBSD) || os(FreeBSD)
return .uptime
#else
Expand Down
28 changes: 16 additions & 12 deletions Sources/WASI/Platform/PlatformTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@ extension WASIAbi.Fdflags {
if platformOpenOptions.contains(.append) {
fdFlags.insert(.APPEND)
}
if platformOpenOptions.contains(.dataSync) {
fdFlags.insert(.DSYNC)
}
if platformOpenOptions.contains(.nonBlocking) {
fdFlags.insert(.NONBLOCK)
}
if platformOpenOptions.contains(.fileSync) {
fdFlags.insert(.SYNC)
}
#if !os(WASI)
if platformOpenOptions.contains(.dataSync) {
fdFlags.insert(.DSYNC)
}
if platformOpenOptions.contains(.fileSync) {
fdFlags.insert(.SYNC)
}
#endif
#if os(Linux)
if platformOpenOptions.contains(.readSync) {
fdFlags.insert(.RSYNC)
Expand All @@ -64,15 +66,17 @@ extension WASIAbi.Fdflags {
flags.insert(.append)
}
#if !os(Windows)
if self.contains(.DSYNC) {
flags.insert(.dataSync)
}
if self.contains(.NONBLOCK) {
flags.insert(.nonBlocking)
}
if self.contains(.SYNC) {
flags.insert(.fileSync)
}
#if !os(WASI)
if self.contains(.DSYNC) {
flags.insert(.dataSync)
}
if self.contains(.SYNC) {
flags.insert(.fileSync)
}
#endif
#if os(Linux)
if self.contains(.RSYNC) {
flags.insert(.readSync)
Expand Down
10 changes: 8 additions & 2 deletions Sources/WASI/Platform/SandboxPrimitives/Open.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import SystemPackage
#elseif os(Windows)
import CSystem
import ucrt
#elseif os(WASI)
import WASILibc
#else
#error("Unsupported Platform")
#endif
Expand Down Expand Up @@ -127,13 +129,17 @@ struct PathResolution {
throw openErrno
}

try self.symlink(component: component)
#if os(WASI)
throw Errno.notSupported
#else
try self.symlink(component: component)
#endif
#endif
}
}
}

#if !os(Windows)
#if !os(Windows) && !os(WASI)
mutating func symlink(component: FilePath.Component) throws {
/// Thin wrapper around readlinkat(2)
func _readlinkat(_ fd: CInt, _ path: UnsafePointer<CChar>) throws -> FilePath {
Expand Down
4 changes: 3 additions & 1 deletion Sources/WASI/WASI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import WasmTypes
import Android
#elseif os(Windows)
import ucrt
#elseif os(WASI)
import WASILibc
#else
#error("Unsupported Platform")
#endif
Expand Down Expand Up @@ -1391,7 +1393,7 @@ public class WASIBridgeToHost: WASI {
fdTable[2] = .file(StdioFileEntry(fd: stderr, accessMode: .write))

for (guestPath, hostPath) in preopens {
#if os(Windows)
#if os(Windows) || os(WASI)
let fd = try FileDescriptor.open(FilePath(hostPath), .readWrite)
#else
let fd = try hostPath.withCString { cHostPath in
Expand Down
Loading
Loading