# CMakeLists.txt for the ZoneMinder binaries

# Create files from the .in files
configure_file(zm_config_data.h.in "${CMAKE_BINARY_DIR}/zm_config_data.h" @ONLY)

# Group together all the source files that are used by all the binaries (zmc, zmu, zms etc)
set(ZM_BIN_SRC_FILES
  zm_analysis_thread.cpp
  zm_poll_thread.cpp
  zm_buffer.cpp
  zm_camera.cpp
  zm_comms.cpp
  zm_config.cpp
  zm_crypt.cpp
  zm.cpp
  zm_db.cpp
  zm_decoder_thread.cpp
  zm_group_permission.cpp
  zm_monitor_permission.cpp
  zm_logger.cpp
  zm_event.cpp
  zm_eventstream.cpp
  zm_event_tag.cpp
  zm_exception.cpp
  zm_fifo.cpp
  zm_fifo_debug.cpp
  zm_fifo_stream.cpp
  zm_file_camera.cpp
  zm_font.cpp
  zm_frame.cpp
  zm_group.cpp
  zm_image.cpp
  zm_jpeg.cpp
  zm_libvlc_camera.cpp
  zm_libvnc_camera.cpp
  zm_local_camera.cpp
  zm_monitor.cpp
  zm_monitor_monitorlink.cpp
  zm_monitor_rtsp2web.cpp
  zm_monitor_go2rtc.cpp
  zm_monitor_janus.cpp
  zm_monitor_amcrest.cpp
  zm_monitor_onvif.cpp
  zm_monitorlink_expression.cpp
  #zm_monitorlink_token.cpp
  zm_monitorstream.cpp
  zm_mqtt.cpp
  zm_ffmpeg.cpp
  zm_ffmpeg_camera.cpp
  zm_ffmpeg_input.cpp
  zm_mpeg.cpp
  zm_packet.cpp
  zm_packetqueue.cpp
  zm_poly.cpp
  zm_regexp.cpp
  zm_remote_camera.cpp
  zm_remote_camera_http.cpp
  zm_remote_camera_nvsocket.cpp
  zm_remote_camera_rtsp.cpp
  zm_rtp.cpp
  zm_rtp_ctrl.cpp
  zm_rtp_data.cpp
  zm_rtp_source.cpp
  zm_rtsp.cpp
  zm_rtsp_auth.cpp
  zm_rtsp_server_fifo_source.cpp
  zm_rtsp_server_fifo_adts_source.cpp
  zm_rtsp_server_fifo_h264_source.cpp
  zm_rtsp_server_fifo_audio_source.cpp
  zm_rtsp_server_fifo_video_source.cpp
  zm_sdp.cpp
  zm_server.cpp
  zm_signal.cpp
  zm_stream.cpp
  zm_swscale.cpp
  zm_tag.cpp
  zm_time.cpp
  zm_uri.cpp
  zm_user.cpp
  zm_utils.cpp
  zm_videostore.cpp
  zm_zone.cpp
  zm_storage.cpp)

if(GSOAP_FOUND)
  set(ZM_BIN_SRC_FILES
  ${ZM_BIN_SRC_FILES}
  bindings.h
  ${CMAKE_BINARY_DIR}/generated/soapPullPointSubscriptionBindingProxy.cpp
  ${CMAKE_BINARY_DIR}/generated/soapC.cpp
  ${GSOAP_PLUGIN_DIR}/smdevp.c
  ${GSOAP_PLUGIN_DIR}/mecevp.c
  ${GSOAP_PLUGIN_DIR}/wsaapi.c
  ${GSOAP_PLUGIN_DIR}/wsseapi.c
  ${GSOAP_PLUGIN_DIR}/../custom/struct_timeval.c
  )

  SET(GCC_COMPILE_FLAGS "-DWITH_OPENSSL -DWITH_DOM")
  SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_COMPILE_FLAGS}")

  #Create the directory that will host files generated by GSOAP
  file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/generated)

  #some files are generated by gsoap
  set_source_files_properties( ${CMAKE_BINARY_DIR}/generated/soapClientLib.c       PROPERTIES GENERATED TRUE )
  set_source_files_properties( ${CMAKE_BINARY_DIR}/generated/soapC.c       PROPERTIES GENERATED TRUE )
  set_source_files_properties( ${CMAKE_BINARY_DIR}/generated/soapPullPointSubscriptionBindingProxy.cpp     PROPERTIES GENERATED TRUE )
  set_source_files_properties( ${GSOAP_PLUGIN_DIR}/smdevp.c PROPERTIES LANGUAGE CXX)
  set_source_files_properties( ${GSOAP_PLUGIN_DIR}/mecevp.c PROPERTIES LANGUAGE CXX)
  set_source_files_properties( ${GSOAP_PLUGIN_DIR}/wsaapi.c PROPERTIES LANGUAGE CXX)
  set_source_files_properties( ${GSOAP_PLUGIN_DIR}/wsseapi.c PROPERTIES LANGUAGE CXX)
  set_source_files_properties( ${GSOAP_PLUGIN_DIR}/../custom/struct_timeval.c PROPERTIES LANGUAGE CXX)

  #Create a cmake target that generate gsoap files
  add_custom_command(
    OUTPUT ${CMAKE_BINARY_DIR}/generated/soapC.cpp
    OUTPUT ${CMAKE_BINARY_DIR}/generated/soapPullPointSubscriptionBindingProxy.cpp
    #COMMAND ${GSOAP_WSDL2H} -d -P -O2 -o ${CMAKE_BINARY_DIR}/generated/bindings.h http://www.onvif.org/onvif/ver10/events/wsdl/event.wsdl
    #COMMAND echo '\#import \"wsse.h\"' >> ${CMAKE_BINARY_DIR}/generated/bindings.h
    #COMMAND echo '\#import \"struct_timeval.h\"' >> ${CMAKE_BINARY_DIR}/generated/bindings.h
    COMMAND ${GSOAP_SOAPCPP2} -a -n -2 -C -I ${GSOAP_PLUGIN_DIR}/.. -I ${GSOAP_PLUGIN_DIR}/../import/ -I ${GSOAP_PLUGIN_DIR}/../custom/ -d ${CMAKE_BINARY_DIR}/generated -j -x ${CMAKE_CURRENT_SOURCE_DIR}/bindings.h
    COMMENT "CREATING STUBS AND GLUE CODE"
  )

  add_custom_target(GSOAP_GENERATION_TARGET
        DEPENDS ${CMAKE_BINARY_DIR}/generated/soapC.cpp
        DEPENDS ${CMAKE_BINARY_DIR}/generated/soapPullPointSubscriptionBindingProxy.cpp
        DEPENDS ${GSOAP_PLUGIN_DIR}/smdevp.c
        DEPENDS ${GSOAP_PLUGIN_DIR}/mecevp.c
        DEPENDS ${GSOAP_PLUGIN_DIR}/wsaapi.c
        DEPENDS ${GSOAP_PLUGIN_DIR}/wsseapi.c
        DEPENDS ${GSOAP_PLUGIN_DIR}/../custom/struct_timeval.c
  )

endif()

# A fix for cmake recompiling the source files for every target.
add_library(zm STATIC ${ZM_BIN_SRC_FILES})

target_include_directories(zm
  PUBLIC
    ${CMAKE_BINARY_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}
    ../dep/booleval/include
    )

if(GSOAP_FOUND)
target_include_directories(zm
  PUBLIC
    ${CMAKE_BINARY_DIR}/generated
    ${GSOAP_PLUGIN_DIR}/..
    ${GSOAP_INCLUDE_DIR})

endif()

target_link_libraries(zm
  PUBLIC
    FFMPEG::avcodec
    FFMPEG::avdevice
    FFMPEG::avformat
    FFMPEG::avutil
    FFMPEG::swresample
    FFMPEG::swscale
    libbcrypt::bcrypt
    RtspServer::RtspServer
    martinmoene::span-lite
    ${ZM_BIN_LIBS}
  PRIVATE
    zm-core-interface)

set(GSOAP_LIBRARIES ${GSOAP_CXX_LIBRARIES})
if(HAVE_LIBOPENSSL)
  set(GSOAP_LIBRARIES ${GSOAP_SSL_CXX_LIBRARIES})
endif()

if(GSOAP_FOUND)
  target_link_libraries(zm
    PUBLIC
      ${GSOAP_LIBRARIES}
      ${OPENSSL_SSL_LIBRARY}
      ${OPENSSL_CRYPTO_LIBRARY})
endif()

if(${ZM_JWT_BACKEND} STREQUAL "jwt_cpp")
  target_link_libraries(zm
    PUBLIC
      jwt-cpp::jwt-cpp)
elseif(${ZM_JWT_BACKEND} STREQUAL "libjwt")
  target_link_libraries(zm
    PUBLIC
      JWT::libjwt)
endif()

if(TARGET V4L2::videodev2)
  target_link_libraries(zm
    PRIVATE
      V4L2::videodev2)
endif()

add_executable(zmc zmc.cpp)
add_executable(zms zms.cpp)
add_executable(zmu zmu.cpp)
add_executable(zmbenchmark zmbenchmark.cpp)

if(GSOAP_FOUND)
  #Make sure that the client is compiled only after gsoap has been processed
  add_dependencies(zmc GSOAP_GENERATION_TARGET)
endif()

target_link_libraries(zmc
  PRIVATE
    zm-core-interface
    zm
    ${ZM_EXTRA_LIBS}
    ${CMAKE_DL_LIBS})

target_link_libraries(zms
  PRIVATE
    zm-core-interface
    zm
    ${ZM_EXTRA_LIBS}
    ${CMAKE_DL_LIBS})

target_link_libraries(zmu
  PRIVATE
    zm-core-interface
    zm
    ${ZM_EXTRA_LIBS}
    ${CMAKE_DL_LIBS})

target_link_libraries(zmbenchmark
  PRIVATE
    zm-core-interface
    zm
    ${ZM_EXTRA_LIBS}
    ${CMAKE_DL_LIBS})

# Generate man files for the binaries destined for the bin folder
if(BUILD_MAN)
  foreach(CBINARY zmc zmu)
    POD2MAN(${CMAKE_CURRENT_SOURCE_DIR}/${CBINARY}.cpp ${CBINARY} 8 ${ZM_MANPAGE_DEST_PREFIX})
  endforeach(CBINARY zmc zmu)
endif()

install(TARGETS zmc zmu RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(TARGETS zms RUNTIME DESTINATION "${ZM_CGIDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(CODE "execute_process(COMMAND ln -sf zms nph-zms WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/nph-zms DESTINATION "${ZM_CGIDIR}")

if(HAVE_RTSP_SERVER)
  add_executable(zm_rtsp_server zm_rtsp_server.cpp)
  target_link_libraries(zm_rtsp_server
    PRIVATE
      zm-core-interface
      zm
      ${ZM_EXTRA_LIBS}
      ${CMAKE_DL_LIBS})
  install(TARGETS zm_rtsp_server RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif()
