Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FreeBSD] Adding FreeBSD support #77836

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

michael-yuji
Copy link
Contributor

This commit adds required conditional compilation blocks to enable building and running
on FreeBSD (tested on x86_64 FreeBSD 14.1-RELEASE-p6).

Also implements FreeBSD synchronization shims using _umtx_op(2)

@michael-yuji michael-yuji requested a review from a team as a code owner November 25, 2024 22:53
@lin72h
Copy link

lin72h commented Nov 25, 2024

It's my early Christmas gift. Thanks for working on this.

@michael-yuji
Copy link
Contributor Author

It's my early Christmas gift. Thanks for working on this.

unfortunately this PR alone here is not enough. I do have patches to other swift components to get it fully working and going to PR them to coming weeks. But even with those, you'll need to have a functional swiftc (by bootstrapping a swift 5.8+) on FreeBSD to build them. personally I've done a multi-stages bootstrap until I now have a toolchain ready.

you also need a patch to the base libc++ to workaround this issue

@lin72h
Copy link

lin72h commented Nov 26, 2024

it's very impressive work especially the bootstrap part!

@@ -65,6 +65,7 @@ headers = [
'spawn.h',
'strings.h',
'sys/event.h',
'sys/extattr.h',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this header available universally? I think that this might need to be under a FreeBSD condition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The gyb expands '${header}' to an include guarded by __has_include, which test if the header can be included. similarly, the Linux specific sys/inotify.h header is also in the list.

#if __has_include(<${header}>)
#include <${header}>
#endif

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, any headers added to this file are just ignored if they don't exist, as there are already some OpenBSD-specific headers.

Have you considered adding a FreeBSD overlay instead? You could take a look at the recent Musl, WASI, and Android overlays for examples.

I know that's more work, but the WASI one isn't so bad, and FreeBSD may not be either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's definitely on my radar! I'm not sure yet if I have to bandwidth to include that change in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shoulda just called them all import C.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And yeah, the implementation is actually very difficult, especially when C++ gets involved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the feedback! Sorry for the late reply I was extremely sick for the past 2 weeks.
I certainly agree FreeBSD shouldn't use Glibc. In fact I have been working on the overlay for quite a while now but never gotten into a state I'm perfectly happy about it. More specifically I'd love to follow the Darwin modulemap and make certain C headers replaceable by clang, however it doesn't seems to be possible without making changes to the FreeBSD source tree.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My plan is to put the overlay changes into a separate PR, due to size of diff is quite big and this is already a rather large PR (as you can imagine all instance of where import Glibc occurs needs to be patched).

I have a working implementation ready to go, either committing to this PR, or as a separate PR, depending on what will be more comfortable for you to review. Wdyt @al45tair @ian-twilightcoder @grynspan @finagolfin

This also helps keep my head sane as I've been to maintaining quite a few separate trees of all the swift sub-projects locally to implement various feature for FreeBSD and it's getting quite messy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no opinion either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overlay PR created. #79261

@finagolfin
Copy link
Member

Nice, there is some work to get Swift 6 bootstrapping again, #77815, that you'll want to follow.

Pinging @mhjacobson and @3405691582, who added BSD support before and may be able to help review.

@3405691582
Copy link
Contributor

As a heads up, the code uses LLVM target triples and the build system has a few places where it assumes that the platform calls the architecture with the same name as LLVM does. This isn't a problem for FreeBSD on what LLVM calls x86_64, since they apparently both seem to use the same spelling, but for what LLVM calls aarch64, both OpenBSD and FreeBSD call it arm64. This causes headaches.

In the past, I've tried to keep some meaningful separation between platform spelling and LLVM spelling, but I'm reconsidering that in #77879. You probably won't need to do anything right now for this pr if you're just targeting x86_64, though, and what you have seems good to me, but keep this in mind if you're going to also be working on arm64.

@khng300
Copy link

khng300 commented Dec 1, 2024

As a heads up, the code uses LLVM target triples and the build system has a few places where it assumes that the platform calls the architecture with the same name as LLVM does. This isn't a problem for FreeBSD on what LLVM calls x86_64, since they apparently both seem to use the same spelling, but for what LLVM calls aarch64, both OpenBSD and FreeBSD call it arm64. This causes headaches.

In the past, I've tried to keep some meaningful separation between platform spelling and LLVM spelling, but I'm reconsidering that in #77879. You probably won't need to do anything right now for this pr if you're just targeting x86_64, though, and what you have seems good to me, but keep this in mind if you're going to also be working on arm64.

Which is not correct for the FreeBSD part. On FreeBSD itself, arm64 is the TARGET, meanwhile aarch64 is the TARGET_ARCH and MACHINE_ARCH. Below is what I got from a build of the FreeBSD tree on my side:

CMD cc -target aarch64-unknown-freebsd15.0 --sysroot=

For reference how we build the -target tuple in the tree:

Makefile.inc1:		MACHINE_ARCH=${TARGET_ARCH}
Makefile:	TARGET=${_TARGET} TARGET_ARCH=${_TARGET_ARCH} ${_MAKEARGS}
Makefile:_TARGET_ARCH=	${TARGET:S/arm64/aarch64/:S/riscv/riscv64/:S/arm/armv7/}
./Makefile.inc1:MACHINE_TRIPLE?=${MACHINE_ARCH:S/amd64/x86_64/}-${MACHINE_TRIPLE_ABI}-freebsd${OS_REVISION}

@QuietMisdreavus QuietMisdreavus removed their request for review December 2, 2024 17:47
@michael-yuji
Copy link
Contributor Author

@swift-ci please smoke test

@michael-yuji
Copy link
Contributor Author

@swift-ci please test

michael-yuji and others added 4 commits February 1, 2025 23:02
This commit adds required conditional compilation blocks to enable bulding on
FreeBSD (tested on x86_64 FreeBSD 14.1-RELEASE-p6). Also implements FreeBSD
synchronization shims using `_umtx_op(2)`
@@ -422,7 +422,14 @@ class DerivativeFunctionTypeError
Kind kind;

/// The type and index of a differentiability parameter or result.
using TypeAndIndex = std::pair<Type, unsigned>;
/// std::pair does not have a trivial copy constructor on FreeBSD <= 14 for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you just change the call sites that are using the constructor? That would simplify the diff.

@@ -2562,6 +2562,10 @@ PlatformAvailability::PlatformAvailability(const LangOptions &langOpts)
case PlatformKind::visionOSApplicationExtension:
break;

case PlatformKind::FreeBSD:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we coalesce the non-Apple cases?

@@ -2680,6 +2687,10 @@ bool PlatformAvailability::treatDeprecatedAsUnavailable(
// No deprecation filter on xrOS
return false;

case PlatformKind::FreeBSD:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we coalesce?

@@ -244,6 +244,8 @@ getLinkerPlatformId(OriginallyDefinedInAttr::ActiveVersion Ver,
llvm_unreachable("cannot find platform kind");
case swift::PlatformKind::OpenBSD:
llvm_unreachable("not used for this platform");
case swift::PlatformKind::FreeBSD:
llvm_unreachable("not used for this platform");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we coalesce? (Also, nitpick, the order of FreeBSD relative to OpenBSD is inconsistent. It's not important in any practical sense, but consistency is a good thing.)

@@ -338,12 +338,12 @@ public var SIG_DFL: sig_t? { return nil }
public var SIG_IGN: sig_t { return unsafeBitCast(1, to: sig_t.self) }
public var SIG_ERR: sig_t { return unsafeBitCast(-1, to: sig_t.self) }
public var SIG_HOLD: sig_t { return unsafeBitCast(5, to: sig_t.self) }
#elseif os(OpenBSD)
#elseif os(OpenBSD) || os(FreeBSD)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: platform order

@@ -19,7 +19,7 @@
/// It's not named just Glibc so that it doesn't conflict in the event of a
/// future official glibc modulemap.
module SwiftGlibc [system] {
% if CMAKE_SDK in ["LINUX", "OPENBSD"]:
% if CMAKE_SDK in ["LINUX", "OPENBSD", "FREEBSD"]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: platform order

@@ -24,7 +24,7 @@

// Clang has been defining __INTxx_TYPE__ macros for a long time.
// __UINTxx_TYPE__ are defined only since Clang 3.5.
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__OpenBSD__) && !defined(__wasi__)
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__wasi__)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: platf—okay you get the idea

@available(SwiftStdlib 6.0, *)
@frozen
@_staticExclusiveOnly
public struct _MutexHandle: ~Copyable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually need to be public?

@@ -16,7 +16,7 @@ StdOptionalTestSuite.test("pointee") {
let pointee = nonNilOpt.pointee
expectEqual(123, pointee)

#if !os(Linux) // crashes on Ubuntu 18.04 (rdar://113414160)
#if !os(Linux) && !os(FreeBSD) // crashes on Ubuntu 18.04 (rdar://113414160)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is crashing on FreeBSD as well, can you file a GitHub issue or Radar as appropriate and reference it here too?

@@ -27,14 +27,22 @@ if #available(OSX 10.10, iOS 8.0, *) {
// dispatch/source.h
_ = DispatchSource.makeUserDataAddSource()
_ = DispatchSource.makeUserDataOrSource()
#if !os(FreeBSD)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this compiling on Linux right now? Surely whatever guards Linux should guard FreeBSD too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DispatchSource is basically kqueue wrapper, which exists on FreeBSD and Darwin but not on Linux

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure we want to commit to supporting it at this time, or does it make more sense to leverage future improvements aimed at Linux?

@jakepetroules
Copy link
Contributor

I'm considering this a blocker for swiftlang/swift-build#12 since that requires the header file providing access to the xattr functions to be in the modulemap in order to enable xattr support in Swift Build's filesystem implementation.

@jakepetroules
Copy link
Contributor

@swift-ci test

Copy link
Contributor

@egorzhdan egorzhdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks amazing! I have just one comment about a C++ interop test.

@@ -1,4 +1,4 @@
// RUN: %target-swift-ide-test -print-module -module-to-print=FakeToolchain -tools-directory %S/Inputs/fake-toolchain/bin -source-filename=x -enable-experimental-cxx-interop -Xcc -stdlib=libc++ | %FileCheck %s
// RUN: %target-swift-ide-test -print-module -module-to-print=FakeToolchain -tools-directory %S/Inputs/fake-toolchain/bin -source-filename=x -enable-experimental-cxx-interop -Xcc -stdlib=libc++ -Xcc -I%S/Inputs/fake-toolchain/include/c++/v1 | %FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right – this test basically checks that passing libc++ include paths via -I or -isystem is not required when using -stdlib=libc++.

I wonder if this -I flag turns out to be needed on FreeBSD because of the lack of support for -stdlib=libc++ in Clang Driver on this specific platform?

Either way, could you please disable the test on FreeBSD instead?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.