CMakeLists.txt 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. # Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
  2. # Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 2 or (at your option)
  7. # version 3 of the License.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. cmake_minimum_required(VERSION 3.16.0)
  17. project(KeePassXC)
  18. set(APP_ID "org.keepassxc.${PROJECT_NAME}")
  19. # Version Number
  20. set(KEEPASSXC_VERSION_MAJOR "2")
  21. set(KEEPASSXC_VERSION_MINOR "8")
  22. set(KEEPASSXC_VERSION_PATCH "0")
  23. set(KEEPASSXC_VERSION "${KEEPASSXC_VERSION_MAJOR}.${KEEPASSXC_VERSION_MINOR}.${KEEPASSXC_VERSION_PATCH}")
  24. string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
  25. # CMake Modules
  26. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
  27. include(CMakeToolsHelpers OPTIONAL) # Support Visual Studio Code
  28. include(FeatureSummary)
  29. include(KPXCMacDeployHelpers)
  30. include(CLangFormat)
  31. include(CompilerFlags)
  32. include(CheckCCompilerFlag)
  33. include(CheckCXXCompilerFlag)
  34. include(CheckCXXSourceCompiles)
  35. # Build Scope
  36. option(WITH_TESTS "Enable building of unit tests" ON)
  37. option(WITH_GUI_TESTS "Enable building of GUI tests" OFF)
  38. option(WITH_WARN_DEPRECATED "Development only: warn about deprecated methods, including Qt." OFF)
  39. option(WITH_ASAN "Enable address sanitizer checks (Linux / macOS only)" OFF)
  40. option(WITH_COVERAGE "Use to build with coverage tests (GCC only)." OFF)
  41. option(WITH_APP_BUNDLE "Enable Application Bundle for macOS" ON)
  42. option(WITH_CCACHE "Use ccache for build" OFF)
  43. option(WITH_X11 "Enable building with X11 dependencies" ON)
  44. # Advanced Features Control
  45. option(KPXC_MINIMAL "Build KeePassXC with the minimal feature set required for basic usage" OFF)
  46. option(KPXC_FEATURE_BROWSER "Browser integration and passkeys support" ON)
  47. option(KPXC_FEATURE_SSHAGENT "SSH Agent integration" ON)
  48. option(KPXC_FEATURE_FDOSECRETS "freedesktop.org Secret Service integration; replace system keyring" ON)
  49. if(KPXC_MINIMAL)
  50. # Disable advanced features in minimal mode
  51. set(KPXC_FEATURE_BROWSER OFF)
  52. set(KPXC_FEATURE_SSHAGENT OFF)
  53. set(KPXC_FEATURE_FDOSECRETS OFF)
  54. endif()
  55. # Minor Feature Flags
  56. option(KPXC_FEATURE_NETWORK "Include code that reaches out to external networks (e.g. downloading icons)" ON)
  57. option(KPXC_FEATURE_UPDATES "Include automatic update checks; disable for managed distributions" ON)
  58. option(KPXC_FEATURE_DOCS "Build offline documentation; requires asciidoctor tool" ON)
  59. # Reconcile update feature with overall network feature
  60. if(NOT KPXC_FEATURE_NETWORK AND KPXC_FEATURE_UPDATES)
  61. message(STATUS "Disabling KPXC_FEATURE_UPDATES because KPXC_FEATURE_NETWORK is disabled")
  62. set(KPXC_FEATURE_UPDATES OFF)
  63. endif()
  64. # FDO Secrets is only available on Linux
  65. if(NOT UNIX OR APPLE OR HAIKU)
  66. set(KPXC_FEATURE_FDOSECRETS OFF)
  67. endif()
  68. # Define feature summaries
  69. add_feature_info("Browser" KPXC_FEATURE_BROWSER "Browser integration and passkeys support")
  70. add_feature_info("SSH Agent" KPXC_FEATURE_SSHAGENT "SSH Agent integration")
  71. if(UNIX AND NOT APPLE)
  72. add_feature_info("Secret Service" KPXC_FEATURE_FDOSECRETS "Replace system keyring with freedesktop.org Secret Service integration")
  73. endif()
  74. add_feature_info("Networking" KPXC_FEATURE_NETWORK "Code that can reach out to external networks is included (e.g. downloading icons)")
  75. add_feature_info("Update Checks" KPXC_FEATURE_UPDATES "Periodic update checks can be performed")
  76. add_feature_info("Documentation" KPXC_FEATURE_DOCS "Offline documentation")
  77. # Retrieve git HEAD revision hash
  78. set(GIT_HEAD_OVERRIDE "" CACHE STRING "Manually set the Git HEAD hash when missing (eg, when no .git folder exists)")
  79. execute_process(COMMAND git rev-parse --short=7 HEAD
  80. WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  81. OUTPUT_VARIABLE GIT_HEAD
  82. ERROR_QUIET)
  83. string(STRIP "${GIT_HEAD}" GIT_HEAD)
  84. if(GIT_HEAD STREQUAL "" AND NOT GIT_HEAD_OVERRIDE STREQUAL "")
  85. string(SUBSTRING "${GIT_HEAD_OVERRIDE}" 0 7 GIT_HEAD)
  86. elseif(EXISTS ${CMAKE_SOURCE_DIR}/.gitrev)
  87. file(READ ${CMAKE_SOURCE_DIR}/.gitrev GIT_HEAD)
  88. endif()
  89. message(STATUS "Found Git HEAD Revision: ${GIT_HEAD}\n")
  90. # KeePassXC Versioning and Build Type
  91. set(OVERRIDE_VERSION "" CACHE STRING "Override the KeePassXC Version for Snapshot builds")
  92. set(KEEPASSXC_BUILD_TYPE "Snapshot" CACHE STRING "Set KeePassXC build type to distinguish between stable releases and snapshots")
  93. set_property(CACHE KEEPASSXC_BUILD_TYPE PROPERTY STRINGS Snapshot Release)
  94. # Check if on a tag or has .version file, if so build as a release
  95. execute_process(COMMAND git tag --points-at HEAD
  96. WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  97. OUTPUT_VARIABLE GIT_TAG
  98. ERROR_QUIET)
  99. string(REGEX REPLACE "latest" "" GIT_TAG "${GIT_TAG}")
  100. if(GIT_TAG MATCHES "[0-9]+\.[0-9]+\.[0-9]+")
  101. string(STRIP "${GIT_TAG}" GIT_TAG)
  102. set(OVERRIDE_VERSION ${GIT_TAG})
  103. elseif(EXISTS ${CMAKE_SOURCE_DIR}/.version)
  104. file(READ ${CMAKE_SOURCE_DIR}/.version OVERRIDE_VERSION)
  105. endif()
  106. string(REGEX REPLACE "(\r?\n)+" "" OVERRIDE_VERSION "${OVERRIDE_VERSION}")
  107. if(OVERRIDE_VERSION)
  108. if(OVERRIDE_VERSION MATCHES "^[\\.0-9]+$")
  109. set(KEEPASSXC_BUILD_TYPE "Release")
  110. set(KEEPASSXC_VERSION ${OVERRIDE_VERSION})
  111. else()
  112. set(KEEPASSXC_BUILD_TYPE "Snapshot")
  113. endif()
  114. endif()
  115. if(KEEPASSXC_BUILD_TYPE STREQUAL "Release")
  116. set(KEEPASSXC_BUILD_TYPE_RELEASE ON)
  117. else()
  118. set(KEEPASSXC_BUILD_TYPE_SNAPSHOT ON)
  119. set(KEEPASSXC_VERSION "${KEEPASSXC_VERSION}-snapshot")
  120. endif()
  121. message(STATUS "Setting up build for KeePassXC v${KEEPASSXC_VERSION}\n")
  122. # Distribution info
  123. set(KEEPASSXC_DIST_TYPE "Native" CACHE STRING "KeePassXC Distribution Type")
  124. set_property(CACHE KEEPASSXC_DIST_TYPE PROPERTY STRINGS Snap AppImage Flatpak Native)
  125. if(KEEPASSXC_DIST_TYPE STREQUAL "Snap")
  126. set(KEEPASSXC_DIST_SNAP ON)
  127. elseif(KEEPASSXC_DIST_TYPE STREQUAL "AppImage")
  128. set(KEEPASSXC_DIST_APPIMAGE ON)
  129. elseif(KEEPASSXC_DIST_TYPE STREQUAL "Flatpak")
  130. set(KEEPASSXC_DIST_FLATPAK ON)
  131. endif()
  132. # Standards
  133. set(CMAKE_C_STANDARD 99)
  134. set(CMAKE_CXX_STANDARD 20)
  135. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  136. # Compiler Features
  137. if(APPLE)
  138. # Perform the platform checks before applying the stricter compiler flags.
  139. # Otherwise the kSecAccessControlTouchIDCurrentSet deprecation warning will result in an error.
  140. try_compile(XC_APPLE_COMPILER_SUPPORT_BIOMETRY
  141. ${CMAKE_BINARY_DIR}/macos-trycompile/
  142. ${CMAKE_SOURCE_DIR}/cmake/compiler-checks/control_biometry_support.mm)
  143. message(STATUS "Biometry compiler support: ${XC_APPLE_COMPILER_SUPPORT_BIOMETRY}")
  144. try_compile(XC_APPLE_COMPILER_SUPPORT_TOUCH_ID
  145. ${CMAKE_BINARY_DIR}/macos-trycompile/
  146. ${CMAKE_SOURCE_DIR}/cmake/compiler-checks/control_touch_id_support.mm)
  147. message(STATUS "Touch ID compiler support: ${XC_APPLE_COMPILER_SUPPORT_TOUCH_ID}")
  148. try_compile(XC_APPLE_COMPILER_SUPPORT_WATCH
  149. ${CMAKE_BINARY_DIR}/macos-trycompile/
  150. ${CMAKE_SOURCE_DIR}/cmake/compiler-checks/control_watch_support.mm)
  151. message(STATUS "Apple watch compiler support: ${XC_APPLE_COMPILER_SUPPORT_WATCH}")
  152. try_compile(HAVE_PT_DENY_ATTACH
  153. ${CMAKE_BINARY_DIR}/macos-trycompile/
  154. ${CMAKE_SOURCE_DIR}/cmake/compiler-checks/ptrace_deny_attach.cpp)
  155. endif()
  156. if(UNIX)
  157. check_cxx_source_compiles("#include <sys/prctl.h>
  158. int main() { prctl(PR_SET_DUMPABLE, 0); return 0; }"
  159. HAVE_PR_SET_DUMPABLE)
  160. check_cxx_source_compiles("#include <malloc.h>
  161. int main() { return 0; }"
  162. HAVE_MALLOC_H)
  163. check_cxx_source_compiles("#include <malloc.h>
  164. int main() { malloc_usable_size(NULL); return 0; }"
  165. HAVE_MALLOC_USABLE_SIZE)
  166. check_cxx_source_compiles("#include <sys/resource.h>
  167. int main() {
  168. struct rlimit limit;
  169. limit.rlim_cur = 0;
  170. limit.rlim_max = 0;
  171. setrlimit(RLIMIT_CORE, &limit);
  172. return 0;
  173. }" HAVE_RLIMIT_CORE)
  174. endif()
  175. # ccache support
  176. if(WITH_CCACHE)
  177. find_program(CCACHE_FOUND ccache)
  178. if(NOT CCACHE_FOUND)
  179. message(FATAL_ERROR "ccache requested but cannot be found.")
  180. endif()
  181. set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_FOUND})
  182. endif()
  183. # Create position independent code for shared libraries and executables
  184. set(CMAKE_POSITION_INDEPENDENT_CODE ON)
  185. if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14.0")
  186. cmake_policy(SET CMP0083 NEW)
  187. include(CheckPIESupported)
  188. check_pie_supported()
  189. endif()
  190. if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
  191. set(IS_32BIT TRUE)
  192. endif()
  193. set(CLANG_COMPILER_ID_REGEX "^(Apple)?[Cc]lang$")
  194. if("${CMAKE_C_COMPILER}" MATCHES "clang$"
  195. OR "${CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS}" MATCHES "__clang__"
  196. OR "${CMAKE_C_COMPILER_ID}" MATCHES ${CLANG_COMPILER_ID_REGEX})
  197. set(CMAKE_COMPILER_IS_CLANG 1)
  198. endif()
  199. if("${CMAKE_CXX_COMPILER}" MATCHES "clang(\\+\\+)?$"
  200. OR "${CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS}" MATCHES "__clang__"
  201. OR "${CMAKE_CXX_COMPILER_ID}" MATCHES ${CLANG_COMPILER_ID_REGEX})
  202. set(CMAKE_COMPILER_IS_CLANGXX 1)
  203. endif()
  204. # Compiler Flags
  205. add_gcc_compiler_flags("-fno-common")
  206. find_package(OpenMP)
  207. if(OpenMP_FOUND)
  208. add_gcc_compiler_cflags(${OpenMP_C_FLAGS})
  209. add_gcc_compiler_cxxflags(${OpenMP_CXX_FLAGS})
  210. endif()
  211. add_gcc_compiler_flags("-Wall -Wextra -Wundef -Wpointer-arith -Wno-long-long")
  212. add_gcc_compiler_flags("-Wformat=2 -Wmissing-format-attribute")
  213. add_gcc_compiler_flags("-fvisibility=hidden")
  214. add_gcc_compiler_cxxflags("-fvisibility-inlines-hidden")
  215. if(CMAKE_BUILD_TYPE_LOWER STREQUAL "debug")
  216. check_add_gcc_compiler_flag("-Wshadow-compatible-local")
  217. check_add_gcc_compiler_flag("-Wshadow-local")
  218. add_gcc_compiler_flags("-Werror")
  219. # C++20 marks enum arithmetic as deprecated, but we use it in Botan and Qt5
  220. add_gcc_compiler_cxxflags("-Wno-deprecated-enum-enum-conversion -Wno-error=deprecated ")
  221. endif()
  222. if (NOT HAIKU)
  223. if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8.999) OR CMAKE_COMPILER_IS_CLANGXX)
  224. add_gcc_compiler_flags("-fstack-protector-strong")
  225. else()
  226. add_gcc_compiler_flags("-fstack-protector --param=ssp-buffer-size=4")
  227. endif()
  228. endif()
  229. add_gcc_compiler_cxxflags("-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual")
  230. add_gcc_compiler_cflags("-Wchar-subscripts -Wwrite-strings")
  231. if(WITH_ASAN)
  232. if(NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR APPLE))
  233. message(FATAL_ERROR "WITH_ASAN is only supported on Linux / macOS at the moment.")
  234. endif()
  235. add_gcc_compiler_flags("-fsanitize=address -DWITH_ASAN")
  236. if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  237. if(NOT (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9))
  238. add_gcc_compiler_flags("-fsanitize=leak -DWITH_LSAN")
  239. endif()
  240. endif()
  241. endif()
  242. if(CMAKE_BUILD_TYPE_LOWER MATCHES "(release|relwithdebinfo|minsizerel)")
  243. add_gcc_compiler_flags("-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2")
  244. endif()
  245. check_add_gcc_compiler_flag("-Werror=format-security")
  246. check_add_gcc_compiler_flag("-Werror=implicit-function-declaration" C)
  247. check_add_gcc_compiler_flag("-Wcast-align")
  248. if(UNIX AND NOT APPLE)
  249. check_add_gcc_compiler_flag("-Qunused-arguments")
  250. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed -Wl,--no-undefined")
  251. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro,-z,now -pie")
  252. set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--as-needed")
  253. set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro,-z,now")
  254. endif()
  255. check_cxx_compiler_flag("-fsized-deallocation" CXX_HAS_fsized_deallocation)
  256. if(CXX_HAS_fsized_deallocation)
  257. # Do additional check: the deallocation functions must be there too.
  258. set(CMAKE_REQUIRED_FLAGS "-fsized-deallocation")
  259. check_cxx_source_compiles("#include <new>
  260. int main() { void * ptr = nullptr; std::size_t size = 1; ::operator delete(ptr, size); }"
  261. HAVE_DEALLOCATION_FUNCTIONS)
  262. if(HAVE_DEALLOCATION_FUNCTIONS)
  263. check_add_gcc_compiler_flag("-fsized-deallocation" CXX)
  264. endif()
  265. unset(CMAKE_REQUIRED_FLAGS)
  266. endif()
  267. if(APPLE AND CMAKE_COMPILER_IS_CLANGXX)
  268. add_gcc_compiler_cxxflags("-stdlib=libc++")
  269. endif()
  270. if(WITH_WARN_DEPRECATED)
  271. add_definitions(-DQT_DEPRECATED_WARNINGS)
  272. else()
  273. add_definitions(-DQT_NO_DEPRECATED_WARNINGS)
  274. add_gcc_compiler_cxxflags("-Wno-deprecated-declarations")
  275. endif()
  276. # MSVC specific options
  277. if (MSVC)
  278. if(MSVC_TOOLSET_VERSION LESS 142)
  279. message(FATAL_ERROR "Only Microsoft Visual Studio 2019 and newer are supported!")
  280. endif()
  281. # Turn on multi-processor support and faster PDB generation (/Zf)
  282. add_compile_options(/permissive- /utf-8 /MP /Zf)
  283. # Enable built-in ASAN
  284. add_compile_definitions(/fsanitize=address)
  285. # Enable high entropy ASLR on release builds
  286. if(CMAKE_BUILD_TYPE_LOWER STREQUAL "release")
  287. add_compile_options(/guard:cf)
  288. add_link_options(/DYNAMICBASE /HIGHENTROPYVA /GUARD:CF)
  289. endif()
  290. elseif(MINGW)
  291. # Enable high entropy ASLR on release builds
  292. if(CMAKE_BUILD_TYPE_LOWER STREQUAL "release")
  293. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase -Wl,--high-entropy-va")
  294. set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase -Wl,--high-entropy-va")
  295. endif()
  296. endif()
  297. if(WIN32)
  298. set(PROGNAME KeePassXC)
  299. set(CLI_INSTALL_DIR ".")
  300. set(PROXY_INSTALL_DIR ".")
  301. set(BIN_INSTALL_DIR ".")
  302. set(PLUGIN_INSTALL_DIR ".")
  303. set(DATA_INSTALL_DIR "share")
  304. elseif(APPLE AND WITH_APP_BUNDLE)
  305. set(PROGNAME KeePassXC)
  306. set(BUNDLE_INSTALL_DIR "${PROGNAME}.app/Contents")
  307. set(CMAKE_INSTALL_MANDIR "${BUNDLE_INSTALL_DIR}/Resources/man")
  308. set(CLI_INSTALL_DIR "${BUNDLE_INSTALL_DIR}/MacOS")
  309. set(PROXY_INSTALL_DIR "${BUNDLE_INSTALL_DIR}/MacOS")
  310. set(BIN_INSTALL_DIR "${BUNDLE_INSTALL_DIR}/MacOS")
  311. set(PLUGIN_INSTALL_DIR "${BUNDLE_INSTALL_DIR}/PlugIns")
  312. set(DATA_INSTALL_DIR "${BUNDLE_INSTALL_DIR}/Resources")
  313. add_definitions(-DWITH_APP_BUNDLE)
  314. else()
  315. include(GNUInstallDirs)
  316. set(PROGNAME keepassxc)
  317. set(CLI_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}")
  318. set(PROXY_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}")
  319. set(BIN_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}")
  320. set(PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/keepassxc")
  321. set(DATA_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/keepassxc")
  322. endif()
  323. if(WITH_COVERAGE)
  324. # Include code coverage, use with -DCMAKE_BUILD_TYPE=Debug
  325. include(CodeCoverage)
  326. append_coverage_compiler_flags()
  327. set(COVERAGE_EXCLUDES
  328. "'^(.+/)?thirdparty/.*'"
  329. "'^(.+/)?main\\.cpp$$'"
  330. "'^(.+/)?cli/keepassxc-cli\\.cpp$$'"
  331. "'^(.+/)?proxy/keepassxc-proxy\\.cpp$$'")
  332. if(WITH_COVERAGE AND CMAKE_COMPILER_IS_CLANGXX)
  333. set(MAIN_BINARIES
  334. "$<TARGET_FILE:${PROGNAME}>"
  335. "$<TARGET_FILE:keepassxc-cli>"
  336. "$<TARGET_FILE:keepassxc-proxy>")
  337. setup_target_for_coverage_llvm(
  338. NAME coverage
  339. BINARY ${MAIN_BINARIES}
  340. SOURCES_ROOT ${CMAKE_SOURCE_DIR}/src
  341. )
  342. else()
  343. setup_target_for_coverage_gcovr(
  344. NAME coverage
  345. SOURCES_ROOT ${CMAKE_SOURCE_DIR}/src
  346. )
  347. endif()
  348. endif()
  349. # Find Qt
  350. set(QT_COMPONENTS Core Network Concurrent Gui Svg Widgets Test LinguistTools)
  351. if(UNIX AND NOT APPLE)
  352. if(WITH_X11)
  353. list(APPEND QT_COMPONENTS X11Extras)
  354. endif()
  355. find_package(Qt5 COMPONENTS ${QT_COMPONENTS} DBus REQUIRED)
  356. elseif(APPLE)
  357. find_package(Qt5 COMPONENTS ${QT_COMPONENTS} REQUIRED HINTS
  358. /usr/local/opt/qt@5/lib/cmake
  359. /usr/local/Cellar/qt@5/*/lib/cmake
  360. /opt/homebrew/opt/qt@5/lib/cmake
  361. ENV PATH)
  362. find_package(Qt5 COMPONENTS MacExtras HINTS
  363. /usr/local/opt/qt@5/lib/cmake
  364. /usr/local/Cellar/qt@5/*/lib/cmake
  365. /opt/homebrew/opt/qt@5/lib/cmake
  366. ENV PATH)
  367. else()
  368. find_package(Qt5 COMPONENTS ${QT_COMPONENTS} REQUIRED)
  369. endif()
  370. # Minimum Qt version check
  371. if(Qt5Core_VERSION VERSION_LESS "5.12.0")
  372. message(FATAL_ERROR "Qt version 5.12.0 or higher is required")
  373. endif()
  374. # C++20 is not supported before Qt 5.15.0
  375. if(Qt5Core_VERSION VERSION_LESS "5.15.0")
  376. set(CMAKE_CXX_STANDARD 17)
  377. endif()
  378. # Process moc automatically
  379. set(CMAKE_AUTOMOC ON)
  380. # Process .ui files automatically
  381. set(CMAKE_AUTOUIC ON)
  382. # Process .qrc files automatically
  383. set(CMAKE_AUTORCC ON)
  384. add_definitions(-DQT_NO_EXCEPTIONS -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII)
  385. if(NOT CMAKE_BUILD_TYPE_LOWER STREQUAL "debug")
  386. add_definitions(-DQT_NO_DEBUG_OUTPUT)
  387. endif()
  388. get_filename_component(Qt5_PREFIX ${Qt5_DIR}/../../.. REALPATH)
  389. if(APPLE)
  390. # Add includes under Qt5 Prefix in case Qt6 is also installed
  391. include_directories(SYSTEM ${Qt5_PREFIX}/include)
  392. set(CMAKE_MACOSX_RPATH TRUE)
  393. find_program(MACDEPLOYQT_EXE macdeployqt HINTS ${Qt5_PREFIX}/bin ${Qt5_PREFIX}/tools/qt5/bin ENV PATH)
  394. if(NOT MACDEPLOYQT_EXE)
  395. message(FATAL_ERROR "macdeployqt is required to build on macOS")
  396. endif()
  397. message(STATUS "Using macdeployqt: ${MACDEPLOYQT_EXE}")
  398. set(MACDEPLOYQT_EXTRA_BINARIES "")
  399. elseif(WIN32)
  400. find_program(WINDEPLOYQT_EXE windeployqt HINTS ${Qt5_PREFIX}/bin ${Qt5_PREFIX}/tools/qt5/bin ENV PATH)
  401. if(NOT WINDEPLOYQT_EXE)
  402. message(FATAL_ERROR "windeployqt is required to build on Windows")
  403. endif()
  404. message(STATUS "Using windeployqt: ${WINDEPLOYQT_EXE}")
  405. endif()
  406. # Find Botan
  407. # TODO: Increase minimum to 2.19.1 and drop Argon2 package
  408. find_package(Botan REQUIRED)
  409. if(BOTAN_VERSION VERSION_GREATER_EQUAL "3.0.0")
  410. set(WITH_BOTAN3 TRUE)
  411. elseif(BOTAN_VERSION VERSION_LESS "2.12.0")
  412. # Check for minimum Botan version
  413. message(FATAL_ERROR "Botan 2.12.0 or higher is required")
  414. endif()
  415. include_directories(SYSTEM ${BOTAN_INCLUDE_DIR})
  416. # Find Argon2 -- Botan 2.18 and below does not support threaded Argon2
  417. find_library(ARGON2_LIBRARIES NAMES argon2)
  418. find_path(ARGON2_INCLUDE_DIR NAMES argon2.h PATH_SUFFIXES local/include)
  419. include_directories(SYSTEM ${ARGON2_INCLUDE_DIR})
  420. # Find zlib
  421. find_package(ZLIB REQUIRED)
  422. if(ZLIB_VERSION_STRING VERSION_LESS "1.2.0")
  423. message(FATAL_ERROR "zlib 1.2.0 or higher is required to use the gzip format")
  424. endif()
  425. include_directories(SYSTEM ${ZLIB_INCLUDE_DIR})
  426. # Find Minizip
  427. find_package(Minizip REQUIRED)
  428. # Find PCSC and LibUSB for hardware key support
  429. find_package(PCSC REQUIRED)
  430. include_directories(SYSTEM ${PCSC_INCLUDE_DIRS})
  431. if(UNIX AND NOT APPLE)
  432. find_library(LIBUSB_LIBRARIES NAMES usb-1.0 REQUIRED)
  433. find_path(LIBUSB_INCLUDE_DIR NAMES libusb.h PATH_SUFFIXES "libusb-1.0" "libusb" REQUIRED)
  434. include_directories(SYSTEM ${LIBUSB_INCLUDE_DIR})
  435. # For PolKit QuickUnlock
  436. find_library(KEYUTILS_LIBRARIES NAMES keyutils REQUIRED)
  437. endif()
  438. # Find zxcvbn or use the bundled version
  439. find_library(ZXCVBN_LIBRARIES zxcvbn)
  440. if(NOT ZXCVBN_LIBRARIES)
  441. add_subdirectory(src/thirdparty/zxcvbn)
  442. set(ZXCVBN_LIBRARIES zxcvbn)
  443. endif()
  444. # Add KeePassXC sources and tests
  445. add_subdirectory(src)
  446. add_subdirectory(share)
  447. if(WITH_TESTS)
  448. enable_testing()
  449. add_subdirectory(tests)
  450. endif()
  451. if(KPXC_FEATURE_DOCS)
  452. add_subdirectory(docs)
  453. endif()
  454. # Print out summary information
  455. message(STATUS "")
  456. feature_summary(QUIET_ON_EMPTY WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
  457. feature_summary(QUIET_ON_EMPTY WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")