Skip to content

Commit 548a434

Browse files
michael-yujijakepetroules
authored andcommitted
Fix building and testing on FreeBSD; Add FreeBSD platform support
1 parent 08d26bc commit 548a434

29 files changed

+118
-24
lines changed

CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ find_package(Foundation QUIET)
5252
find_package(SQLite3 REQUIRED)
5353

5454
# Enable `package` modifier for the whole package.
55-
add_compile_options("$<$<COMPILE_LANGUAGE:Swift>:-package-name;SwiftPM>")
55+
if(CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
56+
add_compile_options("$<$<COMPILE_LANGUAGE:Swift>:-package-name;SwiftPM>" -L/usr/local/lib)
57+
else()
58+
add_compile_options("$<$<COMPILE_LANGUAGE:Swift>:-package-name;SwiftPM>")
59+
endif()
5660

5761
add_subdirectory(BuildSupport/SwiftSyntax)
5862
add_subdirectory(Sources)

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ let package = Package(
205205
name: "Basics",
206206
dependencies: [
207207
"_AsyncFileSystem",
208-
.target(name: "SPMSQLite3", condition: .when(platforms: [.macOS, .iOS, .tvOS, .watchOS, .visionOS, .macCatalyst, .linux])),
208+
.target(name: "SPMSQLite3", condition: .when(platforms: [.macOS, .iOS, .tvOS, .watchOS, .visionOS, .macCatalyst, .linux, .custom("freebsd")])),
209209
.product(name: "SwiftToolchainCSQLite", package: "swift-toolchain-sqlite", condition: .when(platforms: [.windows, .android])),
210210
.product(name: "DequeModule", package: "swift-collections"),
211211
.product(name: "OrderedCollections", package: "swift-collections"),

Sources/Basics/Archiver/ZipArchiver.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ public struct ZipArchiver: Archiver, Cancellable {
109109
arguments: [windowsTar, "-a", "-c", "-f", destinationPath.pathString, directory.basename],
110110
workingDirectory: directory.parentDirectory
111111
)
112+
#elseif os(FreeBSD)
113+
let process = AsyncProcess(
114+
arguments: ["tar", "-c", "--format", "zip", "-f", destinationPath.pathString, directory.basename],
115+
workingDirectory: directory.parentDirectory
116+
)
112117
#else
113118
// This is to work around `swift package-registry publish` tool failing on
114119
// Amazon Linux 2 due to it having an earlier Glibc version (rdar://116370323)

Sources/Basics/Cancellator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public final class Cancellator: Cancellable, Sendable {
7575

7676
// Install the default signal handler.
7777
var action = sigaction()
78-
#if canImport(Darwin) || os(OpenBSD)
78+
#if canImport(Darwin) || os(OpenBSD) || os(FreeBSD)
7979
action.__sigaction_u.__sa_handler = SIG_DFL
8080
#elseif canImport(Musl)
8181
action.__sa_handler.sa_handler = SIG_DFL

Sources/Basics/Concurrency/AsyncProcess.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ package final class AsyncProcess {
553553
return stdinPipe.fileHandleForWriting
554554
#elseif(!canImport(Darwin) || os(macOS))
555555
// Initialize the spawn attributes.
556-
#if canImport(Darwin) || os(Android) || os(OpenBSD)
556+
#if canImport(Darwin) || os(Android) || os(OpenBSD) || os(FreeBSD)
557557
var attributes: posix_spawnattr_t? = nil
558558
#else
559559
var attributes = posix_spawnattr_t()
@@ -598,7 +598,7 @@ package final class AsyncProcess {
598598
posix_spawnattr_setflags(&attributes, Int16(flags))
599599

600600
// Setup the file actions.
601-
#if canImport(Darwin) || os(Android) || os(OpenBSD)
601+
#if canImport(Darwin) || os(Android) || os(OpenBSD) || os(FreeBSD)
602602
var fileActions: posix_spawn_file_actions_t? = nil
603603
#else
604604
var fileActions = posix_spawn_file_actions_t()
@@ -614,6 +614,8 @@ package final class AsyncProcess {
614614
if #available(macOS 10.15, *) {
615615
posix_spawn_file_actions_addchdir_np(&fileActions, workingDirectory)
616616
}
617+
#elseif os(FreeBSD)
618+
posix_spawn_file_actions_addchdir_np(&fileActions, workingDirectory)
617619
#elseif os(Linux)
618620
guard SPM_posix_spawn_file_actions_addchdir_np_supported() else {
619621
throw AsyncProcess.Error.workingDirectoryNotSupported

Sources/Basics/DispatchTimeInterval+Extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ extension DispatchTimeInterval {
9595
}
9696

9797
// remove when available to all platforms
98-
#if os(Linux) || os(Windows) || os(Android) || os(OpenBSD)
98+
#if os(Linux) || os(Windows) || os(Android) || os(OpenBSD) || os(FreeBSD)
9999
extension DispatchTime {
100100
public func distance(to: DispatchTime) -> DispatchTimeInterval {
101101
let final = to.uptimeNanoseconds

Sources/Basics/Triple+Basics.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ extension Triple {
6262
os == .openbsd
6363
}
6464

65+
public func isFreeBSD() -> Bool {
66+
os == .freebsd
67+
}
68+
6569
/// Returns the triple string for the given platform version.
6670
///
6771
/// This is currently meant for Apple platforms only.
@@ -139,7 +143,7 @@ extension Triple {
139143
switch os {
140144
case _ where isDarwin():
141145
return ".dylib"
142-
case .linux, .openbsd:
146+
case .linux, .openbsd, .freebsd:
143147
return ".so"
144148
case .win32:
145149
return ".dll"
@@ -179,7 +183,7 @@ extension Triple {
179183
switch os {
180184
case _ where isDarwin():
181185
return ""
182-
case .linux, .openbsd:
186+
case .linux, .openbsd, .freebsd:
183187
return ""
184188
case .win32:
185189
return ".exe"

Sources/Basics/Vendor/Triple+Platforms.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ extension Triple {
304304

305305
case .linux:
306306
return environment == .android ? "android" : "linux"
307-
case .freeBSD:
307+
case .freebsd:
308308
return "freebsd"
309309
case .openbsd:
310310
return "openbsd"

Sources/Basics/Vendor/Triple.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,7 +1089,7 @@ extension Triple {
10891089
case cloudABI = "cloudabi"
10901090
case darwin
10911091
case dragonFly = "dragonfly"
1092-
case freeBSD = "freebsd"
1092+
case freebsd = "freebsd"
10931093
case fuchsia
10941094
case ios
10951095
case kfreebsd
@@ -1137,7 +1137,7 @@ extension Triple {
11371137
case _ where os.hasPrefix("dragonfly"):
11381138
return .dragonFly
11391139
case _ where os.hasPrefix("freebsd"):
1140-
return .freeBSD
1140+
return .freebsd
11411141
case _ where os.hasPrefix("fuchsia"):
11421142
return .fuchsia
11431143
case _ where os.hasPrefix("ios"):

Sources/Build/BuildDescription/ProductBuildDescription.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ public final class ProductBuildDescription: SPMBuildCore.ProductBuildDescription
270270
// Set rpath such that dynamic libraries are looked up
271271
// adjacent to the product, unless overridden.
272272
if !self.buildParameters.linkingParameters.shouldDisableLocalRpath {
273-
if triple.isLinux() {
273+
if triple.isLinux() || triple.isFreeBSD() {
274274
args += ["-Xlinker", "-rpath=$ORIGIN"]
275275
} else if triple.isDarwin() {
276276
let rpath = self.product.type == .test ? "@loader_path/../../../" : "@loader_path"

Sources/Build/BuildDescription/SwiftModuleBuildDescription.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public final class SwiftModuleBuildDescription {
144144
public var moduleOutputPath: AbsolutePath { // note: needs to be public because of sourcekit-lsp
145145
// If we're an executable and we're not allowing test targets to link against us, we hide the module.
146146
let triple = buildParameters.triple
147-
let allowLinkingAgainstExecutables = (triple.isDarwin() || triple.isLinux() || triple.isWindows()) && self.toolsVersion >= .v5_5
147+
let allowLinkingAgainstExecutables = (triple.isDarwin() || triple.isLinux() || triple.isFreeBSD() || triple.isWindows()) && self.toolsVersion >= .v5_5
148148
let dirPath = (target.type == .executable && !allowLinkingAgainstExecutables) ? self.tempsPath : self.modulesPath
149149
return dirPath.appending(component: "\(self.target.c99name).swiftmodule")
150150
}

Sources/Build/BuildPlan/BuildPlan+Product.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ extension BuildPlan {
6363
for description in dependencies.staticTargets {
6464
if case let target as ClangModule = description.module.underlying, target.isCXX {
6565
let triple = buildProduct.buildParameters.triple
66-
if triple.isDarwin() {
66+
if triple.isDarwin() || triple.isFreeBSD() {
6767
buildProduct.additionalFlags += ["-lc++"]
6868
} else if triple.isWindows() {
6969
// Don't link any C++ library.

Sources/Build/BuildPlan/BuildPlan.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ extension BuildParameters {
148148
let args: [String]
149149
if self.triple.isApple() {
150150
args = ["-alias", "_\(target.c99name)_main", "_main"]
151-
} else if self.triple.isLinux() {
151+
} else if self.triple.isLinux() || self.triple.isFreeBSD() {
152152
args = ["--defsym", "main=\(target.c99name)_main"]
153153
} else {
154154
return nil

Sources/Commands/SwiftTestCommand.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1538,7 +1538,7 @@ private extension Basics.Diagnostic {
15381538
/// it duplicates the definition of this constant in its own source. Any changes
15391539
/// to this constant in either package must be mirrored in the other.
15401540
private var EXIT_NO_TESTS_FOUND: CInt {
1541-
#if os(macOS) || os(Linux) || canImport(Android)
1541+
#if os(macOS) || os(Linux) || canImport(Android) || os(FreeBSD)
15421542
EX_UNAVAILABLE
15431543
#elseif os(Windows)
15441544
ERROR_NOT_FOUND

Sources/PackageCollections/Providers/JSONPackageCollectionProvider.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ private typealias JSONModel = PackageCollectionModel.V1
3232
struct JSONPackageCollectionProvider: PackageCollectionProvider {
3333
// TODO: This can be removed when the `Security` framework APIs that the `PackageCollectionsSigning`
3434
// module depends on are available on all Apple platforms.
35-
#if os(macOS) || os(Linux) || os(Windows) || os(Android)
35+
#if os(macOS) || os(Linux) || os(Windows) || os(Android) || os(FreeBSD)
3636
static let isSignatureCheckSupported = true
3737
#else
3838
static let isSignatureCheckSupported = false
@@ -551,6 +551,8 @@ extension PackageModel.Platform {
551551
self = PackageModel.Platform.wasi
552552
case let name where name.contains("openbsd"):
553553
self = PackageModel.Platform.openbsd
554+
case let name where name.contains("freebsd"):
555+
self = PackageModel.Platform.freebsd
554556
default:
555557
return nil
556558
}

Sources/PackageDescription/SupportedPlatforms.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ public struct Platform: Equatable, Sendable {
6969
/// The OpenBSD platform.
7070
@available(_PackageDescription, introduced: 5.8)
7171
public static let openbsd: Platform = Platform(name: "openbsd")
72+
73+
/// The FreeBSD platform
74+
// @available(_PackageDescription, introduced: ??.??)
75+
public static let freebsd: Platform = Platform(name: "freebsd")
7276
}
7377

7478
/// A platform that the Swift package supports.

Sources/PackageLoading/Platform.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public enum Platform: Equatable, Sendable {
2525
case darwin
2626
case linux(LinuxFlavor)
2727
case windows
28+
case freebsd
2829

2930
/// Recognized flavors of linux.
3031
public enum LinuxFlavor: Equatable, Sendable {
@@ -44,6 +45,8 @@ extension Platform {
4445
{
4546
case "darwin"?:
4647
return .darwin
48+
case "freebsd"?:
49+
return .freebsd
4750
case "linux"?:
4851
return Platform.findCurrentPlatformLinux(localFileSystem)
4952
default:
@@ -89,15 +92,15 @@ extension Platform {
8992
public var dynamicLibraryExtension: String {
9093
switch self {
9194
case .darwin: return ".dylib"
92-
case .linux, .android: return ".so"
95+
case .linux, .android, .freebsd: return ".so"
9396
case .windows: return ".dll"
9497
}
9598
}
9699

97100
public var executableExtension: String {
98101
switch self {
99102
case .windows: return ".exe"
100-
case .linux, .android, .darwin: return ""
103+
case .linux, .android, .darwin, .freebsd: return ""
101104
}
102105
}
103106
}

Sources/PackageLoading/Target+PkgConfig.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ extension SystemPackageProviderDescription {
154154
return " yum install \(packages.joined(separator: " "))\n"
155155
case .nuget(let packages):
156156
return " nuget install \(packages.joined(separator: " "))\n"
157+
case .pkg(let packages):
158+
return " pkg install \(packages.joined(separator: " "))\n"
157159
}
158160
}
159161

@@ -180,9 +182,13 @@ extension SystemPackageProviderDescription {
180182
switch platform {
181183
case .darwin, .windows, .linux:
182184
return true
183-
case .android:
185+
case .android, .freebsd:
184186
return false
185187
}
188+
case .pkg:
189+
if case .freebsd = platform {
190+
return true
191+
}
186192
}
187193
return false
188194
}
@@ -215,6 +221,8 @@ extension SystemPackageProviderDescription {
215221
return []
216222
case .nuget:
217223
return []
224+
case .pkg:
225+
return []
218226
}
219227
}
220228

Sources/PackageModel/Manifest/SystemPackageProviderDescription.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ public enum SystemPackageProviderDescription: Hashable, Codable, Sendable {
1616
case apt([String])
1717
case yum([String])
1818
case nuget([String])
19+
case pkg([String])
1920
}
2021

2122
extension SystemPackageProviderDescription {
2223
private enum CodingKeys: String, CodingKey {
23-
case brew, apt, yum, nuget
24+
case brew, apt, yum, nuget, pkg
2425
}
2526

2627
public func encode(to encoder: Encoder) throws {
@@ -38,6 +39,9 @@ extension SystemPackageProviderDescription {
3839
case let .nuget(a1):
3940
var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .nuget)
4041
try unkeyedContainer.encode(a1)
42+
case let .pkg(a1):
43+
var unkeyedContainer = container.nestedUnkeyedContainer(forKey: .pkg)
44+
try unkeyedContainer.encode(a1)
4145
}
4246
}
4347

@@ -63,6 +67,10 @@ extension SystemPackageProviderDescription {
6367
var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key)
6468
let a1 = try unkeyedValues.decode([String].self)
6569
self = .nuget(a1)
70+
case .pkg:
71+
var unkeyedValues = try values.nestedUnkeyedContainer(forKey: key)
72+
let a1 = try unkeyedValues.decode([String].self)
73+
self = .pkg(a1)
6674
}
6775
}
6876
}

Sources/PackageModel/ManifestSourceGeneration.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ fileprivate extension SourceCodeFragment {
416416
case .nuget(let names):
417417
let params = [SourceCodeFragment(strings: names)]
418418
self.init(enum: "nuget", subnodes: params)
419+
case .pkg(let names):
420+
let params = [SourceCodeFragment(strings: names)]
421+
self.init(enum: "pkg", subnodes: params)
419422
}
420423
}
421424

Sources/PackageModel/Platform.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public struct Platform: Equatable, Hashable, Codable, Sendable {
4949
public static let windows: Platform = Platform(name: "windows", oldestSupportedVersion: .unknown)
5050
public static let wasi: Platform = Platform(name: "wasi", oldestSupportedVersion: .unknown)
5151
public static let openbsd: Platform = Platform(name: "openbsd", oldestSupportedVersion: .unknown)
52+
public static let freebsd: Platform = Platform(name: "freebsd", oldestSupportedVersion: .unknown)
53+
5254

5355
}
5456

Sources/PackageModel/PlatformRegistry.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public struct PlatformRegistry {
3838
.macOS,
3939
.macCatalyst,
4040
.openbsd,
41+
.freebsd,
4142
.tvOS,
4243
.visionOS,
4344
.wasi,

Sources/SPMBuildCore/BinaryTarget+Extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ extension Triple.OS {
9999
/// Returns a representation of the receiver that can be compared with platform strings declared in an XCFramework.
100100
fileprivate var asXCFrameworkPlatformString: String? {
101101
switch self {
102-
case .darwin, .linux, .wasi, .win32, .openbsd, .noneOS:
102+
case .darwin, .linux, .wasi, .win32, .openbsd, .freebsd, .noneOS:
103103
return nil // XCFrameworks do not support any of these platforms today.
104104
case .macosx:
105105
return "macos"

Sources/SPMBuildCore/BuildParameters/BuildParameters.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ public struct BuildParameters: Encodable {
115115
return .windows
116116
} else if self.triple.isOpenBSD() {
117117
return .openbsd
118+
} else if self.triple.isFreeBSD() {
119+
return .freebsd
118120
} else {
119121
return .linux
120122
}

Sources/XCBuildSupport/PIFBuilder.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,6 +1727,9 @@ extension [PackageCondition] {
17271727
case .openbsd:
17281728
result += PIF.PlatformFilter.openBSDFilters
17291729

1730+
case .freebsd:
1731+
result += PIF.PlatformFilter.freeBSDFilters
1732+
17301733
default:
17311734
assertionFailure("Unhandled platform condition: \(condition)")
17321735
}
@@ -1789,6 +1792,11 @@ extension PIF.PlatformFilter {
17891792
.init(platform: "openbsd"),
17901793
]
17911794

1795+
/// FreeBSD filters.
1796+
public static let freeBSDFilters: [PIF.PlatformFilter] = [
1797+
.init(platform: "freebsd"),
1798+
]
1799+
17921800
/// WebAssembly platform filters.
17931801
public static let webAssemblyFilters: [PIF.PlatformFilter] = [
17941802
.init(platform: "wasi"),

Tests/BasicsTests/Archiver/UniversalArchiverTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ final class UniversalArchiverTests: XCTestCase {
8282
inputArchivePath = AbsolutePath(#file).parentDirectory
8383
.appending(components: "Inputs", "invalid_archive.zip")
8484
await XCTAssertAsyncThrowsError(try await archiver.extract(from: inputArchivePath, to: tmpdir)) { error in
85-
#if os(Windows)
85+
#if os(Windows) || os(FreeBSD)
8686
XCTAssertMatch((error as? StringError)?.description, .contains("Unrecognized archive format"))
8787
#else
8888
XCTAssertMatch((error as? StringError)?.description, .contains("End-of-central-directory signature not found"))

0 commit comments

Comments
 (0)