Skip to content

Commit 9730e14

Browse files
committed
Add FreeBSD support
This allows building Swift Build for FreeBSD hosts, as well as building for a FreeBSD target from a FreeBSD host.
1 parent ac0a1ce commit 9730e14

16 files changed

+77
-15
lines changed

Diff for: Package.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ let package = Package(
105105
"SWBBuildSystem",
106106
"SWBServiceCore",
107107
"SWBTaskExecution",
108-
.product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .android, .windows])),
108+
.product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .openbsd, .android, .windows, .custom("freebsd")])),
109109
],
110110
exclude: ["CMakeLists.txt"],
111111
swiftSettings: swiftSettings(languageMode: .v5)),
@@ -195,8 +195,8 @@ let package = Package(
195195
"SWBCSupport",
196196
"SWBLibc",
197197
.product(name: "ArgumentParser", package: "swift-argument-parser"),
198-
.product(name: "Crypto", package: "swift-crypto", condition: .when(platforms: [.linux, .android])),
199-
.product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .android, .windows])),
198+
.product(name: "Crypto", package: "swift-crypto", condition: .when(platforms: [.linux, .openbsd, .android, .custom("freebsd")])),
199+
.product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .openbsd, .android, .windows, .custom("freebsd")])),
200200
],
201201
exclude: ["CMakeLists.txt"],
202202
swiftSettings: swiftSettings(languageMode: .v5)),
@@ -432,7 +432,7 @@ if useLocalDependencies {
432432
package.dependencies += [
433433
.package(url: "https://github.com/apple/swift-crypto.git", "2.0.0"..<"4.0.0"),
434434
.package(url: "https://github.com/swiftlang/swift-driver.git", branch: "main"),
435-
.package(url: "https://github.com/apple/swift-system.git", .upToNextMajor(from: "1.4.1")),
435+
.package(url: "https://github.com/apple/swift-system.git", .upToNextMajor(from: "1.4.2")),
436436
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.3"),
437437
]
438438
if !useLLBuildFramework {

Diff for: Sources/SWBCore/Core.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,6 @@ struct CoreRegistryDelegate : PlatformRegistryDelegate, SDKRegistryDelegate, Spe
685685
extension OperatingSystem {
686686
/// Whether the Core is allowed to create a fallback toolchain, SDK, and platform for this operating system in cases where no others have been provided.
687687
internal var createFallbackSystemToolchain: Bool {
688-
return self == .linux
688+
return self == .linux || self == .freebsd
689689
}
690690
}

Diff for: Sources/SWBCore/SDKRegistry.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ public final class SDKRegistry: SDKRegistryLookup, CustomStringConvertible, Send
623623
private func fallbackSystemSDKSettings(operatingSystem: OperatingSystem) throws -> [String: PropertyListItem] {
624624
let defaultProperties: [String: PropertyListItem]
625625
switch operatingSystem {
626-
case .linux:
626+
case .linux, .freebsd:
627627
defaultProperties = [
628628
// Workaround to avoid `-dependency_info` on Linux.
629629
"LD_DEPENDENCY_INFO_FILE": .plString(""),

Diff for: Sources/SWBCore/Settings/Settings.swift

+2
Original file line numberDiff line numberDiff line change
@@ -5299,6 +5299,8 @@ extension OperatingSystem {
52995299
return "windows"
53005300
case .linux:
53015301
return "linux"
5302+
case .freebsd:
5303+
return "freebsd"
53025304
case .android:
53035305
return "android"
53045306
case .unknown:

Diff for: Sources/SWBGenericUnixPlatform/Plugin.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ struct GenericUnixPlatformSpecsExtension: SpecificationsExtension {
2424
}
2525

2626
func specificationDomains() -> [String: [String]] {
27-
["linux": ["generic-unix"]]
27+
[
28+
"linux": ["generic-unix"],
29+
"freebsd": ["generic-unix"],
30+
]
2831
}
2932
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
(
14+
{
15+
Domain = freebsd;
16+
Identifier = com.apple.pbx.linkers.libtool;
17+
BasedOn = generic-unix:com.apple.pbx.linkers.libtool;
18+
Type = Linker;
19+
Options = (
20+
{
21+
Name = "LIBTOOL_USE_RESPONSE_FILE";
22+
Type = Boolean;
23+
DefaultValue = NO;
24+
},
25+
);
26+
},
27+
)

Diff for: Sources/SWBTestSupport/RunDestinationTestSupport.swift

+10
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ extension _RunDestinationInfo {
9898
windows
9999
case .linux:
100100
linux
101+
case .freebsd:
102+
freebsd
101103
case .android:
102104
android
103105
case .unknown:
@@ -259,6 +261,14 @@ extension _RunDestinationInfo {
259261
return .init(platform: "linux", sdk: "linux", sdkVariant: "linux", targetArchitecture: arch, supportedArchitectures: ["x86_64", "aarch64"], disableOnlyActiveArch: false)
260262
}
261263

264+
/// A run destination targeting FreeBSD generic device, using the public SDK.
265+
package static var freebsd: Self {
266+
guard let arch = Architecture.hostStringValue else {
267+
preconditionFailure("Unknown architecture \(Architecture.host.stringValue ?? "<nil>")")
268+
}
269+
return .init(platform: "freebsd", sdk: "freebsd", sdkVariant: "freebsd", targetArchitecture: arch, supportedArchitectures: ["x86_64", "aarch64"], disableOnlyActiveArch: false)
270+
}
271+
262272
/// A run destination targeting Android generic device, using the public SDK.
263273
package static var android: Self {
264274
return .init(platform: "android", sdk: "android", sdkVariant: "android", targetArchitecture: "undefined_arch", supportedArchitectures: ["armv7", "aarch64", "riscv64", "i686", "x86_64"], disableOnlyActiveArch: true)

Diff for: Sources/SWBTestSupport/SkippedTestSupport.swift

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ extension KnownSDK {
4848
return windows
4949
case .success(.linux):
5050
return linux
51+
case .success(.freebsd):
52+
return freebsd
5153
case .success(.android):
5254
return android
5355
case .success(.unknown), .failure:
@@ -68,6 +70,7 @@ extension KnownSDK {
6870
extension KnownSDK {
6971
package static let windows: Self = "windows"
7072
package static let linux: Self = "linux"
73+
package static let freebsd: Self = "freebsd"
7174
package static let android: Self = "android"
7275
package static let qnx: Self = "qnx"
7376
package static let wasi: Self = "wasi"

Diff for: Sources/SWBUtil/Architecture.swift

+7-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,13 @@ public struct Architecture: Sendable {
9898
if uname(&buf) == 0 {
9999
return withUnsafeBytes(of: &buf.machine) { buf in
100100
let data = Data(buf)
101-
return String(decoding: data[0...(data.lastIndex(where: { $0 != 0 }) ?? 0)], as: UTF8.self)
101+
let value = String(decoding: data[0...(data.lastIndex(where: { $0 != 0 }) ?? 0)], as: UTF8.self)
102+
switch value {
103+
case "amd64":
104+
return "x86_64"
105+
default:
106+
return value
107+
}
102108
}
103109
}
104110
return nil

Diff for: Sources/SWBUtil/FSProxy.swift

+8
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,9 @@ class LocalFS: FSProxy, @unchecked Sendable {
765765
#if os(Windows)
766766
// Implement ADS on Windows? See also https://github.com/swiftlang/swift-foundation/issues/1166
767767
return []
768+
#elseif os(FreeBSD)
769+
// FreeBSD blocked on https://github.com/swiftlang/swift/pull/77836
770+
return []
768771
#elseif os(OpenBSD)
769772
// OpenBSD no longer supports extended attributes
770773
return []
@@ -805,6 +808,8 @@ class LocalFS: FSProxy, @unchecked Sendable {
805808
func setExtendedAttribute(_ path: Path, key: String, value: ByteString) throws {
806809
#if os(Windows)
807810
// Implement ADS on Windows? See also https://github.com/swiftlang/swift-foundation/issues/1166
811+
#elseif os(FreeBSD)
812+
// FreeBSD blocked on https://github.com/swiftlang/swift/pull/77836
808813
#elseif os(OpenBSD)
809814
// OpenBSD no longer supports extended attributes
810815
#else
@@ -825,6 +830,9 @@ class LocalFS: FSProxy, @unchecked Sendable {
825830
#if os(Windows)
826831
// Implement ADS on Windows? See also https://github.com/swiftlang/swift-foundation/issues/1166
827832
return nil
833+
#elseif os(FreeBSD)
834+
// FreeBSD blocked on https://github.com/swiftlang/swift/pull/77836
835+
return nil
828836
#elseif os(OpenBSD)
829837
// OpenBSD no longer supports extended attributes
830838
return nil

Diff for: Sources/SWBUtil/Lock.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public final class Lock: @unchecked Sendable {
2828
let mutex: UnsafeMutablePointer<SRWLOCK> = UnsafeMutablePointer.allocate(capacity: 1)
2929
#else
3030
@usableFromInline
31-
let mutex: UnsafeMutablePointer<pthread_mutex_t> = UnsafeMutablePointer.allocate(capacity: 1)
31+
let mutex: UnsafeMutablePointer<pthread_mutex_t?> = UnsafeMutablePointer.allocate(capacity: 1)
3232
#endif
3333

3434
public init() {

Diff for: Sources/SWBUtil/ProcessInfo.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ extension ProcessInfo {
9797
return .windows
9898
#elseif os(Linux)
9999
return .linux
100+
#elseif os(FreeBSD)
101+
return .freebsd
100102
#else
101103
if try FileManager.default.isReadableFile(atPath: systemVersionPlistURL.filePath.str) {
102104
switch try systemVersion().productName {
@@ -127,6 +129,7 @@ public enum OperatingSystem: Hashable, Sendable {
127129
case visionOS(simulator: Bool)
128130
case windows
129131
case linux
132+
case freebsd
130133
case android
131134
case unknown
132135

@@ -155,7 +158,7 @@ public enum OperatingSystem: Hashable, Sendable {
155158
return .macho
156159
case .windows:
157160
return .pe
158-
case .linux, .android, .unknown:
161+
case .linux, .freebsd, .android, .unknown:
159162
return .elf
160163
}
161164
}

Diff for: Tests/SWBBuildServiceTests/BuildServiceTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import SWBTestSupport
3737
}
3838
}
3939

40-
@Test func macCatalystSupportsProductTypes() async throws {
40+
@Test(.skipHostOS(.freebsd, "#expect(throws:) crashes on FreeBSD")) func macCatalystSupportsProductTypes() async throws {
4141
#expect(try await withBuildService { try await $0.productTypeSupportsMacCatalyst(developerPath: nil, productTypeIdentifier: "com.apple.product-type.application") })
4242
#expect(try await withBuildService { try await $0.productTypeSupportsMacCatalyst(developerPath: nil, productTypeIdentifier: "com.apple.product-type.framework") })
4343
#expect(try await !withBuildService { try await $0.productTypeSupportsMacCatalyst(developerPath: nil, productTypeIdentifier: "com.apple.product-type.application.on-demand-install-capable") })

Diff for: Tests/SWBUtilTests/FSProxyTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ import SWBTestSupport
488488
case .android, .linux:
489489
// This will _usually_ be correct on Linux-derived OSes (see above), but not always.
490490
#expect(current_gid == ownership.group)
491-
case .macOS, .iOS, .tvOS, .watchOS, .visionOS:
491+
case .macOS, .iOS, .tvOS, .watchOS, .visionOS, .freebsd:
492492
#expect(parentDirOwnership.group == ownership.group)
493493
case .windows:
494494
// POSIX permissions don't exist, so everything is hardcoded to zero.
@@ -566,7 +566,7 @@ import SWBTestSupport
566566
}
567567
}
568568

569-
@Test(.skipHostOS(.windows))
569+
@Test(.skipHostOS(.windows), .skipHostOS(.freebsd, "Blocked on https://github.com/swiftlang/swift/pull/77836"))
570570
func extendedAttributesSupport() throws {
571571
try withTemporaryDirectory { (tmpDir: Path) in
572572
// Many filesystems on other platforms (e.g. various non-ext4 temporary filesystems on Linux) don't support xattrs and will return ENOTSUP.

Diff for: Tests/SWBUtilTests/MiscTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import SWBUtil
2525
#expect(SWBUtil.userCacheDir().str.hasPrefix("/var/folders"))
2626
case .android:
2727
#expect(SWBUtil.userCacheDir().str.hasPrefix("/data/local/tmp"))
28-
case .linux, .unknown:
28+
case .linux, .freebsd, .unknown:
2929
#expect(SWBUtil.userCacheDir().str.hasPrefix("/tmp"))
3030
}
3131
}

Diff for: Tests/SWBUtilTests/WaitConditionTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import Testing
4646
}
4747

4848
/// Tests cancellation behaviors.
49-
@Test
49+
@Test(.skipHostOS(.freebsd, "#expect(throws:) crashes on FreeBSD"))
5050
func cancellation() async {
5151
let condition = CancellableWaitCondition()
5252
let task = Task {

0 commit comments

Comments
 (0)