148 lines
5.2 KiB
CMake
148 lines
5.2 KiB
CMake
cmake_minimum_required(VERSION 3.16)
|
|
project(libmodbus_win C)
|
|
|
|
option(MODBUS_ENABLE_RTU "Build RTU backend (modbus-rtu.c)" ON)
|
|
option(MODBUS_ENABLE_TCP "Build TCP backend (modbus-tcp.c)" ON)
|
|
option(MODBUS_FIX_MSVC_SOCKOPT_WARNINGS "Fix MSVC winsock C4133 warnings" ON)
|
|
|
|
set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
|
|
|
# --- 1) Prepare shim include dir (build-only includes live here) ---
|
|
set(SHIM_INC_DIR "${CMAKE_CURRENT_BINARY_DIR}/include")
|
|
file(MAKE_DIRECTORY "${SHIM_INC_DIR}")
|
|
|
|
# We expect config.h to exist in ${SRC_DIR}/config.h (you generate it via src/win32/configure.js)
|
|
if(NOT EXISTS "${SRC_DIR}/win32/config.h")
|
|
message(FATAL_ERROR
|
|
"config.h not found at ${SRC_DIR}/win32/config.h. "
|
|
"Run src/win32/configure.js and copy config.h into src/ before configuring with CMake.")
|
|
endif()
|
|
|
|
# --- 2) Generate shim modbus.h (static-friendly MODBUS_API) ---
|
|
file(READ "${SRC_DIR}/modbus.h" MODBUS_H_TXT)
|
|
|
|
set(MODBUS_API_BLOCK
|
|
"#if defined(_MSC_VER)
|
|
# if defined(DLLBUILD)
|
|
/* define DLLBUILD when building the DLL */
|
|
# define MODBUS_API __declspec(dllexport)
|
|
# else
|
|
# define MODBUS_API __declspec(dllimport)
|
|
# endif
|
|
#else
|
|
# define MODBUS_API
|
|
#endif")
|
|
|
|
set(MODBUS_API_BLOCK_REPL
|
|
"#if defined(_MSC_VER)
|
|
/* Static library: do NOT use dllimport/dllexport in public headers */
|
|
# if defined(DLLBUILD)
|
|
# define MODBUS_API __declspec(dllexport)
|
|
# else
|
|
# define MODBUS_API
|
|
# endif
|
|
#else
|
|
# define MODBUS_API
|
|
#endif")
|
|
|
|
string(REPLACE "${MODBUS_API_BLOCK}" "${MODBUS_API_BLOCK_REPL}" MODBUS_H_TXT "${MODBUS_H_TXT}")
|
|
file(WRITE "${SHIM_INC_DIR}/modbus.h" "${MODBUS_H_TXT}")
|
|
|
|
# Copy remaining headers needed to compile (build-only set includes private/config)
|
|
file(COPY "${SRC_DIR}/modbus-tcp.h" DESTINATION "${SHIM_INC_DIR}")
|
|
file(COPY "${SRC_DIR}/modbus-rtu.h" DESTINATION "${SHIM_INC_DIR}")
|
|
file(COPY "${SRC_DIR}/modbus-version.h" DESTINATION "${SHIM_INC_DIR}")
|
|
|
|
# Build-only headers required by .c files
|
|
file(COPY "${SRC_DIR}/win32/config.h" DESTINATION "${SHIM_INC_DIR}")
|
|
file(COPY "${SRC_DIR}/modbus-private.h" DESTINATION "${SHIM_INC_DIR}")
|
|
file(COPY "${SRC_DIR}/modbus-tcp-private.h" DESTINATION "${SHIM_INC_DIR}")
|
|
file(COPY "${SRC_DIR}/modbus-rtu-private.h" DESTINATION "${SHIM_INC_DIR}")
|
|
|
|
# --- 3) Generate shim sources (do not modify upstream sources on disk) ---
|
|
set(SHIM_SRC_DIR "${CMAKE_CURRENT_BINARY_DIR}/shim_src")
|
|
file(MAKE_DIRECTORY "${SHIM_SRC_DIR}")
|
|
|
|
function(make_shim_source in_file out_file)
|
|
file(READ "${in_file}" TXT)
|
|
|
|
# Force includes via include paths (so our shim headers win)
|
|
string(REPLACE "#include \"modbus.h\"" "#include <modbus.h>" TXT "${TXT}")
|
|
string(REPLACE "#include \"modbus-tcp.h\"" "#include <modbus-tcp.h>" TXT "${TXT}")
|
|
string(REPLACE "#include \"modbus-rtu.h\"" "#include <modbus-rtu.h>" TXT "${TXT}")
|
|
string(REPLACE "#include \"modbus-version.h\"" "#include <modbus-version.h>" TXT "${TXT}")
|
|
|
|
# Some files include private/config with quotes; route those too
|
|
string(REPLACE "#include \"config.h\"" "#include <config.h>" TXT "${TXT}")
|
|
string(REPLACE "#include \"modbus-private.h\"" "#include <modbus-private.h>" TXT "${TXT}")
|
|
string(REPLACE "#include \"modbus-tcp-private.h\"" "#include <modbus-tcp-private.h>" TXT "${TXT}")
|
|
string(REPLACE "#include \"modbus-rtu-private.h\"" "#include <modbus-rtu-private.h>" TXT "${TXT}")
|
|
|
|
# Optional: silence MSVC winsock setsockopt warnings (C4133)
|
|
# On Windows setsockopt expects const char* optval; libmodbus passes &int.
|
|
if (MSVC AND MODBUS_FIX_MSVC_SOCKOPT_WARNINGS)
|
|
string(REPLACE ", &option, sizeof(int))" ", (const char*)&option, sizeof(int))" TXT "${TXT}")
|
|
endif()
|
|
|
|
file(WRITE "${out_file}" "${TXT}")
|
|
endfunction()
|
|
|
|
# Base sources
|
|
make_shim_source("${SRC_DIR}/modbus.c" "${SHIM_SRC_DIR}/modbus.c")
|
|
make_shim_source("${SRC_DIR}/modbus-data.c" "${SHIM_SRC_DIR}/modbus-data.c")
|
|
|
|
set(MODBUS_SOURCES
|
|
"${SHIM_SRC_DIR}/modbus.c"
|
|
"${SHIM_SRC_DIR}/modbus-data.c"
|
|
)
|
|
|
|
if(MODBUS_ENABLE_TCP)
|
|
make_shim_source("${SRC_DIR}/modbus-tcp.c" "${SHIM_SRC_DIR}/modbus-tcp.c")
|
|
list(APPEND MODBUS_SOURCES "${SHIM_SRC_DIR}/modbus-tcp.c")
|
|
endif()
|
|
|
|
if(MODBUS_ENABLE_RTU)
|
|
make_shim_source("${SRC_DIR}/modbus-rtu.c" "${SHIM_SRC_DIR}/modbus-rtu.c")
|
|
list(APPEND MODBUS_SOURCES "${SHIM_SRC_DIR}/modbus-rtu.c")
|
|
endif()
|
|
|
|
add_library(modbus STATIC ${MODBUS_SOURCES})
|
|
|
|
# --- MSVC: silence WinSock signature warning (setsockopt wants const char*) ---
|
|
if (MSVC)
|
|
target_compile_options(modbus PRIVATE /wd4133)
|
|
endif()
|
|
|
|
# Use shim headers for build + consumers (PUBLIC), but we will INSTALL only public headers explicitly
|
|
target_include_directories(modbus
|
|
PUBLIC
|
|
"${SHIM_INC_DIR}"
|
|
)
|
|
|
|
if (WIN32)
|
|
target_link_libraries(modbus PUBLIC ws2_32)
|
|
endif()
|
|
|
|
# --- Install: only public headers (no config.h, no *-private.h) ---
|
|
include(GNUInstallDirs)
|
|
|
|
install(TARGETS modbus
|
|
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
|
)
|
|
|
|
set(PUBLIC_HEADERS
|
|
"${SHIM_INC_DIR}/modbus.h"
|
|
"${SHIM_INC_DIR}/modbus-version.h"
|
|
)
|
|
|
|
if(MODBUS_ENABLE_TCP)
|
|
list(APPEND PUBLIC_HEADERS "${SHIM_INC_DIR}/modbus-tcp.h")
|
|
endif()
|
|
|
|
if(MODBUS_ENABLE_RTU)
|
|
list(APPEND PUBLIC_HEADERS "${SHIM_INC_DIR}/modbus-rtu.h")
|
|
endif()
|
|
|
|
install(FILES ${PUBLIC_HEADERS}
|
|
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
|
) |