Skip to content

Commit 014d874

Browse files
authored
Additional FreeBSD fixes (#865)
Add FreeBSD support for swift-testing. ### Result: With this PR, swift-testing can be built on FreeBSD (tested on x86_64 FreeBSD 14.1-RELEASE-p6) ### Known issue: There are some issue running `swift test` on this repo, but most likely due to bugs in my host toolchain. - Tests failed to link due to duplicated main symbols: ``` error: link command failed with exit code 1 (use -v to see invocation) ld: error: duplicate symbol: main >>> defined at TestingMacrosMain.swift:0 (/zdata/swift-main/swift-project/swift-testing/Sources/TestingMacros/TestingMacrosMain.swift:0) >>> /zdata/swift-main/swift-project/swift-testing/.build/x86_64-unknown-freebsd14.1/debug/TestingMacros-tool.build/TestingMacrosMain.swift.o:(main) >>> defined at runner.swift:0 (/zdata/swift-main/swift-project/swift-testing/.build/x86_64-unknown-freebsd14.1/debug/swift-testingPackageTests.derived/runner.swift:0) >>> /zdata/swift-main/swift-project/swift-testing/.build/x86_64-unknown-freebsd14.1/debug/swift_testingPackageTests-tool.build/runner.swift.o:(.text.main+0x0) clang: error: linker command failed with exit code 1 (use -v to see invocation) [25/26] Linking swift-testingPackageTests.xctest ``` - [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 c61e5ad commit 014d874

File tree

5 files changed

+32
-11
lines changed

5 files changed

+32
-11
lines changed

Sources/Testing/ExitTests/ExitTest.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ extension ExitTest {
114114
// As with Linux, disable the generation core files. FreeBSD does not, as
115115
// far as I can tell, special-case RLIMIT_CORE=1.
116116
var rl = rlimit(rlim_cur: 0, rlim_max: 0)
117-
_ = setrlimit(CInt(RLIMIT_CORE.rawValue), &rl)
117+
_ = setrlimit(RLIMIT_CORE, &rl)
118118
#elseif os(Windows)
119119
// On Windows, similarly disable Windows Error Reporting and the Windows
120120
// Error Reporting UI. Note we expect to be the first component to call

Sources/Testing/ExitTests/SpawnProcess.swift

+8-1
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,19 @@ func spawnExecutable(
143143
#if SWT_TARGET_OS_APPLE
144144
// Close all other file descriptors open in the parent.
145145
flags |= CShort(POSIX_SPAWN_CLOEXEC_DEFAULT)
146-
#elseif os(Linux) || os(FreeBSD)
146+
#elseif os(Linux)
147147
// This platform doesn't have POSIX_SPAWN_CLOEXEC_DEFAULT, but we can at
148148
// least close all file descriptors higher than the highest inherited one.
149149
// We are assuming here that the caller didn't set FD_CLOEXEC on any of
150150
// these file descriptors.
151151
_ = swt_posix_spawn_file_actions_addclosefrom_np(fileActions, highestFD + 1)
152+
#elseif os(FreeBSD)
153+
// Like Linux, this platfrom doesn't have POSIX_SPAWN_CLOEXEC_DEFAULT;
154+
// However; unlike Linux, all non-EOL FreeBSD (>= 13.1) supports
155+
// `posix_spawn_file_actions_addclosefrom_np` and therefore we don't need
156+
// need `swt_posix_spawn_file_actions_addclosefrom_np` to guard the availability
157+
// of this api.
158+
_ = posix_spawn_file_actions_addclosefrom_np(fileActions, highestFD + 1)
152159
#else
153160
#warning("Platform-specific implementation missing: cannot close unused file descriptors")
154161
#endif

Sources/Testing/ExitTests/WaitFor.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,11 @@ private let _childProcessContinuations = Locked<[pid_t: CheckedContinuation<Exit
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)
89+
let result = UnsafeMutablePointer<pthread_cond_t?>.allocate(capacity: 1)
90+
#else
8891
let result = UnsafeMutablePointer<pthread_cond_t>.allocate(capacity: 1)
92+
#endif
8993
_ = pthread_cond_init(result, nil)
9094
return result
9195
}()
@@ -132,7 +136,7 @@ private let _createWaitThread: Void = {
132136

133137
// Create the thread. It will run immediately; because it runs in an infinite
134138
// loop, we aren't worried about detaching or joining it.
135-
#if SWT_TARGET_OS_APPLE
139+
#if SWT_TARGET_OS_APPLE || os(FreeBSD)
136140
var thread: pthread_t?
137141
#else
138142
var thread = pthread_t()

Sources/Testing/Support/Locked.swift

+10-8
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,22 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
3636
/// To keep the implementation of this type as simple as possible,
3737
/// `pthread_mutex_t` is used on Apple platforms instead of `os_unfair_lock`
3838
/// or `OSAllocatedUnfairLock`.
39-
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
40-
private typealias _Lock = pthread_mutex_t
39+
#if SWT_TARGET_OS_APPLE || os(Linux) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
40+
typealias PlatformLock = pthread_mutex_t
41+
#elseif os(FreeBSD)
42+
typealias PlatformLock = pthread_mutex_t?
4143
#elseif os(Windows)
42-
private typealias _Lock = SRWLOCK
44+
typealias PlatformLock = SRWLOCK
4345
#elseif os(WASI)
4446
// No locks on WASI without multithreaded runtime.
45-
private typealias _Lock = Void
47+
typealias PlatformLock = Void
4648
#else
4749
#warning("Platform-specific implementation missing: locking unavailable")
48-
private typealias _Lock = Void
50+
typealias PlatformLock = Void
4951
#endif
5052

5153
/// A type providing heap-allocated storage for an instance of ``Locked``.
52-
private final class _Storage: ManagedBuffer<T, _Lock> {
54+
private final class _Storage: ManagedBuffer<T, PlatformLock> {
5355
deinit {
5456
withUnsafeMutablePointerToElements { lock in
5557
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(Android) || (os(WASI) && compiler(>=6.1) && _runtime(_multithreaded))
@@ -66,7 +68,7 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
6668
}
6769

6870
/// Storage for the underlying lock and wrapped value.
69-
private nonisolated(unsafe) var _storage: ManagedBuffer<T, _Lock>
71+
private nonisolated(unsafe) var _storage: ManagedBuffer<T, PlatformLock>
7072

7173
init(rawValue: T) {
7274
_storage = _Storage.create(minimumCapacity: 1, makingHeaderWith: { _ in rawValue })
@@ -142,7 +144,7 @@ struct Locked<T>: RawRepresentable, Sendable where T: Sendable {
142144
/// - Warning: Callers that unlock the lock _must_ lock it again before the
143145
/// closure returns. If the lock is not acquired when `body` returns, the
144146
/// effect is undefined.
145-
nonmutating func withUnsafeUnderlyingLock<R>(_ body: (UnsafeMutablePointer<pthread_mutex_t>, T) throws -> R) rethrows -> R {
147+
nonmutating func withUnsafeUnderlyingLock<R>(_ body: (UnsafeMutablePointer<PlatformLock>, T) throws -> R) rethrows -> R {
146148
try withLock { value in
147149
try _storage.withUnsafeMutablePointerToElements { lock in
148150
try body(lock, value)

Sources/_TestingInternals/include/Includes.h

+8
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@
8080
#include <pthread.h>
8181
#endif
8282

83+
#if __has_include(<pthread_np.h>)
84+
#include <pthread_np.h>
85+
#endif
86+
8387
#if __has_include(<pty.h>)
8488
#include <pty.h>
8589
#endif
@@ -125,6 +129,10 @@
125129
#endif
126130
#endif
127131

132+
#if defined(__FreeBSD__)
133+
#include <libutil.h>
134+
#endif
135+
128136
#if defined(_WIN32)
129137
#define WIN32_LEAN_AND_MEAN
130138
#define NOMINMAX

0 commit comments

Comments
 (0)