From b5da30d3f0e6d7f5c4d722b0ccd0a6482a96e2ae Mon Sep 17 00:00:00 2001 From: Joel Winarske Date: Sun, 12 Jul 2026 13:54:35 -0700 Subject: [PATCH] Adopt shared UniqueFd, per-config LTO, and tidy hygiene - Hoist UniqueFd out of src/bluez/hidraw.hpp into src/utils/unique_fd.h so any client can reuse it. Add a default constructor, explicit operator bool, release(), reset(), and borrow-vs-own semantics (Borrow()) so a descriptor owned elsewhere - e.g. one received over D-Bus as sdbus::UnixFd - is not closed here. Include it directly where used, and pull hidraw.hpp into the owner headers that inherit from Hidraw rather than relying on a transitive include. - Enable LTO per configuration via CMAKE_INTERPROCEDURAL_OPTIMIZATION_ for Release/MinSizeRel/RelWithDebInfo, and drop the per-target set_property blocks that forced it on every build type. Debug builds no longer pay for LTO; optimized builds are unchanged. - clang-tidy: set WarningsAsErrors and a HeaderFilterRegex that excludes both third_party and the generated src/proxy headers, so a local run matches CI. - Pin cache-apt-pkgs-action and ccache-action to commit SHAs. - Remove the generated tidy-results-*.txt artifacts and ignore them. Signed-off-by: Joel Winarske --- .clang-tidy | 8 ++ .github/workflows/ci.yml | 10 +-- .gitignore | 4 +- CMakeLists.txt | 8 ++ src/avahi/CMakeLists.txt | 3 - src/bluez/CMakeLists.txt | 3 - src/bluez/hidraw.hpp | 39 +-------- src/bluez/horipad_steam/CMakeLists.txt | 3 - src/bluez/horipad_steam/input_reader.h | 2 +- src/bluez/ps5_dual_sense/CMakeLists.txt | 3 - src/bluez/ps5_dual_sense/input_reader.h | 2 +- src/bluez/xbox_controller/CMakeLists.txt | 3 - src/bluez/xbox_controller/input_reader.h | 2 +- src/bluez/xbox_controller/xbox_controller.h | 1 + src/connman/CMakeLists.txt | 3 - src/flatpak/CMakeLists.txt | 3 - src/fwupd/CMakeLists.txt | 3 - src/geoclue2/CMakeLists.txt | 3 - src/hostname1/CMakeLists.txt | 3 - src/locale1/CMakeLists.txt | 3 - src/login1/CMakeLists.txt | 3 - src/network1/CMakeLists.txt | 3 - src/packagekit/CMakeLists.txt | 3 - src/realtimekit1/CMakeLists.txt | 3 - src/resolve1/CMakeLists.txt | 3 - src/systemd1/CMakeLists.txt | 3 - src/timedate1/CMakeLists.txt | 3 - src/timesync1/CMakeLists.txt | 3 - src/udisks2/CMakeLists.txt | 6 -- src/upower/CMakeLists.txt | 3 - src/utils/CMakeLists.txt | 3 - src/utils/unique_fd.h | 94 +++++++++++++++++++++ src/wpa_supplicant/CMakeLists.txt | 3 - third_party/CMakeLists.txt | 3 - 34 files changed, 123 insertions(+), 122 deletions(-) create mode 100644 src/utils/unique_fd.h diff --git a/.clang-tidy b/.clang-tidy index 259c4e1..5c86c0d 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -150,4 +150,12 @@ clang-analyzer-security.*, cppcoreguidelines-pro-bounds-*, cppcoreguidelines-pro-type-reinterpret-cast' +# Promote all enabled checks to errors so a local `clang-tidy` run fails the +# same way CI does (CI passes -warnings-as-errors='*' on the command line). +WarningsAsErrors: '*' + +# Lint this project's own headers, but not third-party submodules or the +# generated proxy headers under src/proxy/. +HeaderFilterRegex: '^(?!.*(third_party|/proxy/)).*$' + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbb3e54..dc5c6b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: - name: Install dependencies # awalsh128/cache-apt-pkgs-action — caches the .deb set between runs. # Tag-pinned to match the convention used in the sibling drm-cxx repo. - uses: awalsh128/cache-apt-pkgs-action@v1 + uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1 with: packages: cmake ninja-build libudev-dev libsystemd-dev pkg-config gcc-14 g++-14 version: 1.0 @@ -79,7 +79,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install clang-format - uses: awalsh128/cache-apt-pkgs-action@v1 + uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1 with: packages: clang-format version: 1.0 @@ -117,7 +117,7 @@ jobs: - name: Install dependencies # Repo added above, so the cache action can resolve the LLVM packages. - uses: awalsh128/cache-apt-pkgs-action@v1 + uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1 with: packages: >- clang-19 clang-tidy-19 llvm-19 llvm-19-dev lld-19 @@ -208,7 +208,7 @@ jobs: 'deb https://apt.llvm.org/noble/ llvm-toolchain-noble-19 main' - name: Install dependencies - uses: awalsh128/cache-apt-pkgs-action@v1 + uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1 with: packages: "cmake ninja-build libudev-dev libsystemd-dev pkg-config ${{ matrix.compiler.name == 'gcc-14' && 'gcc-14 g++-14' || 'clang-19 llvm-19 llvm-19-dev lld-19 libc++-19-dev libc++abi-19-dev' }}" version: 1.0 @@ -217,7 +217,7 @@ jobs: # Caches object files across runs. The pinned submodules # (sdbus-c++, spdlog, glaze) don't change, so their compiles hit the # cache after the first run. Tag-pinned per the drm-cxx convention. - uses: hendrikmuhs/ccache-action@v1 + uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639 # v1 with: key: ${{ matrix.compiler.name }} diff --git a/.gitignore b/.gitignore index 287e6d1..aab2b16 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ _codeql_detected_source_root .vscode/ -clang-format-files \ No newline at end of file +clang-format-files +# clang-tidy run artifacts +tidy-results-*.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 65380e0..f10bd89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,14 @@ if (ENABLE_LTO) ) if (IPO_SUPPORT_RESULT) message(STATUS "IPO .................... supported") + # Enable LTO for optimized configurations only. Debug builds skip it + # so local iteration stays fast; Release/MinSizeRel/RelWithDebInfo + # (the CI and default build types) keep it. Setting these before the + # add_subdirectory() calls below makes every target inherit them, so + # no per-target set_property() is needed. + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL ON) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON) else () message(STATUS "IPO .................... not supported: ${IPO_SUPPORT_OUTPUT}") endif () diff --git a/src/avahi/CMakeLists.txt b/src/avahi/CMakeLists.txt index 835382a..7cbf713 100644 --- a/src/avahi/CMakeLists.txt +++ b/src/avahi/CMakeLists.txt @@ -9,9 +9,6 @@ target_link_libraries(avahi_server_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET avahi_server_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS avahi_server_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/bluez/CMakeLists.txt b/src/bluez/CMakeLists.txt index c5d0843..eb63a3b 100644 --- a/src/bluez/CMakeLists.txt +++ b/src/bluez/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(bluez_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET bluez_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS bluez_client RUNTIME DESTINATION share/sdbus-cpp-examples) diff --git a/src/bluez/hidraw.hpp b/src/bluez/hidraw.hpp index cf46bf6..36010b2 100644 --- a/src/bluez/hidraw.hpp +++ b/src/bluez/hidraw.hpp @@ -33,47 +33,10 @@ #include #include "../utils/logging.h" +#include "../utils/unique_fd.h" #include "hexdump.hpp" -/// RAII wrapper for a POSIX file descriptor. -/// Automatically closes the fd when it goes out of scope, preventing leaks -/// on every error-path break/return/exception. -struct UniqueFd { - explicit UniqueFd(const int fd) noexcept : fd_(fd) {} - - ~UniqueFd() { - if (fd_ >= 0) { - ::close(fd_); - } - } - - // Non-copyable, movable - UniqueFd(const UniqueFd&) = delete; - UniqueFd& operator=(const UniqueFd&) = delete; - - UniqueFd(UniqueFd&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; } - UniqueFd& operator=(UniqueFd&& other) noexcept { - if (this != &other) { - if (fd_ >= 0) { - ::close(fd_); - } - fd_ = other.fd_; - other.fd_ = -1; - } - return *this; - } - - /// Returns true if the fd is valid (>= 0). - [[nodiscard]] bool valid() const noexcept { return fd_ >= 0; } - - /// Returns the raw file descriptor. - [[nodiscard]] int get() const noexcept { return fd_; } - - private: - int fd_; -}; - class Hidraw { public: Hidraw() = default; diff --git a/src/bluez/horipad_steam/CMakeLists.txt b/src/bluez/horipad_steam/CMakeLists.txt index 7747031..798abcb 100644 --- a/src/bluez/horipad_steam/CMakeLists.txt +++ b/src/bluez/horipad_steam/CMakeLists.txt @@ -17,9 +17,6 @@ target_link_libraries(horipad_steam_client spdlog::spdlog PkgConfig::UDEV ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET horipad_steam_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS horipad_steam_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/bluez/horipad_steam/input_reader.h b/src/bluez/horipad_steam/input_reader.h index 800fa14..773dc15 100644 --- a/src/bluez/horipad_steam/input_reader.h +++ b/src/bluez/horipad_steam/input_reader.h @@ -18,7 +18,7 @@ #include #include -#include "../hidraw.hpp" +#include "../../utils/unique_fd.h" #include "horipad_stream_01ab_0196.h" class InputReader { diff --git a/src/bluez/ps5_dual_sense/CMakeLists.txt b/src/bluez/ps5_dual_sense/CMakeLists.txt index 5b7a4cf..0499615 100644 --- a/src/bluez/ps5_dual_sense/CMakeLists.txt +++ b/src/bluez/ps5_dual_sense/CMakeLists.txt @@ -17,9 +17,6 @@ target_link_libraries(dual_sense_client spdlog::spdlog PkgConfig::UDEV ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET dual_sense_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS dual_sense_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/bluez/ps5_dual_sense/input_reader.h b/src/bluez/ps5_dual_sense/input_reader.h index 55b7f94..5c7c60d 100644 --- a/src/bluez/ps5_dual_sense/input_reader.h +++ b/src/bluez/ps5_dual_sense/input_reader.h @@ -19,7 +19,7 @@ #include #include -#include "../hidraw.hpp" +#include "../../utils/unique_fd.h" #include "dual_sense_0ce6.h" class InputReader { diff --git a/src/bluez/xbox_controller/CMakeLists.txt b/src/bluez/xbox_controller/CMakeLists.txt index 82da766..93e4c4a 100644 --- a/src/bluez/xbox_controller/CMakeLists.txt +++ b/src/bluez/xbox_controller/CMakeLists.txt @@ -17,9 +17,6 @@ target_link_libraries(xbox_controller_client spdlog::spdlog PkgConfig::UDEV ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET xbox_controller_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS xbox_controller_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/bluez/xbox_controller/input_reader.h b/src/bluez/xbox_controller/input_reader.h index f519525..cab6a3c 100644 --- a/src/bluez/xbox_controller/input_reader.h +++ b/src/bluez/xbox_controller/input_reader.h @@ -18,7 +18,7 @@ #include #include -#include "../hidraw.hpp" +#include "../../utils/unique_fd.h" #include "xbox_controller_02fd.h" class InputReader { diff --git a/src/bluez/xbox_controller/xbox_controller.h b/src/bluez/xbox_controller/xbox_controller.h index 0483e09..b4f9afb 100644 --- a/src/bluez/xbox_controller/xbox_controller.h +++ b/src/bluez/xbox_controller/xbox_controller.h @@ -20,6 +20,7 @@ #include "../../upower/upower_client.h" #include "../adapter1.h" #include "../device1.h" +#include "../hidraw.hpp" #include "../input1.h" #include "../udev_monitor.hpp" diff --git a/src/connman/CMakeLists.txt b/src/connman/CMakeLists.txt index b6127b0..08858ca 100644 --- a/src/connman/CMakeLists.txt +++ b/src/connman/CMakeLists.txt @@ -11,9 +11,6 @@ target_link_libraries(connman_client spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET connman_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS connman_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/flatpak/CMakeLists.txt b/src/flatpak/CMakeLists.txt index b4dcc28..5b0c29c 100644 --- a/src/flatpak/CMakeLists.txt +++ b/src/flatpak/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(flatpak_system_helper_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET flatpak_system_helper_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS flatpak_system_helper_client RUNTIME DESTINATION share/sdbus-cpp-examples) diff --git a/src/fwupd/CMakeLists.txt b/src/fwupd/CMakeLists.txt index b3c0ed0..7b3812a 100644 --- a/src/fwupd/CMakeLists.txt +++ b/src/fwupd/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(fwupd_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET fwupd_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS fwupd_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/geoclue2/CMakeLists.txt b/src/geoclue2/CMakeLists.txt index c5bfcdb..8facff9 100644 --- a/src/geoclue2/CMakeLists.txt +++ b/src/geoclue2/CMakeLists.txt @@ -12,9 +12,6 @@ target_link_libraries(geoclue2_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET geoclue2_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS geoclue2_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/hostname1/CMakeLists.txt b/src/hostname1/CMakeLists.txt index 81cd209..37638fd 100644 --- a/src/hostname1/CMakeLists.txt +++ b/src/hostname1/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(hostname1_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET hostname1_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS hostname1_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/locale1/CMakeLists.txt b/src/locale1/CMakeLists.txt index 22c55dc..40f9474 100644 --- a/src/locale1/CMakeLists.txt +++ b/src/locale1/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(locale1_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET locale1_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS locale1_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/login1/CMakeLists.txt b/src/login1/CMakeLists.txt index 61cdad7..c2305c6 100644 --- a/src/login1/CMakeLists.txt +++ b/src/login1/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(login1_manager_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET login1_manager_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS login1_manager_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/network1/CMakeLists.txt b/src/network1/CMakeLists.txt index 8e06268..6850491 100644 --- a/src/network1/CMakeLists.txt +++ b/src/network1/CMakeLists.txt @@ -11,9 +11,6 @@ target_link_libraries(network1_client spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET network1_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS network1_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/packagekit/CMakeLists.txt b/src/packagekit/CMakeLists.txt index 79a8872..bc3bb2f 100644 --- a/src/packagekit/CMakeLists.txt +++ b/src/packagekit/CMakeLists.txt @@ -12,9 +12,6 @@ target_link_libraries(packagekit_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET packagekit_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS packagekit_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/realtimekit1/CMakeLists.txt b/src/realtimekit1/CMakeLists.txt index 6de9811..4121d07 100644 --- a/src/realtimekit1/CMakeLists.txt +++ b/src/realtimekit1/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(realtimekit1_manager_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET realtimekit1_manager_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS realtimekit1_manager_client RUNTIME DESTINATION share/sdbus-cpp-examples) diff --git a/src/resolve1/CMakeLists.txt b/src/resolve1/CMakeLists.txt index ec4b824..aa45bd0 100644 --- a/src/resolve1/CMakeLists.txt +++ b/src/resolve1/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(resolve1_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET resolve1_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS resolve1_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/systemd1/CMakeLists.txt b/src/systemd1/CMakeLists.txt index 99a4fcb..e9ddf07 100644 --- a/src/systemd1/CMakeLists.txt +++ b/src/systemd1/CMakeLists.txt @@ -11,9 +11,6 @@ target_link_libraries(systemd1_client spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET systemd1_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS systemd1_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/timedate1/CMakeLists.txt b/src/timedate1/CMakeLists.txt index f4db26c..2972395 100644 --- a/src/timedate1/CMakeLists.txt +++ b/src/timedate1/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(timedate1_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET timedate1_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS timedate1_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/timesync1/CMakeLists.txt b/src/timesync1/CMakeLists.txt index 1185fbc..0d1bce7 100644 --- a/src/timesync1/CMakeLists.txt +++ b/src/timesync1/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(timesync1_manager_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET timesync1_manager_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS timesync1_manager_client RUNTIME DESTINATION share/sdbus-cpp-examples) diff --git a/src/udisks2/CMakeLists.txt b/src/udisks2/CMakeLists.txt index 2e38d1e..d5963e1 100644 --- a/src/udisks2/CMakeLists.txt +++ b/src/udisks2/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries(udisks2_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET udisks2_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS udisks2_client RUNTIME DESTINATION share/sdbus-cpp-examples) @@ -27,9 +24,6 @@ target_link_libraries(udisks2_monitor_daemon sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET udisks2_monitor_daemon PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS udisks2_monitor_daemon RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/upower/CMakeLists.txt b/src/upower/CMakeLists.txt index b55e307..58a22b6 100644 --- a/src/upower/CMakeLists.txt +++ b/src/upower/CMakeLists.txt @@ -9,9 +9,6 @@ target_link_libraries(upower_client sdbus-c++ spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET upower_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS upower_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 2fbc8aa..5e9bbab 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -9,6 +9,3 @@ target_link_libraries(utils glaze::glaze spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET utils PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () diff --git a/src/utils/unique_fd.h b/src/utils/unique_fd.h new file mode 100644 index 0000000..a5376ba --- /dev/null +++ b/src/utils/unique_fd.h @@ -0,0 +1,94 @@ +// Copyright (c) 2026 Joel Winarske +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_UTILS_UNIQUE_FD_H +#define SRC_UTILS_UNIQUE_FD_H + +#include + +/// RAII owner for a POSIX file descriptor. +/// +/// Closes the fd on destruction, preventing leaks on every error-path +/// break/return/exception. Non-copyable, movable. A UniqueFd may either own +/// its fd (the default — it is closed on destruction/reset) or borrow one whose +/// lifetime is managed elsewhere (see Borrow()); a borrowed fd is never closed. +/// This matters for descriptors received over D-Bus (sdbus::UnixFd) or handed +/// in by a caller, where closing here would be a double-close. +class UniqueFd { + public: + UniqueFd() noexcept = default; + + explicit UniqueFd(const int fd) noexcept : fd_(fd) {} + + /// Wrap a borrowed fd this object must NOT close. + [[nodiscard]] static UniqueFd Borrow(const int fd) noexcept { + UniqueFd f(fd); + f.owns_ = false; + return f; + } + + ~UniqueFd() { reset(); } + + // Non-copyable. + UniqueFd(const UniqueFd&) = delete; + UniqueFd& operator=(const UniqueFd&) = delete; + + // Movable. + UniqueFd(UniqueFd&& other) noexcept : fd_(other.fd_), owns_(other.owns_) { + other.fd_ = -1; + other.owns_ = true; + } + UniqueFd& operator=(UniqueFd&& other) noexcept { + if (this != &other) { + reset(); + fd_ = other.fd_; + owns_ = other.owns_; + other.fd_ = -1; + other.owns_ = true; + } + return *this; + } + + /// Returns true if the fd is valid (>= 0). + [[nodiscard]] bool valid() const noexcept { return fd_ >= 0; } + explicit operator bool() const noexcept { return fd_ >= 0; } + + /// Returns the raw file descriptor without transferring ownership. + [[nodiscard]] int get() const noexcept { return fd_; } + + /// Relinquish ownership and return the fd; the caller becomes responsible + /// for closing it. Leaves this wrapper empty. + [[nodiscard]] int release() noexcept { + const int fd = fd_; + fd_ = -1; + owns_ = true; + return fd; + } + + /// Close the currently-owned fd (if any) and optionally adopt a new one, + /// which is then owned. + void reset(const int fd = -1) noexcept { + if (owns_ && fd_ >= 0 && fd_ != fd) { + ::close(fd_); + } + fd_ = fd; + owns_ = true; + } + + private: + int fd_ = -1; + bool owns_ = true; +}; + +#endif // SRC_UTILS_UNIQUE_FD_H diff --git a/src/wpa_supplicant/CMakeLists.txt b/src/wpa_supplicant/CMakeLists.txt index d3d4b4b..12aed20 100644 --- a/src/wpa_supplicant/CMakeLists.txt +++ b/src/wpa_supplicant/CMakeLists.txt @@ -11,9 +11,6 @@ target_link_libraries(wpa_supplicant1_client spdlog::spdlog ) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET wpa_supplicant1_client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () install(TARGETS wpa_supplicant1_client RUNTIME DESTINATION share/sdbus-cpp-examples) \ No newline at end of file diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index c7a6100..386a540 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -5,9 +5,6 @@ set(SDBUSCPP_BUILD_CODEGEN ON) set(SDBUSCPP_INSTALL OFF CACHE BOOL "Do not install sdbus-cpp" FORCE) add_subdirectory(sdbus-cpp) -if (ENABLE_LTO AND IPO_SUPPORT_RESULT) - set_property(TARGET sdbus-c++ PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif () target_link_libraries(sdbus-c++-objlib PUBLIC toolchain::toolchain) target_link_libraries(sdbus-c++ PUBLIC toolchain::toolchain) install(TARGETS toolchain EXPORT sdbus-c++-targets)