Skip to content

Commit 6077347

Browse files
Merge pull request #584 from kateinoigakukun/yt/wasi-support
Complete WebAssembly/WASI Support
2 parents 1d2e39c + d321db1 commit 6077347

File tree

8 files changed

+56
-13
lines changed

8 files changed

+56
-13
lines changed

Package.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ extension Array where Element == PackageDescription.SwiftSetting {
130130

131131
.define("SWT_TARGET_OS_APPLE", .when(platforms: [.macOS, .iOS, .macCatalyst, .watchOS, .tvOS, .visionOS])),
132132

133-
.define("SWT_NO_FILE_IO", .when(platforms: [.wasi])),
134133
.define("SWT_NO_EXIT_TESTS", .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi])),
135134
.define("SWT_NO_SNAPSHOT_TYPES", .when(platforms: [.linux, .windows, .wasi])),
136135
.define("SWT_NO_DYNAMIC_LINKING", .when(platforms: [.wasi])),

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ for various platforms:
102102
| **visionOS** | | | Supported |
103103
| **Ubuntu 22.04** | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-6.0-linux)](https://ci.swift.org/job/swift-testing-main-swift-6.0-linux/) | [![Build Status](https://ci.swift.org/buildStatus/icon?job=swift-testing-main-swift-main-linux)](https://ci.swift.org/view/Swift%20Packages/job/swift-testing-main-swift-main-linux/) | Supported |
104104
| **Windows** | | [![Build Status](https://ci-external.swift.org/buildStatus/icon?job=swift-testing-main-swift-main-windows)](https://ci-external.swift.org/job/swift-testing-main-swift-main-windows/) | Supported |
105+
| **Wasm** | | | Experimental |
105106

106107
### Works with XCTest
107108

Sources/Testing/Support/FileHandle.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ struct FileHandle: ~Copyable, Sendable {
141141
/// descriptor, `nil` is passed to `body`.
142142
borrowing func withUnsafePOSIXFileDescriptor<R>(_ body: (CInt?) throws -> R) rethrows -> R {
143143
try withUnsafeCFILEHandle { handle in
144-
#if SWT_TARGET_OS_APPLE || os(Linux)
144+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
145145
let fd = fileno(handle)
146146
#elseif os(Windows)
147147
let fd = _fileno(handle)
@@ -210,6 +210,8 @@ struct FileHandle: ~Copyable, Sendable {
210210
defer {
211211
_unlock_file(handle)
212212
}
213+
#elseif os(WASI)
214+
// No file locking on WASI yet.
213215
#else
214216
#warning("Platform-specific implementation missing: cannot lock a file handle")
215217
#endif
@@ -233,7 +235,7 @@ extension FileHandle {
233235
// If possible, reserve enough space in the resulting buffer to contain
234236
// the contents of the file being read.
235237
var size: Int?
236-
#if SWT_TARGET_OS_APPLE || os(Linux)
238+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
237239
withUnsafePOSIXFileDescriptor { fd in
238240
var s = stat()
239241
if let fd, 0 == fstat(fd, &s) {
@@ -371,7 +373,7 @@ extension FileHandle {
371373
extension FileHandle {
372374
/// Is this file handle a TTY or PTY?
373375
var isTTY: Bool {
374-
#if SWT_TARGET_OS_APPLE || os(Linux)
376+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
375377
// If stderr is a TTY and TERM is set, that's good enough for us.
376378
withUnsafePOSIXFileDescriptor { fd in
377379
if let fd, 0 != isatty(fd), let term = Environment.variable(named: "TERM"), !term.isEmpty {
@@ -397,7 +399,7 @@ extension FileHandle {
397399

398400
/// Is this file handle a pipe or FIFO?
399401
var isPipe: Bool {
400-
#if SWT_TARGET_OS_APPLE || os(Linux)
402+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(WASI)
401403
withUnsafePOSIXFileDescriptor { fd in
402404
guard let fd else {
403405
return false

Sources/Testing/Support/Locked.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
4242
private typealias _Lock = SRWLOCK
4343
#elseif os(WASI)
4444
// No locks on WASI without multithreaded runtime.
45+
private typealias _Lock = Void
4546
#else
4647
#warning("Platform-specific implementation missing: locking unavailable")
4748
private typealias _Lock = Void

Sources/Testing/Traits/Tags/Tag.Color+Loading.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,29 @@ private var _appDataDirectoryPath: String? {
4949
/// On Apple platforms and on Linux, this path is equivalent to
5050
/// `"~/.swift-testing"`. On Windows, it is equivalent to
5151
/// `"%HOMEPATH%\AppData\Local\.swift-testing"`.
52-
var swiftTestingDirectoryPath: String {
52+
/// The value of this property is `nil` if the platform does not support the
53+
/// concept of a home directory, or if the home directory could not be
54+
/// determined.
55+
var swiftTestingDirectoryPath: String? {
5356
// The (default) name of the .swift-testing directory.
5457
let swiftTestingDirectoryName = ".swift-testing"
5558

5659
#if os(macOS) || (os(iOS) && targetEnvironment(macCatalyst)) || os(Linux)
5760
if let homeDirectoryPath = _homeDirectoryPath {
5861
return appendPathComponent(swiftTestingDirectoryName, to: homeDirectoryPath)
5962
}
63+
return nil
6064
#elseif os(Windows)
6165
if let appDataDirectoryPath = _appDataDirectoryPath {
6266
return appendPathComponent(swiftTestingDirectoryName, to: appDataDirectoryPath)
6367
}
68+
return nil
69+
#elseif os(WASI)
70+
return nil
6471
#else
6572
#warning("Platform-specific implementation missing: .swift-testing directory location unavailable")
73+
return nil
6674
#endif
67-
return ""
6875
}
6976

7077
/// Read tag colors out of the file `"tag-colors.json"` in a given directory.
@@ -83,7 +90,12 @@ var swiftTestingDirectoryPath: String {
8390
/// assumed to contain a JSON object (a dictionary) where the keys are tags'
8491
/// string values and the values represent tag colors. For a list of the
8592
/// supported formats for tag colors in this dictionary, see <doc:AddingTags>.
86-
func loadTagColors(fromFileInDirectoryAtPath swiftTestingDirectoryPath: String = swiftTestingDirectoryPath) throws -> [Tag: Tag.Color] {
93+
func loadTagColors(fromFileInDirectoryAtPath swiftTestingDirectoryPath: String? = swiftTestingDirectoryPath) throws -> [Tag: Tag.Color] {
94+
guard let swiftTestingDirectoryPath else {
95+
// If the platform does not support user-specific configuration, skip custom
96+
// tag colors.
97+
return [:]
98+
}
8799
// Find the path to the tag-colors.json file and try to load its contents.
88100
let tagColorsPath = appendPathComponent("tag-colors.json", to: swiftTestingDirectoryPath)
89101
let fileHandle = try FileHandle(forReadingAtPath: tagColorsPath)

Sources/_TestingInternals/Discovery.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,26 @@ struct SWTRelativePointer {
8686
}
8787
};
8888

89+
/// A type representing a 32-bit absolute function pointer, usually used on platforms
90+
/// where relative function pointers are not supported.
91+
///
92+
/// This type is derived from `AbsoluteFunctionPointer` in the Swift repository.
93+
template <typename T>
94+
struct SWTAbsoluteFunctionPointer {
95+
private:
96+
T *_pointer;
97+
static_assert(sizeof(T *) == sizeof(int32_t), "Function pointer must be 32-bit when using compact absolute pointer");
98+
99+
public:
100+
const T *_Nullable get(void) const & {
101+
return _pointer;
102+
}
103+
104+
const T *_Nullable operator ->(void) const & {
105+
return get();
106+
}
107+
};
108+
89109
/// A type representing a pointer relative to itself with low bits reserved for
90110
/// use as flags.
91111
///
@@ -98,6 +118,13 @@ struct SWTRelativePointerIntPair: public SWTRelativePointer<T, maskValue> {
98118
}
99119
};
100120

121+
template <typename T>
122+
#if defined(__wasm32__)
123+
using SWTCompactFunctionPointer = SWTAbsoluteFunctionPointer<T>;
124+
#else
125+
using SWTCompactFunctionPointer = SWTRelativePointer<T>;
126+
#endif
127+
101128
/// A type representing a metatype as constructed during compilation of a Swift
102129
/// module.
103130
///
@@ -114,7 +141,7 @@ struct SWTTypeContextDescriptor {
114141
size_t state;
115142
};
116143
using MetadataAccessFunction = __attribute__((swiftcall)) MetadataAccessResponse(size_t);
117-
SWTRelativePointer<MetadataAccessFunction> _metadataAccessFunction;
144+
SWTCompactFunctionPointer<MetadataAccessFunction> _metadataAccessFunction;
118145

119146
public:
120147
const char *_Nullable getName(void) const& {

Sources/_TestingInternals/include/Includes.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@
2727
/// - Note: Avoid including headers that aren't actually used.
2828

2929
#include <errno.h>
30-
#if __has_include(<signal.h>)
30+
/// Guard against including `signal.h` on WASI. The `signal.h` header file
31+
/// itself is available in wasi-libc, but it's just a stub that doesn't actually
32+
/// do anything. And also including it requires a special macro definition
33+
/// (`_WASI_EMULATED_SIGNAL`) and it causes compilation errors without the macro.
34+
#if __has_include(<signal.h>) && !defined(__wasi__)
3135
#include <signal.h>
3236
#endif
3337
#include <stdio.h>

cmake/modules/shared/CompilerSettings.cmake

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ add_compile_options(
2020
if(APPLE)
2121
add_compile_definitions("SWT_TARGET_OS_APPLE")
2222
endif()
23-
if(WASI)
24-
add_compile_definitions("SWT_NO_FILE_IO")
25-
endif()
2623
if(CMAKE_SYSTEM_NAME IN_LIST "iOS;watchOS;tvOS;visionOS;WASI")
2724
add_compile_definitions("SWT_NO_EXIT_TESTS")
2825
endif()

0 commit comments

Comments
 (0)