From 1d89bf6c8e49321f01c8db7a916f0ddf6925fb7c Mon Sep 17 00:00:00 2001 From: 3405691582 Date: Thu, 13 Nov 2025 07:04:12 -0500 Subject: [PATCH] OpenBSD support. There is potential for simplifying some of these conditional chains. For now, I have avoided doing this since this should be picked onto the release branch and simply extending the chains limits the risk scope slightly. --- Sources/SwiftDocC/Benchmark/Benchmark.swift | 2 ++ Sources/SwiftDocC/Benchmark/Metrics/PeakMemory.swift | 2 +- .../External Data/OutOfProcessReferenceResolver.swift | 2 +- Sources/SwiftDocC/Model/Rendering/RenderContext.swift | 2 +- .../FoundationExtensions/AutoreleasepoolShim.swift | 2 +- Sources/SwiftDocC/Utility/Synchronization.swift | 8 ++++---- .../SwiftDocCUtilities/Utility/DirectoryMonitor.swift | 2 +- Sources/SwiftDocCUtilities/Utility/Signal.swift | 2 +- Sources/docc/main.swift | 2 +- .../Servers/DocumentationSchemeHandlerTests.swift | 4 ++-- Tests/SwiftDocCTests/Servers/FileServerTests.swift | 2 +- Tests/SwiftDocCTests/Utility/LMDBTests.swift | 2 +- Tests/SwiftDocCUtilitiesTests/C+Extensions.swift | 2 +- .../DirectoryMonitorTests.swift | 10 +++++----- build-script-helper.py | 5 +++++ 15 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Sources/SwiftDocC/Benchmark/Benchmark.swift b/Sources/SwiftDocC/Benchmark/Benchmark.swift index 91def41539..51654324fe 100644 --- a/Sources/SwiftDocC/Benchmark/Benchmark.swift +++ b/Sources/SwiftDocC/Benchmark/Benchmark.swift @@ -48,6 +48,8 @@ public class Benchmark: Encodable { public let platform = "Android" #elseif os(FreeBSD) public let platform = "FreeBSD" + #elseif os(OpenBSD) + public let platform = "OpenBSD" #else public let platform = "unsupported" #endif diff --git a/Sources/SwiftDocC/Benchmark/Metrics/PeakMemory.swift b/Sources/SwiftDocC/Benchmark/Metrics/PeakMemory.swift index d8506cd074..5acb4575b3 100644 --- a/Sources/SwiftDocC/Benchmark/Metrics/PeakMemory.swift +++ b/Sources/SwiftDocC/Benchmark/Metrics/PeakMemory.swift @@ -67,7 +67,7 @@ extension Benchmark { ) else { return nil } return Int64(pmcStats.PeakWorkingSetSize) } - #elseif os(FreeBSD) + #elseif os(FreeBSD) || os(OpenBSD) private static func peakMemory() -> Int64? { var usage = rusage() if (getrusage(RUSAGE_SELF, &usage) == -1) { diff --git a/Sources/SwiftDocC/Infrastructure/External Data/OutOfProcessReferenceResolver.swift b/Sources/SwiftDocC/Infrastructure/External Data/OutOfProcessReferenceResolver.swift index 25523e6520..6c70a86b0e 100644 --- a/Sources/SwiftDocC/Infrastructure/External Data/OutOfProcessReferenceResolver.swift +++ b/Sources/SwiftDocC/Infrastructure/External Data/OutOfProcessReferenceResolver.swift @@ -517,7 +517,7 @@ private class LongRunningService: ExternalLinkResolving { /// This private class is only used by the ``OutOfProcessReferenceResolver`` and shouldn't be used for general communication with other processes. private class LongRunningProcess: ExternalLinkResolving { - #if os(macOS) || os(Linux) || os(Android) || os(FreeBSD) + #if os(macOS) || os(Linux) || os(Android) || os(FreeBSD) || os(OpenBSD) private let process: Process init(location: URL, errorOutputHandler: @escaping (String) -> Void) throws { diff --git a/Sources/SwiftDocC/Model/Rendering/RenderContext.swift b/Sources/SwiftDocC/Model/Rendering/RenderContext.swift index 367845ad35..00654a4a16 100644 --- a/Sources/SwiftDocC/Model/Rendering/RenderContext.swift +++ b/Sources/SwiftDocC/Model/Rendering/RenderContext.swift @@ -61,7 +61,7 @@ public struct RenderContext { ) } - #if os(macOS) || os(iOS) || os(Android) || os(Windows) || os(FreeBSD) + #if os(macOS) || os(iOS) || os(Android) || os(Windows) || os(FreeBSD) || os(OpenBSD) // Concurrently render content on macOS/iOS, Windows & Android let results: [(reference: ResolvedTopicReference, content: RenderReferenceStore.TopicContent)] = references.concurrentPerform { reference, results in results.append((reference, renderContentFor(reference))) diff --git a/Sources/SwiftDocC/Utility/FoundationExtensions/AutoreleasepoolShim.swift b/Sources/SwiftDocC/Utility/FoundationExtensions/AutoreleasepoolShim.swift index 783a29a8ec..8765ab4d79 100644 --- a/Sources/SwiftDocC/Utility/FoundationExtensions/AutoreleasepoolShim.swift +++ b/Sources/SwiftDocC/Utility/FoundationExtensions/AutoreleasepoolShim.swift @@ -8,7 +8,7 @@ See https://swift.org/CONTRIBUTORS.txt for Swift project authors */ -#if os(Linux) || os(Android) || os(Windows) || os(FreeBSD) +#if os(Linux) || os(Android) || os(Windows) || os(FreeBSD) || os(OpenBSD) /// A shim for non-ObjC targets that runs the given block of code. /// /// The existence of this shim allows you the use of auto-release pools to optimize memory footprint on Darwin platforms while maintaining diff --git a/Sources/SwiftDocC/Utility/Synchronization.swift b/Sources/SwiftDocC/Utility/Synchronization.swift index 80395c176f..9ba2ea8266 100644 --- a/Sources/SwiftDocC/Utility/Synchronization.swift +++ b/Sources/SwiftDocC/Utility/Synchronization.swift @@ -35,7 +35,7 @@ public class Synchronized { #elseif os(Linux) || os(Android) /// A lock type appropriate for the current platform. var lock: UnsafeMutablePointer - #elseif os(FreeBSD) + #elseif os(FreeBSD) || os(OpenBSD) /// A lock type appropriate for the current platform. var lock: UnsafeMutablePointer #elseif os(Windows) @@ -56,7 +56,7 @@ public class Synchronized { lock = UnsafeMutablePointer.allocate(capacity: 1) lock.initialize(to: pthread_mutex_t()) pthread_mutex_init(lock, nil) - #elseif os(FreeBSD) + #elseif os(FreeBSD) || os(OpenBSD) lock = UnsafeMutablePointer.allocate(capacity: 1) lock.initialize(to: nil) pthread_mutex_init(lock, nil) @@ -84,7 +84,7 @@ public class Synchronized { #elseif os(Linux) || os(Android) pthread_mutex_lock(lock) defer { pthread_mutex_unlock(lock) } - #elseif os(FreeBSD) + #elseif os(FreeBSD) || os(OpenBSD) pthread_mutex_lock(lock) defer { pthread_mutex_unlock(lock) } #elseif os(Windows) @@ -123,7 +123,7 @@ extension Lock { #elseif os(Linux) || os(Android) pthread_mutex_lock(lock) defer { pthread_mutex_unlock(lock) } - #elseif os(FreeBSD) + #elseif os(FreeBSD) || os(OpenBSD) pthread_mutex_lock(lock) defer { pthread_mutex_unlock(lock) } #elseif os(Windows) diff --git a/Sources/SwiftDocCUtilities/Utility/DirectoryMonitor.swift b/Sources/SwiftDocCUtilities/Utility/DirectoryMonitor.swift index 57795e0d08..e999c6c296 100644 --- a/Sources/SwiftDocCUtilities/Utility/DirectoryMonitor.swift +++ b/Sources/SwiftDocCUtilities/Utility/DirectoryMonitor.swift @@ -11,7 +11,7 @@ import Foundation import SwiftDocC -#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) +#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD) import Darwin /// A throttle object to filter events that come too fast. diff --git a/Sources/SwiftDocCUtilities/Utility/Signal.swift b/Sources/SwiftDocCUtilities/Utility/Signal.swift index 54da5201e8..ac603fe2ac 100644 --- a/Sources/SwiftDocCUtilities/Utility/Signal.swift +++ b/Sources/SwiftDocCUtilities/Utility/Signal.swift @@ -27,7 +27,7 @@ public struct Signal { signalAction.__sigaction_handler = unsafeBitCast(callback, to: sigaction.__Unnamed_union___sigaction_handler.self) #elseif os(Android) signalAction.sa_handler = callback - #elseif os(FreeBSD) + #elseif os(FreeBSD) || os(OpenBSD) signalAction.__sigaction_u.__sa_handler = callback #else signalAction.__sigaction_u = unsafeBitCast(callback, to: __sigaction_u.self) diff --git a/Sources/docc/main.swift b/Sources/docc/main.swift index 1715eed8e1..f01d3ee4c9 100644 --- a/Sources/docc/main.swift +++ b/Sources/docc/main.swift @@ -8,7 +8,7 @@ See https://swift.org/CONTRIBUTORS.txt for Swift project authors */ -#if os(macOS) || os(Linux) || os(Android) || os(Windows) || os(FreeBSD) +#if os(macOS) || os(Linux) || os(Android) || os(Windows) || os(FreeBSD) || os(OpenBSD) import SwiftDocCUtilities await Task { diff --git a/Tests/SwiftDocCTests/Servers/DocumentationSchemeHandlerTests.swift b/Tests/SwiftDocCTests/Servers/DocumentationSchemeHandlerTests.swift index aa2c5ba9d6..035f45f932 100644 --- a/Tests/SwiftDocCTests/Servers/DocumentationSchemeHandlerTests.swift +++ b/Tests/SwiftDocCTests/Servers/DocumentationSchemeHandlerTests.swift @@ -24,7 +24,7 @@ class DocumentationSchemeHandlerTests: XCTestCase { forResource: "LegacyBundle_DoNotUseInNewTests", withExtension: "docc", subdirectory: "Test Bundles")! func testDocumentationSchemeHandler() { - #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) + #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD) let topicSchemeHandler = DocumentationSchemeHandler(withTemplateURL: templateURL) let request = URLRequest(url: baseURL.appendingPathComponent("/images/figure1.jpg")) @@ -50,7 +50,7 @@ class DocumentationSchemeHandlerTests: XCTestCase { } func testSetData() { - #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) + #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD) let topicSchemeHandler = DocumentationSchemeHandler(withTemplateURL: templateURL) let data = "hello!".data(using: .utf8)! diff --git a/Tests/SwiftDocCTests/Servers/FileServerTests.swift b/Tests/SwiftDocCTests/Servers/FileServerTests.swift index 4ed3db5f9b..6c1966714c 100644 --- a/Tests/SwiftDocCTests/Servers/FileServerTests.swift +++ b/Tests/SwiftDocCTests/Servers/FileServerTests.swift @@ -164,7 +164,7 @@ class FileServerTests: XCTestCase { (response, data) = fileServer.response(to: failingRequest) XCTAssertNil(data) // Initializing a URLResponse with `nil` as MIME type in Linux returns nil - #if os(Linux) || os(Android) || os(Windows) || os(FreeBSD) + #if os(Linux) || os(Android) || os(Windows) || os(FreeBSD) || os(OpenBSD) XCTAssertNil(response.mimeType) #else // Doing the same in macOS or iOS returns the default MIME type diff --git a/Tests/SwiftDocCTests/Utility/LMDBTests.swift b/Tests/SwiftDocCTests/Utility/LMDBTests.swift index dd50b29604..fdbb06dbbd 100644 --- a/Tests/SwiftDocCTests/Utility/LMDBTests.swift +++ b/Tests/SwiftDocCTests/Utility/LMDBTests.swift @@ -237,7 +237,7 @@ final class SwiftLMDBTests: XCTestCase { } func testArrayOfInt() throws { -#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) +#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD) let database = try environment.openDatabase() var array: [UInt32] = [] diff --git a/Tests/SwiftDocCUtilitiesTests/C+Extensions.swift b/Tests/SwiftDocCUtilitiesTests/C+Extensions.swift index 3d52435ffa..f74934c5a5 100644 --- a/Tests/SwiftDocCUtilitiesTests/C+Extensions.swift +++ b/Tests/SwiftDocCUtilitiesTests/C+Extensions.swift @@ -11,7 +11,7 @@ import Foundation #if os(Windows) import ucrt -#elseif os(Linux) || os(Android) || os(FreeBSD) +#elseif os(Linux) || os(Android) || os(FreeBSD) || os(OpenBSD) import Glibc #else import Darwin diff --git a/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift b/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift index efd9b23b15..e268d35827 100644 --- a/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift +++ b/Tests/SwiftDocCUtilitiesTests/DirectoryMonitorTests.swift @@ -11,7 +11,7 @@ import XCTest @testable import SwiftDocCUtilities -#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) +#if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD) fileprivate extension NSNotification.Name { static let testNodeUpdated = NSNotification.Name(rawValue: "testNodeUpdated") static let testDirectoryReloaded = NSNotification.Name(rawValue: "testDirectoryReloaded") @@ -24,7 +24,7 @@ func fileURLsAreEqual(_ url1: URL, _ url2: URL) -> Bool { #endif class DirectoryMonitorTests: XCTestCase { - #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) + #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD) // - MARK: Directory watching test infra /// Method that automates setting up a directory monitor, setting up the relevant expectations for a test, @@ -115,7 +115,7 @@ class DirectoryMonitorTests: XCTestCase { /// Tests a succession of file system changes and verifies that they produce /// the expected monitor events. func testMonitorUpdates() throws { - #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) + #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD) // Create temp folder & sub-folder. let tempSubfolderURL = try createTemporaryDirectory(named: "subfolder") @@ -164,7 +164,7 @@ class DirectoryMonitorTests: XCTestCase { } func testMonitorDoesNotTriggerUpdates() throws { - #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) + #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD) // Create temp folder & sub-folder. let tempSubfolderURL = try createTemporaryDirectory(named: "subfolder") @@ -197,7 +197,7 @@ class DirectoryMonitorTests: XCTestCase { /// Tests a zero sum change aggregation triggers an event. func testMonitorZeroSumSizeChangesUpdates() throws { - #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) + #if !os(Linux) && !os(Android) && !os(Windows) && !os(FreeBSD) && !os(OpenBSD) // Create temp folder & sub-folder. let tempSubfolderURL = try createTemporaryDirectory(named: "subfolder") diff --git a/build-script-helper.py b/build-script-helper.py index 78594f62a4..3cfbc59990 100755 --- a/build-script-helper.py +++ b/build-script-helper.py @@ -176,6 +176,11 @@ def get_swiftpm_options(action, args): ] if action == 'install': swiftpm_args += ['--disable-local-rpath'] + elif build_os.startswith('openbsd'): + swiftpm_args += [ + '-Xlinker', '-rpath', '-Xlinker', '$ORIGIN/../lib/swift/openbsd', + '-Xlinker', '-z', '-Xlinker', 'origin', + ] else: swiftpm_args += [ # Library rpath for swift, dispatch, Foundation, etc. when installing