# SPDX-License-Identifier: Apache-2.0
# Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.

cmake_minimum_required(VERSION 3.10...4.0)
if (POLICY CMP0144)
  message("--using CMP0144 for Protobuf checking")
  cmake_policy(SET CMP0144 NEW)
else (POLICY CMP0144)
  message("--CMP0144 is not supported, skipping xbtracer")
  return()
endif ()

find_package(Protobuf)
if (NOT Protobuf_FOUND)
  message("Protobuf is not found, skipping xbtracer")
  return()
endif (NOT Protobuf_FOUND)
message("Protobuf version is ${Protobuf_VERSION}.")
if (Protobuf_VERSION VERSION_LESS 3.0)
  # we use timestamp feature of protobuf
  message("Protobuf version ${Protobuf_VERSION} is less than 3.0, skip xbtracer.")
  return()
endif (Protobuf_VERSION VERSION_LESS 3.0)

include_directories (
${Protobuf_INCLUDE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
)
# Generate Cpp files from Proto file
file(GLOB PROTO_SRC_FILES
  "${CMAKE_CURRENT_SOURCE_DIR}/src/*.proto"
)

PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${PROTO_SRC_FILES})

add_custom_target(xbtracer_generated_code DEPENDS ${ProtoSources} ${ProtoHeaders})

add_library(xbtracer_protobuf STATIC ${ProtoSources} ${ProtoHeaders})
add_dependencies(xbtracer_protobuf xbtracer_generated_code)
if (MSVC)
  target_compile_options(xbtracer_protobuf PRIVATE /wd4244 /wd4267)
endif(MSVC)

include_directories(
  "${CMAKE_CURRENT_SOURCE_DIR}/src"
  ${XRT_BINARY_DIR}/gen
)

file(GLOB XBTRACER_COMMON_SRC_FILES
  "${CMAKE_CURRENT_SOURCE_DIR}/src/common/*.cpp"
)

add_library(xbtracer_common STATIC ${XBTRACER_COMMON_SRC_FILES})
if (NOT WIN32)
  target_link_libraries(xbtracer_common PRIVATE dl)
endif (NOT WIN32)

file(GLOB XBTRACER_WRAPPER_SRC_FILES
  "${CMAKE_CURRENT_SOURCE_DIR}/src/wrapper/*.cpp"
)

add_library(xrt_trace SHARED ${XBTRACER_WRAPPER_SRC_FILES} ${ProtoHeaders})
set_target_properties(xrt_trace PROPERTIES VERSION ${XRT_VERSION_STRING} SOVERSION ${XRT_SOVERSION})
target_compile_definitions(xrt_trace PRIVATE XRT_ABI_VERSION=${XRT_VERSION_MAJOR})

target_link_libraries(xrt_trace PRIVATE xbtracer_common xbtracer_protobuf ${Protobuf_LIBRARIES} xrt_coreutil)
add_dependencies(xrt_trace xbtracer_common xbtracer_protobuf xrt_coreutil)

file(GLOB XBTRACER_CAPTURE_SRC_FILES
  "${CMAKE_CURRENT_SOURCE_DIR}/src/capture/*.cpp"
)

add_executable(xrt-tracer ${XBTRACER_CAPTURE_SRC_FILES})
target_link_libraries(xrt-tracer PRIVATE xbtracer_common)
add_dependencies(xrt-tracer xbtracer_common)

file(GLOB XBREPLAY_SRC_FILES
  "${CMAKE_CURRENT_SOURCE_DIR}/src/replay/*.cpp"
)
add_executable(xrt-replay ${XBREPLAY_SRC_FILES})
target_link_libraries(xrt-replay PRIVATE xbtracer_common xbtracer_protobuf ${Protobuf_LIBRARIES} xrt_coreutil)
if (NOT WIN32)
  target_link_libraries(xrt-replay PRIVATE pthread)
endif (NOT WIN32)
add_dependencies(xrt-replay xbtracer_common xbtracer_protobuf xrt_coreutil)
# TODO: when buiding with yocto for APU in CI, the status return from message to jason convertion function
# provided from protobuf built from yocto doesn't match the one in the absl library, which results in
# build failure. After fixing this issue in yocto APU build, we can always print message as JSON.
# for now, we by default disable it, as it is not the key feature in the tracer/replay prototype, and replay
# only tries to dump JSON message when it fails to replay a function.
if (XRT_XBTRACER_ENABLE_JSON)
  target_compile_options(xrt-replay PRIVATE XBTRACER_PROTOBUF_HAS_JASON)

  add_executable(xbtracer_dump
    src/misc/xbtracer_dump.cpp
  )
  target_link_libraries(xbtracer_dump PRIVATE xbtracer_common xbtracer_protobuf ${Protobuf_LIBRARIES})
  add_dependencies(xbtracer_dump xbtracer_common xbtracer_protobuf xrt_coreutil)
endif (XRT_XBTRACER_ENABLE_JSON)

if (WIN32)
include (detoursUtil.cmake)

target_include_directories(xrt_trace PRIVATE ${DETOURS_INCLUDE})
target_link_libraries(xrt_trace PRIVATE ms_detours)
add_dependencies(xrt_trace ms_detours)
target_include_directories(xrt-tracer PRIVATE ${DETOURS_INCLUDE})
target_link_libraries(xrt-tracer PRIVATE ms_detours)
add_dependencies(xrt-tracer ms_detours)
endif(WIN32)

# Install our built executable
set(XBTRACER_TARGETS xrt-tracer xrt-replay)
install (TARGETS ${XBTRACER_TARGETS}
  RUNTIME DESTINATION ${XRT_INSTALL_UNWRAPPED_DIR} COMPONENT ${XRT_BASE_COMPONENT})

# Do not install loader scripts if installing into system default
if (NOT XRT_INSTALL_BIN_DIR STREQUAL XRT_INSTALL_UNWRAPPED_DIR)
  set (XBTRACER_HELPER_SCRIPTS xrt-tracer.bat xrt-replay.bat)
  install (PROGRAMS ${XBTRACER_HELPER_SCRIPTS}
    DESTINATION ${XRT_INSTALL_BIN_DIR} COMPONENT ${XRT_BASE_COMPONENT})
endif()

install(TARGETS xrt_trace
  RUNTIME DESTINATION ${XRT_INSTALL_BIN_DIR} COMPONENT ${XRT_BASE_COMPONENT}
  LIBRARY DESTINATION ${XRT_INSTALL_LIB_DIR} COMPONENT ${XRT_BASE_COMPONENT} NAMELINK_SKIP
)
