Skip to content

Commit a6e9bdd

Browse files
committed
Add platform-specific branches for FreeBSD.
This PR adds support for FreeBSD where we have platform-specific code. Most changes simply involve changing `os(Linux)` to `os(Linux) || os(FreeBSD)`, although there is some actual platform-specific code and at least one spot where Darwin and FreeBSD share an implementation but Linux does not. > [!NOTE] > This new code is minimally tested. The Swift project does not officially > support FreeBSD.
1 parent dab00ae commit a6e9bdd

22 files changed

+95
-60
lines changed

Sources/Testing/ABI/EntryPoints/EntryPoint.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ extension Event.ConsoleOutputRecorder.Options {
673673
/// Whether or not the system terminal claims to support 16-color ANSI escape
674674
/// codes.
675675
private static var _terminalSupports16ColorANSIEscapeCodes: Bool {
676-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android)
676+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android)
677677
if let termVariable = Environment.variable(named: "TERM") {
678678
return termVariable != "dumb"
679679
}
@@ -695,7 +695,7 @@ extension Event.ConsoleOutputRecorder.Options {
695695
/// Whether or not the system terminal claims to support 256-color ANSI escape
696696
/// codes.
697697
private static var _terminalSupports256ColorANSIEscapeCodes: Bool {
698-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android)
698+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android)
699699
if let termVariable = Environment.variable(named: "TERM") {
700700
return strstr(termVariable, "256") != nil
701701
}
@@ -717,7 +717,7 @@ extension Event.ConsoleOutputRecorder.Options {
717717
/// Whether or not the system terminal claims to support true-color ANSI
718718
/// escape codes.
719719
private static var _terminalSupportsTrueColorANSIEscapeCodes: Bool {
720-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android)
720+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android)
721721
if let colortermVariable = Environment.variable(named: "COLORTERM") {
722722
return strstr(colortermVariable, "truecolor") != nil
723723
}

Sources/Testing/ABI/EntryPoints/SwiftPMEntryPoint.swift

Lines changed: 1 addition & 1 deletion
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(Android) || os(WASI)
27+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || os(WASI)
2828
EX_UNAVAILABLE
2929
#elseif os(Windows)
3030
CInt(ERROR_NOT_FOUND)

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) || os(Android) || os(WASI)
103+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || os(WASI)
104104
switch self {
105105
case .default:
106106
// Unicode: WHITE DIAMOND

Sources/Testing/ExitTests/ExitCondition.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,13 @@ public enum ExitCondition: Sendable {
4242
/// |-|-|
4343
/// | 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) |
4444
/// | Linux | [`<stdlib.h>`](https://sourceware.org/glibc/manual/latest/html_node/Exit-Status.html), `<sysexits.h>` |
45+
/// | FreeBSD | `<stdlib.h>`, `<sysexits.h>` |
4546
/// | Windows | [`<stdlib.h>`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure) |
4647
///
47-
/// On macOS and Windows, the full exit code reported by the process is
48-
/// yielded to the parent process. Linux and other POSIX-like systems may only
49-
/// reliably report the low unsigned 8 bits (0&ndash;255) of the exit code.
48+
/// On macOS, FreeBSD, and Windows, the full exit code reported by the process
49+
/// is yielded to the parent process. Linux and other POSIX-like systems may
50+
/// only reliably report the low unsigned 8 bits (0&ndash;255) of the exit
51+
/// code.
5052
case exitCode(_ exitCode: CInt)
5153

5254
/// The process terminated with the given signal.
@@ -61,6 +63,7 @@ public enum ExitCondition: Sendable {
6163
/// |-|-|
6264
/// | macOS | [`<signal.h>`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/signal.3.html) |
6365
/// | Linux | [`<signal.h>`](https://sourceware.org/glibc/manual/latest/html_node/Standard-Signals.html) |
66+
/// | FreeBSD | `<signal.h>` |
6467
/// | Windows | [`<signal.h>`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/signal-constants) |
6568
///
6669
/// On Windows, by default, the C runtime will terminate a process with exit

Sources/Testing/ExitTests/ExitTest.swift

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ public struct ExitTest: Sendable {
4747
EXCEPTION_DEFAULT,
4848
THREAD_STATE_NONE
4949
)
50-
#elseif os(Linux)
51-
// On Linux, disable the generation of core files (although they will often
52-
// be disabled by default.) If a particular Linux distro performs additional
53-
// crash diagnostics, we may want to special-case them as well if we can.
50+
#elseif os(Linux) || os(FreeBSD)
51+
// On Linux and FreeBSD, disable the generation of core files (although they
52+
// will often be disabled by default.) If a particular Linux distro performs
53+
// additional crash diagnostics, we may want to special-case them as well if we can.
5454
var rl = rlimit(rlim_cur: 0, rlim_max: 0)
5555
_ = setrlimit(CInt(RLIMIT_CORE.rawValue), &rl)
5656
#elseif os(Windows)
@@ -322,13 +322,14 @@ extension ExitTest {
322322
for key in childEnvironment.keys where key.starts(with: "XCTest") {
323323
childEnvironment.removeValue(forKey: key)
324324
}
325-
#elseif os(Linux)
325+
#endif
326+
326327
if childEnvironment["SWIFT_BACKTRACE"] == nil {
327328
// Disable interactive backtraces unless explicitly enabled to reduce
328-
// the noise level during the exit test. Only needed on Linux.
329+
// the noise level during the exit test.
329330
childEnvironment["SWIFT_BACKTRACE"] = "enable=no"
330331
}
331-
#endif
332+
332333
// Insert a specific variable that tells the child process which exit test
333334
// to run.
334335
try JSON.withEncoding(of: exitTest.sourceLocation) { json in
@@ -364,11 +365,11 @@ extension ExitTest {
364365
// use, so use this typealias to paper over the differences.
365366
#if SWT_TARGET_OS_APPLE
366367
typealias P<T> = T?
367-
#elseif os(Linux)
368+
#elseif os(Linux) || os(FreeBSD)
368369
typealias P<T> = T
369370
#endif
370371

371-
#if SWT_TARGET_OS_APPLE || os(Linux)
372+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD)
372373
let pid = try withUnsafeTemporaryAllocation(of: P<posix_spawn_file_actions_t>.self, capacity: 1) { fileActions in
373374
guard 0 == posix_spawn_file_actions_init(fileActions.baseAddress!) else {
374375
throw CError(rawValue: swt_errno())

Sources/Testing/ExitTests/WaitFor.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
internal import _TestingInternals
1414

15-
#if SWT_TARGET_OS_APPLE || os(Linux)
15+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD)
1616
/// Block the calling thread, wait for the target process to exit, and return
1717
/// a value describing the conditions under which it exited.
1818
///
@@ -104,11 +104,16 @@ private let _createWaitThreadImpl: Void = {
104104
{ _ in
105105
// Set the thread name to help with diagnostics. Note that different
106106
// platforms support different thread name lengths. See MAXTHREADNAMESIZE
107-
// on Darwin and TASK_COMM_LEN on Linux.
107+
// on Darwin, TASK_COMM_LEN on Linux, and MAXCOMLEN on FreeBSD. We try to
108+
// maximize legibility in the available space.
108109
#if SWT_TARGET_OS_APPLE
109110
_ = pthread_setname_np("Swift Testing exit test monitor")
110-
#else
111+
#elseif os(Linux)
111112
_ = pthread_setname_np(pthread_self(), "SWT ExT monitor")
113+
#elseif os(FreeBSD)
114+
_ = pthread_set_name_np(pthread_self(), "SWT ex test monitor")
115+
#else
116+
#warning("Platform-specific implementation missing: thread naming unavailable")
112117
#endif
113118

114119
// Run an infinite loop that waits for child processes to terminate and

Sources/Testing/SourceAttribution/Backtrace+Symbolication.swift

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,12 @@ extension Backtrace {
7070
result[i] = SymbolicatedAddress(address: address, offset: offset, symbolName: symbolName)
7171
}
7272
}
73-
#elseif os(Linux)
74-
// Although Linux has dladdr(), it does not have symbol names from ELF
75-
// binaries by default. The standard library's backtracing functionality has
76-
// implemented sufficient ELF/DWARF parsing to be able to symbolicate Linux
77-
// backtraces. TODO: adopt the standard library's Backtrace on Linux
78-
// Note that this means on Linux we don't have demangling capability (since
79-
// we don't have the mangled symbol names in the first place) so this code
80-
// does not check the mode argument.
73+
#elseif os(Linux) || os(FreeBSD) || os(Android)
74+
// Although these platforms have dladdr(), they do not have symbol names
75+
// from DWARF binaries by default, only from shared libraries. The standard
76+
// library's backtracing functionality has implemented sufficient ELF/DWARF
77+
// parsing to be able to symbolicate Linux backtraces.
78+
// TODO: adopt the standard library's Backtrace on these platforms
8179
#elseif os(Windows)
8280
_withDbgHelpLibrary { hProcess in
8381
guard let hProcess else {

Sources/Testing/SourceAttribution/Backtrace.swift

Lines changed: 1 addition & 1 deletion
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)
72+
#elseif os(Linux) || os(FreeBSD)
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))

Sources/Testing/Support/Additions/CommandLineAdditions.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ extension CommandLine {
3838
buffer[readCount] = 0 // NUL-terminate the string.
3939
return String(cString: buffer.baseAddress!)
4040
}
41+
#elseif os(FreeBSD)
42+
var mib = [CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1]
43+
try mib.withUnsafeMutableBufferPointer { mib in
44+
var bufferCount = 0
45+
guard 0 == sysctl(mib.baseAddress!, .init(mib.count), nil, &bufferCount, nil, 0) else {
46+
throw CError(rawValue: swt_errno())
47+
}
48+
return try withUnsafeTemporaryAllocation(of: CChar.self, capacity: bufferCount) { buffer in
49+
guard 0 == sysctl(mib.baseAddress!, .init(mib.count), nil, &bufferCount, nil, 0) else {
50+
throw CError(rawValue: swt_errno())
51+
}
52+
return String(cString: buffer.baseAddress!)
53+
}
54+
}
4155
#elseif os(Windows)
4256
return try withUnsafeTemporaryAllocation(of: wchar_t.self, capacity: Int(MAX_PATH) * 2) { buffer in
4357
guard 0 != GetModuleFileNameW(nil, buffer.baseAddress!, DWORD(buffer.count)) else {

Sources/Testing/Support/Environment.swift

Lines changed: 3 additions & 3 deletions
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(Android) || os(WASI)
45+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || 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(Android)
106+
#elseif os(Linux) || os(FreeBSD) || 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(Android) || os(WASI)
173+
#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || 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)