CMakeLists.txt 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. cmake_minimum_required(VERSION 3.2)
  2. include(CMakeParseArguments)
  3. set(CMAKE_C_STANDARD 99)
  4. set(CMAKE_C_STANDARD_REQUIRED ON)
  5. set(CMAKE_C_EXTENSIONS OFF)
  6. if(MSVC)
  7. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /WX")
  8. else()
  9. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror -pedantic-errors")
  10. endif()
  11. # zf_test
  12. set(HEADERS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
  13. add_library(zf_test INTERFACE)
  14. target_include_directories(zf_test INTERFACE $<BUILD_INTERFACE:${HEADERS_DIR}>)
  15. set(HEADERS zf_test.h)
  16. add_custom_target(zf_test_headers SOURCES ${HEADERS})
  17. function(add_test_target target)
  18. cmake_parse_arguments(arg
  19. "COMPILE_ONLY"
  20. ""
  21. "SOURCES;CSTD;CXXSTD;DEFINES"
  22. ${ARGN})
  23. if(arg_COMPILE_ONLY)
  24. add_library(${target} STATIC ${arg_SOURCES})
  25. else()
  26. add_executable(${target} ${arg_SOURCES})
  27. target_link_libraries(${target} zf_test)
  28. add_test(NAME ${target} COMMAND ${target})
  29. endif()
  30. if(arg_CSTD)
  31. set_property(TARGET ${target} PROPERTY C_STANDARD "${arg_CSTD}")
  32. endif()
  33. if(arg_CXXSTD)
  34. set_property(TARGET ${target} PROPERTY CXX_STANDARD "${arg_CXXSTD}")
  35. endif()
  36. set_property(TARGET ${target} PROPERTY COMPILE_DEFINITIONS "${arg_DEFINES}")
  37. target_include_directories(${target} PRIVATE "${PROJECT_SOURCE_DIR}/zf_log")
  38. endfunction()
  39. function(add_test_target_group target)
  40. add_test_target(${target}_c99 ${ARGN} CSTD 99)
  41. add_test_target(${target}_c11 ${ARGN} CSTD 11)
  42. endfunction()
  43. add_test_target_group(test_log_level_switches_verbose SOURCES test_log_level_switches.c DEFINES ZF_LOG_LEVEL=ZF_LOG_VERBOSE)
  44. add_test_target_group(test_log_level_switches_debug SOURCES test_log_level_switches.c DEFINES ZF_LOG_LEVEL=ZF_LOG_DEBUG)
  45. add_test_target_group(test_log_level_switches_info SOURCES test_log_level_switches.c DEFINES ZF_LOG_LEVEL=ZF_LOG_INFO)
  46. add_test_target_group(test_log_level_switches_warn SOURCES test_log_level_switches.c DEFINES ZF_LOG_LEVEL=ZF_LOG_WARN)
  47. add_test_target_group(test_log_level_switches_error SOURCES test_log_level_switches.c DEFINES ZF_LOG_LEVEL=ZF_LOG_ERROR)
  48. add_test_target_group(test_log_level_switches_fatal SOURCES test_log_level_switches.c DEFINES ZF_LOG_LEVEL=ZF_LOG_FATAL)
  49. add_test_target_group(test_log_level_switches_none SOURCES test_log_level_switches.c DEFINES ZF_LOG_LEVEL=ZF_LOG_NONE)
  50. add_test_target_group(test_log_level_override SOURCES test_log_level_override.c)
  51. add_test_target_group(test_log_message_content SOURCES test_log_message_content.c)
  52. add_test_target_group(test_log_message_content_Os SOURCES test_log_message_content.c DEFINES ZF_LOG_OPTIMIZE_SIZE=1)
  53. add_test_target_group(test_log_message_content_empty_format SOURCES test_log_message_content.c DEFINES
  54. "ZF_LOG_MESSAGE_CTX_FORMAT=()"
  55. "ZF_LOG_MESSAGE_TAG_FORMAT=()"
  56. "ZF_LOG_MESSAGE_SRC_FORMAT=()")
  57. add_test_target_group(test_log_message_content_empty_format_Os SOURCES test_log_message_content.c DEFINES
  58. "ZF_LOG_OPTIMIZE_SIZE=1"
  59. "ZF_LOG_MESSAGE_CTX_FORMAT=()"
  60. "ZF_LOG_MESSAGE_TAG_FORMAT=()"
  61. "ZF_LOG_MESSAGE_SRC_FORMAT=()")
  62. # Here we use several F_INIT() fields in a row to workaround CMake problem with ";", which acts
  63. # as a list separator in CMake. If not for CMake, context format specification could look like:
  64. # #define ZF_LOG_MESSAGE_CTX_FORMAT \
  65. # (YEAR, S("-ctx:"), F_INIT(( struct { int v; } f_box_a; f_box_a.v = 45; )), F_UINT(4, f_box_a.v))
  66. add_test_target_group(test_log_message_content_custom_fields SOURCES test_log_message_content.c DEFINES
  67. "ZF_LOG_MESSAGE_CTX_FORMAT=(YEAR, S(\"-ctx:\"), F_INIT(( struct { int v )), F_INIT(( } f_box_a )), F_INIT(( f_box_a.v = 45 )), F_UINT(4, f_box_a.v))"
  68. "ZF_LOG_MESSAGE_TAG_FORMAT=(S(\"-tag:\"), F_INIT(( struct { int v )), F_INIT(( } f_box_b )), F_INIT(( f_box_b.v = 36 )), F_UINT(4, f_box_b.v))"
  69. "ZF_LOG_MESSAGE_SRC_FORMAT=(S(\"-src:\"), F_INIT(( struct { int v )), F_INIT(( } f_box_c )), F_INIT(( f_box_c.v = 27 )), F_UINT(4, f_box_c.v))")
  70. add_test_target_group(test_log_message_content_custom_fields_Os SOURCES test_log_message_content.c DEFINES
  71. "ZF_LOG_OPTIMIZE_SIZE=1"
  72. "ZF_LOG_MESSAGE_CTX_FORMAT=(YEAR, S(\"ctx:\"), F_INIT(( struct { int v )), F_INIT(( } f_box_a )), F_INIT(( f_box_a.v = 45 )), F_UINT(4, f_box_a.v))"
  73. "ZF_LOG_MESSAGE_TAG_FORMAT=(S(\"tag:\"), F_INIT(( struct { int v )), F_INIT(( } f_box_b )), F_INIT(( f_box_b.v = 36 )), F_UINT(4, f_box_b.v))"
  74. "ZF_LOG_MESSAGE_SRC_FORMAT=(S(\"src:\"), F_INIT(( struct { int v )), F_INIT(( } f_box_c )), F_INIT(( f_box_c.v = 27 )), F_UINT(4, f_box_c.v))")
  75. add_test_target_group(test_source_location_none SOURCES test_source_location.c
  76. DEFINES ZF_LOG_SRCLOC=ZF_LOG_SRCLOC_NONE TEST_SRCLOC=ZF_LOG_SRCLOC_NONE)
  77. add_test_target_group(test_source_location_short SOURCES test_source_location.c
  78. DEFINES ZF_LOG_SRCLOC=ZF_LOG_SRCLOC_SHORT TEST_SRCLOC=ZF_LOG_SRCLOC_SHORT)
  79. add_test_target_group(test_source_location_long SOURCES test_source_location.c
  80. DEFINES ZF_LOG_SRCLOC=ZF_LOG_SRCLOC_LONG TEST_SRCLOC=ZF_LOG_SRCLOC_LONG)
  81. add_test_target_group(test_source_location_none_Os SOURCES test_source_location.c
  82. DEFINES ZF_LOG_SRCLOC=ZF_LOG_SRCLOC_NONE TEST_SRCLOC=ZF_LOG_SRCLOC_NONE ZF_LOG_OPTIMIZE_SIZE=1)
  83. add_test_target_group(test_source_location_short_Os SOURCES test_source_location.c
  84. DEFINES ZF_LOG_SRCLOC=ZF_LOG_SRCLOC_SHORT TEST_SRCLOC=ZF_LOG_SRCLOC_SHORT ZF_LOG_OPTIMIZE_SIZE=1)
  85. add_test_target_group(test_source_location_long_Os SOURCES test_source_location.c
  86. DEFINES ZF_LOG_SRCLOC=ZF_LOG_SRCLOC_LONG TEST_SRCLOC=ZF_LOG_SRCLOC_LONG ZF_LOG_OPTIMIZE_SIZE=1)
  87. add_test_target_group(test_conditional SOURCES test_conditional.c)
  88. add_test_target_group(test_censoring_off SOURCES test_censoring.c DEFINES ZF_LOG_CENSORING=ZF_LOG_UNCENSORED TEST_LOG_SECRETS=1)
  89. add_test_target_group(test_censoring_on SOURCES test_censoring.c DEFINES ZF_LOG_CENSORING=ZF_LOG_CENSORED TEST_LOG_SECRETS=0)
  90. add_test_target_group(test_private_parts SOURCES test_private_parts.c)
  91. add_test_target_group(test_decoration SOURCES test_decoration.module.c test_decoration.main.c)
  92. add_test_target_group(test_aux_spec SOURCES test_aux_spec.c)
  93. add_test_target_group(test_builtin_output_facilities SOURCES test_builtin_output_facilities.c COMPILE_ONLY)
  94. add_test_target_group(test_externally_defined_state SOURCES test_externally_defined_state.c)
  95. add_test_target(test_externally_defined_state_cpp SOURCES test_externally_defined_state_cpp.cpp CXXSTD 11)
  96. add_test_target(test_compilation_cpp SOURCES test_compilation_cpp.cpp CXXSTD 11)
  97. # generated code size tests
  98. add_executable(filesize_check filesize_check.c)
  99. set(CODE_SIZE_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/code_size_tests")
  100. function(save_preprocessor_output target)
  101. if(MSVC)
  102. # MSVC lacks this feature, /P suppresses compilation.
  103. #target_compile_options(${target} PRIVATE "/P")
  104. else()
  105. target_compile_options(${target} PRIVATE "-save-temps")
  106. endif()
  107. endfunction()
  108. function(add_copy_command src dst)
  109. add_custom_command(OUTPUT "${dst}"
  110. COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${src}" "${dst}"
  111. DEPENDS "${src}")
  112. set_source_files_properties("${dst}" PROPERTIES GENERATED TRUE)
  113. endfunction()
  114. # copy reference and current versions of zf_log.h
  115. add_copy_command("${CMAKE_CURRENT_SOURCE_DIR}/zf_log.h.master" "${CODE_SIZE_SOURCE_DIR}/prev/zf_log.h")
  116. add_copy_command("${PROJECT_SOURCE_DIR}/zf_log/zf_log.h" "${CODE_SIZE_SOURCE_DIR}/curr/zf_log.h")
  117. function(add_code_size_test target)
  118. cmake_parse_arguments(arg
  119. ""
  120. ""
  121. "SOURCES;DEFINES"
  122. ${ARGN})
  123. set(prev_sources "${CODE_SIZE_SOURCE_DIR}/prev/zf_log.h")
  124. set(curr_sources "${CODE_SIZE_SOURCE_DIR}/curr/zf_log.h")
  125. foreach(src ${arg_SOURCES})
  126. # "-save-temps" will put all ".s" files directly in the "tests" build
  127. # directory which is not specific for the target. Since it's useful to
  128. # examine those files, test sources will be copied with different
  129. # names for *-prev and *-curr targets. That way generated "*.s" files
  130. # will have different names too and will not overwrite each other.
  131. get_filename_component(src_name "${src}" NAME_WE)
  132. get_filename_component(src_ext "${src}" EXT)
  133. get_filename_component(src_path "${src}" ABSOLUTE)
  134. set(src_copy_prev "${CODE_SIZE_SOURCE_DIR}/${target}-${src_name}-prev${src_ext}")
  135. set(src_copy_curr "${CODE_SIZE_SOURCE_DIR}/${target}-${src_name}-curr${src_ext}")
  136. add_copy_command("${src_path}" "${src_copy_prev}")
  137. add_copy_command("${src_path}" "${src_copy_curr}")
  138. list(APPEND prev_sources "${src_copy_prev}")
  139. list(APPEND curr_sources "${src_copy_curr}")
  140. endforeach()
  141. # prev library
  142. add_library(${target}-prev STATIC ${prev_sources})
  143. target_include_directories(${target}-prev PRIVATE "${CODE_SIZE_SOURCE_DIR}/prev")
  144. target_compile_definitions(${target}-prev PRIVATE ${arg_DEFINES})
  145. save_preprocessor_output(${target}-prev)
  146. # curr library
  147. add_library(${target}-curr STATIC ${curr_sources})
  148. target_include_directories(${target}-curr PRIVATE "${CODE_SIZE_SOURCE_DIR}/curr")
  149. target_compile_definitions(${target}-curr PRIVATE ${arg_DEFINES})
  150. save_preprocessor_output(${target}-curr)
  151. # test case
  152. add_dependencies(filesize_check ${target}-prev ${target}-curr)
  153. add_test(NAME ${target}_check
  154. COMMAND filesize_check "$<TARGET_FILE:${target}-prev>" "$<TARGET_FILE:${target}-curr>")
  155. endfunction()
  156. add_code_size_test(test_call_site_size_msg_only SOURCES test_call_site_size_msg_only.c)
  157. add_code_size_test(test_call_site_size_fmt_args SOURCES test_call_site_size_fmt_args.c)
  158. add_code_size_test(test_call_site_size_conditional_true SOURCES test_call_site_size_conditional.c DEFINES TEST_CONDITION=1)
  159. add_code_size_test(test_call_site_size_conditional_false SOURCES test_call_site_size_conditional.c DEFINES TEST_CONDITION=0)
  160. add_code_size_test(test_call_site_size_censoring_on SOURCES test_call_site_size_censoring.c DEFINES ZF_LOG_CENSORING=ZF_LOG_CENSORED)
  161. add_code_size_test(test_call_site_size_censoring_off SOURCES test_call_site_size_censoring.c DEFINES ZF_LOG_CENSORING=ZF_LOG_UNCENSORED)