--- CMakeLists.txt.orig	2026-02-20 00:30:46 UTC
+++ CMakeLists.txt
@@ -45,15 +45,25 @@ set(EVENT2_MINIMUM 2.1.0)
 set(WOLFSSL_MINIMUM 3.4)
 set(DEFLATE_MINIMUM 1.7)
 set(EVENT2_MINIMUM 2.1.0)
+# fast_float's version file is configured with `COMPATIBILITY SameMajorVersion`
+# The version range currently distributed varies greatly (e.g. Debian Trixie -> 8.0.0, Ubuntu 24.04 -> 3.9.0)
+# set(FAST_FLOAT_MINIMUM 3...8)
+set(FMT_MINIMUM 8.0.1)
 set(GIOMM_MINIMUM 2.26.0)
 set(GLIBMM_MINIMUM 2.60.0)
 set(GTKMM3_MINIMUM 3.24.0)
 set(GTKMM4_MINIMUM 4.11.1)
 set(OPENSSL_MINIMUM 1.1.0)
 set(MBEDTLS_MINIMUM 2.7)
-set(NPM_MINIMUM 10.2.3) # Node.js 20.10 (eslint-plugin-unicorn)
-set(PSL_MINIMUM 0.21.1)
+set(MINIUPNPC_MINIMUM 2.2.1)
+set(NPM_MINIMUM 10.8.2) # Node.js 20.19 (stylelint@17)
+set(PSL_MINIMUM 0.21.0)
 set(QT_MINIMUM 5.15)
+set(SIGSLOT_MINIMUM 1.2.3)
+set(SMALL_MINIMUM 0.2.2)
+# utf8cpp v4's version file is configured with `COMPATIBILITY SameMajorVersion`
+# and does not support version range.
+# set(UTF8CPP_MINIMUM 3.1...4)
 
 option(ENABLE_DAEMON "Build daemon" ON)
 tr_auto_option(ENABLE_GTK "Build GTK client" AUTO)
@@ -71,14 +81,21 @@ tr_auto_option(RUN_CLANG_TIDY "Run clang-tidy on the c
 option(INSTALL_LIB "Install the library" OFF)
 tr_auto_option(ENABLE_DEPRECATED "Allow deprecated API use of upstream packages, e.g. GTK" AUTO)
 tr_auto_option(RUN_CLANG_TIDY "Run clang-tidy on the code" AUTO)
-tr_auto_option(USE_SYSTEM_EVENT2 "Use system event2 library" AUTO)
-tr_auto_option(USE_SYSTEM_DEFLATE "Use system deflate library" AUTO)
-tr_auto_option(USE_SYSTEM_DHT "Use system dht library" AUTO)
-tr_auto_option(USE_SYSTEM_MINIUPNPC "Use system miniupnpc library" AUTO)
-tr_auto_option(USE_SYSTEM_NATPMP "Use system natpmp library" AUTO)
-tr_auto_option(USE_SYSTEM_UTP "Use system utp library" AUTO)
-tr_auto_option(USE_SYSTEM_B64 "Use system b64 library" AUTO)
-tr_auto_option(USE_SYSTEM_PSL "Use system psl library" AUTO)
+tr_auto_option(USE_SYSTEM_DEFAULT "Default value for USE_SYSTEM_* options" AUTO)
+tr_auto_option(RUN_CLANG_TIDY "Run clang-tidy on the code" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_EVENT2 "Use system event2 library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_DEFLATE "Use system deflate library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_DHT "Use system dht library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_FAST_FLOAT "Use system fast_float library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_FMT "Use system fmt library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_MINIUPNPC "Use system miniupnpc library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_NATPMP "Use system natpmp library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_SMALL "Use system small library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_UTF8CPP "Use system uft8cpp library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_UTP "Use system utp library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_WIDE_INTEGER "Use system WideInteger library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_B64 "Use system b64 library" ${USE_SYSTEM_DEFAULT})
+tr_auto_option(USE_SYSTEM_PSL "Use system psl library" ${USE_SYSTEM_DEFAULT})
 tr_list_option(USE_GTK_VERSION "Use specific GTK version" AUTO 3 4)
 tr_list_option(USE_QT_VERSION "Use specific Qt version" AUTO 5 6)
 tr_list_option(WITH_CRYPTO "Use specified crypto library" AUTO ccrypto mbedtls openssl wolfssl)
@@ -239,26 +256,13 @@ set(SOURCE_ICONS_DIR "${PROJECT_SOURCE_DIR}/icons")
 
 set(SOURCE_ICONS_DIR "${PROJECT_SOURCE_DIR}/icons")
 
-find_package(FastFloat)
-find_package(Fmt)
 find_package(RapidJSON)
-find_package(Small)
-find_package(UtfCpp)
-find_package(WideInteger)
 
 find_package(Threads)
 find_package(PkgConfig QUIET)
 
 find_package(CURL ${CURL_MINIMUM} REQUIRED)
 
-if(ENABLE_DEPRECATED STREQUAL "AUTO")
-    if(DEFINED ENV{CI})
-        set(ENABLE_DEPRECATED OFF)
-    else()
-        set(ENABLE_DEPRECATED ON)
-    endif()
-endif()
-
 set(CRYPTO_PKG "")
 if(WITH_CRYPTO STREQUAL "AUTO" OR WITH_CRYPTO STREQUAL "ccrypto")
     tr_get_required_flag(WITH_CRYPTO CCRYPTO_IS_REQUIRED)
@@ -369,7 +373,7 @@ if(GTK_FOUND)
         INTERFACE
             ${GTK${GTK_VERSION}_CFLAGS_OTHER})
 
-    target_include_directories(transmission::gtk_impl SYSTEM
+    target_include_directories(transmission::gtk_impl
         INTERFACE
             ${GTK${GTK_VERSION}_INCLUDE_DIRS})
 
@@ -408,6 +412,9 @@ if(ENABLE_QT)
         Network
         Svg
         LinguistTools)
+    if(ENABLE_TESTS)
+        list(APPEND QT_REQUIRED_MODULES Test)
+    endif()
     set(QT_OPTIONAL_MODULES
         DBus
         AxContainer
@@ -428,7 +435,7 @@ if(ENABLE_QT)
         foreach(M ${QT_REQUIRED_MODULES})
             find_package(Qt${Qt_VERSION_MAJOR}${M} ${QT_MINIMUM} QUIET)
             if(Qt${Qt_VERSION_MAJOR}${M}_FOUND)
-                if(NOT M STREQUAL "LinguistTools")
+                if(NOT M STREQUAL "LinguistTools" AND NOT M STREQUAL "Test")
                     list(APPEND QT_TARGETS Qt${Qt_VERSION_MAJOR}::${M})
                 endif()
             else()
@@ -493,19 +500,24 @@ endif()
     tr_fixup_auto_option(ENABLE_MAC MAC_FOUND MAC_IS_REQUIRED)
 endif()
 
+# Don't build libdeflate as subdirectory as its CMakeLists.txt
+# messes with global CMAKE_* variables and global compiler options
 if(WIN32 AND NOT MINGW)
     set(DEFLATE_LIB_NAME deflatestatic)
 else()
     set(DEFLATE_LIB_NAME deflate)
 endif()
-tr_add_external_auto_library(DEFLATE libdeflate ${DEFLATE_LIB_NAME}
-    TARGET deflate::deflate
+tr_add_external_auto_library(DEFLATE libdeflate
+    LIBNAME ${DEFLATE_LIB_NAME}
+    TARGET libdeflate::libdeflate
     CMAKE_ARGS
         -DLIBDEFLATE_BUILD_SHARED_LIB=OFF
         -DLIBDEFLATE_BUILD_GZIP=OFF)
 
-tr_add_external_auto_library(EVENT2 libevent event
-    TARGET libevent::event
+tr_add_external_auto_library(EVENT2 Libevent
+    SUBPROJECT
+    SOURCE_DIR libevent
+    COMPONENTS core extra
     CMAKE_ARGS
         -DEVENT__DISABLE_OPENSSL:BOOL=ON
         -DEVENT__DISABLE_BENCHMARK:BOOL=ON
@@ -513,8 +525,14 @@ tr_add_external_auto_library(EVENT2 libevent event
         -DEVENT__DISABLE_REGRESS:BOOL=ON
         -DEVENT__DISABLE_SAMPLES:BOOL=ON
         -DEVENT__LIBRARY_TYPE:STRING=STATIC)
+# Workaround, perm fix: https://github.com/libevent/libevent/pull/1791
+if(NOT TARGET libevent::core)
+    add_library(libevent::core ALIAS event_core)
+    add_library(libevent::extra ALIAS event_extra)
+endif()
 
-tr_add_external_auto_library(NATPMP libnatpmp natpmp
+tr_add_external_auto_library(NATPMP libnatpmp
+    LIBNAME natpmp
     TARGET natpmp::natpmp
     CMAKE_ARGS
         -DBUILD_SHARED_LIBS=OFF)
@@ -530,14 +548,16 @@ endif()
 else()
     set(TR_MINIUPNPC_LIBNAME miniupnpc)
 endif()
-tr_add_external_auto_library(MINIUPNPC miniupnp/miniupnpc ${TR_MINIUPNPC_LIBNAME}
-    TARGET miniupnpc::libminiupnpc
+tr_add_external_auto_library(MINIUPNPC miniupnpc
+    LIBNAME ${TR_MINIUPNPC_LIBNAME}
+    SOURCE_DIR miniupnp/miniupnpc
+    TARGET miniupnpc::miniupnpc
     CMAKE_ARGS
         -DUPNPC_BUILD_STATIC=ON
         -DUPNPC_BUILD_SHARED=OFF
         -DUPNPC_BUILD_TESTS=OFF)
 if(NOT USE_SYSTEM_MINIUPNPC)
-    target_compile_definitions(miniupnpc::libminiupnpc
+    target_compile_definitions(miniupnpc::miniupnpc
         INTERFACE
             MINIUPNP_STATICLIB)
 endif()
@@ -546,26 +566,90 @@ add_subdirectory(${TR_THIRD_PARTY_SOURCE_DIR}/wildmat)
 add_subdirectory(${TR_THIRD_PARTY_SOURCE_DIR}/madler-crcany)
 add_subdirectory(${TR_THIRD_PARTY_SOURCE_DIR}/wildmat)
 
-tr_add_external_auto_library(DHT dht dht
+tr_add_external_auto_library(DHT dht
+    LIBNAME dht
     TARGET dht::dht)
 
-tr_add_external_auto_library(PSL libpsl psl
+tr_add_external_auto_library(PSL libpsl
+    LIBNAME psl
     TARGET psl::psl)
 
 if(ENABLE_UTP)
-    tr_add_external_auto_library(UTP libutp utp
+    tr_add_external_auto_library(UTP libutp
         SUBPROJECT
-        TARGET libutp::libutp
         CMAKE_ARGS
             -DLIBUTP_SHARED:BOOL=OFF)
 endif()
 
-tr_add_external_auto_library(B64 libb64 b64
+tr_add_external_auto_library(B64 libb64
     SUBPROJECT
-    TARGET libb64::libb64
     CMAKE_ARGS
         -DLIBB64_SHARED:BOOL=OFF)
 
+tr_add_external_auto_library(FAST_FLOAT FastFloat
+    SUBPROJECT
+    SOURCE_DIR fast_float
+    CMAKE_ARGS
+        -DFASTFLOAT_INSTALL=OFF
+        -DFASTFLOAT_TEST=OFF
+        -DFASTFLOAT_SANITIZE=OFF
+        -DFASTFLOAT_CXX_STANDARD=${CMAKE_CXX_STANDARD})
+
+tr_add_external_auto_library(FMT fmt
+    SUBPROJECT
+    CMAKE_ARGS
+        -DFMT_INSTALL=OFF
+        -DFMT_SYSTEM_HEADERS=ON)
+if(NOT TARGET transmission::fmt-header-only)
+    add_library(transmission::fmt-header-only INTERFACE IMPORTED)
+    target_link_libraries(transmission::fmt-header-only
+        INTERFACE
+            fmt::fmt-header-only)
+    target_compile_definitions(transmission::fmt-header-only
+        INTERFACE
+            FMT_USE_EXCEPTIONS=0 # {fmt} >= 11.2.0
+            FMT_EXCEPTIONS=0 # {fmt} < 11.2.0
+    )
+endif()
+
+tr_add_external_auto_library(SMALL small
+    SUBPROJECT
+    CMAKE_ARGS
+        -DSMALL_BUILD_WITH_EXCEPTIONS=OFF)
+add_library(transmission::small INTERFACE IMPORTED)
+target_link_libraries(transmission::small
+    INTERFACE
+        small::small)
+target_compile_definitions(transmission::small
+    INTERFACE
+        SMALL_DISABLE_EXCEPTIONS=1)
+
+tr_add_external_auto_library(UTF8CPP utf8cpp
+    SUBPROJECT
+    SOURCE_DIR utfcpp)
+if (NOT TARGET utf8::cpp)
+    add_library(utf8::cpp ALIAS utf8cpp)
+endif()
+
+tr_add_external_auto_library(WIDE_INTEGER WideInteger
+    SUBPROJECT
+    SOURCE_DIR wide-integer)
+add_library(transmission::WideInteger INTERFACE IMPORTED)
+target_link_libraries(transmission::WideInteger
+    INTERFACE
+        WideInteger::WideInteger)
+include(CheckCXXSourceCompiles)
+check_cxx_source_compiles(
+"int main()
+{
+    unsigned __int128 u;
+    signed __int128 i;
+    return 0;
+}" TR_HAVE_INT128)
+target_compile_definitions(transmission::WideInteger
+    INTERFACE
+        $<$<BOOL:${TR_HAVE_INT128}>:WIDE_INTEGER_HAS_LIMB_TYPE_UINT64>)
+
 set(TR_WEB_ASSETS ${PROJECT_SOURCE_DIR}/web/public_html)
 if(REBUILD_WEB)
     tr_get_required_flag(REBUILD_WEB NPM_IS_REQUIRED)
@@ -804,11 +888,6 @@ endif()
     endif()
 endif()
 
-if(ENABLE_TESTS)
-    enable_testing()
-    add_subdirectory(tests)
-endif()
-
 function(tr_install_web DST_DIR)
     if(INSTALL_WEB)
         install(
@@ -836,6 +915,11 @@ endforeach()
         add_subdirectory(${P})
     endif()
 endforeach()
+
+if(ENABLE_TESTS)
+    enable_testing()
+    add_subdirectory(tests)
+endif()
 
 if(ENABLE_DAEMON OR ENABLE_GTK OR ENABLE_QT)
     tr_install_web(${CMAKE_INSTALL_DATAROOTDIR}/${TR_NAME})
