cmake_minimum_required(VERSION 2.8.12)


if(NOT LTR_SDK_SUFFIX)
    include(cmake/ltrnames/ltrnames.cmake)
endif(NOT LTR_SDK_SUFFIX)

project(ltrapi C)

set(LTRAPI_VER_MAJOR 1)
set(LTRAPI_VER_MINOR 32)
set(LTRAPI_VER_PATCH 39)
set(LTRAPI_VERSION   ${LTRAPI_VER_MAJOR}.${LTRAPI_VER_MINOR}.${LTRAPI_VER_PATCH})

option(LTR_FORCE_RESET_WHEN_IN_USE "Send STOP-RESET-STOP if module in use for compatibility with old behavior" OFF)
option(LTR_BUILD_EXAMPLES  "Build ltrapi C examples" OFF)
option(LTR_DEBUG_PRINT "Debug console printf" OFF)
option(LTR_ERROR_PRINT "Debug console printf" OFF)
option(LTRAPI_USE_KD_STORESLOTS  "Enable slot configuration store in crate support" OFF)
# linux: с версии 1.31.2 по-умолчанию приход сигнала на Linux не прерывает работу функций
# Recv() и Send(), т.к. в некоторых случаях сигналы могут использоваться переодически
# и нарушать работу функций (например в Mono при нескольких потоках).
# Для использования старого поведения можно включить данную опцию
option(LTRAPI_STOP_ON_SIGNAL "Stop Recv() and Send() on linux signal" OFF)
option(LTRAPI_BUILD_STATIC "Build static libraries rather dynamic" OFF)
option(LTRAPI_BUILD_FABRIC_MODULES "Build library for fabric modules" OFF)
option(LTRAPI_BUILD_DEVELOP_MODULES "Build library for currently development modules" OFF)
option(LTRAPI_BUILD_MATH_EXAMPLES "Build examples required math & fft libraries" OFF)

if(WIN32)
    option(LTRAPI_USE_WSA_SOCKS "Use WSA Sockets on Windows" OFF)
endif(WIN32)

if(LTR_PRODUCT_NAMES_FILE)
    include(${LTR_PRODUCT_NAMES_FILE})
endif(LTR_PRODUCT_NAMES_FILE)

if(WIN32)
    option(LTRAPI_BUILD_BORLAND_LIBS "Make .lib files for Borland C++/C++ Builder compiler" OFF)
    option(LTRAPI_BUILD_MINGW_LIBS "Make .a files for mingw compiler" OFF)
endif(WIN32)

if(NOT LTRAPI_PREPARE_HEADERS)
    option(LTRAPI_PREPARE_HEADERS "prepare pucblic ltrapi headers in build directory" OFF)
endif(NOT LTRAPI_PREPARE_HEADERS)

add_definitions(-DLTRAPI_DISABLE_COMPAT_DEFS)
if(LTR_FORCE_RESET_WHEN_IN_USE)
    add_definitions(-DLTR_FORCE_RESET_WHEN_IN_USE)
endif(LTR_FORCE_RESET_WHEN_IN_USE)

if(LTRAPI_STOP_ON_SIGNAL)
    add_definitions(-DLTRAPI_STOP_ON_SIGNAL)
endif(LTRAPI_STOP_ON_SIGNAL)

if(LTR_DEBUG_PRINT)
    add_definitions(-DLTR_DEBUG_PRINT)
endif(LTR_DEBUG_PRINT)

if(LTR_ERROR_PRINT)
    add_definitions(-DLTR_ERROR_PRINT)
endif(LTR_ERROR_PRINT)

if(NOT ${CMAKE_VERSION}  VERSION_LESS "3.0.0") 
    string(TIMESTAMP CURRENT_YEAR "%Y")
endif()    

# для QNX4 используются всегда статические библиотеки
if(${CMAKE_SYSTEM_NAME} STREQUAL "QNX4")
    set(LTRAPI_BUILD_STATIC ON)
endif()

if(LTR_BUILD_EXAMPLES)
    set(LTRAPI_PREPARE_HEADERS ON)
endif(LTR_BUILD_EXAMPLES)

include(CheckIncludeFiles)
include(CheckTypeSize)
include(CheckFunctionExists)
include(CheckSymbolExists)


if(CMAKE_COMPILER_IS_GNUCC)
    set(WARNOPTS
        -Werror=implicit-int -Werror=implicit-function-declaration -Werror=strict-prototypes -Werror=return-type
        -Wall -Wextra
        -Wformat-security -Winit-self -Wstrict-aliasing -Wfloat-equal
        -Wundef -Wshadow -Wunsafe-loop-optimizations -Wpointer-arith -Wcast-align
        -Wwrite-strings  -Wsign-compare -Waggregate-return -Winline
        -Wno-unused-parameter -Wno-unused-variable -Wno-aggregate-return)
    add_definitions(${WARNOPTS})
endif(CMAKE_COMPILER_IS_GNUCC)

if(MSVC)
    add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS)

    #чтобы не зависеть от runtime включаем его внутрь библиотек
    foreach(flag_var
            CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
            CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
       if(${flag_var} MATCHES "/MD")
          string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
       endif(${flag_var} MATCHES "/MD")
    endforeach(flag_var)

    #убираем флаг /INCREMENTAL, так как в MSVC с ним могут быть
    #внутренние ошибки линковщика
    foreach(flag_var
            CMAKE_SHARED_LINKER_FLAGS
            CMAKE_SHARED_LINKER_FLAGS_DEBUG
            CMAKE_SHARED_LINKER_FLAGS_RELEASE
            CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
            CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
            CMAKE_EXE_LINKER_FLAGS
            CMAKE_EXE_LINKER_FLAGS_DEBUG
            CMAKE_EXE_LINKER_FLAGS_RELEASE
            CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
            CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO)
       if(${flag_var} MATCHES "/INCREMENTAL:YES")
          string(REGEX REPLACE "/INCREMENTAL:YES" "/INCREMENTAL:NO" ${flag_var} "${${flag_var}}")
       endif(${flag_var} MATCHES "/INCREMENTAL:YES")
    endforeach(flag_var)

endif(MSVC)

set(LTRAPI_SOURCE_DIR ${PROJECT_SOURCE_DIR})
set(LTRAPI_BINARY_DIR  ${PROJECT_BINARY_DIR})
set(LTRAPI_INCLUDE_DIR  ${PROJECT_BINARY_DIR}/include)
set(LTRAPI_LIB_DIR ${PROJECT_SOURCE_DIR}/lib)


set(LTRAPI_CMAKE_DIR ${PROJECT_SOURCE_DIR}/cmake)
set(LTRAPI_MODULE_CMAKE_TEMPLATE ${PROJECT_SOURCE_DIR}/cmake/ltrmodule.cmake)

if(UNIX)
    if(NOT LTRAPI_INSTALL_INCLUDE)
        set(LTRAPI_INSTALL_INCLUDE          include/ltr/include)
    endif(NOT LTRAPI_INSTALL_INCLUDE)
    if(${CMAKE_SYSTEM_NAME} STREQUAL "QNX" AND CMAKE_CROSSCOMPILING)
        set(LTRAPI_INSTALL_LIB          /${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_INSTALL_PREFIX}/lib)
        set(LTRAPI_INSTALL_EXAMPLES     /${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_INSTALL_PREFIX}/bin)
    else()
        if(NOT LTRAPI_INSTALL_LIB)
            set(LTRAPI_INSTALL_LIB          lib)
        endif(NOT LTRAPI_INSTALL_LIB)
        set(LTRAPI_INSTALL_EXAMPLES     bin)
    endif()
    if(NOT LTRAPI_INSTALL_DATA)
        set(LTRAPI_INSTALL_DATA             share/ltrapi)
    endif(NOT LTRAPI_INSTALL_DATA)

    if(NOT LTRAPI_INSTALL_PASCAL)
        set(LTRAPI_INSTALL_PASCAL       include/ltr/pascal)
    endif(NOT LTRAPI_INSTALL_PASCAL)
elseif(WIN32)
    set(LTRAPI_INSTALL_INCLUDE      ltr/include)
    set(LTRAPI_INSTALL_LIB          ltr/lib)
    set(LTRAPI_INSTALL_EXAMPLES     ltr/bin/examples)
    set(LTRAPI_INSTALL_DATA         ltr/data)
    set(LTRAPI_INSTALL_PASCAL       ltr/include/pascal2)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "QNX4")
    set(LTRAPI_INSTALL_INCLUDE      include/ltr/include)    
    set(LTRAPI_INSTALL_LIB          lib)
    set(LTRAPI_INSTALL_EXAMPLES     bin)
    set(LTRAPI_INSTALL_DATA         share/ltrapi)    
endif(UNIX)

set(LTRAPI_CONFIG_FILE ${PROJECT_SOURCE_DIR}/config.h.in)



check_include_files("stdint.h" LTRAPI_HAVE_STDINT_H)
check_include_files("inttypes.h" LTRAPI_HAVE_INTTYPES_H)
if(WIN32)
    set(LTRAPI_HAVE_INT64             YES)
    set(LTRAPI_HAVE_UINT64            YES)
else(WIN32)
    check_type_size(int64_t           INT64)
    check_type_size(uint64_t          UINT64)
    set(LTRAPI_HAVE_INT64             ${HAVE_INT64})
    set(LTRAPI_HAVE_UINT64            ${HAVE_UINT64})
endif(WIN32)

set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} sys/socket.h time.h)
check_type_size(socklen_t HAVE_SOCKLEN_T)
check_symbol_exists(MSG_NOSIGNAL ${CMAKE_EXTRA_INCLUDE_FILES} HAVE_MSG_NOSIGNAL)
check_function_exists(strnlen HAVE_STRNLEN)
check_include_files("string.h" HAVE_STRING_H)

check_function_exists(usleep LTRAPI_HAVE_USLEEP)

if(${CMAKE_SYSTEM_NAME} STREQUAL "QNX4")
    set(__QNX4__ ON)
    set(LTRAPI_HAVE_NANOSLEEP ON)
else()
    check_function_exists(strlen LTRAPI_HAVE_NANOSLEEP)
endif()

check_include_files("sys/timers.h" HAVE_SYS_TIMERS_H)
if(HAVE_SYS_TIMERS_H)
    check_symbol_exists(CLOCK_MONOTONIC "sys/timers.h" HAVE_CLOCK_MONOTONIC)
endif(HAVE_SYS_TIMERS_H)
if(NOT HAVE_CLOCK_MONOTONIC)
    check_symbol_exists(CLOCK_MONOTONIC "time.h" HAVE_CLOCK_MONOTONIC)
endif(NOT HAVE_CLOCK_MONOTONIC)

configure_file(ltrapi_config.h.in ${LTRAPI_INCLUDE_DIR}/ltrapi_config.h)


#set(CMAKE_VERBOSE_MAKEFILE ON)

add_subdirectory(ltrapi)
add_subdirectory(ltrlogapi)
add_subdirectory(ltr010api)
add_subdirectory(ltr030api)
add_subdirectory(ltr032api)
add_subdirectory(ltr021api)
add_subdirectory(ltrbootapi)
add_subdirectory(ltravrapi)


#API модулей
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "QNX4")
add_subdirectory(ltr114api)
add_subdirectory(ltr212api)
endif()
add_subdirectory(ltr11api)
add_subdirectory(ltr12api)
add_subdirectory(ltr22api)
add_subdirectory(ltr24api)
add_subdirectory(ltr25api)
add_subdirectory(ltr27api)
add_subdirectory(ltr34api)
add_subdirectory(ltr35api)
add_subdirectory(ltr41api)
add_subdirectory(ltr42api)
add_subdirectory(ltr43api)
add_subdirectory(ltr51api)
add_subdirectory(ltr210api)
add_subdirectory(ltr216api)
add_subdirectory(ltedsapi)
add_subdirectory(lpw25api)

if(LTRAPI_BUILD_FABRIC_MODULES)
    # если включена опция, то добавляем сборку API для производственных
    # модулей, которые используются только для наладки, а не пользователями
    add_subdirectory(ltrfapi)
endif(LTRAPI_BUILD_FABRIC_MODULES)

if(WIN32)
    add_subdirectory(ltrModulesNet)
endif(WIN32)


if(LTRAPI_BUILD_BORLAND_LIBS)
    #цель для построения всех .lib фалов Borland C++
    add_custom_target(borland_libs ALL
                      DEPENDS ${LTRAPI_BORLAND_LIBS})
endif(LTRAPI_BUILD_BORLAND_LIBS)

if(LTRAPI_BUILD_MINGW_LIBS)
    #цель для построения всех .a файлов для mingw
    add_custom_target(mingw_libs ALL
                      DEPENDS ${LTRAPI_MINGW_LIBS})
endif(LTRAPI_BUILD_MINGW_LIBS)

if(LTR_BUILD_EXAMPLES)
    add_subdirectory(examples)
endif(LTR_BUILD_EXAMPLES)

#цели для сборки пакетов
if(UNIX AND LTR_CMAKE_PACKAGES)
    set(PACKAGE_NAME     ltrapi)
    set(PACKAGE_VERSION  ${LTRAPI_VERSION})
    set(PACKAGE_FREEBSD_CATEGORY  science)
    include(${LTR_CMAKE_PACKAGES})
endif(UNIX AND LTR_CMAKE_PACKAGES)

if(WIN32)
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nuget/ltrapi.nuspec.in
                  ${CMAKE_CURRENT_BINARY_DIR}/ltrapi.nuspec)
endif(WIN32)


if(WIN32 AND LTR_BUILD_WIN_INSTALLERS)
    set(LTR_CONVERTED_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/src)
    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/x64)
    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/x86)
    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src)

    string(REGEX REPLACE "/" "\\\\" ICONV_EXEC ${ICONV_EXEC})
    string(REGEX REPLACE "/" "\\\\" LTR_CONVERTED_SOURCE_DIR ${LTR_CONVERTED_SOURCE_DIR})
    set(LTR_ORIG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
    string(REGEX REPLACE "/" "\\\\" LTR_ORIG_SOURCE_DIR ${LTR_ORIG_SOURCE_DIR})

    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/win_install/conv_src_cp1251.bat.in
                   ${CMAKE_CURRENT_BINARY_DIR}/conv_src_cp1251.bat @ONLY)
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/win_install/make64.bat.in
               ${CMAKE_CURRENT_BINARY_DIR}/x64/make.bat @ONLY)
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/win_install/make32.bat.in
               ${CMAKE_CURRENT_BINARY_DIR}/x86/make.bat @ONLY)
    add_custom_target(convert_src
        COMMAND cmd /c conv_src_cp1251.bat
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

    add_custom_target(api64
        COMMAND cmd /c make.bat
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/x64
        DEPENDS convert_src)

    #x86 версию собираем 2008 студией (Express) для совместимости с Win2000
    #set(VS2008_SETENV "${VS2008_DIR}/vcvarsall.bat")
    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/x86)
    add_custom_target(api32
        COMMAND cmd /c make.bat
        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/x86
        DEPENDS convert_src
        )

    set(INSTALLER_NAME ${LTR_CRATE_NAME_LOWER}dll_${LTRAPI_VERSION}.exe)

    set(PASCAL_OLD_PATH ${CMAKE_CURRENT_SOURCE_DIR}/win_install/pascal_old)

    #конфигурируем NSIS-файл
    configure_file(win_install/ltrapi.nsi.in
                   ${PROJECT_BINARY_DIR}/ltrapi.nsi @ONLY)

    #собираем сам установщик
    add_custom_target(ltrapi-installer
        #по nsi файлу создаем установщик
        COMMAND ${NSIS_EXEC} ltrapi.nsi
        DEPENDS api32
        DEPENDS api64
        DEPENDS ltrModulesNet
        DEPENDS ${PROJECT_BINARY_DIR}/ltrapi.nsi
        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    )

    if(NOT WIN_INSTALLER_NOSIGN)
        #подписываем установщик при неободимости
        add_custom_command(TARGET ltrapi-installer POST_BUILD
            COMMAND "${SIGNTOOL_EXEC}" sign /v /n "${SIGN_COMPANY_NAME}" /t ${CERT_TIMESTAMP_URL} ${INSTALLER_NAME}
            WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
        )
    endif(NOT WIN_INSTALLER_NOSIGN)

    #nuget
    add_custom_target(ltrapi-nuget
        #по nsi файлу создаем установщик
        COMMAND ${NUGET_EXEC} pack
        DEPENDS api32
        DEPENDS api64
        DEPENDS ${PROJECT_BINARY_DIR}/ltrapi.nuspec
        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    )

    add_custom_target(ltrapi-nuget-nodep
        #по nsi файлу создаем установщик
        COMMAND ${NUGET_EXEC} pack
        DEPENDS ${PROJECT_BINARY_DIR}/ltrapi.nuspec
        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
    )
endif(WIN32 AND LTR_BUILD_WIN_INSTALLERS)
