Skip to content

Commit fe5a7cd

Browse files
authored
Add partial WASI/Wasm support. (#301)
This PR allows building using the SwiftWasm toolchain from https://swiftwasm.org. As of right now, macro plugins do not build correctly for Wasm, so swift-testing is not usable, but it is buildable! ## Testing A workaround is provided on the [jgrynspan/wasi-workaround](https://github.com/apple/swift-testing/tree/jgrynspan/wasi-workaround) branch in order to facilitate testing. Check out that branch, then set the environment variable `SWT_COMPILER_PLUGIN_ENABLED` to `0` when building: ```sh SWT_COMPILER_PLUGIN_ENABLED=0 swift build --triple wasm32-unknown-wasi ``` The macros target should build except for its main function (which will emit a warning about being unsupported) as should the primary library target. It is not possible to build the testing library's tests yet. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
1 parent 932cb01 commit fe5a7cd

File tree

11 files changed

+27
-6
lines changed

11 files changed

+27
-6
lines changed

Package.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ extension Array where Element == PackageDescription.SwiftSetting {
123123
.enableUpcomingFeature("InternalImportsByDefault"),
124124

125125
.define("SWT_TARGET_OS_APPLE", .when(platforms: [.macOS, .iOS, .macCatalyst, .watchOS, .tvOS, .visionOS])),
126+
127+
.define("SWT_NO_FILE_IO", .when(platforms: [.wasi])),
126128
]
127129
}
128130

[email protected]

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ extension Array where Element == PackageDescription.SwiftSetting {
123123
.enableUpcomingFeature("InternalImportsByDefault"),
124124

125125
.define("SWT_TARGET_OS_APPLE", .when(platforms: [.macOS, .iOS, .macCatalyst, .watchOS, .tvOS, .visionOS])),
126+
127+
.define("SWT_NO_FILE_IO", .when(platforms: [.wasi])),
126128
]
127129
}
128130

Sources/Testing/Events/Recorder/Event.Symbol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ extension Event.Symbol {
100100
/// be used to represent it in text-based output. The value of this property
101101
/// is platform-dependent.
102102
public var unicodeCharacter: Character {
103-
#if SWT_TARGET_OS_APPLE || os(Linux)
103+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
104104
switch self {
105105
case .default:
106106
// Unicode: WHITE DIAMOND

Sources/Testing/Events/TimeValue.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ extension TimeValue: Codable {}
7575

7676
extension TimeValue: CustomStringConvertible {
7777
var description: String {
78+
#if os(WASI)
79+
// BUG: https://github.com/apple/swift/issues/72398
80+
return String(describing: Duration(self))
81+
#else
7882
let (secondsFromAttoseconds, attosecondsRemaining) = attoseconds.quotientAndRemainder(dividingBy: 1_000_000_000_000_000_000)
7983
let seconds = seconds + secondsFromAttoseconds
8084
var milliseconds = attosecondsRemaining / 1_000_000_000_000_000
@@ -88,6 +92,7 @@ extension TimeValue: CustomStringConvertible {
8892
}
8993
return String(cString: buffer.baseAddress!)
9094
}
95+
#endif
9196
}
9297
}
9398

Sources/Testing/SourceAttribution/Backtrace.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ public struct Backtrace: Sendable {
7272
initializedCount = .init(backtrace(addresses.baseAddress!, .init(addresses.count)))
7373
#elseif os(Windows)
7474
initializedCount = Int(RtlCaptureStackBackTrace(0, ULONG(addresses.count), addresses.baseAddress!, nil))
75+
#elseif os(WASI)
76+
// SEE: https://github.com/WebAssembly/WASI/issues/159
77+
// SEE: https://github.com/apple/swift/pull/31693
78+
initializedCount = 0
7579
#else
7680
#warning("Platform-specific implementation missing: backtraces unavailable")
7781
initializedCount = 0

Sources/Testing/Support/Environment.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ enum Environment {
3636
static func variable(named name: String) -> String? {
3737
#if SWT_NO_ENVIRONMENT_VARIABLES
3838
simulatedEnvironment.rawValue[name]
39-
#elseif SWT_TARGET_OS_APPLE || os(Linux)
39+
#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
4040
getenv(name).flatMap { String(validatingUTF8: $0) }
4141
#elseif os(Windows)
4242
name.withCString(encodedAs: UTF16.self) { name in

Sources/Testing/Support/FileHandle.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ struct FileHandle: ~Copyable, Sendable {
140140
let fd: CInt = -1
141141
#endif
142142

143-
if fd >= 0 {
143+
if Bool(fd >= 0) {
144144
return try body(fd)
145145
}
146146
return try body(nil)

Sources/Testing/Support/Locked.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
4040
private typealias _Lock = pthread_mutex_t
4141
#elseif os(Windows)
4242
private typealias _Lock = SRWLOCK
43+
#elseif os(WASI)
44+
// No locks on WASI.
4345
#else
4446
#warning("Platform-specific implementation missing: locking unavailable")
4547
private typealias _Lock = Void
@@ -53,6 +55,8 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
5355
_ = pthread_mutex_destroy(lock)
5456
#elseif os(Windows)
5557
// No deinitialization needed.
58+
#elseif os(WASI)
59+
// No locks on WASI.
5660
#else
5761
#warning("Platform-specific implementation missing: locking unavailable")
5862
#endif
@@ -70,6 +74,8 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
7074
_ = pthread_mutex_init(lock, nil)
7175
#elseif os(Windows)
7276
InitializeSRWLock(lock)
77+
#elseif os(WASI)
78+
// No locks on WASI.
7379
#else
7480
#warning("Platform-specific implementation missing: locking unavailable")
7581
#endif
@@ -105,6 +111,8 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
105111
defer {
106112
ReleaseSRWLockExclusive(lock)
107113
}
114+
#elseif os(WASI)
115+
// No locks on WASI.
108116
#else
109117
#warning("Platform-specific implementation missing: locking unavailable")
110118
#endif

Sources/Testing/Support/Versions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ let operatingSystemVersion: String = {
3131
default:
3232
return "\(productVersion) (\(buildNumber))"
3333
}
34-
#elseif !SWT_NO_UNAME && (SWT_TARGET_OS_APPLE || os(Linux))
34+
#elseif !SWT_NO_UNAME && (SWT_TARGET_OS_APPLE || os(Linux) || os(WASI))
3535
var name = utsname()
3636
if 0 == uname(&name) {
3737
let release = withUnsafeBytes(of: name.release) { release in

Sources/TestingInternals/Discovery.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ static void enumerateTypeMetadataSections(const SectionEnumerator& body) {
260260
}
261261
}
262262

263-
#elif defined(__linux__) || defined(_WIN32)
263+
#elif defined(__linux__) || defined(_WIN32) || defined(__wasi__)
264264
#pragma mark - Linux/Windows implementation
265265

266266
/// Specifies the address range corresponding to a section.

0 commit comments

Comments
 (0)