From 354d96209c187853c19e919f631914869adfbe15 Mon Sep 17 00:00:00 2001 From: molyuu Date: Mon, 15 Dec 2025 12:27:51 +0800 Subject: [PATCH] all: initial support for freebsd - Added FreeBSD CI. - Use `copy_file_range(2)` over `sendfile(2)` which has wider compatibility. - Special case pam on freebsd and document `configDirectory` incompatibility. - Disable jemalloc for FreeBSD by default as it is the system allocator. - Disable breakpad by default on FreeBSD as breakpad is not supported. --- .github/workflows/build.yml | 40 +++++++++++++++++++++++++++++++ CMakeLists.txt | 9 +++++-- changelog/next.md | 1 + src/core/logging.cpp | 17 +++++++++---- src/core/paths.cpp | 4 ++-- src/core/toolsupport.cpp | 2 +- src/services/pam/conversation.cpp | 2 ++ src/services/pam/qml.hpp | 6 +++++ src/services/pam/subprocess.cpp | 8 +++++++ 9 files changed, 79 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dc6e8a72..46c1a653 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,3 +61,43 @@ jobs: run: | cmake -GNinja -B build -DCRASH_REPORTER=OFF cmake --build build + + freebsd: + name: FreeBSD + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build in FreeBSD VM + uses: vmactions/freebsd-vm@v1 + with: + release: "15.0" + usesh: true + + prepare: | + pkg update -f && pkg install -y \ + cmake \ + pkgconf \ + cli11 \ + spirv-tools \ + qt6-base \ + qt6-declarative \ + qt6-shadertools \ + qt6-wayland \ + wayland \ + wayland-protocols \ + vulkan-headers \ + libdrm \ + libxcb \ + pipewire \ + polkit \ + glib \ + mesa-libs \ + git \ + bash \ + ninja \ + gitup + + run: | + cmake -GNinja -B build -DCMAKE_C_FLAGS="-I/usr/local/include -L/usr/local/lib" -DCMAKE_CXX_FLAGS="-I/usr/local/include -L/usr/local/lib" + cmake --build build \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c8670013..257ad94b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,8 +44,13 @@ boption(BUILD_TESTING "Build tests (dev)" OFF) boption(ASAN "ASAN (dev)" OFF) # note: better output with gcc than clang boption(FRAME_POINTERS "Keep Frame Pointers (dev)" ${ASAN}) -boption(CRASH_REPORTER "Crash Handling" ON) -boption(USE_JEMALLOC "Use jemalloc" ON) +if (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + boption(CRASH_REPORTER "Crash Handling" OFF) + boption(USE_JEMALLOC "Use jemalloc" OFF) +else() + boption(CRASH_REPORTER "Crash Handling" ON) + boption(USE_JEMALLOC "Use jemalloc" ON) +endif() boption(SOCKETS "Unix Sockets" ON) boption(WAYLAND "Wayland" ON) boption(WAYLAND_WLR_LAYERSHELL " Wlroots Layer-Shell" ON REQUIRES WAYLAND) diff --git a/changelog/next.md b/changelog/next.md index 8a48ba54..78571039 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -21,6 +21,7 @@ set shell id. ## Other Changes +- FreeBSD is now partially supported. - IPC operations filter available instances to the current display connection by default. ## Bug Fixes diff --git a/src/core/logging.cpp b/src/core/logging.cpp index 5c809f68..10ea453a 100644 --- a/src/core/logging.cpp +++ b/src/core/logging.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "instanceinfo.hpp" #include "logcat.hpp" @@ -392,7 +392,7 @@ void ThreadLogging::initFs() { delete detailedFile; detailedFile = nullptr; } else { - auto lock = flock { + struct flock lock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, @@ -414,7 +414,7 @@ void ThreadLogging::initFs() { auto* oldFile = this->file; if (oldFile) { oldFile->seek(0); - sendfile(file->handle(), oldFile->handle(), nullptr, oldFile->size()); + copy_file_range(oldFile->handle(), nullptr, file->handle(), nullptr, oldFile->size(), 0); } this->file = file; @@ -426,7 +426,14 @@ void ThreadLogging::initFs() { auto* oldFile = this->detailedFile; if (oldFile) { oldFile->seek(0); - sendfile(detailedFile->handle(), oldFile->handle(), nullptr, oldFile->size()); + copy_file_range( + oldFile->handle(), + nullptr, + detailedFile->handle(), + nullptr, + oldFile->size(), + 0 + ); } crash::CrashInfo::INSTANCE.logFd = detailedFile->handle(); @@ -889,7 +896,7 @@ bool LogReader::continueReading() { } void LogFollower::FcntlWaitThread::run() { - auto lock = flock { + struct flock lock = { .l_type = F_RDLCK, // won't block other read locks when we take it .l_whence = SEEK_SET, .l_start = 0, diff --git a/src/core/paths.cpp b/src/core/paths.cpp index 55beb87c..6555e54e 100644 --- a/src/core/paths.cpp +++ b/src/core/paths.cpp @@ -361,7 +361,7 @@ void QsPaths::createLock() { return; } - auto lock = flock { + struct flock lock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, @@ -389,7 +389,7 @@ bool QsPaths::checkLock(const QString& path, InstanceLockInfo* info, bool allowD auto file = QFile(QDir(path).filePath("instance.lock")); if (!file.open(QFile::ReadOnly)) return false; - auto lock = flock { + struct flock lock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, diff --git a/src/core/toolsupport.cpp b/src/core/toolsupport.cpp index afce008b..8aa5ac9d 100644 --- a/src/core/toolsupport.cpp +++ b/src/core/toolsupport.cpp @@ -54,7 +54,7 @@ bool QmlToolingSupport::lockTooling() { return false; } - auto lock = flock { + struct flock lock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, // NOLINT (fcntl.h??) .l_start = 0, diff --git a/src/services/pam/conversation.cpp b/src/services/pam/conversation.cpp index 6d27978f..500abd5a 100644 --- a/src/services/pam/conversation.cpp +++ b/src/services/pam/conversation.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include "../../core/logcat.hpp" diff --git a/src/services/pam/qml.hpp b/src/services/pam/qml.hpp index a8ffcc35..a36184ef 100644 --- a/src/services/pam/qml.hpp +++ b/src/services/pam/qml.hpp @@ -6,7 +6,11 @@ #include #include #include +#ifdef __FreeBSD__ +#include +#else #include +#endif #include #include "conversation.hpp" @@ -35,6 +39,8 @@ class PamContext /// /// The configuration directory is resolved relative to the current file if not an absolute path. /// + /// On FreeBSD this property is ignored as the pam configuration directory cannot be changed. + /// /// This property may not be set while @@active is true. Q_PROPERTY(QString configDirectory READ configDirectory WRITE setConfigDirectory NOTIFY configDirectoryChanged); /// The user to authenticate as. If unset the current user will be used. diff --git a/src/services/pam/subprocess.cpp b/src/services/pam/subprocess.cpp index f99b279d..dc362284 100644 --- a/src/services/pam/subprocess.cpp +++ b/src/services/pam/subprocess.cpp @@ -7,7 +7,11 @@ #include #include #include +#ifdef __FreeBSD__ +#include +#else #include +#endif #include #include @@ -83,7 +87,11 @@ PamIpcExitCode PamSubprocess::exec(const char* configDir, const char* config, co logIf(this->log) << "Starting pam session for user \"" << user << "\" with config \"" << config << "\" in dir \"" << configDir << "\"" << std::endl; +#ifdef __FreeBSD__ + auto result = pam_start(config, user, &conv, &handle); +#else auto result = pam_start_confdir(config, user, &conv, configDir, &handle); +#endif if (result != PAM_SUCCESS) { logIf(true) << "Unable to start pam conversation with error \"" << pam_strerror(handle, result)