OpENer.cmake 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. FUNCTION(opener_add_definition)
  2. FOREACH(ARG ${ARGV})
  3. set_property(GLOBAL APPEND PROPERTY OPENER_DEFINITION ${ARG})
  4. ENDFOREACH(ARG)
  5. ENDFUNCTION(opener_add_definition)
  6. ##############################################
  7. # Adds platform specific include directories #
  8. ##############################################
  9. macro(opener_platform_support ARGS)
  10. if(OpENer_PLATFORM STREQUAL "")
  11. message(FATAL_ERROR "No platform selected!")
  12. endif(OpENer_PLATFORM STREQUAL "")
  13. include( ${OpENer_BUILDSUPPORT_DIR}/${OpENer_PLATFORM}/OpENer_PLATFORM_INCLUDES.cmake)
  14. opener_platform_spec()
  15. endmacro(opener_platform_support ARGS)
  16. #######################################
  17. # Adds common Include directories #
  18. #######################################
  19. macro(opener_common_includes)
  20. set( SRC_DIR "${OpENer_SOURCE_DIR}/src" )
  21. set( API_SRC_DIR "${SRC_DIR}/api" )
  22. set( CORE_SRC_DIR "${SRC_DIR}/core" )
  23. set( CIP_SRC_DIR "${SRC_DIR}/cip" )
  24. set( ENET_ENCAP_SRC_DIR "${SRC_DIR}/enet_encap" )
  25. set( PORTS_SRC_DIR "${SRC_DIR}/ports")
  26. set( NVDATA_SRC_DIR "${SRC_DIR}/ports/nvdata")
  27. set( UTILS_SRC_DIR "${SRC_DIR}/utils")
  28. include_directories( ${PROJECT_SOURCE_DIR} ${SRC_DIR} ${API_SRC_DIR} ${CORE_SRC_DIR} ${CIP_SRC_DIR} ${CIP_CONNETION_MANAGER_SRC_DIR} ${ENET_ENCAP_SRC_DIR} ${PORTS_SRC_DIR} ${UTILS_SRC_DIR} ${OpENer_CIP_OBJECTS_DIR} ${NVDATA_SRC_DIR} )
  29. include_directories( "${PROJECT_BINARY_DIR}/src/ports" )
  30. endmacro(opener_common_includes)
  31. MACRO(opener_add_cip_object NAME DESCRIPTION)
  32. set(OpENer_CIP_OBJECT_${NAME} OFF CACHE BOOL "${DESCRIPTION}")
  33. FOREACH(dependencies ${ARGN})
  34. if(NOT ${dependencies})
  35. return()
  36. endif(NOT ${dependencies})
  37. ENDFOREACH(dependencies)
  38. if(NOT OpENer_CIP_OBJECT_${NAME})
  39. return()
  40. endif(NOT OpENer_CIP_OBJECT_${NAME})
  41. ENDMACRO(opener_add_cip_object)
  42. #######################################
  43. # Creates options for trace level #
  44. #######################################
  45. macro(createTraceLevelOptions)
  46. add_definitions( -DOPENER_WITH_TRACES )
  47. set( TRACE_LEVEL 0 )
  48. set( OpENer_TRACE_LEVEL_ERROR ON CACHE BOOL "Error trace level" )
  49. set( OpENer_TRACE_LEVEL_WARNING ON CACHE BOOL "Warning trace level" )
  50. set( OpENer_TRACE_LEVEL_STATE ON CACHE BOOL "State trace level" )
  51. set( OpENer_TRACE_LEVEL_INFO ON CACHE BOOL "Info trace level" )
  52. if(OpENer_TRACE_LEVEL_ERROR)
  53. math( EXPR TRACE_LEVEL "${TRACE_LEVEL} + 1" )
  54. endif(OpENer_TRACE_LEVEL_ERROR)
  55. if(OpENer_TRACE_LEVEL_WARNING)
  56. math( EXPR TRACE_LEVEL "${TRACE_LEVEL} + 2" )
  57. endif(OpENer_TRACE_LEVEL_WARNING)
  58. if(OpENer_TRACE_LEVEL_STATE)
  59. math( EXPR TRACE_LEVEL "${TRACE_LEVEL} + 4" )
  60. endif(OpENer_TRACE_LEVEL_STATE)
  61. if(OpENer_TRACE_LEVEL_INFO)
  62. math( EXPR TRACE_LEVEL "${TRACE_LEVEL} + 8" )
  63. endif(OpENer_TRACE_LEVEL_INFO)
  64. add_definitions(-DOPENER_TRACE_LEVEL=${TRACE_LEVEL})
  65. endmacro(createTraceLevelOptions)
  66. #######################################
  67. # Build hardening, sanitizers, coverage
  68. #######################################
  69. # Easy toggles for sanitizers, hardening, coverage and warnings
  70. option(OpENer_ENABLE_ASAN "Enable AddressSanitizer" OFF)
  71. option(OpENer_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer" OFF)
  72. option(OpENer_ENABLE_TSAN "Enable ThreadSanitizer" OFF)
  73. option(OpENer_ENABLE_MSAN "Enable MemorySanitizer (Clang only)" OFF)
  74. option(OpENer_ENABLE_LSAN "Enable LeakSanitizer" OFF)
  75. option(OpENer_ENABLE_COVERAGE "Enable code coverage flags" OFF)
  76. option(OpENer_ENABLE_HARDENING "Enable hardening flags (FORTIFY, PIE, RELRO, stack protector)" OFF)
  77. option(OpENer_ENABLE_STRICT_WARNINGS "Enable comprehensive warnings" OFF)
  78. function(opener_apply_build_options)
  79. # Compose sanitizer list
  80. set(_sanitizers "")
  81. if(OpENer_ENABLE_ASAN)
  82. list(APPEND _sanitizers address)
  83. endif()
  84. if(OpENer_ENABLE_UBSAN)
  85. list(APPEND _sanitizers undefined)
  86. endif()
  87. if(OpENer_ENABLE_TSAN)
  88. list(APPEND _sanitizers thread)
  89. endif()
  90. if(OpENer_ENABLE_MSAN)
  91. list(APPEND _sanitizers memory)
  92. endif()
  93. if(OpENer_ENABLE_LSAN)
  94. list(APPEND _sanitizers leak)
  95. endif()
  96. if(_sanitizers)
  97. string(REPLACE ";" "," _sanitizer_string "${_sanitizers}")
  98. # Apply to compile and link flags only for enabled languages
  99. foreach(lang C CXX)
  100. # Skip languages that haven't been enabled
  101. if(NOT DEFINED CMAKE_${lang}_COMPILER_ID)
  102. continue()
  103. endif()
  104. if(CMAKE_${lang}_COMPILER_ID MATCHES "Clang" OR CMAKE_${lang}_COMPILER_ID MATCHES "GNU")
  105. set(var_cflags "${CMAKE_${lang}_FLAGS}")
  106. set(var_cflags "${var_cflags} -fsanitize=${_sanitizer_string} -fno-omit-frame-pointer")
  107. set(CMAKE_${lang}_FLAGS "${var_cflags}")
  108. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=${_sanitizer_string}")
  109. else()
  110. message(WARNING "Sanitizers requested but unsupported compiler: ${CMAKE_${lang}_COMPILER_ID}")
  111. endif()
  112. endforeach()
  113. # UBSan: add recover behavior to aid debugging if only UBSan requested
  114. if(OpENer_ENABLE_UBSAN)
  115. add_compile_options(-fno-sanitize-recover=undefined)
  116. endif()
  117. endif()
  118. if(OpENer_ENABLE_COVERAGE)
  119. if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "")
  120. message(STATUS "Enabling code coverage flags")
  121. foreach(lang C CXX)
  122. set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -g -O0 --coverage")
  123. endforeach()
  124. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
  125. else()
  126. message(WARNING "Coverage requested but build type is not Debug; consider using -DCMAKE_BUILD_TYPE=Debug")
  127. endif()
  128. endif()
  129. if(OpENer_ENABLE_HARDENING)
  130. message(STATUS "Enabling hardening/fortify flags")
  131. add_compile_options(-fstack-protector-strong -D_FORTIFY_SOURCE=2)
  132. # PIE and RELRO
  133. add_compile_options(-fPIE)
  134. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now -pie")
  135. endif()
  136. if(OpENer_ENABLE_STRICT_WARNINGS)
  137. message(STATUS "Enabling strict warning flags")
  138. add_compile_options(-Wall -Wextra -Wpedantic -Wconversion -Wshadow -Wdouble-promotion -Wformat=2)
  139. endif()
  140. endfunction(opener_apply_build_options)
  141. ## If this is a Debug or CI/Test build, enable a sensible default set of
  142. ## sanitizers, coverage, hardening and strict warnings to make CI runs
  143. ## more effective. This will apply when the build type is Debug, tests are
  144. ## enabled (OpENer_TESTS) or the CI environment variable is present. These
  145. ## cache variables are forced here so CI scripts that don't pass flags still
  146. ## get the helpful defaults.
  147. if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR OpENer_TESTS OR DEFINED ENV{CI})
  148. message(STATUS "CI/Debug/Test detected: enabling sanitizer/coverage/hardening defaults")
  149. set(OpENer_ENABLE_ASAN ON CACHE BOOL "Enable AddressSanitizer" FORCE)
  150. set(OpENer_ENABLE_UBSAN ON CACHE BOOL "Enable UndefinedBehaviorSanitizer" FORCE)
  151. set(OpENer_ENABLE_LSAN ON CACHE BOOL "Enable LeakSanitizer" FORCE)
  152. set(OpENer_ENABLE_COVERAGE ON CACHE BOOL "Enable code coverage flags" FORCE)
  153. set(OpENer_ENABLE_HARDENING ON CACHE BOOL "Enable hardening flags (FORTIFY, PIE, RELRO, stack protector)" FORCE)
  154. set(OpENer_ENABLE_STRICT_WARNINGS ON CACHE BOOL "Enable comprehensive warnings" FORCE)
  155. # MSAN and TSAN remain opt-in only due to toolchain/runtime requirements
  156. endif()
  157. # Apply options immediately so callers don't need to remember to invoke the function
  158. opener_apply_build_options()