CMakeLists.txt 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. cmake_minimum_required(VERSION 3.2)
  2. include(ExternalProject)
  3. include(CMakeParseArguments)
  4. set(THREADS_PREFER_PTHREAD_FLAG ON)
  5. find_package(Threads REQUIRED)
  6. find_package(PythonInterp 2.7 REQUIRED)
  7. set(CMAKE_C_STANDARD 11)
  8. set(CMAKE_C_STANDARD_REQUIRED ON)
  9. set(CMAKE_C_EXTENSIONS OFF)
  10. set(CMAKE_CXX_STANDARD 11)
  11. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  12. set(CMAKE_CXX_EXTENSIONS OFF)
  13. if(MSVC)
  14. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /WX")
  15. else()
  16. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -pedantic-errors")
  17. endif()
  18. option(ZF_LOG_PERF_TEST_SAVE_TEMPS "Save preprocessor and disassembler output" OFF)
  19. option(ZF_LOG_PERF_TEST_ZF_LOG_OS "Add zf_log built with ZF_LOG_OPTIMIZE_SIZE to performance tests" OFF)
  20. option(ZF_LOG_PERF_TEST_VERBOSE_3P_BUILD "Enable verbose build output for 3rd party libraries (noisy)" OFF)
  21. # Launch rules are target properties (RULE_LAUNCH_COMPILE, RULE_LAUNCH_LINK)
  22. # that are used to time compilation and linking. Tests that require this
  23. # properties will be disabled if current generator doesn't support launch
  24. # rules. See CMake documentation for up to date list of generators that support
  25. # launch rules.
  26. if(CMAKE_GENERATOR MATCHES "Makefiles" OR
  27. CMAKE_GENERATOR MATCHES "Ninja")
  28. set(LAUNCH_RULES ON)
  29. else()
  30. message(WARNING "Timing compilation and linking is not supported by \"${CMAKE_GENERATOR}\" generator!")
  31. set(LAUNCH_RULES OFF)
  32. endif()
  33. # Since a lot of 3rd party dependencies envolved, it's only so much we can do here.
  34. # Non-Unix support is possible, but not in the scope right now.
  35. if(NOT UNIX)
  36. message(WARNING "Performance tests only maintained for Unix platforms!")
  37. endif()
  38. # For convenience, ZF_LOG_PERF_TEST_VERBOSE_3P_BUILD is inverse of what is
  39. # actually needed. SILENT_3P_BUILD variable will be used instead.
  40. set(SILENT_3P_BUILD ON)
  41. if(ZF_LOG_PERF_TEST_VERBOSE_3P_BUILD)
  42. set(SILENT_3P_BUILD OFF)
  43. endif()
  44. function(add_target target)
  45. cmake_parse_arguments(arg
  46. "STATICLIB;EXECUTABLE;NO_THREADS"
  47. "TIME_COMPILE;TIME_LINK"
  48. "SOURCES;DEFINES;INCLUDES;COMPILE_OPTIONS;LIBRARIES"
  49. ${ARGN})
  50. if(ZF_LOG_PERF_TEST_SAVE_TEMPS)
  51. # Clang writes *.s and *.ii files into its current working directory.
  52. # Since the same source files are used in multiple targets, need to
  53. # copy them, so they will have different names for different targets.
  54. set(SOURCES "")
  55. foreach(source ${arg_SOURCES})
  56. if(IS_ABSOLUTE source)
  57. set(src "${source}")
  58. else()
  59. set(src "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
  60. endif()
  61. get_filename_component(src_name "${source}" NAME)
  62. set(dst "${CMAKE_CURRENT_BINARY_DIR}/sources/${target}-${src_name}")
  63. add_custom_command(OUTPUT "${dst}"
  64. COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${src}" "${dst}"
  65. DEPENDS "${src}")
  66. list(APPEND SOURCES "${dst}")
  67. endforeach()
  68. else()
  69. set(SOURCES ${arg_SOURCES})
  70. endif()
  71. if(arg_STATICLIB)
  72. add_library(${target} STATIC ${SOURCES})
  73. elseif(arg_EXECUTABLE)
  74. add_executable(${target} ${SOURCES})
  75. if(NOT NO_THREADS)
  76. target_link_libraries(${target} Threads::Threads)
  77. endif()
  78. else()
  79. message(FATAL_ERROR "Test target type is not specified.")
  80. endif()
  81. if(ZF_LOG_PERF_SAVE_TEMPS)
  82. target_include_directories(${target} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
  83. target_compile_options(${target} PRIVATE "-save-temps")
  84. endif()
  85. if(arg_DEFINES)
  86. set_property(TARGET ${target} PROPERTY COMPILE_DEFINITIONS "${arg_DEFINES}")
  87. endif()
  88. if(arg_INCLUDES)
  89. target_include_directories(${target} PRIVATE ${arg_INCLUDES})
  90. endif()
  91. if(arg_COMPILE_OPTIONS)
  92. target_compile_options(${target} PRIVATE ${arg_COMPILE_OPTIONS})
  93. endif()
  94. if(arg_LIBRARIES)
  95. target_link_libraries(${target} ${arg_LIBRARIES})
  96. endif()
  97. if(arg_TIME_COMPILE)
  98. set_property(TARGET ${target} PROPERTY RULE_LAUNCH_COMPILE
  99. "\"${PYTHON_EXECUTABLE}\" \"${CMAKE_CURRENT_SOURCE_DIR}/time_it.py\" \"${arg_TIME_COMPILE}\"")
  100. set_property(TARGET ${target} PROPERTY TIME_COMPILE "${arg_TIME_COMPILE}")
  101. endif()
  102. if(arg_TIME_LINK)
  103. set_property(TARGET ${target} PROPERTY RULE_LAUNCH_LINK
  104. "\"${PYTHON_EXECUTABLE}\" \"${CMAKE_CURRENT_SOURCE_DIR}/time_it.py\" \"${arg_TIME_LINK}\"")
  105. set_property(TARGET ${target} PROPERTY TIME_LINK "${arg_TIME_LINK}")
  106. endif()
  107. endfunction()
  108. # zf_log
  109. set(ZF_LOG_DIR "${PROJECT_SOURCE_DIR}/zf_log")
  110. add_library(zf_log_n STATIC "${ZF_LOG_DIR}/zf_log.h" "${ZF_LOG_DIR}/zf_log.c")
  111. target_include_directories(zf_log_n PUBLIC "${ZF_LOG_DIR}")
  112. add_library(zf_log_Os STATIC "${ZF_LOG_DIR}/zf_log.h" "${ZF_LOG_DIR}/zf_log.c")
  113. target_include_directories(zf_log_Os PUBLIC "${ZF_LOG_DIR}")
  114. set_property(TARGET zf_log_Os PROPERTY COMPILE_DEFINITIONS "ZF_LOG_OPTIMIZE_SIZE")
  115. # spdlog
  116. set(SPDLOG_DIR "${CMAKE_CURRENT_BINARY_DIR}/spdlog")
  117. ExternalProject_Add(spdlog_ep
  118. PREFIX "${SPDLOG_DIR}"
  119. UPDATE_COMMAND ""
  120. GIT_REPOSITORY "https://github.com/gabime/spdlog.git"
  121. GIT_TAG "e91e1b80f9c4332bcef8388ff48ee705128e5519"
  122. CMAKE_GENERATOR "${CMAKE_GENERATOR}"
  123. CMAKE_ARGS
  124. "-DCMAKE_TOOLCHAIN_FILE:filepath=${CMAKE_TOOLCHAIN_FILE}"
  125. "-DCMAKE_INSTALL_PREFIX:path=<INSTALL_DIR>"
  126. "-DCMAKE_BUILD_TYPE:string=${CMAKE_BUILD_TYPE}"
  127. "-DCMAKE_OSX_ARCHITECTURES:string=${CMAKE_OSX_ARCHITECTURES}"
  128. "-DCMAKE_OSX_DEPLOYMENT_TARGET:string=${CMAKE_OSX_DEPLOYMENT_TARGET}"
  129. "-DCMAKE_OSX_SYSROOT:path=${CMAKE_OSX_SYSROOT}"
  130. LOG_DOWNLOAD ${SILENT_3P_BUILD}
  131. LOG_UPDATE ${SILENT_3P_BUILD}
  132. LOG_CONFIGURE ${SILENT_3P_BUILD}
  133. LOG_BUILD ${SILENT_3P_BUILD}
  134. LOG_TEST ${SILENT_3P_BUILD}
  135. LOG_INSTALL ${SILENT_3P_BUILD}
  136. )
  137. add_library(spdlog INTERFACE)
  138. add_dependencies(spdlog spdlog_ep)
  139. set_target_properties(spdlog PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${SPDLOG_DIR}/include")
  140. # easyloggingpp
  141. set(EASYLOG_DIR "${CMAKE_CURRENT_BINARY_DIR}/easyloggingpp")
  142. ExternalProject_Add(easylog_ep
  143. PREFIX "${EASYLOG_DIR}"
  144. UPDATE_COMMAND ""
  145. GIT_REPOSITORY "https://github.com/easylogging/easyloggingpp.git"
  146. GIT_TAG "f926802dfbde716d82b64b8ef3c25b7f0fcfec65"
  147. CONFIGURE_COMMAND ""
  148. BUILD_COMMAND ""
  149. INSTALL_COMMAND "${CMAKE_COMMAND}" -E copy_directory
  150. "<SOURCE_DIR>/src" "<INSTALL_DIR>/include"
  151. LOG_DOWNLOAD ${SILENT_3P_BUILD}
  152. LOG_UPDATE ${SILENT_3P_BUILD}
  153. LOG_CONFIGURE ${SILENT_3P_BUILD}
  154. LOG_BUILD ${SILENT_3P_BUILD}
  155. LOG_TEST ${SILENT_3P_BUILD}
  156. LOG_INSTALL ${SILENT_3P_BUILD}
  157. )
  158. add_library(easylog INTERFACE)
  159. add_dependencies(easylog easylog_ep)
  160. set_target_properties(easylog PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${EASYLOG_DIR}/include")
  161. # g3log
  162. set(G3LOG_DIR "${CMAKE_CURRENT_BINARY_DIR}/g3log")
  163. set(G3LOG_LIBRARY "${CMAKE_STATIC_LIBRARY_PREFIX}g3logger${CMAKE_STATIC_LIBRARY_SUFFIX}")
  164. ExternalProject_Add(g3log_ep
  165. PREFIX "${G3LOG_DIR}"
  166. UPDATE_COMMAND ""
  167. GIT_REPOSITORY "https://github.com/KjellKod/g3log.git"
  168. GIT_TAG "1c6ede6db4fbb12006b61a913de737df56b9dd32"
  169. CMAKE_GENERATOR "${CMAKE_GENERATOR}"
  170. CMAKE_ARGS
  171. "-Wno-dev"
  172. "-DCMAKE_TOOLCHAIN_FILE:filepath=${CMAKE_TOOLCHAIN_FILE}"
  173. "-DCMAKE_INSTALL_PREFIX:path=<INSTALL_DIR>"
  174. "-DCMAKE_BUILD_TYPE:string=${CMAKE_BUILD_TYPE}"
  175. "-DCMAKE_OSX_ARCHITECTURES:string=${CMAKE_OSX_ARCHITECTURES}"
  176. "-DCMAKE_OSX_DEPLOYMENT_TARGET:string=${CMAKE_OSX_DEPLOYMENT_TARGET}"
  177. "-DCMAKE_OSX_SYSROOT:path=${CMAKE_OSX_SYSROOT}"
  178. "-DUSE_DYNAMIC_LOGGING_LEVELS:bool=ON"
  179. INSTALL_COMMAND "${CMAKE_COMMAND}" -E copy_directory
  180. "<SOURCE_DIR>/src/g3log" "<INSTALL_DIR>/include/g3log"
  181. COMMAND "${CMAKE_COMMAND}" -E copy_if_different
  182. "<BINARY_DIR>/${G3LOG_LIBRARY}" "<INSTALL_DIR>/lib/${G3LOG_LIBRARY}"
  183. LOG_DOWNLOAD ${SILENT_3P_BUILD}
  184. LOG_UPDATE ${SILENT_3P_BUILD}
  185. LOG_CONFIGURE ${SILENT_3P_BUILD}
  186. LOG_BUILD ${SILENT_3P_BUILD}
  187. LOG_TEST ${SILENT_3P_BUILD}
  188. LOG_INSTALL ${SILENT_3P_BUILD}
  189. )
  190. add_library(g3log INTERFACE)
  191. add_dependencies(g3log g3log_ep)
  192. set_target_properties(g3log PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${G3LOG_DIR}/include")
  193. set_target_properties(g3log PROPERTIES INTERFACE_LINK_LIBRARIES "${G3LOG_DIR}/lib/${G3LOG_LIBRARY}")
  194. # glog
  195. set(GLOG_DIR "${CMAKE_CURRENT_BINARY_DIR}/glog")
  196. set(GLOG_LIBRARY "${CMAKE_STATIC_LIBRARY_PREFIX}glog${CMAKE_STATIC_LIBRARY_SUFFIX}")
  197. ExternalProject_Add(glog_ep
  198. PREFIX "${GLOG_DIR}"
  199. UPDATE_COMMAND ""
  200. GIT_REPOSITORY "https://github.com/google/glog.git"
  201. GIT_TAG "4d391fe692ae6b9e0105f473945c415a3ce5a401"
  202. CMAKE_GENERATOR "${CMAKE_GENERATOR}"
  203. CMAKE_ARGS
  204. "-Wno-dev"
  205. "-DCMAKE_TOOLCHAIN_FILE:filepath=${CMAKE_TOOLCHAIN_FILE}"
  206. "-DCMAKE_INSTALL_PREFIX:path=<INSTALL_DIR>"
  207. "-DCMAKE_BUILD_TYPE:string=${CMAKE_BUILD_TYPE}"
  208. "-DCMAKE_OSX_ARCHITECTURES:string=${CMAKE_OSX_ARCHITECTURES}"
  209. "-DCMAKE_OSX_DEPLOYMENT_TARGET:string=${CMAKE_OSX_DEPLOYMENT_TARGET}"
  210. "-DCMAKE_OSX_SYSROOT:path=${CMAKE_OSX_SYSROOT}"
  211. LOG_DOWNLOAD ${SILENT_3P_BUILD}
  212. LOG_UPDATE ${SILENT_3P_BUILD}
  213. LOG_CONFIGURE ${SILENT_3P_BUILD}
  214. LOG_BUILD ${SILENT_3P_BUILD}
  215. LOG_TEST ${SILENT_3P_BUILD}
  216. LOG_INSTALL ${SILENT_3P_BUILD}
  217. )
  218. add_library(glog INTERFACE)
  219. add_dependencies(glog glog_ep)
  220. set_target_properties(glog PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLOG_DIR}/include")
  221. set_target_properties(glog PROPERTIES INTERFACE_LINK_LIBRARIES "${GLOG_DIR}/lib/${GLOG_LIBRARY}")
  222. function(get_test_library lib var)
  223. if((lib STREQUAL "zf_log_n") OR (lib STREQUAL "zf_log_Os"))
  224. set(lib "zf_log")
  225. endif()
  226. set(${var} "${lib}" PARENT_SCOPE)
  227. endfunction()
  228. function(get_test_compile_options lib var)
  229. set(compile_options)
  230. if(lib STREQUAL "g3log")
  231. # g3log public headers generate "braced-scalar-init" warnings
  232. set(compile_options "-Wno-braced-scalar-init")
  233. endif()
  234. set(${var} "${compile_options}" PARENT_SCOPE)
  235. endfunction()
  236. function(add_executable_size_test lib)
  237. get_test_library("${lib}" test_library)
  238. get_test_compile_options("${lib}" compile_options)
  239. add_target(test_call_site_size.str.${lib}.1 STATICLIB LIBRARIES "${lib}"
  240. COMPILE_OPTIONS ${compile_options}
  241. TIME_COMPILE "${CMAKE_CURRENT_BINARY_DIR}/compile_time.${lib}.json"
  242. SOURCES test_executable_size.cpp
  243. DEFINES "TEST_LIBRARY=${test_library}"
  244. "TEST_SEVERAL_STATEMENTS")
  245. add_target(test_call_site_size.str.${lib}.2 STATICLIB LIBRARIES "${lib}"
  246. COMPILE_OPTIONS ${compile_options}
  247. SOURCES test_executable_size.cpp
  248. DEFINES "TEST_LIBRARY=${test_library}"
  249. "TEST_SEVERAL_STATEMENTS" "TEST_EXTRA_STATEMENT")
  250. add_target(test_call_site_size.fmti.${lib}.1 STATICLIB LIBRARIES "${lib}"
  251. COMPILE_OPTIONS ${compile_options}
  252. SOURCES test_executable_size.cpp
  253. DEFINES "TEST_LIBRARY=${test_library}"
  254. "TEST_FORMAT_INTS" "TEST_SEVERAL_STATEMENTS")
  255. add_target(test_call_site_size.fmti.${lib}.2 STATICLIB LIBRARIES "${lib}"
  256. COMPILE_OPTIONS ${compile_options}
  257. SOURCES test_executable_size.cpp
  258. DEFINES "TEST_LIBRARY=${test_library}"
  259. "TEST_FORMAT_INTS" "TEST_SEVERAL_STATEMENTS" "TEST_EXTRA_STATEMENT")
  260. add_target(test_executable_size.m1.${lib} EXECUTABLE LIBRARIES "${lib}" NO_THREADS
  261. COMPILE_OPTIONS ${compile_options}
  262. TIME_LINK "${CMAKE_CURRENT_BINARY_DIR}/link_time.${lib}.json"
  263. SOURCES test_executable_size.cpp
  264. DEFINES "TEST_LIBRARY=${test_library}")
  265. list(APPEND PARAMETERS "-p" "call_site_size:str:${lib}:1:$<TARGET_FILE:test_call_site_size.str.${lib}.1>")
  266. list(APPEND PARAMETERS "-p" "call_site_size:str:${lib}:2:$<TARGET_FILE:test_call_site_size.str.${lib}.2>")
  267. list(APPEND PARAMETERS "-p" "call_site_size:fmti:${lib}:1:$<TARGET_FILE:test_call_site_size.fmti.${lib}.1>")
  268. list(APPEND PARAMETERS "-p" "call_site_size:fmti:${lib}:2:$<TARGET_FILE:test_call_site_size.fmti.${lib}.2>")
  269. list(APPEND PARAMETERS "-p" "executable_size:m1:${lib}:$<TARGET_FILE:test_executable_size.m1.${lib}>")
  270. if(LAUNCH_RULES)
  271. list(APPEND PARAMETERS "-p" "compile_time:${lib}:$<TARGET_PROPERTY:test_call_site_size.str.${lib}.1,TIME_COMPILE>")
  272. list(APPEND PARAMETERS "-p" "link_time:${lib}:$<TARGET_PROPERTY:test_executable_size.m1.${lib},TIME_LINK>")
  273. endif()
  274. set(PARAMETERS "${PARAMETERS}" PARENT_SCOPE)
  275. endfunction()
  276. if(ZF_LOG_PERF_TEST_ZF_LOG_OS)
  277. add_executable_size_test(zf_log_Os)
  278. endif()
  279. add_executable_size_test(zf_log_n)
  280. add_executable_size_test(spdlog)
  281. add_executable_size_test(easylog)
  282. add_executable_size_test(g3log)
  283. add_executable_size_test(glog)
  284. function(add_speed_test lib)
  285. get_test_library("${lib}" test_library)
  286. get_test_compile_options("${lib}" compile_options)
  287. add_target(test_speed.str.${lib} EXECUTABLE
  288. COMPILE_OPTIONS ${compile_options}
  289. SOURCES test_speed.cpp
  290. DEFINES "TEST_LIBRARY=${test_library}" "TEST_NULL_SINK"
  291. LIBRARIES "${lib}")
  292. add_target(test_speed.fmti.${lib} EXECUTABLE
  293. COMPILE_OPTIONS ${compile_options}
  294. SOURCES test_speed.cpp
  295. DEFINES "TEST_LIBRARY=${test_library}" "TEST_NULL_SINK" "TEST_FORMAT_INTS"
  296. LIBRARIES "${lib}")
  297. add_target(test_speed.str-off.${lib} EXECUTABLE
  298. COMPILE_OPTIONS ${compile_options}
  299. SOURCES test_speed.cpp
  300. DEFINES "TEST_LIBRARY=${test_library}" "TEST_NULL_SINK" "TEST_LOG_OFF"
  301. LIBRARIES "${lib}")
  302. add_target(test_speed.slowf-off.${lib} EXECUTABLE
  303. COMPILE_OPTIONS ${compile_options}
  304. SOURCES test_speed.cpp
  305. DEFINES "TEST_LIBRARY=${test_library}" "TEST_NULL_SINK" "TEST_FORMAT_SLOW_FUNC" "TEST_LOG_OFF"
  306. LIBRARIES "${lib}")
  307. list(APPEND PARAMETERS "-p" "speed:str:${lib}:$<TARGET_FILE:test_speed.str.${lib}>")
  308. list(APPEND PARAMETERS "-p" "speed:fmti:${lib}:$<TARGET_FILE:test_speed.fmti.${lib}>")
  309. list(APPEND PARAMETERS "-p" "speed:str-off:${lib}:$<TARGET_FILE:test_speed.str-off.${lib}>")
  310. list(APPEND PARAMETERS "-p" "speed:slowf-off:${lib}:$<TARGET_FILE:test_speed.slowf-off.${lib}>")
  311. set(PARAMETERS "${PARAMETERS}" PARENT_SCOPE)
  312. endfunction()
  313. if(ZF_LOG_PERF_TEST_ZF_LOG_OS)
  314. add_speed_test(zf_log_Os)
  315. endif()
  316. add_speed_test(zf_log_n)
  317. add_speed_test(spdlog)
  318. add_speed_test(easylog)
  319. add_speed_test(g3log)
  320. add_speed_test(glog)
  321. # results
  322. add_test(NAME perf_tests COMMAND "${PYTHON_EXECUTABLE}"
  323. "${CMAKE_CURRENT_SOURCE_DIR}/run_tests.py"
  324. -t "${CMAKE_CURRENT_BINARY_DIR}/results.txt"
  325. -m "${CMAKE_CURRENT_BINARY_DIR}/results.md"
  326. -b "${CMAKE_BUILD_TYPE}"
  327. -v
  328. ${PARAMETERS})