CMakeLists.txt 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #######################################
  2. # Required CMake version #
  3. #######################################
  4. cmake_minimum_required( VERSION 3.18 )
  5. #######################################
  6. # Project name #
  7. #######################################
  8. project( OpENer LANGUAGES C VERSION 2.3 )
  9. #######################################
  10. # C Settings #
  11. # #
  12. # Here you can set various C-related #
  13. # options for the project. #
  14. #######################################
  15. # Set C17 as minimum standard
  16. set(CMAKE_C_STANDARD 17)
  17. set(CMAKE_C_STANDARD_REQUIRED ON)
  18. set(CMAKE_C_EXTENSIONS OFF)
  19. # Add modern compiler warnings
  20. if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
  21. add_compile_options(
  22. -Wall
  23. -Wextra
  24. -pedantic
  25. -Wconversion
  26. -Wshadow
  27. -Wformat
  28. -Wformat-security
  29. )
  30. elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC")
  31. add_compile_options(/W4)
  32. endif()
  33. #######################################
  34. # AddressSanitizer Configuration #
  35. #######################################
  36. option(ENABLE_ADDRESS_SANITIZER "Enable AddressSanitizer for memory error detection" OFF)
  37. option(ENABLE_UNDEFINED_SANITIZER "Enable UndefinedBehaviorSanitizer" OFF)
  38. if(ENABLE_ADDRESS_SANITIZER OR ENABLE_UNDEFINED_SANITIZER)
  39. if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
  40. message(STATUS "Enabling sanitizers for security testing")
  41. set(SANITIZER_FLAGS "")
  42. if(ENABLE_ADDRESS_SANITIZER)
  43. list(APPEND SANITIZER_FLAGS "-fsanitize=address")
  44. message(STATUS " - AddressSanitizer (ASAN) enabled")
  45. endif()
  46. if(ENABLE_UNDEFINED_SANITIZER)
  47. list(APPEND SANITIZER_FLAGS "-fsanitize=undefined")
  48. message(STATUS " - UndefinedBehaviorSanitizer (UBSAN) enabled")
  49. endif()
  50. # Common sanitizer flags
  51. add_compile_options(
  52. ${SANITIZER_FLAGS}
  53. -fno-omit-frame-pointer
  54. -g
  55. )
  56. add_link_options(${SANITIZER_FLAGS})
  57. # For memory leak detection in ASAN
  58. set(ENV{ASAN_OPTIONS} "detect_leaks=1:halt_on_error=1")
  59. set(ENV{UBSAN_OPTIONS} "print_stacktrace=1:halt_on_error=1")
  60. else()
  61. message(WARNING "Sanitizers requested but compiler is not GNU or Clang")
  62. endif()
  63. endif()
  64. #######################################
  65. # Project version #
  66. #######################################
  67. if( NOT DEFINED OpENer_Device_Config_Vendor_Id )
  68. set( OpENer_Device_Config_Vendor_Id 1 CACHE STRING "Device Vendor ID" )
  69. endif()
  70. if( NOT DEFINED OpENer_Device_Config_Device_Type )
  71. set( OpENer_Device_Config_Device_Type 12 CACHE STRING "Device Type ID" )
  72. endif()
  73. if( NOT DEFINED OpENer_Device_Config_Product_Code )
  74. set( OpENer_Device_Config_Product_Code 65001 CACHE STRING "Device Product Code" )
  75. endif()
  76. if( NOT DEFINED OpENer_Device_Config_Device_Name )
  77. set( OpENer_Device_Config_Device_Name "OpENer PC" CACHE STRING "Device Name" )
  78. endif()
  79. if(NOT DEFINED OpENer_Device_Major_Version)
  80. set(OpENer_Device_Major_Version ${PROJECT_VERSION_MAJOR} CACHE STRING "Major Version")
  81. endif()
  82. if(NOT DEFINED OpENer_Device_Minor_Version)
  83. set(OpENer_Device_Minor_Version ${PROJECT_VERSION_MINOR} CACHE STRING "Minor Version")
  84. endif()
  85. configure_file(
  86. "${PROJECT_SOURCE_DIR}/src/ports/devicedata.h.in"
  87. "${PROJECT_BINARY_DIR}/src/ports/devicedata.h"
  88. )
  89. find_path( OpENer_BUILDSUPPORT_DIR OpENer.cmake ${PROJECT_SOURCE_DIR}/buildsupport )
  90. INCLUDE( ${OpENer_BUILDSUPPORT_DIR}/OpENer.cmake )
  91. option(OPENER_RANDOMIZE_CONNECTION_ID "Use randomized connection IDs also for lower 16-bits?" FALSE)
  92. option(OPENER_PRODUCED_DATA_HAS_RUN_IDLE_HEADER "Shall produced data from OpENer also include a run idle header?" FALSE)
  93. option(OPENER_CONSUMED_DATA_HAS_RUN_IDLE_HEADER "Will consumed data from OpENer also include a run idle header?" TRUE)
  94. option(OPENER_INSTALL_AS_LIB "Build and install OpENer as a library" FALSE)
  95. option(BUILD_SHARED_LIBS "Build OpENer as shared library" FALSE)
  96. if(OPENER_RANDOMIZE_CONNECTION_ID)
  97. add_definitions(-DOPENER_RANDOMIZE_CONNECTION_ID)
  98. endif()
  99. if(OPENER_PRODUCED_DATA_HAS_RUN_IDLE_HEADER)
  100. add_definitions(-DOPENER_PRODUCED_DATA_HAS_RUN_IDLE_HEADER)
  101. endif()
  102. if(OPENER_CONSUMED_DATA_HAS_RUN_IDLE_HEADER)
  103. add_definitions(-DOPENER_CONSUMED_DATA_HAS_RUN_IDLE_HEADER)
  104. endif()
  105. option(OPENER_IS_DLR_DEVICE "Is OpENer built with support for a basic DLR device?" FALSE)
  106. if (OPENER_IS_DLR_DEVICE)
  107. add_definitions(-DOPENER_IS_DLR_DEVICE)
  108. endif()
  109. # This buffer size will be used for any received message.
  110. # The same buffer is used for the replied explicit message.
  111. # There are two uses in OpENer:
  112. # 1. Explicit messages will use this buffer to store the data generated by the request
  113. # 2. I/O Connections will use this buffer for the produced data
  114. set( OPENER_ETHERNET_BUFFER_SIZE "512" CACHE STRING "Number of bytes used for the Ethernet message buffer")
  115. add_definitions(-DPC_OPENER_ETHERNET_BUFFER_SIZE=${OPENER_ETHERNET_BUFFER_SIZE} )
  116. #######################################
  117. # Platform switches #
  118. #######################################
  119. set( OpENer_KNOWN_PLATFORMS "POSIX" "WIN32" "MINGW")
  120. set( OpENer_PLATFORM CACHE STRING "Platform OpENer will be built for" )
  121. set_property(CACHE OpENer_PLATFORM PROPERTY STRINGS ${OpENer_KNOWN_PLATFORMS} )
  122. #######################################
  123. # Platform-dependent functions check #
  124. #######################################
  125. INCLUDE( ${OpENer_BUILDSUPPORT_DIR}/OpENer_function_checks.cmake )
  126. #######################################
  127. # OpENer tracer switches #
  128. #######################################
  129. set( OpENer_TRACES OFF CACHE BOOL "Activate OpENer traces" )
  130. if(OpENer_TRACES)
  131. createTraceLevelOptions()
  132. endif(OpENer_TRACES)
  133. #######################################
  134. # OpENer documentation target "doc" #
  135. #######################################
  136. # check if Doxygen is installed
  137. find_package(Doxygen)
  138. if (DOXYGEN_FOUND)
  139. # set input and output files
  140. set(DOXYGEN_IN ${OpENer_SOURCE_DIR}/opener.doxyfile.in)
  141. set(DOXYGEN_OUT ${OpENer_BINARY_DIR}/opener.doxyfile)
  142. # exclude subdirectories of non active platforms depending on OpENer_PLATFORM
  143. set(OpENer_EXCLUDE_PATTERNS "")
  144. if (NOT OpENer_PLATFORM STREQUAL "POSIX")
  145. set(OpENer_EXCLUDE_PATTERNS "${OpENer_EXCLUDE_PATTERNS} */src/ports/POSIX/*")
  146. endif ()
  147. if (NOT OpENer_PLATFORM STREQUAL "WIN32")
  148. set(OpENer_EXCLUDE_PATTERNS "${OpENer_EXCLUDE_PATTERNS} */src/ports/WIN32/*")
  149. endif ()
  150. if (NOT OpENer_PLATFORM STREQUAL "MINGW")
  151. set(OpENer_EXCLUDE_PATTERNS "${OpENer_EXCLUDE_PATTERNS} */src/ports/MINGW/*")
  152. endif ()
  153. # request to configure the file
  154. configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
  155. # note the option ALL which will build the docs always with the default target
  156. add_custom_target( doc # ALL
  157. COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
  158. WORKING_DIRECTORY ${OpENer_SOURCE_DIR}
  159. COMMENT "Generating API documentation with Doxygen"
  160. VERBATIM )
  161. message("-- Doxygen setup done")
  162. else (DOXYGEN_FOUND)
  163. message("Doxygen needs to be installed to generate the Doxygen documentation")
  164. endif (DOXYGEN_FOUND)
  165. #######################################
  166. # Test switch #
  167. #######################################
  168. set( OpENer_TESTS OFF CACHE BOOL "Enable tests to be built" )
  169. if( OpENer_TESTS )
  170. enable_testing()
  171. enable_language( CXX )
  172. set( CPPUTEST_HOME "" CACHE PATH "Path to CppUTest directory" )
  173. INCLUDE( ${OpENer_BUILDSUPPORT_DIR}/OpENer_Tests.cmake )
  174. INCLUDE( ${OpENer_BUILDSUPPORT_DIR}/CodeCoverage.cmake )
  175. APPEND_COVERAGE_COMPILER_FLAGS()
  176. # The used CppUTest framework does not support parallel jobs
  177. SETUP_TARGET_FOR_COVERAGE_LCOV(NAME ${PROJECT_NAME}_coverage EXECUTABLE OpENer_Tests EXCLUDE "tests/*" "src/ports/*/sample_application/*" "${CPPUTEST_HOME}/*")
  178. add_test_includes()
  179. add_definitions( -DOPENER_UNIT_TEST )
  180. add_subdirectory( tests )
  181. endif( OpENer_TESTS )
  182. #######################################
  183. # OpENer C flags #
  184. #######################################
  185. if (OpENer_PLATFORM STREQUAL "WIN32")
  186. set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W4" )
  187. else ()
  188. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wconversion")
  189. endif ()
  190. ####################################################
  191. # Internal cache holding the available CIP objects #
  192. ####################################################
  193. # Add definitions for additional CIP Objects
  194. string(COMPARE NOTEQUAL "${OpENer_ADD_CIP_OBJECTS}" "" OpENer_HAS_ADDITIONAL_OBJECT)
  195. if (OpENer_HAS_ADDITIONAL_OBJECT)
  196. string(REPLACE " " ";" OpENer_ADD_CIP_OBJECTS_LIST ${OpENer_ADD_CIP_OBJECTS})
  197. foreach (CIP_OBJECT IN LISTS OpENer_ADD_CIP_OBJECTS_LIST)
  198. add_definitions(-D${CIP_OBJECT})
  199. endforeach ()
  200. endif ()
  201. set( OpENer_ADD_CIP_OBJECTS "" CACHE INTERNAL STRING )
  202. set( OpENer_ADD_CIP_OBJECTS_INCLUDES "" CACHE INTERNAL STRING )
  203. #######################################
  204. # Add custom CIP objects #
  205. #######################################
  206. set( OpENer_CIP_OBJECTS_DIR ${PROJECT_SOURCE_DIR}/src/cip_objects )
  207. include(${OpENer_BUILDSUPPORT_DIR}/OpENer_CIP_Object_generator.cmake)
  208. # ######################################
  209. # Add subdirectories #
  210. # ######################################
  211. add_subdirectory( src )