cmake_minimum_required(VERSION 3.12.0)
project(cec)

set(cec_NAME cec)
set(cec_DESCRIPTION "libCEC")

enable_language(CXX)

include(CheckCXXSourceCompiles)
include(CheckLibraryExists)
include(CheckIncludeFiles)
include(CheckCXXCompilerFlag)
include(../../cmake/WindowsDebug.cmake)
include(GNUInstallDirs)

check_cxx_compiler_flag("-std=c++11" SUPPORTS_CXX11)
if (SUPPORTS_CXX11)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()

find_package(Threads REQUIRED)

include_directories(${PROJECT_SOURCE_DIR}
                    ${PROJECT_SOURCE_DIR}/../../include)

set(CMAKE_POSITION_INDEPENDENT_CODE on)

# main libCEC files
set(CEC_SOURCES CECClient.cpp
                CECProcessor.cpp
                LibCEC.cpp
                LibCECC.cpp)

# /adapter
set(CEC_SOURCES_ADAPTER adapter/AdapterFactory.cpp)

# /adapter/Pulse-Eight
set(CEC_SOURCES_ADAPTER_P8 adapter/Pulse-Eight/USBCECAdapterMessage.cpp
                           adapter/Pulse-Eight/USBCECAdapterCommands.cpp
                           adapter/Pulse-Eight/USBCECAdapterCommunication.cpp
                           adapter/Pulse-Eight/USBCECAdapterMessageQueue.cpp
                           adapter/Pulse-Eight/USBCECAdapterDetection.cpp)

# /devices
set(CEC_SOURCES_DEVICES devices/CECAudioSystem.cpp
                        devices/CECBusDevice.cpp
                        devices/CECDeviceMap.cpp
                        devices/CECPlaybackDevice.cpp
                        devices/CECRecordingDevice.cpp
                        devices/CECTuner.cpp
                        devices/CECTV.cpp)

# /implementations
set(CEC_SOURCES_IMPLEMENTATIONS implementations/ANCommandHandler.cpp
                                implementations/CECCommandHandler.cpp
                                implementations/SLCommandHandler.cpp
                                implementations/VLCommandHandler.cpp
                                implementations/RLCommandHandler.cpp
                                implementations/PHCommandHandler.cpp
                                implementations/RHCommandHandler.cpp
                                implementations/AQCommandHandler.cpp
                                implementations/SYCommandHandler.cpp)

# /platform/*
set(CEC_SOURCES_PLATFORM platform/adl/adl-edid.cpp
                         platform/nvidia/nv-edid.cpp
                         platform/drm/drm-edid.cpp)

# headers
set(CEC_EXT_HEADERS ${PROJECT_SOURCE_DIR}/../../include/cec.h
                    ${PROJECT_SOURCE_DIR}/../../include/cecc.h
                    ${PROJECT_SOURCE_DIR}/../../include/cecloader.h
                    ${PROJECT_SOURCE_DIR}/../../include/ceccloader.h
                    ${PROJECT_SOURCE_DIR}/../../include/cectypes.h
                    ${PROJECT_SOURCE_DIR}/../../include/version.h)
source_group("Header Files (external)" FILES ${CEC_EXT_HEADERS})
set(CEC_HEADERS devices/CECRecordingDevice.h
                devices/CECTuner.h
                devices/CECAudioSystem.h
                devices/CECTV.h
                devices/CECBusDevice.h
                devices/CECDeviceMap.h
                devices/CECPlaybackDevice.h
                adapter/Exynos/ExynosCEC.h
                adapter/Exynos/ExynosCECAdapterDetection.h
                adapter/Exynos/ExynosCECAdapterCommunication.h
                adapter/Linux/LinuxCECAdapterDetection.h
                adapter/Linux/LinuxCECAdapterCommunication.h
                adapter/AOCEC/AOCEC.h
                adapter/AOCEC/AOCECAdapterDetection.h
                adapter/AOCEC/AOCECAdapterCommunication.h
                adapter/Pulse-Eight/USBCECAdapterMessageQueue.h
                adapter/Pulse-Eight/USBCECAdapterCommunication.h
                adapter/Pulse-Eight/USBCECAdapterCommands.h
                adapter/Pulse-Eight/USBCECAdapterDetection.h
                adapter/Pulse-Eight/USBCECAdapterMessage.h
                adapter/TDA995x/TDA995xCECAdapterDetection.h
                adapter/TDA995x/AdapterMessageQueue.h
                adapter/TDA995x/TDA995xCECAdapterCommunication.h
                adapter/AdapterFactory.h
                adapter/AdapterCommunication.h
                adapter/RPi/RPiCECAdapterMessageQueue.h
                adapter/RPi/RPiCECAdapterCommunication.h
                adapter/RPi/RPiCECAdapterDetection.h
                adapter/IMX/IMXCECAdapterCommunication.h
                adapter/IMX/IMXCECAdapterDetection.h
                CECInputBuffer.h
                platform/os.h
                platform/posix/os-types.h
                platform/posix/os-socket.h
                platform/windows/os-types.h
                platform/windows/os-socket.h
                platform/threads/mutex.h
                platform/threads/threads.h
                platform/util/buffer.h
                platform/util/timeutils.h
                platform/util/util.h
                platform/util/StringUtils.h
                platform/sockets/socket.h
                platform/sockets/cdevsocket.h
                platform/util/baudrate.h
                platform/util/edid.h
                platform/nvidia/nv-edid.h
                platform/adl/adl_structures.h
                platform/adl/adl_defines.h
                platform/adl/adl-edid.h
                platform/adl/adl_sdk.h
                platform/sockets/serialport.h
                platform/X11/randr-edid.h
                CECClient.h
                LibCEC.h
                CECTypeUtils.h
                implementations/SLCommandHandler.h
                implementations/CECCommandHandler.h
                implementations/VLCommandHandler.h
                implementations/RLCommandHandler.h
                implementations/ANCommandHandler.h
                implementations/RHCommandHandler.h
                implementations/PHCommandHandler.h
                implementations/AQCommandHandler.h
                CECProcessor.h)
source_group("Header Files" FILES ${CEC_HEADERS})

# platform and device specific
include(cmake/SetBuildInfo.cmake)
include(cmake/CheckPlatformSupport.cmake)

## create project groups
source_group("Source Files" FILES ${CEC_SOURCES})
source_group("Source Files\\adapter" FILES ${CEC_SOURCES_ADAPTER})
source_group("Source Files\\adapter\\Pulse-Eight" FILES ${CEC_SOURCES_ADAPTER_P8})
source_group("Source Files\\devices" FILES ${CEC_SOURCES_DEVICES})
source_group("Source Files\\implementations" FILES ${CEC_SOURCES_IMPLEMENTATIONS})
source_group("Source Files\\platform" FILES ${CEC_SOURCES_PLATFORM})

list(APPEND CEC_SOURCES ${CEC_HEADERS}
                        ${CEC_EXT_HEADERS}
                        ${CEC_SOURCES_ADAPTER}
                        ${CEC_SOURCES_ADAPTER_P8}
                        ${CEC_SOURCES_DEVICES}
                        ${CEC_SOURCES_IMPLEMENTATIONS}
                        ${CEC_SOURCES_PLATFORM})

# write env.h
set(LIBCEC_LIBREQUIRES "${PLATFORM_LIBREQUIRES}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/env.h.in ${CMAKE_CURRENT_SOURCE_DIR}/env.h)
if (WIN32)
  # write libcec.rc
  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libcec.rc.in ${CMAKE_CURRENT_SOURCE_DIR}/libcec.rc)
  add_definitions(-DDLL_EXPORT)
  add_definitions(-DTARGET_WINDOWS -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS -D_WINSOCKAPI_)
  if (WIN64 OR ARM64)
    string(REPLACE "/arch:SSE2" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
  else()
    add_definitions(-D_USE_32BIT_TIME_T)
  endif()
else()
  # write pkgconfig
  include(../../cmake/PkgConfigHandler.cmake)
  configure_pc_file(cec ${CMAKE_CURRENT_SOURCE_DIR}/libcec.pc.in
                        ${CMAKE_CURRENT_SOURCE_DIR}/libcec.pc
                        ${CMAKE_INSTALL_PREFIX}
                        ${CMAKE_INSTALL_FULL_LIBDIR}
                        ${CMAKE_INSTALL_PREFIX}/include)

  install(FILES         ${CMAKE_CURRENT_SOURCE_DIR}/libcec.pc
          DESTINATION   ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()

# install headers
install(FILES ${PROJECT_SOURCE_DIR}/../../include/cec.h
              ${PROJECT_SOURCE_DIR}/../../include/cecc.h
              ${PROJECT_SOURCE_DIR}/../../include/cecloader.h
              ${PROJECT_SOURCE_DIR}/../../include/ceccloader.h
              ${PROJECT_SOURCE_DIR}/../../include/cectypes.h
              ${PROJECT_SOURCE_DIR}/../../include/version.h
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libcec)

# external dependencies
include(cmake/LinkPlatformSupport.cmake)

set(libsrc ${CEC_SOURCES})
add_library(libobj OBJECT ${libsrc})
set_property(TARGET libobj PROPERTY POSITION_INDEPENDENT_CODE 1)


add_library(cec-shared SHARED $<TARGET_OBJECTS:libobj>)
set_target_properties(cec-shared PROPERTIES
    VERSION   ${LIBCEC_VERSION_MAJOR}.${LIBCEC_VERSION_MINOR}.${LIBCEC_VERSION_PATCH}
    SOVERSION ${LIBCEC_VERSION_MAJOR}
    OUTPUT_NAME cec)
target_link_libraries(cec-shared ${cec_depends})


if(NOT DISABLE_STATIC)
  # Windows names the DLL's import library cec.lib too, so a static library
  # called cec overwrites it - in the build tree and again on install, with
  # whichever target links last winning. Anything then linking the install tree
  # gets unresolved __imp_libcec_* symbols, or silently links libCEC statically.
  # Unix has no such clash: libcec.a next to libcec.so.
  set(CEC_STATIC_NAME cec)
  if(WIN32)
    set(CEC_STATIC_NAME cec-static)
  endif()

  add_library(cec-static STATIC $<TARGET_OBJECTS:libobj>)
  set_target_properties(cec-static PROPERTIES
      VERSION   ${LIBCEC_VERSION_MAJOR}.${LIBCEC_VERSION_MINOR}.${LIBCEC_VERSION_PATCH}
      SOVERSION ${LIBCEC_VERSION_MAJOR}
      OUTPUT_NAME ${CEC_STATIC_NAME})
  target_link_libraries(cec-static ${cec_depends})
endif()

if(WIN32)
  if (MSVC)
    # generate pdb in release mode too
	cmake_policy(SET CMP0141 NEW)
	set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$<CONFIG:Release,RelWithDebInfo>:ProgramDatabase>")

    set_target_properties(cec-shared PROPERTIES
        COMPILE_PDB_NAME_DEBUG cec
        COMPILE_PDB_NAME_RELEASE cec
        COMPILE_PDB_NAME_MINSIZEREL cec
        COMPILE_PDB_NAME_RELWITHDEBINFO cec)

    # install generated pdb
    install(FILES $<TARGET_FILE_DIR:cec-shared>/cec.pdb
            DESTINATION ${LIB_DESTINATION}
			OPTIONAL)
  endif(MSVC)
endif(WIN32)

# install the library (and the static library when built) and export a CMake
# package configuration, so consumers can find_package(libcec) and link the
# imported libcec::cec-shared / libcec::cec-static targets.
set(CEC_INSTALL_TARGETS cec-shared)
if(NOT DISABLE_STATIC)
  list(APPEND CEC_INSTALL_TARGETS cec-static)
endif()

# ARCHIVE is its own destination rather than LIB_DESTINATION: on Windows that is
# bin/, which is where the .dll belongs but not the import library. Everywhere
# else the two are the same value, so this only moves the Windows .lib.
install(TARGETS ${CEC_INSTALL_TARGETS}
        EXPORT libcec
        RUNTIME DESTINATION ${LIB_DESTINATION}
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        LIBRARY DESTINATION ${LIB_DESTINATION})

include(CMakePackageConfigHelpers)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/libcec-config-version.cmake
                                 VERSION ${LIBCEC_VERSION_MAJOR}.${LIBCEC_VERSION_MINOR}.${LIBCEC_VERSION_PATCH}
                                 COMPATIBILITY AnyNewerVersion)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcec-config-version.cmake
              ${CMAKE_CURRENT_SOURCE_DIR}/cmake/libcec-config.cmake
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libcec)

install(EXPORT libcec
        NAMESPACE libcec::
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libcec)

include(cmake/DisplayPlatformSupport.cmake)
