diff --git a/Package.swift b/Package.swift index d84cbf7d3..b52483ce8 100644 --- a/Package.swift +++ b/Package.swift @@ -395,14 +395,14 @@ extension Array where Element == PackageDescription.SwiftSetting { .define("SWT_TARGET_OS_APPLE", .whenApple()), - .define("SWT_NO_EXIT_TESTS", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android]))), - .define("SWT_NO_PROCESS_SPAWNING", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android]))), + .define("SWT_NO_EXIT_TESTS", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .custom("emscripten"), .android]))), + .define("SWT_NO_PROCESS_SPAWNING", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .custom("emscripten"), .android]))), .define("SWT_NO_SNAPSHOT_TYPES", .whenEmbedded(or: .whenApple(false))), - .define("SWT_NO_DYNAMIC_LINKING", .whenEmbedded(or: .when(platforms: [.wasi]))), - .define("SWT_NO_PIPES", .whenEmbedded(or: .when(platforms: [.wasi]))), + .define("SWT_NO_DYNAMIC_LINKING", .whenEmbedded(or: .when(platforms: [.wasi, .custom("emscripten")]))), + .define("SWT_NO_PIPES", .whenEmbedded(or: .when(platforms: [.wasi, .custom("emscripten")]))), .define("SWT_NO_FOUNDATION_FILE_COORDINATION", .whenEmbedded(or: .whenApple(false))), - .define("SWT_NO_IMAGE_ATTACHMENTS", .whenEmbedded(or: .when(platforms: [.linux, .custom("freebsd"), .openbsd, .wasi, .android]))), - .define("SWT_NO_FILE_CLONING", .whenEmbedded(or: .when(platforms: [.openbsd, .wasi, .android]))), + .define("SWT_NO_IMAGE_ATTACHMENTS", .whenEmbedded(or: .when(platforms: [.linux, .custom("freebsd"), .openbsd, .wasi, .custom("emscripten"), .android]))), + .define("SWT_NO_FILE_CLONING", .whenEmbedded(or: .when(platforms: [.openbsd, .wasi, .custom("emscripten"), .android]))), .define("SWT_NO_LEGACY_TEST_DISCOVERY", .whenEmbedded()), .define("SWT_NO_LIBDISPATCH", .whenEmbedded()), @@ -478,14 +478,14 @@ extension Array where Element == PackageDescription.CXXSetting { var result = Self() result += [ - .define("SWT_NO_EXIT_TESTS", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android]))), - .define("SWT_NO_PROCESS_SPAWNING", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android]))), + .define("SWT_NO_EXIT_TESTS", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .custom("emscripten"), .android]))), + .define("SWT_NO_PROCESS_SPAWNING", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .custom("emscripten"), .android]))), .define("SWT_NO_SNAPSHOT_TYPES", .whenEmbedded(or: .whenApple(false))), - .define("SWT_NO_DYNAMIC_LINKING", .whenEmbedded(or: .when(platforms: [.wasi]))), - .define("SWT_NO_PIPES", .whenEmbedded(or: .when(platforms: [.wasi]))), + .define("SWT_NO_DYNAMIC_LINKING", .whenEmbedded(or: .when(platforms: [.wasi, .custom("emscripten")]))), + .define("SWT_NO_PIPES", .whenEmbedded(or: .when(platforms: [.wasi, .custom("emscripten")]))), .define("SWT_NO_FOUNDATION_FILE_COORDINATION", .whenEmbedded(or: .whenApple(false))), - .define("SWT_NO_IMAGE_ATTACHMENTS", .whenEmbedded(or: .when(platforms: [.linux, .custom("freebsd"), .openbsd, .wasi, .android]))), - .define("SWT_NO_FILE_CLONING", .whenEmbedded(or: .when(platforms: [.openbsd, .wasi, .android]))), + .define("SWT_NO_IMAGE_ATTACHMENTS", .whenEmbedded(or: .when(platforms: [.linux, .custom("freebsd"), .openbsd, .wasi, .custom("emscripten"), .android]))), + .define("SWT_NO_FILE_CLONING", .whenEmbedded(or: .when(platforms: [.openbsd, .wasi, .custom("emscripten"), .android]))), .define("SWT_NO_LEGACY_TEST_DISCOVERY", .whenEmbedded()), .define("SWT_NO_LIBDISPATCH", .whenEmbedded()), diff --git a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift index 64cef7759..5a2b6a5a0 100644 --- a/Sources/Testing/ABI/EntryPoints/EntryPoint.swift +++ b/Sources/Testing/ABI/EntryPoints/EntryPoint.swift @@ -798,7 +798,7 @@ extension Event.ConsoleOutputRecorder.Options { // Windows does not set the "TERM" variable, so assume it supports 16-color // ANSI escape codes. true -#elseif os(WASI) +#elseif os(WASI) || os(Emscripten) // The "Terminal" under WASI can be assumed to be the browser's JavaScript // console, which we don't expect supports color escape codes. false @@ -820,7 +820,7 @@ extension Event.ConsoleOutputRecorder.Options { // Windows does not set the "TERM" variable, so assume it supports 256-color // ANSI escape codes. true -#elseif os(WASI) +#elseif os(WASI) || os(Emscripten) // The "Terminal" under WASI can be assumed to be the browser's JavaScript // console, which we don't expect supports color escape codes. false @@ -842,7 +842,7 @@ extension Event.ConsoleOutputRecorder.Options { // Windows does not set the "COLORTERM" variable, so assume it supports // true-color ANSI escape codes. SEE: https://github.com/microsoft/terminal/issues/11057 true -#elseif os(WASI) +#elseif os(WASI) || os(Emscripten) // The "Terminal" under WASI can be assumed to be the browser's JavaScript // console, which we don't expect supports color escape codes. false diff --git a/Sources/Testing/ABI/EntryPoints/SwiftPMEntryPoint.swift b/Sources/Testing/ABI/EntryPoints/SwiftPMEntryPoint.swift index 3c72e9f20..26091d166 100644 --- a/Sources/Testing/ABI/EntryPoints/SwiftPMEntryPoint.swift +++ b/Sources/Testing/ABI/EntryPoints/SwiftPMEntryPoint.swift @@ -24,7 +24,7 @@ private import _TestingInternals /// /// This constant is not part of the public interface of the testing library. var EXIT_NO_TESTS_FOUND: CInt { -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) || os(Emscripten) EX_UNAVAILABLE #elseif os(Windows) CInt(ERROR_NOT_FOUND) diff --git a/Sources/Testing/CMakeLists.txt b/Sources/Testing/CMakeLists.txt index 43a67f0ac..25bfe465f 100644 --- a/Sources/Testing/CMakeLists.txt +++ b/Sources/Testing/CMakeLists.txt @@ -133,12 +133,14 @@ target_link_libraries(Testing PRIVATE _TestingInternals _TestingInterop) if(NOT APPLE) - if(NOT CMAKE_SYSTEM_NAME STREQUAL WASI) + if(NOT CMAKE_SYSTEM_NAME STREQUAL WASI AND NOT CMAKE_SYSTEM_NAME STREQUAL Emscripten) target_link_libraries(Testing PUBLIC dispatch) endif() - target_link_libraries(Testing PUBLIC - Foundation) + if(NOT CMAKE_SYSTEM_NAME STREQUAL Emscripten) + target_link_libraries(Testing PUBLIC + Foundation) + endif() if (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") target_link_libraries(Testing PUBLIC execinfo) diff --git a/Sources/Testing/ExitTests/ExitStatus.swift b/Sources/Testing/ExitTests/ExitStatus.swift index f028e3891..68648f5bb 100644 --- a/Sources/Testing/ExitTests/ExitStatus.swift +++ b/Sources/Testing/ExitTests/ExitStatus.swift @@ -141,7 +141,7 @@ extension ExitStatus: CustomStringConvertible { .flatMap(String.init(validatingCString:)) .map { "SIG\($0)" } #endif -#elseif os(Windows) || os(WASI) +#elseif os(Windows) || os(WASI) || os(Emscripten) // These platforms do not have API to get the programmatic name of a // signal constant. #else diff --git a/Sources/Testing/SourceAttribution/Backtrace.swift b/Sources/Testing/SourceAttribution/Backtrace.swift index 3c6e412be..98f32a7cf 100644 --- a/Sources/Testing/SourceAttribution/Backtrace.swift +++ b/Sources/Testing/SourceAttribution/Backtrace.swift @@ -85,7 +85,7 @@ public struct Backtrace: Sendable { initializedCount = .init(clamping: backtrace(addresses.baseAddress!, .init(clamping: addresses.count))) #elseif os(Windows) initializedCount = Int(clamping: RtlCaptureStackBackTrace(0, ULONG(clamping: addresses.count), addresses.baseAddress!, nil)) -#elseif os(WASI) +#elseif os(WASI) || os(Emscripten) // SEE: https://github.com/WebAssembly/WASI/issues/159 // SEE: https://github.com/swiftlang/swift/pull/31693 #else diff --git a/Sources/Testing/Support/Additions/CommandLineAdditions.swift b/Sources/Testing/Support/Additions/CommandLineAdditions.swift index 6f307acfb..ea21cf500 100644 --- a/Sources/Testing/Support/Additions/CommandLineAdditions.swift +++ b/Sources/Testing/Support/Additions/CommandLineAdditions.swift @@ -107,7 +107,7 @@ extension CommandLine { } } return result! -#elseif os(WASI) +#elseif os(WASI) || os(Emscripten) // WASI does not really have the concept of a file system path to the main // executable, so simply return the first argument--presumably the program // name, but as you know this is not guaranteed by the C standard! diff --git a/Sources/Testing/Support/Environment.swift b/Sources/Testing/Support/Environment.swift index 5280d3954..b2f2f2caf 100644 --- a/Sources/Testing/Support/Environment.swift +++ b/Sources/Testing/Support/Environment.swift @@ -46,7 +46,7 @@ package enum Environment { } } -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) || os(Emscripten) /// Get all environment variables from a POSIX environment block. /// /// - Parameters: @@ -107,7 +107,7 @@ package enum Environment { } #endif return _get(fromEnviron: _NSGetEnviron()!.pointee!) -#elseif os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) +#elseif os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(Emscripten) _get(fromEnviron: swt_environ()) #elseif os(WASI) _get(fromEnviron: __wasilibc_get_environ()) @@ -174,7 +174,7 @@ package enum Environment { } return nil } -#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) +#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) || os(Emscripten) getenv(name).flatMap { String(validatingCString: $0) } #elseif os(Windows) name.withCString(encodedAs: UTF16.self) { name in @@ -258,7 +258,7 @@ extension Environment { environment[name] = value } return true -#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) +#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) || os(Emscripten) if let value { return 0 == setenv(name, value, 1) } diff --git a/Sources/Testing/Support/FileHandle.swift b/Sources/Testing/Support/FileHandle.swift index 338fd064c..111080fe6 100644 --- a/Sources/Testing/Support/FileHandle.swift +++ b/Sources/Testing/Support/FileHandle.swift @@ -309,7 +309,7 @@ struct FileHandle: ~Copyable, Sendable { /// descriptor, `nil` is passed to `body`. borrowing func withUnsafePOSIXFileDescriptor(_ body: (CInt?) throws -> R) rethrows -> R { try withUnsafeCFILEHandle { handle in -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) || os(Emscripten) let fd = fileno(handle) #elseif os(Windows) let fd = _fileno(handle) @@ -368,7 +368,7 @@ struct FileHandle: ~Copyable, Sendable { /// other threads. borrowing func withLock(_ body: () throws -> R) rethrows -> R { try withUnsafeCFILEHandle { handle in -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(Emscripten) flockfile(handle) defer { funlockfile(handle) @@ -403,7 +403,7 @@ extension FileHandle { // If possible, reserve enough space in the resulting buffer to contain // the contents of the file being read. var size: Int? -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) || os(Emscripten) withUnsafePOSIXFileDescriptor { fd in var s = stat() if let fd, 0 == fstat(fd, &s) { @@ -667,7 +667,7 @@ extension FileHandle { extension FileHandle { /// Is this file handle a TTY or PTY? var isTTY: Bool { -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) || os(Emscripten) // If stderr is a TTY and TERM is set, that's good enough for us. withUnsafePOSIXFileDescriptor { fd in if let fd, 0 != isatty(fd), let term = Environment.variable(named: "TERM"), !term.isEmpty { @@ -769,7 +769,7 @@ func fileExists(atPath path: String) -> Bool { /// resolved, the resulting string may differ slightly but refers to the same /// file system object. If the path could not be resolved, returns `nil`. func canonicalizePath(_ path: String) -> String? { -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) || os(Emscripten) path.withCString { path in if let resolvedCPath = realpath(path, nil) { defer { diff --git a/Sources/Testing/Support/Serializer.swift b/Sources/Testing/Support/Serializer.swift index 0d252acd7..8ef87b8db 100644 --- a/Sources/Testing/Support/Serializer.swift +++ b/Sources/Testing/Support/Serializer.swift @@ -20,7 +20,7 @@ private var _cpuCoreCount: Int? { var siInfo = SYSTEM_INFO() GetSystemInfo(&siInfo) return Int(siInfo.dwNumberOfProcessors) -#elseif os(WASI) +#elseif os(WASI) || os(Emscripten) return 1 #else #warning("Platform-specific implementation missing: CPU core count unavailable") diff --git a/Sources/Testing/Support/Versions.swift b/Sources/Testing/Support/Versions.swift index 710a28dcb..423896982 100644 --- a/Sources/Testing/Support/Versions.swift +++ b/Sources/Testing/Support/Versions.swift @@ -88,9 +88,10 @@ let operatingSystemVersion: String = { return result } } -#elseif os(WASI) +#elseif os(WASI) || os(Emscripten) // WASI does not have an API to get the current WASI or Wasm version. // wasi-libc does have uname(3), but it's stubbed out. + // Emscripten's uname(3) is similarly limited. #else #warning("Platform-specific implementation missing: OS version unavailable") #endif diff --git a/Sources/Testing/Traits/Tags/Tag.Color+Loading.swift b/Sources/Testing/Traits/Tags/Tag.Color+Loading.swift index 2ab35b107..52b83f359 100644 --- a/Sources/Testing/Traits/Tags/Tag.Color+Loading.swift +++ b/Sources/Testing/Traits/Tags/Tag.Color+Loading.swift @@ -70,7 +70,7 @@ var swiftTestingDirectoryPath: String? { if let appDataDirectoryPath = _appDataDirectoryPath { return appendPathComponent(swiftTestingDirectoryName, to: appDataDirectoryPath) } -#elseif os(WASI) +#elseif os(WASI) || os(Emscripten) // WASI does not support the concept of a home directory. #else #warning("Platform-specific implementation missing: .swift-testing directory location unavailable") diff --git a/Sources/_TestDiscovery/SectionBounds.swift b/Sources/_TestDiscovery/SectionBounds.swift index 6c5ab63bb..1443a4974 100644 --- a/Sources/_TestDiscovery/SectionBounds.swift +++ b/Sources/_TestDiscovery/SectionBounds.swift @@ -346,7 +346,7 @@ private struct _SectionBound: Sendable, ~Copyable { @_silgen_name(raw: "section$start$__TEXT$__swift5_types") private nonisolated(unsafe) var _typeMetadataSectionBegin: _SectionBound @_silgen_name(raw: "section$end$__TEXT$__swift5_types") private nonisolated(unsafe) var _typeMetadataSectionEnd: _SectionBound #endif -#elseif os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) +#elseif os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI) || os(Emscripten) @_silgen_name(raw: "__start_swift5_tests") private nonisolated(unsafe) var _testContentSectionBegin: _SectionBound @_silgen_name(raw: "__stop_swift5_tests") private nonisolated(unsafe) var _testContentSectionEnd: _SectionBound #if !SWT_NO_LEGACY_TEST_DISCOVERY diff --git a/Sources/_TestingInternals/include/Stubs.h b/Sources/_TestingInternals/include/Stubs.h index 788db76ae..d7f4fa2ef 100644 --- a/Sources/_TestingInternals/include/Stubs.h +++ b/Sources/_TestingInternals/include/Stubs.h @@ -139,7 +139,7 @@ static const IMAGE_SECTION_HEADER *_Null_unspecified swt_IMAGE_FIRST_SECTION(con } #endif -#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__ANDROID__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__ANDROID__) || defined(__EMSCRIPTEN__) /// The environment block. /// /// By POSIX convention, the environment block variable is declared in client diff --git a/cmake/modules/shared/CompilerSettings.cmake b/cmake/modules/shared/CompilerSettings.cmake index cb81e0e4a..3c575ed11 100644 --- a/cmake/modules/shared/CompilerSettings.cmake +++ b/cmake/modules/shared/CompilerSettings.cmake @@ -27,11 +27,11 @@ add_compile_options( if(APPLE) add_compile_definitions("SWT_TARGET_OS_APPLE") endif() -set(SWT_NO_EXIT_TESTS_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI" "Android") +set(SWT_NO_EXIT_TESTS_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI" "Emscripten" "Android") if(CMAKE_SYSTEM_NAME IN_LIST SWT_NO_EXIT_TESTS_LIST) add_compile_definitions("SWT_NO_EXIT_TESTS") endif() -set(SWT_NO_PROCESS_SPAWNING_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI" "Android") +set(SWT_NO_PROCESS_SPAWNING_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI" "Emscripten" "Android") if(CMAKE_SYSTEM_NAME IN_LIST SWT_NO_PROCESS_SPAWNING_LIST) add_compile_definitions("SWT_NO_PROCESS_SPAWNING") endif() @@ -39,14 +39,14 @@ if(NOT APPLE) add_compile_definitions("SWT_NO_SNAPSHOT_TYPES") add_compile_definitions("SWT_NO_FOUNDATION_FILE_COORDINATION") endif() -if(CMAKE_SYSTEM_NAME STREQUAL "WASI") +if(CMAKE_SYSTEM_NAME STREQUAL "WASI" OR CMAKE_SYSTEM_NAME STREQUAL "Emscripten") add_compile_definitions("SWT_NO_DYNAMIC_LINKING") add_compile_definitions("SWT_NO_PIPES") endif() if (NOT (APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Windows")) add_compile_definitions("SWT_NO_IMAGE_ATTACHMENTS") endif() -set(SWT_NO_FILE_CLONING_LIST "OpenBSD" "WASI" "Android") +set(SWT_NO_FILE_CLONING_LIST "OpenBSD" "WASI" "Emscripten" "Android") if(CMAKE_SYSTEM_NAME IN_LIST SWT_NO_FILE_CLONING_LIST) add_compile_definitions("SWT_NO_FILE_CLONING") endif()