
cmake_minimum_required(VERSION 3.14)

include(FetchContent)
FetchContent_Declare(
    mxml
    GIT_REPOSITORY https://github.com/michaelrsweet/mxml.git
    GIT_TAG v4.0.3
)
FetchContent_MakeAvailable(mxml)

set(_ECAT_MASTER_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../..")
if(EXISTS "${CMAKE_SOURCE_DIR}/cmake/VersionAutoIncrement.cmake")
    set(_VERSION_HELPER_DIR "${CMAKE_SOURCE_DIR}")
elseif(EXISTS "${_ECAT_MASTER_ROOT}/cmake/VersionAutoIncrement.cmake")
    set(_VERSION_HELPER_DIR "${_ECAT_MASTER_ROOT}")
else()
    set(_VERSION_HELPER_DIR "")
endif()
if(_VERSION_HELPER_DIR)
    include("${_VERSION_HELPER_DIR}/cmake/VersionAutoIncrement.cmake")
    auto_version("${_VERSION_HELPER_DIR}/version/sdk_c.txt" "CSDK_VERSION")
else()

    message(WARNING "未找到 VersionAutoIncrement.cmake, 使用占位版本 0.0.0")
    set(CSDK_VERSION_MAJOR 0)
    set(CSDK_VERSION_MINOR 0)
    set(CSDK_VERSION_BUILD 0)
    set(CSDK_VERSION_STRING "0.0.0")
endif()

project(darra-ethercat
    VERSION "${CSDK_VERSION_STRING}"
    DESCRIPTION "DarraEtherCAT C SDK"
    LANGUAGES C
)

set(VERSION_MAJOR ${CSDK_VERSION_MAJOR})
set(VERSION_MINOR ${CSDK_VERSION_MINOR})
set(VERSION_BUILD ${CSDK_VERSION_BUILD})
set(VERSION_STRING ${CSDK_VERSION_STRING})

if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/include/dx_version.h.in")
    configure_file(
        "${CMAKE_CURRENT_SOURCE_DIR}/include/dx_version.h.in"
        "${CMAKE_CURRENT_SOURCE_DIR}/include/dx_version.h"
        @ONLY
    )
endif()

message(STATUS "DarraEtherCAT C SDK 版本: ${PROJECT_VERSION}")

option(HEADER_ONLY    "仅头文件模式 (不链接 Darra.Core)" ON)
option(BUILD_EXAMPLES "构建示例程序" ON)
option(SHARED         "构建动态链接库 (仅非头文件模式)" OFF)
set(DLL_DIR "" CACHE PATH "Darra.Core.dll/so 所在目录")

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

if(MSVC)

    add_compile_options(/W4 /utf-8)
    add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
else()

    add_compile_options(-Wall -Wextra -Wpedantic)
endif()

set(ADVANCED_SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/src/master/callback_router.c

    ${CMAKE_CURRENT_SOURCE_DIR}/src/master/config.c

    ${CMAKE_CURRENT_SOURCE_DIR}/src/master/diagnostics.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/master/gateway.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/coe_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/soe_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/cia402_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/fsoe_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/fsoe_pdo_frame.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/mdp_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/eoe_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/aoe_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/foe_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/voe_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/dc_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/pdo_advanced.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/mbx_registry.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/slave/mbx_cache.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/esi_parser.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/eni_parser.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/eni.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/async.c

    ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/async_isolate.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/statics/driver_version.c
)

set(ADVANCED_HEADERS
    ${CMAKE_CURRENT_SOURCE_DIR}/include/ethercat_advanced.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/master/core.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/master/events.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/master/callback_router.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/master/events_emcy.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/master/diagnostics.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/master/config.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/master/mailbox_gateway.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/master/redundancy.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/master/state.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/data/types.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/core.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/coe.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/soe.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/eoe.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/foe.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/aoe.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/voe.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/fsoe.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/dc.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/pdo.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/cia401.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/cia402.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/mdp.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/startup.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/statics/network.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/statics/print.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/statics/version.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/utils/base_data.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/utils/esi.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/utils/xml.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/slave/esi.h
)

if(HEADER_ONLY)

    add_library(darra-ethercat INTERFACE)
    add_library(darra::ethercat ALIAS darra-ethercat)

    target_include_directories(darra-ethercat INTERFACE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>
    )

    target_compile_definitions(darra-ethercat INTERFACE
        DYNAMIC_LOAD
    )

    if(WIN32)
        target_link_libraries(darra-ethercat INTERFACE kernel32)
    else()

        target_link_libraries(darra-ethercat INTERFACE ${CMAKE_DL_LIBS})
    endif()

    add_library(darra-ethercat-advanced STATIC ${ADVANCED_SOURCES})
    add_library(darra::ethercat-advanced ALIAS darra-ethercat-advanced)
    set_target_properties(darra-ethercat-advanced PROPERTIES FOLDER "C SDK")

    target_include_directories(darra-ethercat-advanced PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>
    )
    target_compile_definitions(darra-ethercat-advanced PUBLIC DYNAMIC_LOAD)

    if(WIN32)
        target_link_libraries(darra-ethercat-advanced PUBLIC kernel32)
    else()
        target_link_libraries(darra-ethercat-advanced PUBLIC ${CMAKE_DL_LIBS})
    endif()

    if(NOT TARGET mxml4)

        set(MXML_SOURCES
            ${mxml_SOURCE_DIR}/mxml-attr.c
            ${mxml_SOURCE_DIR}/mxml-file.c
            ${mxml_SOURCE_DIR}/mxml-get.c
            ${mxml_SOURCE_DIR}/mxml-index.c
            ${mxml_SOURCE_DIR}/mxml-node.c
            ${mxml_SOURCE_DIR}/mxml-options.c
            ${mxml_SOURCE_DIR}/mxml-private.c
            ${mxml_SOURCE_DIR}/mxml-search.c
            ${mxml_SOURCE_DIR}/mxml-set.c
            ${mxml_SOURCE_DIR}/mxml-string.c
        )

        set(MXML_SOURCES_EXISTING "")
        foreach(_src ${MXML_SOURCES})
            if(EXISTS "${_src}")
                list(APPEND MXML_SOURCES_EXISTING "${_src}")
            endif()
        endforeach()
        add_library(mxml4 STATIC ${MXML_SOURCES_EXISTING})
        target_include_directories(mxml4 PUBLIC
            $<BUILD_INTERFACE:${mxml_SOURCE_DIR}>
        )

        set(HAVE_LONG_LONG_INT 1)
        set(HAVE_SNPRINTF 1)
        set(HAVE_VSNPRINTF 1)
        set(HAVE_STRDUP 1)
        set(HAVE_STRLCAT 0)
        set(HAVE_STRLCPY 0)
        set(HAVE_PTHREAD_H 0)
        if(EXISTS "${mxml_SOURCE_DIR}/config.h.in")
            configure_file(
                "${mxml_SOURCE_DIR}/config.h.in"
                "${mxml_SOURCE_DIR}/config.h"
            )
        endif()
        set_target_properties(mxml4 PROPERTIES FOLDER "Internal")
    endif()

    target_link_libraries(darra-ethercat-advanced PRIVATE mxml4)
    target_include_directories(darra-ethercat-advanced PRIVATE ${mxml_SOURCE_DIR})

    message(STATUS "构建模式: 仅头文件 (动态加载 DLL) + 高级功能静态库")

else()

    if(DLL_DIR)
        set(_search_paths "${DLL_DIR}")
    else()
        set(_search_paths
            "${CMAKE_CURRENT_SOURCE_DIR}/../../../Darra_EtherCAT_Drive/main/test"
            "${CMAKE_CURRENT_SOURCE_DIR}/lib"
            "${CMAKE_CURRENT_BINARY_DIR}"
        )
    endif()

    find_library(CORE_LIBRARY
        NAMES Darra.Core core
        PATHS ${_search_paths}
        NO_DEFAULT_PATH
    )

    if(NOT CORE_LIBRARY)
        find_library(CORE_LIBRARY
            NAMES Darra.Core core
        )
    endif()

    if(CORE_LIBRARY)
        message(STATUS "找到 Darra.Core 库: ${CORE_LIBRARY}")
    else()
        message(WARNING "未找到 Darra.Core 库, 仅编译头文件依赖")
    endif()

    if(SHARED)
        add_library(darra-ethercat SHARED
            ${ADVANCED_SOURCES}
            ${CMAKE_CURRENT_SOURCE_DIR}/include/ethercat.h
            ${CMAKE_CURRENT_SOURCE_DIR}/include/ethercat_types.h
            ${CMAKE_CURRENT_SOURCE_DIR}/include/ethercat_advanced.h
            ${ADVANCED_HEADERS}
        )
        set_target_properties(darra-ethercat PROPERTIES
            WINDOWS_EXPORT_ALL_SYMBOLS ON
        )
        message(STATUS "构建模式: 动态链接库 (.dll/.so)")
    else()

        add_library(darra-ethercat STATIC ${ADVANCED_SOURCES})
        message(STATUS "构建模式: 静态链接库 (含高级功能)")
    endif()

    add_library(darra::ethercat ALIAS darra-ethercat)

    target_include_directories(darra-ethercat PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>
    )
    if(CORE_LIBRARY)
        target_link_libraries(darra-ethercat PUBLIC ${CORE_LIBRARY})
    endif()

    target_link_libraries(darra-ethercat PUBLIC mxml4)

    if(WIN32 AND NOT SHARED)

    endif()

    add_library(darra-ethercat-advanced INTERFACE)
    target_link_libraries(darra-ethercat-advanced INTERFACE darra-ethercat)
    add_library(darra::ethercat-advanced ALIAS darra-ethercat-advanced)

endif()

if(BUILD_EXAMPLES)
    message(STATUS "构建示例程序")

    add_executable(darra-ethercat-basic examples/basic.c)
    target_link_libraries(darra-ethercat-basic PRIVATE darra-ethercat darra-ethercat-advanced)
    if(NOT HEADER_ONLY)

        target_compile_definitions(darra-ethercat-basic PRIVATE DYNAMIC_LOAD)
        target_include_directories(darra-ethercat-basic PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}/include
        )
        if(WIN32)
            target_link_libraries(darra-ethercat-basic PRIVATE kernel32)
        else()
            target_link_libraries(darra-ethercat-basic PRIVATE ${CMAKE_DL_LIBS})
        endif()
    endif()

    add_executable(darra-ethercat-highlevel examples/highlevel.c)
    target_link_libraries(darra-ethercat-highlevel PRIVATE darra-ethercat darra-ethercat-advanced)
    if(NOT HEADER_ONLY)
        target_compile_definitions(darra-ethercat-highlevel PRIVATE DYNAMIC_LOAD)
        target_include_directories(darra-ethercat-highlevel PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}/include
        )
        if(WIN32)
            target_link_libraries(darra-ethercat-highlevel PRIVATE kernel32)
        else()
            target_link_libraries(darra-ethercat-highlevel PRIVATE ${CMAKE_DL_LIBS})
        endif()
    endif()

    add_executable(darra-ethercat-cia402 examples/cia402.c)
    target_link_libraries(darra-ethercat-cia402 PRIVATE darra-ethercat darra-ethercat-advanced)
    if(NOT HEADER_ONLY)
        target_compile_definitions(darra-ethercat-cia402 PRIVATE DYNAMIC_LOAD)
        target_include_directories(darra-ethercat-cia402 PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}/include
        )
        if(WIN32)
            target_link_libraries(darra-ethercat-cia402 PRIVATE kernel32)
        else()
            target_link_libraries(darra-ethercat-cia402 PRIVATE ${CMAKE_DL_LIBS})
        endif()
    endif()

    set_target_properties(
        darra-ethercat-basic
        darra-ethercat-highlevel
        darra-ethercat-cia402
        PROPERTIES
        RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
        FOLDER "C SDK/Examples"
    )
endif()

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

install(
    DIRECTORY include/
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/darra-ethercat
    FILES_MATCHING PATTERN "*.h"
)

install(
    DIRECTORY src/
    DESTINATION ${CMAKE_INSTALL_DATADIR}/darra-ethercat/src
    FILES_MATCHING PATTERN "*.c"
)

install(TARGETS darra-ethercat
    EXPORT darra-ethercat-targets
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/darra-ethercat
)

if(HEADER_ONLY)

    if(TARGET mxml4)
        install(TARGETS darra-ethercat-advanced mxml4
            EXPORT darra-ethercat-targets
            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
            INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/darra-ethercat
        )
    else()
        install(TARGETS darra-ethercat-advanced
            EXPORT darra-ethercat-targets
            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
            INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/darra-ethercat
        )
    endif()
endif()

if(BUILD_EXAMPLES)
    install(TARGETS
        darra-ethercat-basic
        darra-ethercat-highlevel
        darra-ethercat-cia402
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/examples
    )
endif()

install(
    DIRECTORY examples/
    DESTINATION ${CMAKE_INSTALL_DATADIR}/darra-ethercat/examples
    FILES_MATCHING PATTERN "*.c"
)

install(EXPORT darra-ethercat-targets
    FILE DarraEtherCATTargets.cmake
    NAMESPACE darra::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/darra-ethercat
)

write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/DarraEtherCATConfigVersion.cmake"
    VERSION ${PROJECT_VERSION}
    COMPATIBILITY SameMajorVersion
)

configure_package_config_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/DarraEtherCATConfig.cmake.in"
    "${CMAKE_CURRENT_BINARY_DIR}/DarraEtherCATConfig.cmake"
    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/darra-ethercat
)

install(FILES
    "${CMAKE_CURRENT_BINARY_DIR}/DarraEtherCATConfig.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/DarraEtherCATConfigVersion.cmake"
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/darra-ethercat
)

set(CPACK_PACKAGE_NAME "darra-ethercat")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_VENDOR "Hangzhou Darra Technology Co., Ltd.")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "DarraEtherCAT C SDK - EtherCAT 主站控制库")
set(CPACK_PACKAGE_CONTACT "support@darra.com")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")

if(WIN32)
    set(CPACK_GENERATOR "ZIP;NSIS")
    set(CPACK_NSIS_DISPLAY_NAME "DarraEtherCAT C SDK ${PROJECT_VERSION}")
    set(CPACK_NSIS_PACKAGE_NAME "DarraEtherCAT C SDK")
else()
    set(CPACK_GENERATOR "TGZ;DEB;RPM")
    set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Darra Technology <support@darra.com>")
    set(CPACK_RPM_PACKAGE_LICENSE "Proprietary")
endif()

set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")
set(CPACK_SOURCE_IGNORE_FILES
    "/build/"
    "/\\.git/"
    "/\\.vs/"
    "\\.user$"
)

include(CPack)

message(STATUS "========================================")
message(STATUS "DarraEtherCAT C SDK 配置摘要")
message(STATUS "========================================")
message(STATUS "  版本:         ${PROJECT_VERSION}")
message(STATUS "  头文件模式:   ${HEADER_ONLY}")
message(STATUS "  构建示例:     ${BUILD_EXAMPLES}")
message(STATUS "  动态库:       ${SHARED}")
message(STATUS "  高级功能库:   darra-ethercat-advanced")
message(STATUS "  VMP保护:      Darra.Core.dll (编译后加壳)")
message(STATUS "  安装前缀:     ${CMAKE_INSTALL_PREFIX}")
message(STATUS "  C 编译器:     ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}")
message(STATUS "========================================")
