cmake_minimum_required(VERSION 3.24)

# pyproject.toml extracts the version from this line via regex — keep version on this line
project(musica VERSION 0.16.1)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release" CACHE STRING
      "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
      FORCE)
endif(NOT CMAKE_BUILD_TYPE)

include(GNUInstallDirs)

################################################################################
# Library options to build
include(CMakeDependentOption)

option(MUSICA_BUILD_C_CXX_INTERFACE "Use MUSICA" ON)
option(MUSICA_BUILD_FORTRAN_INTERFACE "Use MUSICA-Fortran interface" OFF)
option(MUSICA_ENABLE_INSTALL "Install the musica library" ON)
option(MUSICA_ENABLE_TESTS "Builds tests that ensures each enabled MUSICA component can be used" ON)
option(MUSICA_ENABLE_MPI "Enable MPI parallel support" OFF)
option(MUSICA_ENABLE_OPENMP "Enable OpemMP support" OFF)
option(MUSICA_ENABLE_MEMCHECK "Enable memory checking" OFF)
option(MUSICA_BUILD_DOCS "Build the documentation" OFF)
option(MUSICA_ENABLE_MICM "Enable MICM" ON)
option(MUSICA_ENABLE_MIAM "Enable MIAM" ON)
option(MUSICA_ENABLE_MIEM "Enable MIEM" OFF)
option(MUSICA_ENABLE_TUVX "Enable TUV-x" ON)
option(MUSICA_ENABLE_CARMA "Enable CARMA" ON)
option(MUSICA_ENABLE_COVERAGE "Enable code coverage output" OFF)
option(MUSICA_BUNDLE_DEPENDENCIES "Bundle dependencies with the library" ON)
option(MUSICA_ENABLE_JAVASCRIPT "Build the JavaScript addon" OFF)
option(MUSICA_ENABLE_JULIA "Build the Julia wrapper" OFF)
option(MUSICA_CREATE_ENVIRONMENT_MODULE "Create an Lmod environment module file" OFF)
option(MUSICA_USE_PREBUILT "Use a prebuilt musica library instead of building from source" OFF)
option(MUSICA_BUILD_SHARED_LIBS "Build MUSICA as shared libraries" OFF)
option(MUSICA_USE_FMT "Use the fmt library instead of the standard library for formatting" ON)

set(MUSICA_GPU_TYPE "None" CACHE STRING "The GPU type being targeted")

set(MUSICA_SET_MICM_DEFAULT_VECTOR_SIZE "4" CACHE STRING "Set MICM vector-ordered matrix dimension")

cmake_dependent_option(
  MUSICA_ENABLE_PYTHON_LIBRARY "Adds pybind11, a lightweight header-only library that exposes C++ types in Python and vice versa" OFF "MUSICA_BUILD_C_CXX_INTERFACE" OFF)

################################################################################
# Project wide setup variables
set(MUSICA_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
set(MUSICA_LIB_DIR ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(MUSICA_PROJECT_SRC_DIR ${PROJECT_SOURCE_DIR})

set(MUSICA_MOD_DIR ${PROJECT_BINARY_DIR}/mod_fortran)
set(MUSICA_INSTALL_MOD_DIR ${CMAKE_INSTALL_INCLUDEDIR}/musica/fortran)

set(musica_compile_definitions "")

# Add flags for various compilers
if(${CMAKE_Fortran_COMPILER_ID} MATCHES "Intel")
  list(APPEND musica_compile_definitions MUSICA_USING_INTEL)
elseif(${CMAKE_Fortran_COMPILER_ID} MATCHES "GNU")
  list(APPEND musica_compile_definitions MUSICA_USING_GNU)
elseif(${CMAKE_Fortran_COMPILER_ID} MATCHES "PGI")
  list(APPEND musica_compile_definitions MUSICA_USING_PGI)
endif()

# TUV-x and CARMA contain fortran sources that are added to the musica target
if(MUSICA_BUILD_FORTRAN_INTERFACE OR MUSICA_ENABLE_TUVX OR MUSICA_ENABLE_CARMA)
  enable_language(Fortran)
endif()

# Add flags when using the ClangCL toolset
if(CMAKE_GENERATOR_TOOLSET STREQUAL "ClangCL")
  list(APPEND musica_compile_definitions MUSICA_USING_CLANGCL)
endif()

# Set the Valgrind suppressions file for tests
set(MEMCHECK_SUPPRESS "--suppressions=${PROJECT_SOURCE_DIR}/valgrind.supp")

################################################################################
# Dependencies
if(MUSICA_BUNDLE_DEPENDENCIES)
  include(${PROJECT_SOURCE_DIR}/cmake/dependencies.cmake)
endif()

################################################################################
if(PROJECT_IS_TOP_LEVEL AND MUSICA_ENABLE_TESTS)
  if(MUSICA_ENABLE_COVERAGE)
    include(CodeCoverage)
    append_coverage_compiler_flags()
    setup_target_for_coverage_lcov(
        NAME coverage
        EXECUTABLE "ctest"
        EXCLUDE "${PROJECT_SOURCE_DIR}/src/test/*"
        BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
        LCOV_ARGS "--ignore-errors" "mismatch")  
  endif()
  enable_testing()
endif()

# disable CMake module scanning on macOS
if (APPLE)
  set(CMAKE_CXX_SCAN_FOR_MODULES OFF)
endif()

################################################################################
if(MUSICA_BUILD_C_CXX_INTERFACE)
  if(MUSICA_USE_PREBUILT)
    # Use prebuilt musica library - useful for faster Python wheel builds
    find_package(musica REQUIRED)
    message(STATUS "Using prebuilt musica library")
  else()
    add_subdirectory(src)
  endif()
endif()

if(MUSICA_BUILD_DOCS)
  add_subdirectory(docs)
endif()

if(MUSICA_BUILD_FORTRAN_INTERFACE)
  add_subdirectory(fortran)
endif()

if(MUSICA_ENABLE_PYTHON_LIBRARY)
  add_subdirectory(python)
endif()

if(MUSICA_ENABLE_JAVASCRIPT)
  add_subdirectory(javascript)
endif()

if(MUSICA_ENABLE_JULIA)
  add_subdirectory(julia)
endif()

################################################################################
# Build summary
include(${PROJECT_SOURCE_DIR}/cmake/summary.cmake)
