message(STATUS "CMake build configuration for ${PROJECT_NAME} (${CMAKE_BUILD_TYPE}) ${PROJECT_VERSION}")

################################################################################
# version file
configure_file(version.cpp.in ${CMAKE_BINARY_DIR}/version.cpp @ONLY)

################################################################################
# MUSICA Library

if (MUSICA_BUILD_SHARED_LIBS)
  add_library(musica SHARED)
else()
  add_library(musica STATIC)
endif()

add_library(musica::musica ALIAS musica)

# Common sources
target_sources(musica PRIVATE
  ${CMAKE_CURRENT_SOURCE_DIR}/utils/error_handler.cpp
  ${CMAKE_CURRENT_SOURCE_DIR}/utils/string.cpp
  ${CMAKE_CURRENT_SOURCE_DIR}/utils/util.cpp
  ${CMAKE_BINARY_DIR}/version.cpp
)
add_subdirectory(configuration)

# MICM sources
if(MUSICA_ENABLE_MICM)
  list(APPEND musica_compile_definitions MUSICA_USE_MICM)
  add_subdirectory(micm)
endif()

# MIAM sources
if(MUSICA_ENABLE_MIAM)
  list(APPEND musica_compile_definitions MUSICA_USE_MIAM)
  add_subdirectory(miam)
  target_link_libraries(musica PUBLIC musica::miam)
endif()

# MIEM sources
if(MUSICA_ENABLE_MIEM)
  list(APPEND musica_compile_definitions MUSICA_USE_MIEM)
endif()

# TUV-x sources
if(MUSICA_ENABLE_TUVX)
  list(APPEND musica_compile_definitions MUSICA_USE_TUVX)
  # Add Fortran utility module needed by TUV-x interface files
  target_sources(musica PRIVATE ${MUSICA_PROJECT_SRC_DIR}/fortran/util.F90)
  add_subdirectory(tuvx)
endif()

# CARMA sources
if(MUSICA_ENABLE_CARMA)
  list(APPEND musica_compile_definitions MUSICA_USE_CARMA)
  add_subdirectory(carma)
endif()

# MICM CUDA Solver
if(UNIX AND NOT APPLE AND NOT ${MUSICA_GPU_TYPE} STREQUAL "None")
  add_subdirectory(cuda)
endif()

################################################################################
# Configure musica target

target_include_directories(musica
  PUBLIC
    $<BUILD_INTERFACE:${MUSICA_PROJECT_SRC_DIR}/include>
    $<INSTALL_INTERFACE:${MUSICA_INSTALL_INCLUDE_DIR}>
)

target_compile_features(musica PUBLIC cxx_std_20)

target_link_libraries(musica
  PUBLIC
    musica::mechanism_configuration
)

# Compile definitions
if (MUSICA_ENABLE_MPI)
  list(APPEND musica_compile_definitions MUSICA_USE_MPI)
endif()

if (MUSICA_ENABLE_OPENMP)
  list(APPEND musica_compile_definitions MUSICA_USE_OPENMP)
endif()

# NetCDF for CARMA or TUV-x
if (MUSICA_ENABLE_CARMA OR MUSICA_ENABLE_TUVX)
  target_link_libraries(musica PRIVATE ${MUSICA_NETCDF_C_TARGET} ${MUSICA_NETCDF_FORTRAN_TARGET})
endif()

target_compile_definitions(musica PUBLIC ${musica_compile_definitions})

################################################################################
# Target properties

set_target_properties(musica PROPERTIES
  ARCHIVE_OUTPUT_DIRECTORY ${MUSICA_LIB_DIR}
  LIBRARY_OUTPUT_DIRECTORY ${MUSICA_LIB_DIR}
  Fortran_MODULE_DIRECTORY ${MUSICA_MOD_DIR}
  VERSION ${PROJECT_VERSION}
  SOVERSION ${PROJECT_VERSION_MAJOR}
)

# Set the rpath for the shared library
if(APPLE)
  set_target_properties(musica PROPERTIES
    INSTALL_RPATH "@loader_path"
    BUILD_WITH_INSTALL_RPATH TRUE
  )
elseif(UNIX)
  set_target_properties(musica PROPERTIES
    INSTALL_RPATH "$ORIGIN"
    BUILD_WITH_INSTALL_RPATH TRUE
  )
endif()

################################################################################
# testing
if(MUSICA_ENABLE_TESTS)
  add_subdirectory(test)
endif()

################################################################################
# Packaging
if(MUSICA_ENABLE_INSTALL AND NOT MUSICA_ENABLE_PYTHON_LIBRARY)
  add_subdirectory(packaging)
endif()
