# Copyright Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT

# Many things need to be configured with paths to additional LLVM tools.
# If a project is using an amd-hip or amd-llvm toolchain, then it will already
# have an implicit dep on the toolchain, so it is safe to reference binaries
# here without worrying about build deps.
therock_cmake_subproject_dist_dir(_blas_hack_hip_dir hip-clr)
cmake_path(APPEND _blas_hack_hip_dir lib/llvm OUTPUT_VARIABLE _toolchain_dir)

# Most libraries need to depend on the profiler, but is conditionally only used
# on Posix.
set(optional_profiler_deps)
if(THEROCK_FLAG_INCLUDE_PROFILER)
  list(APPEND optional_profiler_deps roctracer rocprofiler-sdk)
endif()


##############################################################################
# hipBLAS-common
##############################################################################
set(_blas_subproject_names)

therock_cmake_subproject_declare(hipBLAS-common
EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/projects/hipblas-common"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/hipBLAS-common"
BACKGROUND_BUILD
COMPILER_TOOLCHAIN
  amd-hip
BUILD_DEPS
  rocm-cmake
RUNTIME_DEPS
  hip-clr
)
therock_cmake_subproject_glob_c_sources(hipBLAS-common
SUBDIRS
    library
)
therock_cmake_subproject_provide_package(hipBLAS-common hipblas-common lib/cmake/hipblas-common)
therock_cmake_subproject_activate(hipBLAS-common)
list(APPEND _blas_subproject_names hipBLAS-common)


##############################################################################
# rocRoller
##############################################################################

if(WIN32)
  set(_enable_rocRoller "OFF")
else()
  set(_enable_rocRoller "ON")
endif()

if(_enable_rocRoller)
  therock_cmake_subproject_declare(rocRoller
    EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/shared/rocroller"
    BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/rocRoller"
    BACKGROUND_BUILD
    CMAKE_ARGS
      -DHIP_PLATFORM=amd
      -DROCROLLER_ENABLE_YAML_CPP=ON
      -DROCROLLER_ENABLE_CLIENT=OFF
      -DROCROLLER_BUILD_TESTING=${THEROCK_BUILD_TESTING}
      -DROCROLLER_BUILD_SHARED_LIBS=ON
    CMAKE_INCLUDES
      therock_explicit_finders.cmake
    COMPILER_TOOLCHAIN
      amd-hip
    BUILD_DEPS
      mxDataGenerator
      rocm-cmake
      therock-catch2
      therock-fmt
      therock-googletest
      therock-libdivide
      therock-msgpack-cxx
      therock-spdlog
      therock-yaml-cpp
      # therock-cl11 # will need this dep to enable client
    RUNTIME_DEPS
      therock-host-blas
      hip-clr
      ${optional_profiler_deps}
    TEST_SUBPROJECTS
      hipBLASLt
  )
  therock_cmake_subproject_glob_c_sources(rocRoller
  SUBDIRS
      .
  )
  therock_cmake_subproject_provide_package(rocRoller rocroller lib/cmake/rocroller)
  therock_cmake_subproject_activate(rocRoller)
  list(APPEND _blas_subproject_names rocRoller)
endif()


##############################################################################
# origami
##############################################################################

therock_cmake_subproject_declare(origami
  EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/shared/origami"
  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/origami"
  BACKGROUND_BUILD
  CMAKE_ARGS
    -DHIP_PLATFORM=amd
    -DORIGAMI_BUILD_SHARED_LIBS=ON
    -DORIGAMI_BUILD_TESTING=${THEROCK_BUILD_TESTING}
    # Python bindings (and their nanobind/tsl-robin-map deps) are built out of
    # TheRock; land the C++ library only. Re-enable alongside a nanobind
    # provider once bindings have a home (mirrors the hipDNN direction, #6425).
    -DORIGAMI_ENABLE_PYTHON=OFF
    -DORIGAMI_ENABLE_FETCH=OFF
  COMPILER_TOOLCHAIN
    amd-hip
  BUILD_DEPS
    rocm-cmake
    therock-catch2
  RUNTIME_DEPS
    hip-clr
)
therock_cmake_subproject_glob_c_sources(origami
  SUBDIRS
    .
)
therock_cmake_subproject_provide_package(origami origami lib/cmake/origami)
therock_cmake_subproject_activate(origami)
list(APPEND _blas_subproject_names origami)


##############################################################################
# hipBLASLt
##############################################################################

set(hipBLASLt_runtime_deps)
if(NOT WIN32)
  # Required on Linux.
  list(APPEND hipBLASLt_runtime_deps amdsmi)

  # rocm_smi_lib remains optional (guarded).
  if(TARGET rocm_smi_lib)
    list(APPEND hipBLASLt_runtime_deps rocm_smi_lib)
  endif()
endif()

set(hipBLASLt_rocRoller_deps)
if(_enable_rocRoller)
  list(APPEND hipBLASLt_rocRoller_build_deps
    mxDataGenerator
    therock-fmt
    therock-yaml-cpp
    therock-spdlog
    therock-libdivide
  )
  list(APPEND hipBLASLt_rocRoller_runtime_deps
    rocRoller
  )
endif()

therock_cmake_subproject_declare(hipBLASLt
  EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/projects/hipblaslt"
  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/hipBLASLt"
  BACKGROUND_BUILD
  DEFAULT_GPU_TARGETS
    gfx1100  # TODO: Fix hipblaslt to accept an empty target list.
  CMAKE_ARGS
    -DHIP_PLATFORM=amd
    -DHIPBLASLT_ENABLE_BLIS=OFF  # TODO: Evaluate
    -DTENSILELITE_BUILD_TESTING=OFF
    -DTENSILELITE_ENABLE_CLIENT=$<IF:$<BOOL:${WIN32}>,OFF,${THEROCK_BUILD_TESTING}>
    -DHIPBLASLT_BUILD_TESTING=${THEROCK_BUILD_TESTING}
    -DHIPBLASLT_INSTALL_TENSILELITE_TEST_ARTIFACTS=${THEROCK_BUILD_TESTING}
    -DROCISA_USE_STABLE_ABI=ON
    -DHIPBLASLT_ENABLE_ROCROLLER=${_enable_rocRoller}
    -DHIPBLASLT_ENABLE_FETCH=OFF
    -DHIPBLASLT_ENABLE_THEROCK=ON
  CMAKE_INCLUDES
    therock_explicit_finders.cmake
  COMPILER_TOOLCHAIN
    amd-hip
  BUILD_DEPS
    hipBLAS-common
    rocm-cmake
    therock-googletest
    therock-msgpack-cxx
    ${hipBLASLt_rocRoller_build_deps}
  RUNTIME_DEPS
    hip-clr
    origami
    therock-host-blas
    ${hipBLASLt_rocRoller_runtime_deps}
    ${hipBLASLt_runtime_deps}
    ${optional_profiler_deps}
  TEST_SUBPROJECTS
    hipSPARSELt
    MIOpen
)
therock_cmake_subproject_glob_c_sources(hipBLASLt
  SUBDIRS
    .
)
therock_cmake_subproject_provide_package(hipBLASLt hipblaslt lib/cmake/hipblaslt)
therock_cmake_subproject_activate(hipBLASLt)
list(APPEND _blas_subproject_names hipBLASLt)


##############################################################################
# rocBLAS
##############################################################################

set(rocBLAS_optional_runtime_deps)
if(NOT WIN32)
  # rocBLAS is hard-coded to not expect rocm-smi.
  if(TARGET rocm_smi_lib)
    list(APPEND rocBLAS_optional_runtime_deps rocm_smi_lib)
  endif()
endif()
if(THEROCK_BUILD_TESTING)
  # Client tests link ILP64 reference BLAS (see cmake/finders/FindBLAS.cmake + BLA_SIZEOF_INTEGER=8).
  list(APPEND rocBLAS_optional_runtime_deps therock-host-blas64)
endif()

set(rocBLAS_extra_cmake_args)
if(THEROCK_BUILD_TESTING)
  list(APPEND rocBLAS_extra_cmake_args -DROCBLAS_CLIENTS_REFERENCE_ILP64=ON)
endif()

# Disable rocBLAS samples on Windows due to use of deprecated
# <experimental/filesystem> in client_utility.cpp with MSVC.
# TODO(#3630): Re-enable once upstream rocBLAS migrates to <filesystem>.
if(WIN32)
  set(_blas_build_samples OFF)
else()
  set(_blas_build_samples ${THEROCK_BUILD_TESTING})
endif()

therock_cmake_subproject_declare(rocBLAS
  EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/projects/rocblas"
  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/rocBLAS"
  BACKGROUND_BUILD
  CMAKE_ARGS
    -DHIP_PLATFORM=amd
    -DROCM_PATH=
    -DROCM_DIR=
    -Dhipblaslt_path=
    -DBUILD_WITH_TENSILE=ON
    -DBUILD_WITH_HIPBLASLT=ON
    # TODO: With `Tensile_TEST_LOCAL_PATH` set, the resulting build path is ${Tensile_TEST_LOCAL_PATH}/build.
    "-DTensile_TEST_LOCAL_PATH=${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/shared/tensile"
    # Since using a local Tensile vs fetched, unset TENSILE_VERSION to avoid
    # doing a strict check of exact version.
    -DTENSILE_VERSION=
    -DBUILD_CLIENTS_TESTS=${THEROCK_BUILD_TESTING}
    -DBUILD_CLIENTS_SAMPLES=${_blas_build_samples}
    -DBUILD_CLIENTS_BENCHMARKS=${THEROCK_BUILD_TESTING}
    -DLINK_BLIS=OFF
    ${rocBLAS_extra_cmake_args}
  CMAKE_INCLUDES
    therock_explicit_finders.cmake
  COMPILER_TOOLCHAIN
    amd-hip
  BUILD_DEPS
    hipBLAS-common
    rocm-cmake
    therock-googletest
    therock-msgpack-cxx
  RUNTIME_DEPS
    hip-clr
    hipBLASLt
    ${rocBLAS_optional_runtime_deps}
    ${optional_profiler_deps}
  TEST_SUBPROJECTS
    hipBLAS
    rocSOLVER
)
therock_cmake_subproject_glob_c_sources(rocBLAS
SUBDIRS
    .
)
therock_cmake_subproject_provide_package(rocBLAS rocblas lib/cmake/rocblas)
therock_cmake_subproject_activate(rocBLAS)
list(APPEND _blas_subproject_names rocBLAS)


if(THEROCK_ENABLE_SPARSE)
  ##############################################################################
  # rocSPARSE
  ##############################################################################
  set(_sparse_subproject_names)

  therock_cmake_subproject_declare(rocSPARSE
    EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/projects/rocsparse"
    BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/rocSPARSE"
    BACKGROUND_BUILD
    CMAKE_ARGS
      -DHIP_PLATFORM=amd
      -DROCM_PATH=
      -DROCM_DIR=
      -DBUILD_WITH_ROCBLAS=ON
      -DBUILD_CLIENTS_TESTS=${THEROCK_BUILD_TESTING}
      -DBUILD_CLIENTS_BENCHMARKS=${THEROCK_BUILD_TESTING}
      -DBUILD_CLIENTS_SAMPLES=OFF
    CMAKE_INCLUDES
      therock_explicit_finders.cmake
    COMPILER_TOOLCHAIN
      amd-hip
    BUILD_DEPS
      rocm-cmake
      rocBLAS
      rocPRIM
      therock-googletest
    RUNTIME_DEPS
      hip-clr
      ${optional_profiler_deps}
    TEST_SUBPROJECTS
      hipSPARSE
      rocSOLVER
      hipSOLVER
  )
  therock_cmake_subproject_glob_c_sources(rocSPARSE
    SUBDIRS
      .
  )
  therock_cmake_subproject_provide_package(rocSPARSE rocsparse lib/cmake/rocsparse)
  therock_cmake_subproject_activate(rocSPARSE)
  list(APPEND _sparse_subproject_names rocSPARSE)

  ##############################################################################
  # hipSPARSE
  ##############################################################################

  therock_cmake_subproject_declare(hipSPARSE
    EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/projects/hipsparse"
    BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/hipSPARSE"
    BACKGROUND_BUILD
    CMAKE_ARGS
      -DHIP_PLATFORM=amd
      -DROCM_PATH=
      -DROCM_DIR=
      -DBUILD_CLIENTS_TESTS=${THEROCK_BUILD_TESTING}
      -DBUILD_CLIENTS_BENCHMARKS=${THEROCK_BUILD_TESTING}
      -DBUILD_CLIENTS_SAMPLES=OFF
    COMPILER_TOOLCHAIN
      amd-hip
    BUILD_DEPS
      rocm-cmake
      rocSPARSE
      therock-googletest
    RUNTIME_DEPS
      hip-clr
    TEST_SUBPROJECTS
  )
  therock_cmake_subproject_glob_c_sources(hipSPARSE
    SUBDIRS
      .
  )
  therock_cmake_subproject_provide_package(hipSPARSE hipsparse lib/cmake/hipsparse)
  therock_cmake_subproject_activate(hipSPARSE)
  list(APPEND _blas_subproject_names hipSPARSE)

  ##############################################################################
  # hipSPARSELt
  ##############################################################################

  if(NOT WIN32) # Remove this block once hipSPARSELt is supported on Windows
    # hipSPARSELt expects amd_smi on Linux.
    set(hipSPARSELt_runtime_deps)

    # Required on Linux.
    list(APPEND hipSPARSELt_runtime_deps amdsmi)

    # rocm_smi_lib is optional.
    if(TARGET rocm_smi_lib)
      list(APPEND hipSPARSELt_runtime_deps rocm_smi_lib)
    endif()

    therock_cmake_subproject_declare(hipSPARSELt
      EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/projects/hipsparselt"
      BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/hipSPARSELt"
      BACKGROUND_BUILD
      CMAKE_ARGS
        -DHIP_PLATFORM=amd
        -DHIPSPARSELT_BUILD_TESTING=${THEROCK_BUILD_TESTING}
        -DHIPSPARSELT_ENABLE_BENCHMARKS=${THEROCK_BUILD_TESTING}
        -DHIPSPARSELT_ENABLE_SAMPLES=OFF
        -DHIPSPARSELT_ENABLE_FETCH=OFF
        -DHIPSPARSELT_ENABLE_THEROCK=ON
      COMPILER_TOOLCHAIN
        amd-hip
      BUILD_DEPS
        rocm-cmake
        hipBLAS-common
        hipSPARSE
        rocSPARSE
        therock-googletest
        therock-msgpack-cxx
      RUNTIME_DEPS
        hip-clr
        hipBLASLt
        origami
        therock-host-blas
        ${hipSPARSELt_runtime_deps}
        ${optional_profiler_deps}
      TEST_SUBPROJECTS
    )
    therock_cmake_subproject_glob_c_sources(hipSPARSELt
      SUBDIRS
        .
    )
    therock_cmake_subproject_provide_package(hipSPARSELt hipsparselt lib/cmake/hipsparselt)
    therock_cmake_subproject_activate(hipSPARSELt)
    list(APPEND _blas_subproject_names hipSPARSELt)
  endif()
endif(THEROCK_ENABLE_SPARSE)


if(THEROCK_ENABLE_SOLVER)
  ##############################################################################
  # rocSOLVER
  ##############################################################################

  set(rocSOLVER_optional_deps)
  if(THEROCK_BUILD_TESTING)
    list(APPEND rocSOLVER_optional_deps therock-host-blas)
  endif()

  therock_cmake_subproject_declare(rocSOLVER
      EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/projects/rocsolver"
      BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/rocSOLVER"
      BACKGROUND_BUILD
      CMAKE_ARGS
        -DHIP_PLATFORM=amd
        -DROCM_PATH=
        -DROCM_DIR=
        -DBUILD_CLIENTS_BENCHMARKS=${THEROCK_BUILD_TESTING}
        -DBUILD_CLIENTS_TESTS=${THEROCK_BUILD_TESTING}
        -DROCSOLVER_FIND_PACKAGE_LAPACK_CONFIG=OFF
      COMPILER_TOOLCHAIN
        amd-hip
      BUILD_DEPS
        rocm-cmake
        rocPRIM
        therock-fmt
        therock-googletest
      RUNTIME_DEPS
        hip-clr
        rocBLAS
        ${rocSOLVER_optional_deps}
      TEST_SUBPROJECTS
        hipSOLVER
        hipBLAS
  )
  therock_cmake_subproject_glob_c_sources(rocSOLVER
      SUBDIRS
      .
  )
  therock_cmake_subproject_provide_package(rocSOLVER rocsolver lib/cmake/rocsolver)
  therock_cmake_subproject_activate(rocSOLVER)
  list(APPEND _solver_subproject_names rocSOLVER)

  ##############################################################################
  # hipSOLVER
  ##############################################################################

  set(hipSOLVER_optional_deps)
  if(THEROCK_BUILD_TESTING)
    list(APPEND hipSOLVER_optional_deps therock-host-blas)
  endif()

  if(WIN32)
    set(hipSOLVER_build_with_sparse "OFF")
  else()
    # Note: BUILD_WITH_SPARSE converts rocSPARSE and cholmod to build time vs
    # runtime/dlopen deps.
    set(hipSOLVER_build_with_sparse "ON")
    list(APPEND hipSOLVER_optional_deps therock-SuiteSparse)
  endif()

  therock_cmake_subproject_declare(hipSOLVER
      EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/projects/hipsolver"
      BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/hipSOLVER"
      BACKGROUND_BUILD
      CMAKE_ARGS
        -DHIP_PLATFORM=amd
        -DROCM_PATH=
        -DROCM_DIR=
        -DBUILD_HIPSPARSE_TESTS=OFF
        -DBUILD_WITH_SPARSE=${hipSOLVER_build_with_sparse}
        -DBUILD_CLIENTS_BENCHMARKS=${THEROCK_BUILD_TESTING}
        -DBUILD_CLIENTS_TESTS=${THEROCK_BUILD_TESTING}
        -DHIPSOLVER_FIND_PACKAGE_LAPACK_CONFIG=OFF
        -DEXPORT_FORTRAN_BINDINGS=OFF
      COMPILER_TOOLCHAIN
        amd-hip
      BUILD_DEPS
        rocm-cmake
        therock-googletest
      RUNTIME_DEPS
        hip-clr
        rocBLAS
        rocSOLVER
        rocSPARSE
        ${hipSOLVER_optional_deps}
      TEST_SUBPROJECTS
  )
  therock_cmake_subproject_glob_c_sources(hipSOLVER
      SUBDIRS
      .
  )
  therock_cmake_subproject_provide_package(hipSOLVER hipsolver lib/cmake/hipsolver)
  therock_cmake_subproject_activate(hipSOLVER)
  list(APPEND _blas_subproject_names hipSOLVER)
endif(THEROCK_ENABLE_SOLVER)


##############################################################################
# hipBLAS
##############################################################################

set(hipBLAS_optional_deps)
if(THEROCK_ENABLE_SOLVER)
  list(APPEND hipBLAS_optional_deps rocSOLVER)
endif()
if(THEROCK_BUILD_TESTING)
  # Note: hipBLAS tests require ILP64 host blas
  # https://rocm.docs.amd.com/projects/hipBLAS/en/latest/install/Linux_Install_Guide.html#dependencies-for-building-the-library
  list(APPEND hipBLAS_optional_deps therock-host-blas64)
endif()

therock_cmake_subproject_declare(hipBLAS
  EXTERNAL_SOURCE_DIR "${THEROCK_ROCM_LIBRARIES_SOURCE_DIR}/projects/hipblas"
  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/hipBLAS"
  BACKGROUND_BUILD
  CMAKE_ARGS
    -DHIP_PLATFORM=amd
    -DROCM_PATH=
    -DROCM_DIR=
    "-DBUILD_WITH_SOLVER=${THEROCK_ENABLE_SOLVER}"
    -DBUILD_CLIENTS_TESTS=${THEROCK_BUILD_TESTING}
    -DBUILD_CLIENTS_BENCHMARKS=${THEROCK_BUILD_TESTING}
    -DBUILD_CLIENTS_SAMPLES=OFF
    -DLINK_BLIS=OFF
  COMPILER_TOOLCHAIN
    amd-hip
  BUILD_DEPS
    hipBLAS-common
    rocm-cmake
    therock-googletest
  RUNTIME_DEPS
    hip-clr
    rocBLAS
    ${hipBLAS_optional_deps}
  TEST_SUBPROJECTS
)
therock_cmake_subproject_glob_c_sources(hipBLAS
SUBDIRS
    .
)
therock_cmake_subproject_provide_package(hipBLAS hipblas lib/cmake/hipblas)
therock_cmake_subproject_activate(hipBLAS)
list(APPEND _blas_subproject_names hipBLAS)


##############################################################################
# blas artifact
##############################################################################

therock_provide_artifact(blas
  DESCRIPTOR artifact-blas.toml
  COMPONENTS
      dbg
      dev
      doc
      lib
      run
      test
  SUBPROJECT_DEPS ${_blas_subproject_names}
)
