Skip to content

Commit 33e4d1b

Browse files
authored
Add speculative support for OpenBSD. (#890)
OpenBSD has partial support in the Swift toolchain. This PR adds speculative support for it based on the assumption that what works with FreeBSD will generally also work with OpenBSD. The big differences: 1. We need to include `<util.h>` instead of `<libutil.h>`, 2. `/usr/bin/tar` does not support writing PKZIP files (so we look for the optional `/usr/bin/zip` instead), and 3. OpenBSD has no way to determine the path to the current executable, so we naïvely assume `argv[0]` is correct. These changes are speculative and have not been tested. Partially resolves #888. ### 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 b85decc commit 33e4d1b

25 files changed

+104
-64
lines changed

Documentation/Porting.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ platform conditional and provide a stub implementation:
256256
+++ b/Sources/Testing/Support/FileHandle.swift
257257

258258
var isTTY: Bool {
259-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || os(WASI)
259+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI)
260260
// ...
261261
+#elseif os(Classic)
262262
+ return false

Package.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ let package = Package(
5757
cxxSettings: .packageSettings,
5858
swiftSettings: .packageSettings,
5959
linkerSettings: [
60-
.linkedLibrary("execinfo", .when(platforms: [.custom("freebsd")]))
60+
.linkedLibrary("execinfo", .when(platforms: [.custom("freebsd"), .openbsd]))
6161
]
6262
),
6363
.testTarget(
@@ -127,7 +127,7 @@ let package = Package(
127127
)
128128

129129
// BUG: swift-package-manager-#6367
130-
#if !os(Windows) && !os(FreeBSD)
130+
#if !os(Windows) && !os(FreeBSD) && !os(OpenBSD)
131131
package.targets.append(contentsOf: [
132132
.testTarget(
133133
name: "TestingMacrosTests",
@@ -156,7 +156,7 @@ extension Array where Element == PackageDescription.SwiftSetting {
156156

157157
.define("SWT_NO_EXIT_TESTS", .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android])),
158158
.define("SWT_NO_PROCESS_SPAWNING", .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android])),
159-
.define("SWT_NO_SNAPSHOT_TYPES", .when(platforms: [.linux, .custom("freebsd"), .windows, .wasi])),
159+
.define("SWT_NO_SNAPSHOT_TYPES", .when(platforms: [.linux, .custom("freebsd"), .openbsd, .windows, .wasi])),
160160
.define("SWT_NO_DYNAMIC_LINKING", .when(platforms: [.wasi])),
161161
.define("SWT_NO_PIPES", .when(platforms: [.wasi])),
162162
]
@@ -191,7 +191,7 @@ extension Array where Element == PackageDescription.CXXSetting {
191191
result += [
192192
.define("SWT_NO_EXIT_TESTS", .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android])),
193193
.define("SWT_NO_PROCESS_SPAWNING", .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android])),
194-
.define("SWT_NO_SNAPSHOT_TYPES", .when(platforms: [.linux, .custom("freebsd"), .windows, .wasi])),
194+
.define("SWT_NO_SNAPSHOT_TYPES", .when(platforms: [.linux, .custom("freebsd"), .openbsd, .windows, .wasi])),
195195
.define("SWT_NO_DYNAMIC_LINKING", .when(platforms: [.wasi])),
196196
.define("SWT_NO_PIPES", .when(platforms: [.wasi])),
197197
]

Sources/Overlays/_Testing_Foundation/Attachments/Attachment+URL.swift

+14-1
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,23 @@ private func _compressContentsOfDirectory(at directoryURL: URL) async throws ->
164164
//
165165
// On Linux (which does not have FreeBSD's version of tar(1)), we can use
166166
// zip(1) instead.
167+
//
168+
// OpenBSD's tar(1) does not support writing PKZIP archives, and /usr/bin/zip
169+
// tool is an optional install, so we check if it's present before trying to
170+
// execute it.
167171
#if os(Linux)
168172
let archiverPath = "/usr/bin/zip"
169173
#elseif SWT_TARGET_OS_APPLE || os(FreeBSD)
170174
let archiverPath = "/usr/bin/tar"
175+
#elseif os(OpenBSD)
176+
let archiverPath = "/usr/local/bin/zip"
177+
var isDirectory = false
178+
if !FileManager.default.fileExists(atPath: archiverPath, isDirectory: &isDirectory) || isDirectory {
179+
throw CocoaError(.fileNoSuchFile, userInfo: [
180+
NSLocalizedDescriptionKey: "The 'zip' package is not installed.",
181+
NSFilePathErrorKey: archiverPath
182+
])
183+
}
171184
#elseif os(Windows)
172185
guard let archiverPath = _archiverPath else {
173186
throw CocoaError(.fileWriteUnknown, userInfo: [
@@ -187,7 +200,7 @@ private func _compressContentsOfDirectory(at directoryURL: URL) async throws ->
187200

188201
let sourcePath = directoryURL.fileSystemPath
189202
let destinationPath = temporaryURL.fileSystemPath
190-
#if os(Linux)
203+
#if os(Linux) || os(OpenBSD)
191204
// The zip command constructs relative paths from the current working
192205
// directory rather than from command-line arguments.
193206
process.arguments = [destinationPath, "--recurse-paths", "."]

Sources/Testing/ABI/EntryPoints/EntryPoint.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ extension Event.ConsoleOutputRecorder.Options {
656656
/// Whether or not the system terminal claims to support 16-color ANSI escape
657657
/// codes.
658658
private static var _terminalSupports16ColorANSIEscapeCodes: Bool {
659-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android)
659+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android)
660660
if let termVariable = Environment.variable(named: "TERM") {
661661
return termVariable != "dumb"
662662
}
@@ -678,7 +678,7 @@ extension Event.ConsoleOutputRecorder.Options {
678678
/// Whether or not the system terminal claims to support 256-color ANSI escape
679679
/// codes.
680680
private static var _terminalSupports256ColorANSIEscapeCodes: Bool {
681-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android)
681+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android)
682682
if let termVariable = Environment.variable(named: "TERM") {
683683
return strstr(termVariable, "256") != nil
684684
}
@@ -700,7 +700,7 @@ extension Event.ConsoleOutputRecorder.Options {
700700
/// Whether or not the system terminal claims to support true-color ANSI
701701
/// escape codes.
702702
private static var _terminalSupportsTrueColorANSIEscapeCodes: Bool {
703-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android)
703+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android)
704704
if let colortermVariable = Environment.variable(named: "COLORTERM") {
705705
return strstr(colortermVariable, "truecolor") != nil
706706
}

Sources/Testing/ABI/EntryPoints/SwiftPMEntryPoint.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ private import _TestingInternals
2424
///
2525
/// This constant is not part of the public interface of the testing library.
2626
var EXIT_NO_TESTS_FOUND: CInt {
27-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || os(WASI)
27+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI)
2828
EX_UNAVAILABLE
2929
#elseif os(Windows)
3030
CInt(ERROR_NOT_FOUND)

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ extension Event.Symbol {
106106
/// be used to represent it in text-based output. The value of this property
107107
/// is platform-dependent.
108108
public var unicodeCharacter: Character {
109-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || os(WASI)
109+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI)
110110
switch self {
111111
case .default:
112112
// Unicode: WHITE DIAMOND

Sources/Testing/ExitTests/ExitCondition.swift

+6-4
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,13 @@ public enum ExitCondition: Sendable {
4949
/// | macOS | [`<stdlib.h>`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/_Exit.3.html), [`<sysexits.h>`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sysexits.3.html) |
5050
/// | Linux | [`<stdlib.h>`](https://sourceware.org/glibc/manual/latest/html_node/Exit-Status.html), `<sysexits.h>` |
5151
/// | FreeBSD | [`<stdlib.h>`](https://man.freebsd.org/cgi/man.cgi?exit(3)), [`<sysexits.h>`](https://man.freebsd.org/cgi/man.cgi?sysexits(3)) |
52+
/// | OpenBSD | [`<stdlib.h>`](https://man.openbsd.org/exit.3), [`<sysexits.h>`](https://man.openbsd.org/sysexits.3) |
5253
/// | Windows | [`<stdlib.h>`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure) |
5354
///
54-
/// On macOS, FreeBSD, and Windows, the full exit code reported by the process
55-
/// is yielded to the parent process. Linux and other POSIX-like systems may
56-
/// only reliably report the low unsigned 8 bits (0&ndash;255) of the exit
57-
/// code.
55+
/// On macOS, FreeBSD, OpenBSD, and Windows, the full exit code reported by
56+
/// the process is yielded to the parent process. Linux and other POSIX-like
57+
/// systems may only reliably report the low unsigned 8 bits (0&ndash;255) of
58+
/// the exit code.
5859
case exitCode(_ exitCode: CInt)
5960

6061
/// The process terminated with the given signal.
@@ -70,6 +71,7 @@ public enum ExitCondition: Sendable {
7071
/// | macOS | [`<signal.h>`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/signal.3.html) |
7172
/// | Linux | [`<signal.h>`](https://sourceware.org/glibc/manual/latest/html_node/Standard-Signals.html) |
7273
/// | FreeBSD | [`<signal.h>`](https://man.freebsd.org/cgi/man.cgi?signal(3)) |
74+
/// | OpenBSD | [`<signal.h>`](https://man.openbsd.org/signal.3) |
7375
/// | Windows | [`<signal.h>`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/signal-constants) |
7476
case signal(_ signal: CInt)
7577
}

Sources/Testing/ExitTests/ExitTest.swift

+13-5
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ extension ExitTest {
110110
// SEE: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/coredump.c#n610
111111
var rl = rlimit(rlim_cur: 1, rlim_max: 1)
112112
_ = setrlimit(CInt(RLIMIT_CORE.rawValue), &rl)
113-
#elseif os(FreeBSD)
114-
// As with Linux, disable the generation core files. FreeBSD does not, as
115-
// far as I can tell, special-case RLIMIT_CORE=1.
113+
#elseif os(FreeBSD) || os(OpenBSD)
114+
// As with Linux, disable the generation core files. The BSDs do not, as far
115+
// as I can tell, special-case RLIMIT_CORE=1.
116116
var rl = rlimit(rlim_cur: 0, rlim_max: 0)
117117
_ = setrlimit(RLIMIT_CORE, &rl)
118118
#elseif os(Windows)
@@ -152,6 +152,14 @@ extension ExitTest {
152152
}
153153
#endif
154154

155+
#if os(OpenBSD)
156+
// OpenBSD does not have posix_spawn_file_actions_addclosefrom_np().
157+
// However, it does have closefrom(2), which we call here as a best effort.
158+
if let from = Environment.variable(named: "SWT_CLOSEFROM").flatMap(CInt.init) {
159+
_ = closefrom(from)
160+
}
161+
#endif
162+
155163
do {
156164
try await body()
157165
} catch {
@@ -344,7 +352,7 @@ extension ExitTest {
344352
}
345353

346354
var fd: CInt?
347-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD)
355+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD)
348356
fd = CInt(backChannelEnvironmentVariable)
349357
#elseif os(Windows)
350358
if let handle = UInt(backChannelEnvironmentVariable).flatMap(HANDLE.init(bitPattern:)) {
@@ -541,7 +549,7 @@ extension ExitTest {
541549
// known environment variable to the corresponding file descriptor
542550
// (HANDLE on Windows.)
543551
var backChannelEnvironmentVariable: String?
544-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD)
552+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD)
545553
backChannelEnvironmentVariable = backChannelWriteEnd.withUnsafePOSIXFileDescriptor { fd in
546554
fd.map(String.init(describing:))
547555
}

Sources/Testing/ExitTests/SpawnProcess.swift

+11-8
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal import _TestingInternals
1717

1818
/// A platform-specific value identifying a process running on the current
1919
/// system.
20-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD)
20+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD)
2121
typealias ProcessID = pid_t
2222
#elseif os(Windows)
2323
typealias ProcessID = HANDLE
@@ -62,13 +62,13 @@ func spawnExecutable(
6262
) throws -> ProcessID {
6363
// Darwin and Linux differ in their optionality for the posix_spawn types we
6464
// use, so use this typealias to paper over the differences.
65-
#if SWT_TARGET_OS_APPLE || os(FreeBSD)
65+
#if SWT_TARGET_OS_APPLE || os(FreeBSD) || os(OpenBSD)
6666
typealias P<T> = T?
6767
#elseif os(Linux)
6868
typealias P<T> = T
6969
#endif
7070

71-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD)
71+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD)
7272
return try withUnsafeTemporaryAllocation(of: P<posix_spawn_file_actions_t>.self, capacity: 1) { fileActions in
7373
let fileActions = fileActions.baseAddress!
7474
guard 0 == posix_spawn_file_actions_init(fileActions) else {
@@ -105,9 +105,7 @@ func spawnExecutable(
105105
}
106106

107107
// Forward standard I/O streams and any explicitly added file handles.
108-
#if os(Linux) || os(FreeBSD)
109-
var highestFD = CInt(-1)
110-
#endif
108+
var highestFD = max(STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO)
111109
func inherit(_ fileHandle: borrowing FileHandle, as standardFD: CInt? = nil) throws {
112110
try fileHandle.withUnsafePOSIXFileDescriptor { fd in
113111
guard let fd else {
@@ -118,9 +116,8 @@ func spawnExecutable(
118116
} else {
119117
#if SWT_TARGET_OS_APPLE
120118
_ = posix_spawn_file_actions_addinherit_np(fileActions, fd)
121-
#elseif os(Linux) || os(FreeBSD)
122-
highestFD = max(highestFD, fd)
123119
#endif
120+
highestFD = max(highestFD, fd)
124121
}
125122
}
126123
}
@@ -156,6 +153,12 @@ func spawnExecutable(
156153
// `swt_posix_spawn_file_actions_addclosefrom_np` to guard the
157154
// availability of this function.
158155
_ = posix_spawn_file_actions_addclosefrom_np(fileActions, highestFD + 1)
156+
#elseif os(OpenBSD)
157+
// OpenBSD does not have posix_spawn_file_actions_addclosefrom_np().
158+
// However, it does have closefrom(2), which we can call from within the
159+
// spawned child process if we control its execution.
160+
var environment = environment
161+
environment["SWT_CLOSEFROM"] = String(describing: highestFD + 1)
159162
#else
160163
#warning("Platform-specific implementation missing: cannot close unused file descriptors")
161164
#endif

Sources/Testing/ExitTests/WaitFor.swift

+8-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#if !SWT_NO_PROCESS_SPAWNING
1212
internal import _TestingInternals
1313

14-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD)
14+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD)
1515
/// Block the calling thread, wait for the target process to exit, and return
1616
/// a value describing the conditions under which it exited.
1717
///
@@ -78,14 +78,14 @@ func wait(for pid: consuming pid_t) async throws -> ExitCondition {
7878

7979
return try _blockAndWait(for: pid)
8080
}
81-
#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD)
81+
#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD)
8282
/// A mapping of awaited child PIDs to their corresponding Swift continuations.
8383
private let _childProcessContinuations = Locked<[pid_t: CheckedContinuation<ExitCondition, any Error>]>()
8484

8585
/// A condition variable used to suspend the waiter thread created by
8686
/// `_createWaitThread()` when there are no child processes to await.
8787
private nonisolated(unsafe) let _waitThreadNoChildrenCondition = {
88-
#if os(FreeBSD)
88+
#if os(FreeBSD) || os(OpenBSD)
8989
let result = UnsafeMutablePointer<pthread_cond_t?>.allocate(capacity: 1)
9090
#else
9191
let result = UnsafeMutablePointer<pthread_cond_t>.allocate(capacity: 1)
@@ -136,7 +136,7 @@ private let _createWaitThread: Void = {
136136

137137
// Create the thread. It will run immediately; because it runs in an infinite
138138
// loop, we aren't worried about detaching or joining it.
139-
#if SWT_TARGET_OS_APPLE || os(FreeBSD)
139+
#if SWT_TARGET_OS_APPLE || os(FreeBSD) || os(OpenBSD)
140140
var thread: pthread_t?
141141
#else
142142
var thread = pthread_t()
@@ -147,14 +147,16 @@ private let _createWaitThread: Void = {
147147
{ _ in
148148
// Set the thread name to help with diagnostics. Note that different
149149
// platforms support different thread name lengths. See MAXTHREADNAMESIZE
150-
// on Darwin, TASK_COMM_LEN on Linux, and MAXCOMLEN on FreeBSD. We try to
151-
// maximize legibility in the available space.
150+
// on Darwin, TASK_COMM_LEN on Linux, MAXCOMLEN on FreeBSD, and _MAXCOMLEN
151+
// on OpenBSD. We try to maximize legibility in the available space.
152152
#if SWT_TARGET_OS_APPLE
153153
_ = pthread_setname_np("Swift Testing exit test monitor")
154154
#elseif os(Linux)
155155
_ = swt_pthread_setname_np(pthread_self(), "SWT ExT monitor")
156156
#elseif os(FreeBSD)
157157
_ = pthread_set_name_np(pthread_self(), "SWT ex test monitor")
158+
#elseif os(OpenBSD)
159+
_ = pthread_set_name_np(pthread_self(), "SWT exit test monitor")
158160
#else
159161
#warning("Platform-specific implementation missing: thread naming unavailable")
160162
#endif

Sources/Testing/SourceAttribution/Backtrace+Symbolication.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ extension Backtrace {
7171
result[i] = SymbolicatedAddress(address: address, offset: offset, symbolName: symbolName)
7272
}
7373
}
74-
#elseif os(Linux) || os(FreeBSD) || os(Android)
74+
#elseif os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android)
7575
// Although these platforms have dladdr(), they do not have symbol names
7676
// from DWARF binaries by default, only from shared libraries. The standard
7777
// library's backtracing functionality has implemented sufficient ELF/DWARF

Sources/Testing/SourceAttribution/Backtrace.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public struct Backtrace: Sendable {
6969
initializedCount = addresses.withMemoryRebound(to: UnsafeMutableRawPointer.self) { addresses in
7070
.init(clamping: backtrace(addresses.baseAddress!, .init(clamping: addresses.count)))
7171
}
72-
#elseif os(Linux) || os(FreeBSD)
72+
#elseif os(Linux) || os(FreeBSD) || os(OpenBSD)
7373
initializedCount = .init(clamping: backtrace(addresses.baseAddress!, .init(clamping: addresses.count)))
7474
#elseif os(Windows)
7575
initializedCount = Int(clamping: RtlCaptureStackBackTrace(0, ULONG(clamping: addresses.count), addresses.baseAddress!, nil))
@@ -181,7 +181,7 @@ extension Backtrace {
181181
/// crash. To avoid said crash, we'll keep a strong reference to the
182182
/// object (abandoning memory until the process exits.)
183183
/// ([swift-#62985](https://github.com/swiftlang/swift/issues/62985))
184-
#if os(Windows) || os(FreeBSD)
184+
#if os(Windows) || os(FreeBSD) || os(OpenBSD)
185185
nonisolated(unsafe) var errorObject: AnyObject?
186186
#else
187187
nonisolated(unsafe) weak var errorObject: AnyObject?

Sources/Testing/Support/Additions/CommandLineAdditions.swift

+9-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ extension CommandLine {
5555
return String(cString: buffer.baseAddress!)
5656
}
5757
}
58+
#elseif os(OpenBSD)
59+
// OpenBSD does not have API to get a path to the running executable. Use
60+
// arguments[0]. We do a basic sniff test for a path-like string, but
61+
// otherwise return argv[0] verbatim.
62+
guard let argv0 = arguments.first, argv0.contains("/") else {
63+
throw CError(rawValue: ENOEXEC)
64+
}
65+
return argv0
5866
#elseif os(Windows)
5967
var result: String?
6068
#if DEBUG
@@ -87,7 +95,7 @@ extension CommandLine {
8795
return arguments[0]
8896
#else
8997
#warning("Platform-specific implementation missing: executable path unavailable")
90-
return ""
98+
throw SystemError(description: "The executable path of the current process could not be determined.")
9199
#endif
92100
}
93101
}

Sources/Testing/Support/CError.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ func strerror(_ errorCode: CInt) -> String {
4747
_ = strerror_s(buffer.baseAddress!, buffer.count, errorCode)
4848
return strnlen(buffer.baseAddress!, buffer.count)
4949
}
50-
#elseif os(FreeBSD)
51-
// FreeBSD's implementation of strerror() is not thread-safe.
50+
#elseif os(FreeBSD) || os(OpenBSD)
51+
// FreeBSD's/OpenBSD's implementation of strerror() is not thread-safe.
5252
String(unsafeUninitializedCapacity: 1024) { buffer in
5353
_ = strerror_r(errorCode, buffer.baseAddress!, buffer.count)
5454
return strnlen(buffer.baseAddress!, buffer.count)

Sources/Testing/Support/Environment.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ enum Environment {
4242
}
4343
}
4444

45-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || os(WASI)
45+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI)
4646
/// Get all environment variables from a POSIX environment block.
4747
///
4848
/// - Parameters:
@@ -103,7 +103,7 @@ enum Environment {
103103
}
104104
#endif
105105
return _get(fromEnviron: _NSGetEnviron()!.pointee!)
106-
#elseif os(Linux) || os(FreeBSD) || os(Android)
106+
#elseif os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android)
107107
_get(fromEnviron: swt_environ())
108108
#elseif os(WASI)
109109
_get(fromEnviron: __wasilibc_get_environ())
@@ -170,7 +170,7 @@ enum Environment {
170170
}
171171
return nil
172172
}
173-
#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || os(WASI)
173+
#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) || os(WASI)
174174
getenv(name).flatMap { String(validatingCString: $0) }
175175
#elseif os(Windows)
176176
name.withCString(encodedAs: UTF16.self) { name in

0 commit comments

Comments
 (0)