# CMakeLists.txt for mbpoll - ModBus Master Simulator # Originally generated by CodeLite IDE, modernized for CMake 3.13+ cmake_minimum_required(VERSION 3.13) project(mbpoll VERSION 1.5.3 DESCRIPTION "ModBus Master Simulator" LANGUAGES C) # Standard install directories (man, bin, lib, etc.) include(GNUInstallDirs) # Export compile commands for IDE support set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Set default build type if not specified if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Release' as none was specified.") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo" "MinSizeRel") endif() # Set output directories set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) # Option for custom RTS GPIO support set(MBPOLL_CUSTOM_RTS_GPIO ON CACHE BOOL "Enable custom RTS GPIO (if libpiduino found, only on ARM)") # Check for system getopt (use bundled version on Windows) include(CheckSymbolExists) set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) check_symbol_exists(getopt "getopt.h" HAVE_GETOPT) if(NOT HAVE_GETOPT) set(GETOPT_SOURCES ${CMAKE_SOURCE_DIR}/3rdparty/getopt/getopt.c) set(GETOPT_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/getopt) # Disable pedantic warnings for 3rdparty getopt (uses deprecated 'register' keyword) if(NOT MSVC) set_source_files_properties(${GETOPT_SOURCES} PROPERTIES COMPILE_FLAGS "-Wno-pedantic") endif() endif() # Append cmake/ to module path list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Find dependencies if(WIN32) # On Windows, build libmodbus from bundled sources (no pkg-config needed) set(LIBMODBUS_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libmodbus/src ${CMAKE_SOURCE_DIR}/libmodbus/src/win32) file(GLOB_RECURSE LIBMODBUS_SRCS RELATIVE ${CMAKE_SOURCE_DIR} "libmodbus/src/*.c") find_program(CSCRIPT_PATH NAMES cscript REQUIRED) else() # On Unix, use system libmodbus via pkg-config # Note: 3.1.7+ required for quirks support (-Q/-X options) find_package(PkgConfig REQUIRED) pkg_check_modules(LIBMODBUS REQUIRED libmodbus>=3.1.7) endif() # Search for piduino (optional, for GPIO-based RS-485 RTS control) find_package(PIDUINO QUIET) if(PIDUINO_FOUND AND PIDUINO_WITH_GPIO AND MBPOLL_CUSTOM_RTS_GPIO) message(STATUS "PiDuino ${PIDUINO_VERSION} found - enabling GPIO RTS support") set(MBPOLL_GPIO_RTS ON) set(PROGRAM_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID) else() if(MBPOLL_CUSTOM_RTS_GPIO AND NOT PIDUINO_FOUND) message(STATUS "PiDuino not found - GPIO RTS support disabled") endif() set(MBPOLL_GPIO_RTS OFF) set(PROGRAM_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif() # Get version from git tags include(GitVersion) GetGitVersion(MBPOLL_VERSION) WriteGitVersionFile(${CMAKE_CURRENT_BINARY_DIR}/version-git.h) set(MBPOLL_VERSION_STRING ${MBPOLL_VERSION_MAJOR}.${MBPOLL_VERSION_MINOR}.${MBPOLL_VERSION_PATCH}) # Define source files set(MBPOLL_SOURCES ${CMAKE_SOURCE_DIR}/src/mbpoll.c ${CMAKE_SOURCE_DIR}/src/custom-rts.c ${CMAKE_SOURCE_DIR}/src/serial.c ${CMAKE_SOURCE_DIR}/src/chipio.c ${CMAKE_SOURCE_DIR}/src/utils.c ${LIBMODBUS_SRCS} ${GETOPT_SOURCES}) # Windows resource file if(WIN32) enable_language(RC) set(CMAKE_RC_COMPILE_OBJECT " ${RC_OPTIONS} -O coff -i -o ") list(APPEND MBPOLL_SOURCES ${CMAKE_SOURCE_DIR}/libmodbus/src/win32/modbus.rc) endif() # Create the executable add_executable(mbpoll ${MBPOLL_SOURCES}) # Include directories target_include_directories(mbpoll PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR} ${LIBMODBUS_INCLUDE_DIRS} ${GETOPT_INCLUDE_DIR}) # Compiler-specific options if(MSVC) target_compile_definitions(mbpoll PRIVATE _CRT_SECURE_NO_WARNINGS) else() # Common warning flags target_compile_options(mbpoll PRIVATE -Wall -Wextra -Wpedantic -Wformat-security -Wno-unused-parameter -Wno-unused-function -Wno-unused-const-variable) # Security hardening (Release builds) target_compile_options(mbpoll PRIVATE $<$:-fstack-protector-strong> $<$:-fstack-protector-strong>) target_compile_definitions(mbpoll PRIVATE $<$:_FORTIFY_SOURCE=2> $<$:NDEBUG> $<$:_FORTIFY_SOURCE=2>) # Debug build with Address Sanitizer support target_compile_options(mbpoll PRIVATE $<$:-g> $<$:-O0> $<$:-fno-omit-frame-pointer>) # Optional: Enable sanitizers in debug mode (uncomment to use) # target_compile_options(mbpoll PRIVATE $<$:-fsanitize=address,undefined>) # target_link_options(mbpoll PRIVATE $<$:-fsanitize=address,undefined>) endif() # Compile definitions target_compile_definitions(mbpoll PRIVATE _GNU_SOURCE) target_compile_definitions(mbpoll PRIVATE SKIP_FAILURE_EXIT) if(MBPOLL_GPIO_RTS) target_compile_definitions(mbpoll PRIVATE MBPOLL_GPIO_RTS) target_include_directories(mbpoll PRIVATE ${PIDUINO_INCLUDE_DIRS}) endif() # Link libraries if(WIN32) target_link_libraries(mbpoll PRIVATE wsock32 ws2_32) else() target_link_libraries(mbpoll PRIVATE ${LIBMODBUS_LIBRARIES}) target_link_directories(mbpoll PRIVATE ${LIBMODBUS_LIBRARY_DIRS}) target_compile_options(mbpoll PRIVATE ${LIBMODBUS_CFLAGS_OTHER}) if(MBPOLL_GPIO_RTS) target_link_libraries(mbpoll PRIVATE ${PIDUINO_LIBRARIES}) target_link_directories(mbpoll PRIVATE ${PIDUINO_LIBRARY_DIRS}) endif() endif() # Windows pre-build step for libmodbus configuration if(WIN32) add_custom_command( TARGET mbpoll PRE_BUILD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/libmodbus/src/win32 COMMAND ${CSCRIPT_PATH} ${CMAKE_SOURCE_DIR}/libmodbus/src/win32/configure.js VERBATIM) endif() # Install target install(TARGETS mbpoll RUNTIME DESTINATION bin PERMISSIONS ${PROGRAM_PERMISSIONS}) # Install man page (Unix only) if(UNIX) install(FILES ${CMAKE_SOURCE_DIR}/doc/mbpoll.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) endif() # Uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) # Testing support option(BUILD_TESTING "Build unit tests" ON) if(BUILD_TESTING) enable_testing() add_subdirectory(tests) endif() # CPack configuration for Debian packages set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) set(CPACK_PACKAGE_VERSION "${MBPOLL_VERSION_MAJOR}.${MBPOLL_VERSION_MINOR}.${MBPOLL_VERSION_PATCH}") set(CPACK_PACKAGE_VERSION_MAJOR "${MBPOLL_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${MBPOLL_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${MBPOLL_VERSION_PATCH}") set(CPACK_PACKAGE_CONTACT "Pascal JEAN ") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME} - ${PROJECT_DESCRIPTION}") set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/package_description.txt") set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING") set(CPACK_GENERATOR "DEB") if(CPACK_GENERATOR STREQUAL "DEB") set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/epsilonrt/mbpoll") find_program(dpkg_cmd NAMES dpkg) if(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE AND dpkg_cmd) execute_process( COMMAND ${dpkg_cmd} --print-architecture RESULT_VARIABLE ret OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE) if(ret EQUAL 0) set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${arch}") else() message(WARNING "Unable to get debian architecture!") endif() endif() message(STATUS "Debian architecture: ${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") message(STATUS "Debian package name: ${CPACK_PACKAGE_FILE_NAME}.deb") if(MBPOLL_GPIO_RTS) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libmodbus5 (>= 3.1.7), libpiduino (>= ${PIDUINO_VERSION})") else() set(CPACK_DEBIAN_PACKAGE_DEPENDS "libmodbus5 (>= 3.1.7)") endif() set(CPACK_DEBIAN_PACKAGE_SECTION "utils") endif() include(CPack) # Print configuration summary message(STATUS "") message(STATUS "mbpoll configuration summary:") message(STATUS " Version: ${MBPOLL_VERSION_STRING}") message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") message(STATUS " GPIO RTS support: ${MBPOLL_GPIO_RTS}") message(STATUS " Install prefix: ${CMAKE_INSTALL_PREFIX}") message(STATUS "")