CMakeLists.txt 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. # Copyright(c) 2019 spdlog authors Distributed under the MIT License (http://opensource.org/licenses/MIT)
  2. cmake_minimum_required(VERSION 3.11)
  3. # ---------------------------------------------------------------------------------------
  4. # Start spdlog project
  5. # ---------------------------------------------------------------------------------------
  6. include(cmake/utils.cmake)
  7. include(cmake/ide.cmake)
  8. spdlog_extract_version()
  9. project(spdlog VERSION ${SPDLOG_VERSION} LANGUAGES CXX)
  10. message(STATUS "Build spdlog: ${SPDLOG_VERSION}")
  11. include(GNUInstallDirs)
  12. # ---------------------------------------------------------------------------------------
  13. # Set default build to release
  14. # ---------------------------------------------------------------------------------------
  15. if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  16. set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose Release or Debug" FORCE)
  17. endif()
  18. # ---------------------------------------------------------------------------------------
  19. # Compiler config
  20. # ---------------------------------------------------------------------------------------
  21. if(SPDLOG_USE_STD_FORMAT)
  22. set(CMAKE_CXX_STANDARD 20)
  23. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  24. elseif(NOT CMAKE_CXX_STANDARD)
  25. set(CMAKE_CXX_STANDARD 11)
  26. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  27. endif()
  28. # make sure __cplusplus is defined when using msvc and enable parallel build
  29. if(MSVC)
  30. string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus /MP")
  31. endif()
  32. set(CMAKE_CXX_EXTENSIONS OFF)
  33. if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN" OR CMAKE_SYSTEM_NAME MATCHES "MSYS")
  34. set(CMAKE_CXX_EXTENSIONS ON)
  35. endif()
  36. # ---------------------------------------------------------------------------------------
  37. # Set SPDLOG_MASTER_PROJECT to ON if we are building spdlog
  38. # ---------------------------------------------------------------------------------------
  39. # Check if spdlog is being used directly or via add_subdirectory, but allow overriding
  40. if(NOT DEFINED SPDLOG_MASTER_PROJECT)
  41. if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
  42. set(SPDLOG_MASTER_PROJECT ON)
  43. else()
  44. set(SPDLOG_MASTER_PROJECT OFF)
  45. endif()
  46. endif()
  47. option(SPDLOG_BUILD_ALL "Build all artifacts" OFF)
  48. # build shared option
  49. option(SPDLOG_BUILD_SHARED "Build shared library" OFF)
  50. # precompiled headers option
  51. option(SPDLOG_ENABLE_PCH "Build static or shared library using precompiled header to speed up compilation time" OFF)
  52. # build position independent code
  53. option(SPDLOG_BUILD_PIC "Build position independent code (-fPIC)" OFF)
  54. # example options
  55. option(SPDLOG_BUILD_EXAMPLE "Build example" ${SPDLOG_MASTER_PROJECT})
  56. option(SPDLOG_BUILD_EXAMPLE_HO "Build header only example" OFF)
  57. # testing options
  58. option(SPDLOG_BUILD_TESTS "Build tests" OFF)
  59. option(SPDLOG_BUILD_TESTS_HO "Build tests using the header only version" OFF)
  60. # bench options
  61. option(SPDLOG_BUILD_BENCH "Build benchmarks (Requires https://github.com/google/benchmark.git to be installed)" OFF)
  62. # sanitizer options
  63. option(SPDLOG_SANITIZE_ADDRESS "Enable address sanitizer in tests" OFF)
  64. # warning options
  65. option(SPDLOG_BUILD_WARNINGS "Enable compiler warnings" OFF)
  66. # install options
  67. option(SPDLOG_SYSTEM_INCLUDES "Include as system headers (skip for clang-tidy)." OFF)
  68. option(SPDLOG_INSTALL "Generate the install target" ${SPDLOG_MASTER_PROJECT})
  69. option(SPDLOG_USE_STD_FORMAT "Use std::format instead of fmt library." OFF)
  70. option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
  71. option(SPDLOG_FMT_EXTERNAL_HO "Use external fmt header-only library instead of bundled" OFF)
  72. option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF)
  73. if(SPDLOG_FMT_EXTERNAL AND SPDLOG_FMT_EXTERNAL_HO)
  74. message(FATAL_ERROR "SPDLOG_FMT_EXTERNAL and SPDLOG_FMT_EXTERNAL_HO are mutually exclusive")
  75. endif()
  76. if(SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL_HO)
  77. message(FATAL_ERROR "SPDLOG_USE_STD_FORMAT and SPDLOG_FMT_EXTERNAL_HO are mutually exclusive")
  78. endif()
  79. if(SPDLOG_USE_STD_FORMAT AND SPDLOG_FMT_EXTERNAL)
  80. message(FATAL_ERROR "SPDLOG_USE_STD_FORMAT and SPDLOG_FMT_EXTERNAL are mutually exclusive")
  81. endif()
  82. # misc tweakme options
  83. if(WIN32)
  84. option(SPDLOG_WCHAR_SUPPORT "Support wchar api" OFF)
  85. option(SPDLOG_WCHAR_FILENAMES "Support wchar filenames" OFF)
  86. else()
  87. set(SPDLOG_WCHAR_SUPPORT OFF CACHE BOOL "non supported option" FORCE)
  88. set(SPDLOG_WCHAR_FILENAMES OFF CACHE BOOL "non supported option" FORCE)
  89. endif()
  90. if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
  91. option(SPDLOG_CLOCK_COARSE "Use CLOCK_REALTIME_COARSE instead of the regular clock," OFF)
  92. else()
  93. set(SPDLOG_CLOCK_COARSE OFF CACHE BOOL "non supported option" FORCE)
  94. endif()
  95. option(SPDLOG_PREVENT_CHILD_FD "Prevent from child processes to inherit log file descriptors" OFF)
  96. option(SPDLOG_NO_THREAD_ID "prevent spdlog from querying the thread id on each log call if thread id is not needed" OFF)
  97. option(SPDLOG_NO_TLS "prevent spdlog from using thread local storage" OFF)
  98. option(
  99. SPDLOG_NO_ATOMIC_LEVELS
  100. "prevent spdlog from using of std::atomic log levels (use only if your code never modifies log levels concurrently"
  101. OFF)
  102. option(SPDLOG_DISABLE_DEFAULT_LOGGER "Disable default logger creation" OFF)
  103. # clang-tidy
  104. option(SPDLOG_TIDY "run clang-tidy" OFF)
  105. if(SPDLOG_TIDY)
  106. set(CMAKE_CXX_CLANG_TIDY "clang-tidy")
  107. set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
  108. message(STATUS "Enabled clang-tidy")
  109. endif()
  110. if(SPDLOG_BUILD_PIC)
  111. set(CMAKE_POSITION_INDEPENDENT_CODE ON)
  112. endif()
  113. find_package(Threads REQUIRED)
  114. message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
  115. # ---------------------------------------------------------------------------------------
  116. # Static/Shared library
  117. # ---------------------------------------------------------------------------------------
  118. set(SPDLOG_SRCS src/spdlog.cpp src/stdout_sinks.cpp src/color_sinks.cpp src/file_sinks.cpp src/async.cpp src/cfg.cpp)
  119. if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
  120. list(APPEND SPDLOG_SRCS src/bundled_fmtlib_format.cpp)
  121. endif()
  122. if(SPDLOG_BUILD_SHARED OR BUILD_SHARED_LIBS)
  123. if(WIN32)
  124. configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
  125. list(APPEND SPDLOG_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
  126. endif()
  127. add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
  128. target_compile_definitions(spdlog PUBLIC SPDLOG_SHARED_LIB)
  129. if(MSVC)
  130. target_compile_options(spdlog PUBLIC $<$<AND:$<CXX_COMPILER_ID:MSVC>,$<NOT:$<COMPILE_LANGUAGE:CUDA>>>:/wd4251
  131. /wd4275>)
  132. endif()
  133. if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
  134. target_compile_definitions(spdlog PRIVATE FMT_EXPORT PUBLIC FMT_SHARED)
  135. endif()
  136. else()
  137. add_library(spdlog STATIC ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
  138. endif()
  139. add_library(spdlog::spdlog ALIAS spdlog)
  140. set(SPDLOG_INCLUDES_LEVEL "")
  141. if(SPDLOG_SYSTEM_INCLUDES)
  142. set(SPDLOG_INCLUDES_LEVEL "SYSTEM")
  143. endif()
  144. target_compile_definitions(spdlog PUBLIC SPDLOG_COMPILED_LIB)
  145. target_include_directories(spdlog ${SPDLOG_INCLUDES_LEVEL} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
  146. "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
  147. target_link_libraries(spdlog PUBLIC Threads::Threads)
  148. spdlog_enable_warnings(spdlog)
  149. set_target_properties(spdlog PROPERTIES VERSION ${SPDLOG_VERSION} SOVERSION
  150. ${SPDLOG_VERSION_MAJOR}.${SPDLOG_VERSION_MINOR})
  151. set_target_properties(spdlog PROPERTIES DEBUG_POSTFIX d)
  152. if(COMMAND target_precompile_headers AND SPDLOG_ENABLE_PCH)
  153. configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pch.h.in ${PROJECT_BINARY_DIR}/spdlog_pch.h @ONLY)
  154. target_precompile_headers(spdlog PRIVATE ${PROJECT_BINARY_DIR}/spdlog_pch.h)
  155. endif()
  156. # ---------------------------------------------------------------------------------------
  157. # Header only version
  158. # ---------------------------------------------------------------------------------------
  159. add_library(spdlog_header_only INTERFACE)
  160. add_library(spdlog::spdlog_header_only ALIAS spdlog_header_only)
  161. target_include_directories(
  162. spdlog_header_only ${SPDLOG_INCLUDES_LEVEL} INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
  163. "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
  164. target_link_libraries(spdlog_header_only INTERFACE Threads::Threads)
  165. # ---------------------------------------------------------------------------------------
  166. # Use fmt package if using external fmt
  167. # ---------------------------------------------------------------------------------------
  168. if(SPDLOG_FMT_EXTERNAL OR SPDLOG_FMT_EXTERNAL_HO)
  169. if(NOT TARGET fmt::fmt)
  170. find_package(fmt CONFIG REQUIRED)
  171. endif()
  172. target_compile_definitions(spdlog PUBLIC SPDLOG_FMT_EXTERNAL)
  173. target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_FMT_EXTERNAL)
  174. # use external fmt-header-nly
  175. if(SPDLOG_FMT_EXTERNAL_HO)
  176. target_link_libraries(spdlog PUBLIC fmt::fmt-header-only)
  177. target_link_libraries(spdlog_header_only INTERFACE fmt::fmt-header-only)
  178. else() # use external compile fmt
  179. target_link_libraries(spdlog PUBLIC fmt::fmt)
  180. target_link_libraries(spdlog_header_only INTERFACE fmt::fmt)
  181. endif()
  182. set(PKG_CONFIG_REQUIRES fmt) # add dependency to pkg-config
  183. endif()
  184. # ---------------------------------------------------------------------------------------
  185. # Add required libraries for Android CMake build
  186. # ---------------------------------------------------------------------------------------
  187. if(ANDROID)
  188. target_link_libraries(spdlog PUBLIC log)
  189. target_link_libraries(spdlog_header_only INTERFACE log)
  190. endif()
  191. # ---------------------------------------------------------------------------------------
  192. # Misc definitions according to tweak options
  193. # ---------------------------------------------------------------------------------------
  194. set(SPDLOG_WCHAR_TO_UTF8_SUPPORT ${SPDLOG_WCHAR_SUPPORT})
  195. foreach(
  196. SPDLOG_OPTION
  197. SPDLOG_WCHAR_TO_UTF8_SUPPORT
  198. SPDLOG_WCHAR_FILENAMES
  199. SPDLOG_NO_EXCEPTIONS
  200. SPDLOG_CLOCK_COARSE
  201. SPDLOG_PREVENT_CHILD_FD
  202. SPDLOG_NO_THREAD_ID
  203. SPDLOG_NO_TLS
  204. SPDLOG_NO_ATOMIC_LEVELS
  205. SPDLOG_DISABLE_DEFAULT_LOGGER
  206. SPDLOG_USE_STD_FORMAT)
  207. if(${SPDLOG_OPTION})
  208. target_compile_definitions(spdlog PUBLIC ${SPDLOG_OPTION})
  209. target_compile_definitions(spdlog_header_only INTERFACE ${SPDLOG_OPTION})
  210. endif()
  211. endforeach()
  212. # ---------------------------------------------------------------------------------------
  213. # If exceptions are disabled, disable them in the bundled fmt as well
  214. # ---------------------------------------------------------------------------------------
  215. if(SPDLOG_NO_EXCEPTIONS)
  216. if(NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
  217. target_compile_definitions(spdlog PUBLIC FMT_EXCEPTIONS=0)
  218. endif()
  219. if(NOT MSVC)
  220. target_compile_options(spdlog PRIVATE -fno-exceptions)
  221. else()
  222. target_compile_options(spdlog PRIVATE /EHs-c-)
  223. endif()
  224. endif()
  225. # ---------------------------------------------------------------------------------------
  226. # Build binaries
  227. # ---------------------------------------------------------------------------------------
  228. if(SPDLOG_BUILD_EXAMPLE OR SPDLOG_BUILD_EXAMPLE_HO OR SPDLOG_BUILD_ALL)
  229. message(STATUS "Generating example(s)")
  230. add_subdirectory(example)
  231. spdlog_enable_warnings(example)
  232. if(SPDLOG_BUILD_EXAMPLE_HO)
  233. spdlog_enable_warnings(example_header_only)
  234. endif()
  235. endif()
  236. if(SPDLOG_BUILD_TESTS OR SPDLOG_BUILD_TESTS_HO OR SPDLOG_BUILD_ALL)
  237. message(STATUS "Generating tests")
  238. enable_testing()
  239. add_subdirectory(tests)
  240. endif()
  241. if(SPDLOG_BUILD_BENCH OR SPDLOG_BUILD_ALL)
  242. message(STATUS "Generating benchmarks")
  243. add_subdirectory(bench)
  244. endif()
  245. # ---------------------------------------------------------------------------------------
  246. # Install
  247. # ---------------------------------------------------------------------------------------
  248. if(SPDLOG_INSTALL)
  249. message(STATUS "Generating install")
  250. set(project_config_in "${CMAKE_CURRENT_LIST_DIR}/cmake/spdlogConfig.cmake.in")
  251. set(project_config_out "${CMAKE_CURRENT_BINARY_DIR}/spdlogConfig.cmake")
  252. set(config_targets_file "spdlogConfigTargets.cmake")
  253. set(version_config_file "${CMAKE_CURRENT_BINARY_DIR}/spdlogConfigVersion.cmake")
  254. set(export_dest_dir "${CMAKE_INSTALL_LIBDIR}/cmake/spdlog")
  255. set(pkgconfig_install_dir "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
  256. set(pkg_config "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc")
  257. # ---------------------------------------------------------------------------------------
  258. # Include files
  259. # ---------------------------------------------------------------------------------------
  260. install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" PATTERN "fmt/bundled" EXCLUDE)
  261. install(
  262. TARGETS spdlog spdlog_header_only
  263. EXPORT spdlog
  264. LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
  265. ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
  266. RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
  267. if(NOT SPDLOG_USE_STD_FORMAT AND NOT SPDLOG_FMT_EXTERNAL AND NOT SPDLOG_FMT_EXTERNAL_HO)
  268. install(DIRECTORY include/${PROJECT_NAME}/fmt/bundled/
  269. DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/fmt/bundled/")
  270. endif()
  271. # ---------------------------------------------------------------------------------------
  272. # Install pkg-config file
  273. # ---------------------------------------------------------------------------------------
  274. if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
  275. set(PKG_CONFIG_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
  276. else()
  277. set(PKG_CONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
  278. endif()
  279. if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
  280. set(PKG_CONFIG_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
  281. else()
  282. set(PKG_CONFIG_LIBDIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
  283. endif()
  284. get_target_property(PKG_CONFIG_DEFINES spdlog INTERFACE_COMPILE_DEFINITIONS)
  285. string(REPLACE ";" " -D" PKG_CONFIG_DEFINES "${PKG_CONFIG_DEFINES}")
  286. string(CONCAT PKG_CONFIG_DEFINES "-D" "${PKG_CONFIG_DEFINES}")
  287. configure_file("cmake/${PROJECT_NAME}.pc.in" "${pkg_config}" @ONLY)
  288. install(FILES "${pkg_config}" DESTINATION "${pkgconfig_install_dir}")
  289. # ---------------------------------------------------------------------------------------
  290. # Install CMake config files
  291. # ---------------------------------------------------------------------------------------
  292. export(TARGETS spdlog spdlog_header_only NAMESPACE spdlog::
  293. FILE "${CMAKE_CURRENT_BINARY_DIR}/${config_targets_file}")
  294. install(EXPORT spdlog DESTINATION ${export_dest_dir} NAMESPACE spdlog:: FILE ${config_targets_file})
  295. include(CMakePackageConfigHelpers)
  296. configure_package_config_file("${project_config_in}" "${project_config_out}" INSTALL_DESTINATION ${export_dest_dir})
  297. write_basic_package_version_file("${version_config_file}" COMPATIBILITY SameMajorVersion)
  298. install(FILES "${project_config_out}" "${version_config_file}" DESTINATION "${export_dest_dir}")
  299. # ---------------------------------------------------------------------------------------
  300. # Support creation of installable packages
  301. # ---------------------------------------------------------------------------------------
  302. include(cmake/spdlogCPack.cmake)
  303. endif()