﻿# CMakeList.txt: 顶层 CMake 项目文件，在此处执行全局配置
# 并包含子项目。
#
message(STATUS "CMake version: ${CMAKE_VERSION}")
cmake_minimum_required(VERSION 3.14.0)
project(handdleai VERSION 0.1.0)
string(TIMESTAMP RUN_TIME)
message( " project start : " ${RUN_TIME})
add_compile_definitions(NOMINMAX)

set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
set(CMAKE_DISABLE_SOURCE_CHANGES  ON)

get_directory_property(_has_parent PARENT_DIRECTORY)
if(_has_parent)
  set(is_root_project OFF)
else()
  set(is_root_project ON)
endif()

set(NE_DEVELOPER_DEFAULTS "${is_root_project}" CACHE BOOL "Turns on default settings for development of QTdemo")

option(BUILD_EXAMPLES "Build Examples" "${NE_DEVELOPER_DEFAULTS}")
option(BUILD_MODULES "Build Modules" "${NE_DEVELOPER_DEFAULTS}")
option(BUILD_DEBUG_POSTFIX_D "Append d suffix to debug libraries" OFF)
if (MSVC_VERSION GREATER_EQUAL "1900")
    include(CheckCXXCompilerFlag)
    CHECK_CXX_COMPILER_FLAG("/std:c++17" _cpp_latest_flag_supported)
    if (_cpp_latest_flag_supported)
        add_compile_options("/std:c++17")
    else()
        message(WARNING "Compiler does not support C++17 standard.")
    endif()
else()
    message(WARNING "MSVC version is not supported.")
endif()
# 默认生成参数设置
if(NE_DEVELOPER_DEFAULTS)
  set(CMAKE_CXX_STANDARD 17)
  set(CMAKE_CXX_EXTENSIONS OFF)
  SET(CMAKE_CXX_STANDARD_REQUIRED TRUE)
  # PROJECT_BINARY_DIR 指build生成所在文件夹
  # PROJECT_SOURCE_DIR 指最外层CMakeLists.txt所在文件夹
  # CMAKE_CURRENT_SOURCE_DIR 指正在处理的CMakeLists.txt所在文件夹
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/lib")
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/lib")
  SET(PROJECT_ROOT_PATH ${PROJECT_SOURCE_DIR})
endif()

##################
# 获取默认库路径
# 记录 // include // lib // 子文件夹名
##
if(ON)
   
    # SUBDIRENAMES 遍历子文件夹  
    # ISAbsolutePath ON 子文件夹路径名     OFF 读取文件名 
    macro(SUBDIRENAMES result curdir _temp ISAbsolutePath)
        file(GLOB children RELATIVE ${curdir} ${curdir}/*${_temp}) 
        set(dirlist "")
        foreach(child ${children})
            if(IS_DIRECTORY ${curdir}/${child} )
                if(${child}  MATCHES .*${_temp})
                    if(${ISAbsolutePath})
                        LIST(APPEND dirlist ${curdir}/${child})
                    else()
                        LIST(APPEND dirlist ${child})
                    endif()
                endif()
            endif() 
        endforeach()
        set(${result} ${dirlist})
    endmacro()
    ##########

    ####################### 自动查询路径下库文件 include  lib  拷贝dll
    # 
    macro(FINDDLLDIR result Includes Libs ISMoveDll)
        SET(envs "")
        # Robust DLL copy: copy only concrete *.dll files, log missing cases, avoid invalid arguments.
        if(${ISMoveDll})
            set(_dll_dir "${result}/dll")
            if(EXISTS "${_dll_dir}")
                file(GLOB _dll_files "${_dll_dir}/*.dll")
                if(_dll_files)
                    foreach(_dll IN LISTS _dll_files)
                        if(EXISTS "${_dll}")
                            # Extract just the filename
                            get_filename_component(_dll_name "${_dll}" NAME)
                            if(NOT _dll_name MATCHES "\\.dll$")
                                message(WARNING "[dll-skip] Unexpected file without .dll extension: ${_dll}")
                                continue()
                            endif()
                            set(_dest "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_dll_name}")
                            if(EXISTS "${_dest}")
                                # Optional: skip identical timestamp/size (cheap check)
                                file(SIZE "${_dll}" _src_size)
                                file(SIZE "${_dest}" _dst_size)
                                if(_src_size EQUAL _dst_size)
                                    message(STATUS "[dll-skip] Already present: ${_dll_name}")
                                    continue()
                                endif()
                            endif()
                            message(STATUS "[dll-copy] ${_dll} -> ${_dest}")
                            file(COPY "${_dll}" DESTINATION "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
                        else()
                            message(WARNING "[dll-missing-during-loop] ${_dll}")
                        endif()
                    endforeach()
                else()
                    message(WARNING "[dll-empty] No .dll files found in ${_dll_dir}")
                endif()
            else()
                message(WARNING "[dll-move-fail] Dir does not exist: ${_dll_dir}")
            endif()
        endif()

        list(APPEND ${Includes} ${result}/include)
        SUBDIRENAMES(envs ${result}/include "" ON)
        list(APPEND ${Includes} ${envs})
        SUBDIRENAMES(envs ${result} "lib" ON)
        list(APPEND ${Libs} ${envs})
    endmacro()

    ######################### 去除重复项
    #
    macro(REMOVE_DUPLICATES result )
        SET(DUP "")
        message("[!] RESULT  : " ${result})
        foreach(var ${result})
            list(FIND DUP ${var} _index)
            if(${_index} GREATER -1)
                message("[!] HAVE : " ${var} )
            else()
                message("[!] ADD  : " ${var})
                list(APPEND DUP ${var})
            endif()           
        endforeach()
        set(${result} ${DUP})
    endmacro()


    #########################
    if (MSVC)
        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd /Zi")
        set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD /Zi")
        set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
        add_compile_definitions(_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR=1)
    endif()

    if(MSVC)
        # QT path qt5.14.2
        get_filename_component(PARENT_DIR ${PROJECT_SOURCE_DIR} DIRECTORY)
        SET(ENVPATH ${PARENT_DIR}/GlobalCppEnv) #设置遍历库路径
        SUBDIRENAMES(envs ${ENVPATH} "" OFF) #自动遍历
        # 设置引用库名
        foreach(child  ${envs})
            message("DLL NAME: " ${child})
            FINDDLLDIR(${ENVPATH}/${child} ${child}_include ${child}_lib ON)
            message(${child}_include: ${${child}_include} )
            message(${child}_lib: ${${child}_lib})
            if(${child} MATCHES "opencv")
                if(CMAKE_BUILD_TYPE MATCHES "Debug")
                    SET( ${child}_target_link "opencv_world410d" )
                else()
                    SET( ${child}_target_link "opencv_world410" )
                endif()
            elseif(${child} MATCHES "halcon")
                SET( ${child}_target_link 
                    "halcon"
                    "halconcpp"
                    "hdevenginecpp" )
            elseif(${child} MATCHES "keyence3D")
                SET( ${child}_target_link 
                    "LJX8_IF" )
            elseif(${child} MATCHES "python")
                #set(PYTHON_EXECUTABLE "${PROJECT_ROOT_PATH}/env/python/Python37")
                SET( ${child}_target_link 
                "_tkinter"
                "python3"
                "python312")
            elseif(${child} MATCHES "boost")
                SET( ${child}_target_link 
                    "libboost_python312-vc143-mt-sgd-x64-1_86"
                    "libboost_python312-vc143-mt-s-x64-1_86"
                    "libboost_thread-vc143-mt-gd-x64-1_86"
                    "libboost_chrono-vc143-mt-gd-x64-1_86")
            elseif(${child} MATCHES "basler")
                SET( ${child}_target_link 
                    "PylonC.lib" )
            elseif(${child} MATCHES "sqlite")
                SET( ${child}_target_link 
                    "sqlite3" )
            elseif(${child} MATCHES "myTools")
                SET( ${child}_target_link 
                    "myTools" )
            elseif(${child} MATCHES "mvs")
                SET( ${child}_target_link 
                    "MvCameraControl" )
            elseif(${child} MATCHES "Dalsa")
                SET( ${child}_target_link 
                    "corapi"
                    "SapClassBasic"
                    "SapClassGui")
            elseif(${child} MATCHES "keyence2_5D")
                SET( ${child}_target_link  
                "kglib" )  
            elseif(${child} MATCHES "3DAI")
                if(CMAKE_BUILD_TYPE MATCHES "Debug")
                    SET( ${child}_target_link  "3DAlg")  
                else()
                    SET( ${child}_target_link "3DAlg")  
                endif()                  
            elseif(${child} MATCHES "handdleAI")
                if(CMAKE_BUILD_TYPE MATCHES "Debug")
                    SET( ${child}_target_link "handleAI" )
                else()
                    SET( ${child}_target_link "handleAI" )
                endif() 
            elseif(${child} MATCHES "spdLog")
                if(CMAKE_BUILD_TYPE MATCHES "Debug")
                    SET( ${child}_target_link "spdlogd" )
                else()
                    SET( ${child}_target_link "spdlog" )
                endif() 
            elseif(${child} MATCHES "breakpad")
                if(CMAKE_BUILD_TYPE MATCHES "Debug")
                    SET( ${child}_target_link "libbreakpad_d" )
                else()
                    SET( ${child}_target_link "libbreakpad" )
                endif() 
            elseif(${child} MATCHES "hwinfo")
                if(CMAKE_BUILD_TYPE MATCHES "Debug")
                    SET( ${child}_target_link 
                    "fmtd"
                    "hwinfo_battery_d"
                    "hwinfo_cpu_d"
                    "hwinfo_disk_d"
                    "hwinfo_gpu_d"
                    "hwinfo_mainboard_d"
                    "hwinfo_network_d"
                    "hwinfo_gpu_d"
                    "hwinfo_os_d"
                    "hwinfo_ram_d")
                else()
                    SET( ${child}_target_link
                    "fmt"
                    "hwinfo_battery"
                    "hwinfo_cpu"
                    "hwinfo_disk"
                    "hwinfo_gpu"
                    "hwinfo_mainboard"
                    "hwinfo_network"
                    "hwinfo_gpu"
                    "hwinfo_os"
                    "hwinfo_ram")
                endif() 
            else()
                SET( ${child}_target_link "" )
            endif()
            message(${child}_target_link: ${${child}_target_link})
        endforeach()

        set(Qt5_DIR ${ENVPATH}/qt5/lib/cmake/Qt5)
        set(QT_DIR ${Qt5_DIR}) 
        set(qtlist "Core" "Widgets" "Network" "Gui" "Charts" "PrintSupport" "Concurrent" "SerialPort""Sql" )
        message("QT_Version :" Qt${QT_VERSION_MAJOR})

        add_definitions(-DQT_MESSAGELOGCONTEXT)#打开QT日志信息
    endif()
endif()
##################
# 设置dll后缀
##
if(BUILD_DEBUG_POSTFIX_D)
  set(CMAKE_DEBUG_POSTFIX d)
endif()

# 包含子项目。
##################
# Automated examples
##
include_directories(${CMAKE_SOURCE_DIR}/include)
if(ON)
  add_subdirectory(src)
  add_subdirectory(subModule)
  add_subdirectory(rpcModule)
#   add_subdirectory(plugin)
  
  
endif()

##################
# Automated modules
##


add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")

string(TIMESTAMP RUN_TIME)
message( " project end : "  ${RUN_TIME} "TYPE:"${CMAKE_BUILD_TYPE})


