You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
psblas3/CMakeLists.txt

1381 lines
44 KiB
CMake

# FDEFINES : -DHAVE_LAPACK -DHAVE_FINAL -DHAVE_ISO_FORTRAN_ENV -DHAVE_FLUSH_STMT -DHAVE_VOLATILE -DSERIAL_MPI -DMPI_MOD
# CDEFINES : -DLowerUnderscore -DPtr64Bits
#-----------------------------------
# Set oldest allowable CMake version
#-----------------------------------
cmake_minimum_required(VERSION 3.11...4.2)
cmake_policy(VERSION 3.11.1...3.13.3)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
#----------------------------------------------
# Define canonical CMake build types and extras
#----------------------------------------------
set ( CMAKE_CONFIGURATION_TYPES "Debug" "Release" "MinSizeRel" "RelWithDebInfo" "CodeCoverage" )
set ( CMAKE_BUILD_TYPE "Release"
CACHE STRING "Select which configuration to build." )
set_property ( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES} )
#-----------------------------------------------------
# Determine version from .VERSION file or git describe
#-----------------------------------------------------
include(setVersion)
set_version(
VERSION_VARIABLE PSBLAS_Version
GIT_DESCRIBE_VAR full_git_describe
CUSTOM_VERSION_FILE "${CMAKE_SOURCE_DIR}/.VERSION")
message( STATUS "Building PSBLAS1 version: ${full_git_describe}" )
#------------------------------------------
# Name project and specify source languages
#------------------------------------------
project(psblas
VERSION "${PSBLAS_Version}"
LANGUAGES C Fortran)
#--------------------------------------------------
# Set option to allow building against OpenCoarrays
#--------------------------------------------------
if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
option(PSBLAS_USE_OpenCoarrays "Build enabling linkage to programs using OpenCoarrays" OFF)
endif()
#-----------------------------------------------------------------
# Define a target to create a checksummed & signed release archive
#-----------------------------------------------------------------
set(${CMAKE_PROJECT_NAME}_dist_string "${CMAKE_PROJECT_NAME}-${full_git_describe}")
if(GIT_FOUND)
add_custom_target(dist # OUTPUT "${CMAKE_BINARY_DIR}/${_package_stem_name}.tar.gz"
COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_SOURCE_DIR}/cmake/makeDist.cmake" "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}"
COMMENT "Creating source release asset, ${_package_stem_name}.tar.gz, from ${_full_git_describe} using the `git archive` command."
VERBATIM)
endif()
#--------------------------
# Prohibit in-source builds
#--------------------------
include(CheckOutOfSourceBuild)
#----------------------------------------------------
# Define coverage flags and report untested compilers
#----------------------------------------------------
if ("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU" )
set(gfortran_compiler true)
set(CMAKE_Fortran_COMPILER mpifort)
set ( CMAKE_C_FLAGS_CODECOVERAGE "-fprofile-arcs -ftest-coverage -O0"
CACHE STRING "Code coverage C compiler flags")
set ( CMAKE_Fortran_FLAGS_CODECOVERAGE "-fprofile-arcs -ftest-coverage -O0"
CACHE STRING "Code coverage Fortran compiler flags")
else()
message(WARNING
"\n"
"Attempting untested CMake build with Fortran compiler: ${CMAKE_Fortran_COMPILER_ID}. "
"Please report any failures at https://github.com/sfilippone/psblas3\n\n"
)
endif()
#----------------------------------------------------
# Define -frecursive for GNU Fortran Compiler
#----------------------------------------------------
if ("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU" )
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -frecursive")
message(STATUS "GNU Fortran COMPILER ${CMAKE_Fortran_FLAGS};")
endif()
message(STATUS "cmake flags? ${CMAKE_Fortran_FLAGS};")
#------------------------------------
# Fortran name mangling introspection
#------------------------------------
include("${CMAKE_CURRENT_LIST_DIR}/cmake/CapitalizeString.cmake")
#include(FortranCInterface)
#CapitalizeString(${FortranCInterface_GLOBAL__CASE} fc_case)
#message(STATUS "Name mangling capitalization: ${fc_case}")
#message(STATUS "Name mangling fortran global suffix underscore: ${FortranCInterface_GLOBAL__SUFFIX}")
#if(FortranCInterface_GLOBAL__SUFFIX STREQUAL "")
# add_compile_options("-D${fc_case}Case")
#elseif(FortranCInterface_GLOBAL__SUFFIX STREQUAL "_")
# add_compile_options("-D${fc_case}Underscore")
#elseif(FortranCInterface_GLOBAL__SUFFIX STREQUAL "__")
# add_compile_options("-D${fc_case}DoubleUnderscore")
#else()
# message( FATAL_ERROR "Fortran name mangling suffix, \'${FortranCInterface_GLOBAL__SUFFIX}\', unknown to PSBLAS")
#endif()
# message(STATUS "win? ${WIN32};")
#if(TRUE)#NOT ${WIN32})
#previous check did not work if WIN32 is empty string
#----------------------------------------------
# Determine system endian-ness and pointer size
#----------------------------------------------
# include(TestBigEndian)
# TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
# if(IS_BIG_ENDIAN)
# message( STATUS "System appears to be big endian.")
# else()
# message( STATUS "System appears to be little endian.")
# add_compile_options(-DLittleEndian)
# endif()
# include(CheckTypeSize)
# CHECK_TYPE_SIZE("void *" VOID_P_SIZE LANGUAGE C)
# if(${VOID_P_SIZE} EQUAL 8)
# add_compile_options(-DPtr64Bits)
# endif()
# message(STATUS "Have 64bit pointers")
#endif()
message(STATUS "Using compiler ${CMAKE_C_COMPILER};")
# Define Major and Minor Version and Patch Level, String Version
set(PSBLASMAJOR "3")
set(PSBLASMINOR "9")
set(PSBLASPATCH "0")
set(PSBLASSTRING "\"3.9.0\"")
# Set default values for IPK_SIZE and LPK_SIZE
set(DEFAULT_IPK_SIZE 4)
set(DEFAULT_LPK_SIZE 8)
# Allow user to override with command line definitions
if(NOT DEFINED CMAKE_PSB_IPK)
set(CMAKE_PSB_IPK ${DEFAULT_IPK_SIZE} CACHE STRING "Size of IPK (default: 4)")
endif()
if(NOT DEFINED CMAKE_PSB_LPK)
set(CMAKE_PSB_LPK ${DEFAULT_LPK_SIZE} CACHE STRING "Size of LPK (default: 8)")
endif()
# Use the passed values
set(IPK_SIZE ${CMAKE_PSB_IPK})
set(LPK_SIZE ${CMAKE_PSB_LPK})
# Define IPKDEF and LPKDEF based on the sizes
set(PSB_IPKDEF "#define PSB_IPK${IPK_SIZE}")
set(PSB_LPKDEF "#define PSB_LPK${LPK_SIZE}")
# Output the definitions for verification
message(STATUS "Using IPKDEF: ${PSB_IPKDEF}")
message(STATUS "Using LPKDEF: ${PSB_LPKDEF}")
#add_compile_options(-DPSB_IPK${IPK_SIZE})
#add_compile_options(-DPSB_LPK${LPK_SIZE})
# Add PSB_IPK/LPK flag only for fortran files.
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_IPK${IPK_SIZE}")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_LPK${LPK_SIZE}")
#-----------------------------------------
# Check for some Fortran compiler features
#-----------------------------------------
include(CheckFortranSourceCompiles)
CHECK_Fortran_SOURCE_COMPILES(
"
integer, allocatable :: a(:), b(:)
allocate(a(5))
a = [1,2,3,4,5]
call move_alloc(from=a, to=b)
end
"
HAVE_MOVE_ALLOC
SRC_EXT f90
)
if(HAVE_MOVE_ALLOC)
#add_compile_options(-DHAVE_MOVE_ALLOC)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DHAVE_MOVE_ALLOC")
message(STATUS "-DHAVE_MOVE_ALLOC")
endif()
CHECK_Fortran_SOURCE_COMPILES(
"integer, volatile :: i ; end"
HAVE_VOLATILE
SRC_EXT f90
)
if(HAVE_VOLATILE)
#add_compile_options(-DPSB_HAVE_VOLATILE)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_VOLATILE")
message(STATUS "-DPSB_HAVE_VOLATILE")
endif()
CHECK_Fortran_SOURCE_COMPILES(
"use ISO_FORTRAN_ENV ; end"
HAVE_ISO_FORTRAN_ENV
SRC_EXT f90
)
if(HAVE_ISO_FORTRAN_ENV)
#add_compile_options(-DPSB_HAVE_ISO_FORTRAN_ENV)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_ISO_FORTRAN_ENV")
message(STATUS "-DPSB_HAVE_ISO_FORTRAN_ENV")
endif()
CHECK_Fortran_SOURCE_COMPILES(
"flush(5); end"
HAVE_FLUSH_STMT
SRC_EXT f90
)
if(HAVE_FLUSH_STMT)
#add_compile_options(-DPSB_HAVE_FLUSH_STMT)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_FLUSH_STMT")
message(STATUS "-DPSB_HAVE_FLUSH_STMT")
endif()
CHECK_Fortran_SOURCE_COMPILES(
"
module conftest_mod
type foo
integer :: i
contains
final :: destroy_foo
end type foo
private destroy_foo
contains
subroutine destroy_foo(a)
type(foo) :: a
! Just a test
end subroutine destroy_foo
end module conftest_mod
program conftest
use conftest_mod
type(foo) :: foovar
end program"
HAVE_FINAL
SRC_EXT f90
)
if(HAVE_FINAL)
# add_compile_options(-DPSB_HAVE_FINAL)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_FINAL")
message(STATUS "-DPSB_HAVE_FINAL")
endif()
CHECK_Fortran_SOURCE_COMPILES(
"
program xtt
type foo
integer :: i
end type foo
type, extends(foo) :: new_foo
integer :: j
end type new_foo
class(foo), allocatable :: fooab
type(new_foo) :: nfv
integer :: info
allocate(fooab, mold=nfv, stat=info)
end program"
HAVE_MOLD
SRC_EXT f90)
if(HAVE_MOLD)
# add_compile_options(-DPSB_HAVE_MOLD)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_MOLD")
message(STATUS "-DPSB_HAVE_MOLD")
endif()
CHECK_Fortran_SOURCE_COMPILES(
"
program conftest
type foo
integer :: i
end type foo
type, extends(foo) :: bar
integer j
end type bar
type(bar) :: barvar
end program "
HAVE_EXTENDS_TYPE_OF
SRC_EXT f90)
if(HAVE_EXTENDS_TYPE_OF)
# add_compile_options(-DPSB_HAVE_EXTENDS_TYPE_OF)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_EXTENDS_TYPE_OF")
message(STATUS "-DPSB_HAVE_EXTENDS_TYPE_OF")
endif()
CHECK_Fortran_SOURCE_COMPILES(
"
program stt
type foo
integer :: i
end type foo
type, extends(foo) :: new_foo
integer :: j
end type new_foo
type(foo) :: foov
type(new_foo) :: nfv1, nfv2
write(*,*) 'foov == nfv1? ', same_type_as(foov,nfv1)
write(*,*) 'nfv2 == nfv1? ', same_type_as(nfv2,nfv1)
end program"
HAVE_SAME_TYPE_AS
SRC_EXT f90)
if(HAVE_SAME_TYPE_AS)
# add_compile_options(-DPSB_HAVE_SAME_TYPE_AS)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_SAME_TYPE_AS")
message(STATUS "-DPSB_HAVE_SAME_TYPE_AS")
endif()
#----------------------------------------------------------------------------
# MPI detection and configuration
#----------------------------------------------------------------------------
find_package(MPI REQUIRED Fortran)
if(MPI_FOUND)
message(STATUS ">>> MPI found: ${MPI_C_LIBRARIES} ${MPI_Fortran_LIBRARIES}")
#-----------------------------------------------
# Fedora-specific workaround for noexecstack flag
#-----------------------------------------------
if((MPI_C_LINK_FLAGS MATCHES "noexecstack") OR (MPI_Fortran_LINK_FLAGS MATCHES "noexecstack"))
message(WARNING
"The `noexecstack` linker flag was found in the MPI_<lang>_LINK_FLAGS variable.
This can cause segmentation faults in Fortran codes.
Replacing `noexecstack` with `execstack`."
)
string(REPLACE "noexecstack" "execstack" MPI_C_LINK_FLAGS_FIXED ${MPI_C_LINK_FLAGS})
string(REPLACE "noexecstack" "execstack" MPI_Fortran_LINK_FLAGS_FIXED ${MPI_Fortran_LINK_FLAGS})
set(MPI_C_LINK_FLAGS "${MPI_C_LINK_FLAGS_FIXED}" CACHE STRING "MPI C linking flags" FORCE)
set(MPI_Fortran_LINK_FLAGS "${MPI_Fortran_LINK_FLAGS_FIXED}" CACHE STRING "MPI Fortran linking flags" FORCE)
endif()
#-----------------------------------------------
# Compiler and linker flags setup
#-----------------------------------------------
list(REMOVE_DUPLICATES MPI_Fortran_INCLUDE_PATH)
include_directories(BEFORE ${MPI_C_INCLUDE_PATH} ${MPI_Fortran_INCLUDE_PATH})
set(CMAKE_C_COMPILE_FLAGS "${CMAKE_C_COMPILE_FLAGS} ${MPI_C_COMPILE_FLAGS}")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} ${MPI_C_LINK_FLAGS}")
set(CMAKE_Fortran_COMPILE_FLAGS "${CMAKE_Fortran_COMPILE_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}")
set(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS} ${MPI_Fortran_LINK_FLAGS}")
message(STATUS "MPI include paths: ${MPI_Fortran_INCLUDE_PATH}")
message(STATUS "Fortran link flags: ${CMAKE_Fortran_LINK_FLAGS}")
#-----------------------------------------------
# Ensure mpi.mod is available for CMake
#-----------------------------------------------
set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/modules)
file(MAKE_DIRECTORY ${CMAKE_Fortran_MODULE_DIRECTORY})
# Try to copy mpi.mod or MPI.mod into module directory
set(_mpi_mod_found FALSE)
foreach(_mpi_mod_name mpi.mod MPI.mod)
foreach(_mpi_inc ${MPI_Fortran_INCLUDE_PATH})
if(EXISTS "${_mpi_inc}/${_mpi_mod_name}")
file(COPY "${_mpi_inc}/${_mpi_mod_name}" DESTINATION "${CMAKE_Fortran_MODULE_DIRECTORY}")
message(STATUS "Copied ${_mpi_mod_name} from ${_mpi_inc}")
set(_mpi_mod_found TRUE)
break()
endif()
endforeach()
if(_mpi_mod_found)
break()
endif()
endforeach()
if(NOT _mpi_mod_found)
message(WARNING "mpi.mod not found in MPI include paths; assuming it is built-in to mpifort.")
endif()
#-----------------------------------------------
# Enable MPI Fortran module support
#-----------------------------------------------
if(MPI_Fortran_HAVE_F90_MODULE OR MPI_Fortran_HAVE_F08_MODULE)
add_compile_options(-DPSB_MPI_MOD)
message(STATUS "Defined: -DPSB_MPI_MOD")
endif()
set(PSB_SERIAL_MPI OFF)
else()
#-----------------------------------------------
# Fallback to serial mode (no MPI found)
#-----------------------------------------------
message(WARNING ">>> MPI not found — building in serial mode")
add_compile_options(-DPSB_SERIAL_MPI -DPSB_MPI_MOD)
set(PSB_SERIAL_MPI ON)
set(CSERIALMPI "#define PSB_SERIAL_MPI")
endif()
#-------------------------------------------------------
# Find and Use OpenCoarrays IFF gfortran AND options set
#-------------------------------------------------------
if("${PSBLAS_USE_OpenCoarrays}" AND CMAKE_Fortran_COMPILER_ID MATCHES GNU)
message(STATUS "Set openCoarrays")
find_package(OpenCoarrays)
endif()
#------------------------------
# Find Linear Algebra Libraries
#------------------------------
if(NOT APPLE)
set(BLA_STATIC ON)
endif()
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)
#add_compile_options(-DPSB_HAVE_LAPACK)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_LAPACK")
#--------------------------------
# Find METIS partitioning library
#--------------------------------
include(${CMAKE_CURRENT_LIST_DIR}/cmake/FindMETIS.cmake)
find_package(METIS)
if(METIS_FOUND)
include(CheckTypeSize)
message(STATUS "METIS PATH ${METIS_INCLUDES} and metis libraries ${METIS_LIBRARIES}")
# Make sure this path is correct
# set(METISINCFILE "metis.h") # Adjust this to your actual path
# Specify the configuration file
# set(HEADER_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/util/psb_metis_int.h.in")
# set(HEADER_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/psb_metis_int.h")
# Configure the header file
#configure_file(${HEADER_TEMPLATE} ${HEADER_OUTPUT} @ONLY)
# Check for real sizes using try_compile
include(CheckCSourceCompiles)
#[=====[
# Function to check the size of a type
function(check_metis_real_type type_name)
set(source_code "
#include <metis.h>
#include <stdio.h>
int main() {
printf(\"%zu\\n\", sizeof(${type_name}));
return 0;
}")
# Create a temporary source file
#file(WRITE "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/test_size.c" "${source_code}")
# Try to compile it
#try_compile(COMPILER_RESULT "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp"
# "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/test_size.c")
# Check the result and read the output
set(test_file "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/test_metis_size.c")
file(WRITE "${test_file}" "${source_code}")
# Use try_run to compile AND execute
try_run(RUN_RESULT COMPILE_RESULT
"${CMAKE_BINARY_DIR}"
"${test_file}"
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${METIS_INCLUDES}"
RUN_OUTPUT_VARIABLE type_size
COMPILE_OUTPUT_VARIABLE compile_log
)
if(COMPILE_RESULT AND (RUN_RESULT EQUAL 0))
# if (COMPILER_RESULT)
execute_process(COMMAND "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/test_size"
OUTPUT_VARIABLE type_size)
string(STRIP "${type_size}" type_size)
message(STATUS "Metis ?: ${type_size};")
if (type_name STREQUAL "float")
set(PSB_METIS_REAL_32 "${type_size}" PARENT_SCOPE)
message(STATUS "Metis 32: ${type_size}")
# add_definitions(-DPSB_METIS_REAL_32)
set(CREALMETIS "#define PSB_METIS_REAL_32" PARENT_SCOPE)
elseif (type_name STREQUAL "double")
set(PSB_METIS_REAL_64 "${type_size}" PARENT_SCOPE)
#add_definitions(-DPSB_METIS_REAL_64)
set(CREALMETIS "#define PSB_METIS_REAL_64" PARENT_SCOPE)
message(STATUS "Metis 64: ${type_size}")
endif()
else()
message(WARNING "Failed to compile test for type size: ${type_name}")
endif()
endfunction()
# Check for both float and double
check_metis_real_type(float)
check_metis_real_type(double)
#]=====]
# Set HAVE_METIS if METIS is found
#add_compile_options(-DPSB_HAVE_METIS)
# set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_METIS")
# 1. Tell CMake where to find metis.h for the check
set(CMAKE_EXTRA_INCLUDE_FILES "${METIS_INCLUDES}/metis.h")
# 2. Check the size of Metis's own type: real_t
# This replaces checking 'float' and 'double' separately
check_type_size("real_t" METIS_REAL_SIZE)
check_type_size("idx_t" METIS_IDX_SIZE)
# 3. Handle the result
if(METIS_IDX_SIZE)
if(METIS_IDX_SIZE EQUAL 4)
set(CINTMETIS "#define PSB_METIS_32")
message(STATUS "Metis detected as 32-bit (idx_t is 4 bytes)")
set(METIS_INDEX 32)
elseif(METIS_IDX_SIZE EQUAL 8)
set(CINTMETIS "#define PSB_METIS_64")
message(STATUS "Metis detected as 64-bit (idx_t is 8 bytes)")
set(METIS_INDEX 64)
endif()
else()
message(WARNING "Could not determine size of idx_t from metis.h. Check METIS_INCLUDES.")
endif()
# 3. Handle the result
if(METIS_REAL_SIZE)
if(METIS_REAL_SIZE EQUAL 4)
set(CREALMETIS "#define PSB_METIS_REAL_32")
message(STATUS "Metis detected as 32-bit (real_t is 4 bytes)")
elseif(METIS_REAL_SIZE EQUAL 8)
set(CREALMETIS "#define PSB_METIS_REAL_64")
message(STATUS "Metis detected as 64-bit (real_t is 8 bytes)")
endif()
else()
message(WARNING "Could not determine size of real_t from metis.h. Check METIS_INCLUDES.")
endif()
# clean the variable
set(CMAKE_EXTRA_INCLUDE_FILES "")
# Mismatch Logic Below
if(LPK_SIZE STREQUAL "4" AND METIS_INDEX EQUAL 64)
message(WARNING "Mismatch: Metis IDX is 64-bit but PSBLAS LPK is 32-bit")
set(METIS_FOUND FALSE)
set(CREALMETIS "")
set(CINTMETIS "")
elseif(LPK_SIZE STREQUAL "8" AND METIS_INDEX EQUAL 32)
set(METIS_FOUND FALSE)
message(WARNING "Mismatch: Metis IDX is 32-bit but PSBLAS LPK is 64-bit")
set(CREALMETIS "")
set(CINTMETIS "")
endif()
if(METIS_FOUND)
# Make sure this path is correct
set(METISINCFILE "metis.h") # Adjust this to your actual path
# Specify the configuration file
set(HEADER_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/util/psb_metis_int.h.in")
set(HEADER_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/psb_metis_int.h")
# Configure the header file
configure_file(${HEADER_TEMPLATE} ${HEADER_OUTPUT} @ONLY)
# Set HAVE_METIS if METIS is found and coherent with the system settings
#add_compile_options(-DPSB_HAVE_METIS)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_METIS")
set(CHAVEMETIS "#define PSB_HAVE_METIS")
# set(CINTMETIS "#define PSB_METIS_${METIS_INDEX}")
# set(CREALMETIS "#define PSB_METIS_REAL_${LPK_SIZE}")
# Configure the header file
configure_file(${HEADER_TEMPLATE} ${HEADER_OUTPUT} @ONLY)
# Set HAVE_METIS if METIS is found
#add_compile_options(-DPSB_HAVE_METIS)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_METIS")
endif()
endif()
#---------------------------------------------------
# Use standardized GNU install directory conventions
#---------------------------------------------------
include(GNUInstallDirs)
#set(mod_dir_tail "${${CMAKE_PROJECT_NAME}_dist_string}_${CMAKE_Fortran_COMPILER_ID}-${CMAKE_Fortran_COMPILER_VERSION}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/${${CMAKE_PROJECT_NAME}_dist_string}-tests")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
#set(CMAKE_INSTALL_LIBDIR "lib" CACHE STRING "Library install directory")
#set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE STRING "Include directory")
#set(CMAKE_INSTALL_MODULDIR "modules" CACHE STRING "Modules directory")
#Ser variables exportable for other projects
message(STATUS "Initial CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}")
set(PSB_CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
if(NOT PSB_CMAKE_INSTALL_LIBDIR)
message(STATUS "CMAKE_INSTALL_LIBDIR is set to default value lib")
set(CMAKE_INSTALL_LIBDIR "lib" CACHE STRING "Library install directory" FORCE)
set(PSB_CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
else()
set(CMAKE_INSTALL_LIBDIR ${PSB_CMAKE_INSTALL_LIBDIR})
message(STATUS "CMAKE_INSTALL_LIBDIR is set to: ${CMAKE_INSTALL_LIBDIR}")
endif()
if(NOT PSB_CMAKE_INSTALL_INCLUDEDIR)
message(STATUS "CMAKE_INSTALL_INCLUDEDIR is set to default value lib")
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE STRING "Include directory" FORCE)
set(PSB_CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
else()
set(CMAKE_INSTALL_INCLUDEDIR ${PSB_CMAKE_INSTALL_INCLUDEDIR})
message(STATUS "CMAKE_INSTALL_INCLUDEDIR is set to: ${CMAKE_INSTALL_INCLUDEDIR}")
endif()
if(NOT PSB_CMAKE_INSTALL_MODULDIR)
message(STATUS "CMAKE_INSTALL_MODULDIR is set to default value lib")
set(CMAKE_INSTALL_MODULDIR "modules" CACHE STRING "Modules directory" FORCE)
set(PSB_CMAKE_INSTALL_MODULDIR ${CMAKE_INSTALL_MODULDIR})
else()
set(CMAKE_INSTALL_MODULDIR ${PSB_CMAKE_INSTALL_MODULDIR})
message(STATUS "CMAKE_INSTALL_MODULDIR is set to: ${CMAKE_INSTALL_MODULDIR}")
endif()
#-----------------------------------
# Turn on testing/ctest capabilities
#-----------------------------------
enable_testing()
#------------------------------------------------------------------------------
# Add custom properties on targets for controling number of ranks during tests
#------------------------------------------------------------------------------
define_property(TARGET
PROPERTY MIN_RANKS
BRIEF_DOCS "Minimum allowable ranks for the test <integer>"
FULL_DOCS "Property to mark executable targets run as tests that they require at least <MIN_RANKS> ranks to run"
)
define_property(TARGET
PROPERTY POWER_2_RANKS
BRIEF_DOCS "True if test must be run with a power of 2 ranks (T/F)"
FULL_DOCS "Property to mark executable targets run as tests that they require 2^n ranks."
)
#-----------------------------------------------------
# Publicize installed location to other CMake projects
#-----------------------------------------------------
#install(EXPORT ${CMAKE_PROJECT_NAME}-targets
# DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake"
#)
install(EXPORT ${CMAKE_PROJECT_NAME}-targets
FILE ${CMAKE_PROJECT_NAME}Config.cmake
NAMESPACE ${CMAKE_PROJECT_NAME}::
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/"
)
include(CMakePackageConfigHelpers) # standard CMake module
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}ConfigVersion.cmake"
VERSION "${VERSION}"
COMPATIBILITY SameMajorVersion
)
configure_file("${CMAKE_SOURCE_DIR}/cmake/${CMAKE_PROJECT_NAME}Config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${CMAKE_PROJECT_NAME}Config.cmake" @ONLY)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${CMAKE_PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}ConfigVersion.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}Targets.cmake"
DESTINATION
"${CMAKE_INSTALL_LIBDIR}/cmake/${CMAKE_PROJECT_NAME}"
)
#------------------------------------------
# Add portable unistall command to makefile
#------------------------------------------
# Adapted from the CMake Wiki FAQ
configure_file ( "${CMAKE_SOURCE_DIR}/cmake/uninstall.cmake.in" "${CMAKE_BINARY_DIR}/uninstall.cmake"
@ONLY)
add_custom_target ( uninstall
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_BINARY_DIR}/uninstall.cmake" )
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure)
# See JSON-Fortran's CMakeLists.txt file to find out how to get the check target to depend
# on the test executables
#----------------------------------
# Determine if we're using Open MPI
#---------------------------------
if(MPI_FOUND)
execute_process(COMMAND ${MPIEXEC} --version
OUTPUT_VARIABLE mpi_version_out)
if (mpi_version_out MATCHES "[Oo]pen[ -][Mm][Pp][Ii]")
message( STATUS "OpenMPI detected")
set ( openmpi true )
endif()
endif()
# Optionally check for CUDA requirement
option(PSB_BUILD_CUDA "Build CUDA code" OFF)
if(IPK_SIZE EQUAL 8)
set(PSB_BUILD_CUDA OFF)
message(STATUS "IPK8 is not compatible with CUDA. Cuda is now OFF ${PSB_BUILD_CUDA}")
endif()
if(PSB_BUILD_CUDA)
#if(NOT DEFINED PSB_CUDA_PATH)
# set(PSB_CUDA_PATH "/opt/cuda/12.8")
#endif()
# Include the CMakeLists for the cuda library
include(${CMAKE_CURRENT_LIST_DIR}/cuda/CMakeLists.txt)
include_directories("${PSB_CUDA_PATH}/include")
message(STATUS "${PSB_CUDA_PATH}")
# find_package(CUDA REQUIRED)
enable_language(CUDA)
message(STATUS "Enabled CUDA ${CMAKE_CUDA_COMPILER_VERSION} ${CMAKE_CUDA_ARCHITECTURES};; ${CMAKE_CUDA_HOST_COMPILER_VERSION};")
find_package(CUDAToolkit)
message(STATUS "Enabled CUDA throguh find ${CUDAToolkit_VERSION_MAJOR} ${CUDAToolkit_VERSION};; ${CUDAToolkit_VERSION_MINOR};")
#compute cuda versio for psblas
math(EXPR PSB_CUDA_VERSION "${CUDAToolkit_VERSION_MAJOR} * 1000 + ${CUDAToolkit_VERSION_MINOR} * 10")
message(STATUS "cuda version called has given ${PSB_CUDA_VERSION}:")
# Check for CUDA version
# set(PSB_CUDA_VERSION 12800)
if(PSB_CUDA_VERSION)
message(STATUS "CUDA version: ${PSB_CUDA_VERSION}")
# Define macros for CUDA version
# add_definitions(-DPSB_HAVE_CUDA)
# add_definitions(-DPSB_CUDA_VERSION=${PSB_CUDA_VERSION})
# math(EXPR PSB_CUDA_SHORT_VERSION "${PSB_CUDA_VERSION} / 1000")
# add_definitions(-DPSB_CUDA_SHORT_VERSION=${PSB_CUDA_SHORT_VERSION})
set(PSB_CUDA_SHORT_VERSION ${CUDAToolkit_VERSION_MAJOR})
message(STATUS "cuda version called has given ${PSB_CUDA_SHORT_VERSION}:")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_CUDA")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_CUDA_VERSION=${PSB_CUDA_VERSION}")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_CUDA_SHORT_VERSION=${PSB_CUDA_SHORT_VERSION}")
set(CHAVECUDA "#define PSB_HAVE_CUDA")
set(CSHORTVCUDA "#define PSB_CUDA_SHORT_VERSION ${PSB_CUDA_SHORT_VERSION}")
set(CVERSIONCUDA "#define PSB_CUDA_VERSION ${PSB_CUDA_VERSION}")
else()
message(FATAL_ERROR "CUDA version not found!")
endif()
endif()
#------------------------------------------
# Configure the psb_config.h file
#------------------------------------------
message(STATUS "bin dir ${CMAKE_CURRENT_BINARY_DIR}; source dir ${CMAKE_CURRENT_SOURCE_DIR};;")
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/base/modules/psb_config.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/psb_config.h
@ONLY # Replace variables only
)
#---------------------------------------
# Add the PSBLAS libraries and utilities
#---------------------------------------
# Link order, left to right:
# cbind.a, util.a linsolve.a prec.a base.a
include(${CMAKE_CURRENT_LIST_DIR}/base/CMakeLists.txt)
include_directories("${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}")
foreach(path IN LISTS base_header_C_files)
# Copy the header file to the include directory
file(COPY "${path}" DESTINATION "${CMAKE_BINARY_DIR}/include")
endforeach()
if(WIN32)
add_library(psb_base_C STATIC ${base_source_C_files})
target_compile_definitions(psb_base_C
PRIVATE -DWIN32 -D_LIB -DWIN64)
set_target_properties(psb_base_C
PROPERTIES
LINKER_LANGUAGE C
POSITION_INDEPENDENT_CODE TRUE)
target_link_libraries(psb_base_C
PUBLIC kernel32 user32 shell32)
add_library(base ${base_source_files})
target_link_libraries(base
PUBLIC psb_base_C)
else()
add_library(base_C OBJECT ${base_source_C_files})
add_library(base ${base_source_files} $<TARGET_OBJECTS:base_C>)
endif()
# Set the Fortran module output directory for all targets
set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/modules)
#set(CMAKE_Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/include")
message(STATUS "fortran module direcotry ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}")
include_directories(${MPI_Fortran_INCLUDE_PATH})
message(STATUS "Using MPI include at: ${MPI_Fortran_INCLUDE_PATH}")
set_target_properties(base
PROPERTIES
Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
POSITION_INDEPENDENT_CODE TRUE
OUTPUT_NAME psb_base
LINKER_LANGUAGE Fortran
VERSION ${VERSION} SOVERSION ${SOVERSION}
)
target_include_directories(base PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules>
$<INSTALL_INTERFACE:modules>)
message(STATUS "include dir := ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}")
#target_include_directories(base PUBLIC ${CMAKE_Fortran_MODULE_DIRECTORY})
target_link_libraries(base
PUBLIC ${LAPACK_LINKER_FLAGS} ${LAPACK_LIBRARIES} ${LAPACK95_LIBRARIES}
PUBLIC ${BLAS_LINKER_FLAGS} ${BLAS_LIBRARIES} ${BLAS95_LIBRARIES})
#add_custom_command(
# TARGET base POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E cmake_copy_f90_mod
# ${MPI_Fortran_INCLUDE_PATH}mpi.mod ${CMAKE_BINARY_DIR}/include/mpi.mod
#)
include(${CMAKE_CURRENT_LIST_DIR}/prec/CMakeLists.txt)
add_library(prec ${prec_source_files})
set_target_properties(prec
PROPERTIES
Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
POSITION_INDEPENDENT_CODE TRUE
OUTPUT_NAME psb_prec
LINKER_LANGUAGE Fortran
VERSION ${VERSION} SOVERSION ${SOVERSION}
)
target_include_directories(prec PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules>
$<INSTALL_INTERFACE:modules>)
target_link_libraries(prec PUBLIC base)
include(${CMAKE_CURRENT_LIST_DIR}/linsolve/CMakeLists.txt)
add_library(linsolve ${linsolve_source_files})
set_target_properties(linsolve
PROPERTIES
Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
POSITION_INDEPENDENT_CODE TRUE
OUTPUT_NAME psb_linsolve
LINKER_LANGUAGE Fortran
VERSION ${VERSION} SOVERSION ${SOVERSION}
)
target_include_directories(linsolve PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules>
$<INSTALL_INTERFACE:modules>)
target_link_libraries(linsolve PUBLIC base prec)
include(${CMAKE_CURRENT_LIST_DIR}/ext/CMakeLists.txt)
add_library(ext ${ext_source_files})
set_target_properties(ext
PROPERTIES
Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
POSITION_INDEPENDENT_CODE TRUE
OUTPUT_NAME psb_ext
LINKER_LANGUAGE Fortran
VERSION ${VERSION} SOVERSION ${SOVERSION}
)
target_include_directories(ext PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules>
$<INSTALL_INTERFACE:modules>)
target_link_libraries(ext PUBLIC base prec) #TODO: check actual dependencies
include(${CMAKE_CURRENT_LIST_DIR}/util/CMakeLists.txt)
if(WIN32)
if(METIS_FOUND)
add_library(psb_util_C STATIC ${util_source_C_files})
target_compile_definitions(psb_util_C
PRIVATE -DWIN32 -D_LIB -DWIN64)
set_target_properties(psb_util_C
PROPERTIES
LINKER_LANGUAGE C
POSITION_INDEPENDENT_CODE TRUE
VERSION ${VERSION} SOVERSION ${SOVERSION})
target_link_libraries(psb_util_C
PUBLIC kernel32 user32 shell32)
endif()
add_library(util ${util_source_files})
if(METIS_FOUND)
target_link_libraries(util
PUBLIC psb_util_C)
endif()
else()
if(METIS_FOUND)
foreach(file IN LISTS util_source_C_metis_files)
list(APPEND util_source_C_files file)
endforeach()
endif()
add_library(psb_util_C OBJECT ${util_source_C_files})
add_library(util ${util_source_files} $<TARGET_OBJECTS:psb_util_C>)
endif()
set_target_properties(util
PROPERTIES
Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
POSITION_INDEPENDENT_CODE TRUE
OUTPUT_NAME psb_util
LINKER_LANGUAGE Fortran
VERSION ${VERSION} SOVERSION ${SOVERSION}
)
target_include_directories(util PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules>
$<INSTALL_INTERFACE:modules>)
target_link_libraries(util PUBLIC base prec)
if(METIS_FOUND)
target_include_directories(util
PUBLIC ${METIS_INCLUDES})
target_include_directories(psb_util_C
PUBLIC ${METIS_INCLUDES})
target_link_libraries(util
PUBLIC ${METIS_LIBRARIES})
# target_compile_definitions(psb_util_C
# PUBLIC PSB_HAVE_METIS) #TDDO: CHECK IF THAT _ IS CORRECT
# target_compile_definitions(util
# PUBLIC PSB_HAVE_METIS)
endif()
# Include headers from the 'include' directory in the current directory
include_directories(${CMAKE_BINARY_DIR}/include)
include(${CMAKE_CURRENT_LIST_DIR}/cbind/CMakeLists.txt)
if(WIN32)
add_library(psb_cbind_C STATIC ${cbind_source_C_files})
target_compile_definitions(psb_cbind_C
PRIVATE -DWIN32 -D_LIB -DWIN64)
set_target_properties(psb_cbind_C
PROPERTIES
LINKER_LANGUAGE C
POSITION_INDEPENDENT_CODE TRUE)
target_link_libraries(psb_cbind_C
PUBLIC kernel32 user32 shell32)
add_library(cbind ${cbind_source_files})
target_link_libraries(cbind
PUBLIC psb_cbind_C)
else()
add_library(cbind_C OBJECT ${cbind_source_C_files})
add_library(cbind ${cbind_source_files} $<TARGET_OBJECTS:cbind_C>)
endif()
#add_library(cbind ${cbind_source_files})
set_target_properties(cbind
PROPERTIES
Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/modules"
POSITION_INDEPENDENT_CODE TRUE
OUTPUT_NAME psb_cbind
LINKER_LANGUAGE Fortran
VERSION ${VERSION} SOVERSION ${SOVERSION}
)
#target_include_directories(cbind PUBLIC
# $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules>
# $<INSTALL_INTERFACE:modules>)
# Include directories for the cbind library
target_include_directories(cbind PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules> # Path for building
$<INSTALL_INTERFACE:modules> # Path for installation
)
target_link_libraries(cbind PUBLIC base prec linsolve ext util)
# Custom command to copy all header files
#add_custom_command(
# OUTPUT ${CMAKE_BINARY_DIR}/include/ # Dummy output to represent the target directory
# COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/include # Create the include directory if it doesn't exist
# COMMAND ${CMAKE_COMMAND} -E copy_if_different ${cbind_header_C_files} ${CMAKE_BINARY_DIR}/include/ # Copy all headers
# DEPENDS ${cbind_header_C_files} # Make the copy depend on the header files
# COMMENT "Copying header files to include directory"
#)
# Create a custom target to copy headers
#add_custom_target(copy_headers ALL DEPENDS ${CMAKE_BINARY_DIR}/include/)
foreach(path IN LISTS cbind_header_C_files)
# Copy the header file to the include directory
file(COPY "${path}" DESTINATION "${CMAKE_BINARY_DIR}/include")
endforeach()
message(STATUS "Copied .h files to ${CMAKE_BINARY_DIR}/include")
#target_include_directories(cbind PUBLIC
# $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules>
# $<INSTALL_INTERFACE:modules>)
# Include directories for the cbind library
#target_include_directories(cbind_C PUBLICF
# $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include> # Path for building
# $<INSTALL_INTERFACE:include> # Path for installation
# ${CMAKE_BINARY_DIR}/include # Include the copied headers
#)
#########################################
####### BUILD CUDA LIBRARY ##############
#########################################
# Optionally check for CUDA requirement
#option(PSB_BUILD_CUDA "Build CUDA code" OFF)
if(PSB_BUILD_CUDA)
# if(NOT DEFINED PSB_CUDA_PATH)
# set(PSB_CUDA_PATH "/opt/cuda/12.8")
#endif()
# Include the CMakeLists for the cbind library
#include(${CMAKE_CURRENT_LIST_DIR}/cuda/CMakeLists.txt)
#include_directories("${PSB_CUDA_PATH}/include")
#message(STATUS "${PSB_CUDA_PATH}")
# find_package(CUDA REQUIRED)
#enable_language(CUDA)
# Check for CUDA version
#set(PSB_CUDA_VERSION 12800)
#if(PSB_CUDA_VERSION)
# message(STATUS "CUDA version: ${PSB_CUDA_VERSION}")
# Define macros for CUDA version
# add_definitions(-DPSB_HAVE_CUDA)
# add_definitions(-DPSB_CUDA_VERSION=${PSB_CUDA_VERSION})
#math(EXPR PSB_CUDA_SHORT_VERSION "${PSB_CUDA_VERSION} / 1000")
# add_definitions(-DPSB_CUDA_SHORT_VERSION=${PSB_CUDA_SHORT_VERSION})
#set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_HAVE_CUDA")
#set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_CUDA_VERSION=${PSB_CUDA_VERSION}")
#set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPSB_CUDA_SHORT_VERSION=${PSB_CUDA_SHORT_VERSION}")
#set(CHAVECUDA "#define PSB_HAVE_CUDA")
#set(CSHORTVCUDA "#define PSB_CUDA_SHORT_VERSION ${PSB_CUDA_SHORT_VERSION}")
#set(CVERSIONCUDA "#define PSB_CUDA_VERSION ${PSB_CUDA_VERSION}")
#else()
#message(FATAL_ERROR "CUDA version not found!")
#endif()
# Define the CUDA library
#if(WIN32)
#add_library(psb_cuda_C STATIC ${cuda_source_files})
#target_compile_definitions(psb_cuda_C
# PRIVATE -DWIN32 -D_LIB -DWIN64)
#set_target_properties(psb_cuda_C
# PROPERTIES
# LINKER_LANGUAGE C
# POSITION_INDEPENDENT_CODE TRUE)
#target_link_libraries(psb_cuda_C
# PUBLIC kernel32 user32 shell32)
#else()
#add_library(psb_cuda_C OBJECT ${cuda_source_files})
#endif()
foreach(path IN LISTS cuda_header_C_files)
# Copy the header file to the include directory
file(COPY "${path}" DESTINATION "${CMAKE_BINARY_DIR}/include")
endforeach()
message(STATUS "Copied .h files to ${CMAKE_BINARY_DIR}/include")
foreach(path IN LISTS cuda_header_cu_files)
# Copy the header file to the include directory
file(COPY "${path}" DESTINATION "${CMAKE_BINARY_DIR}/include")
endforeach()
message(STATUS "Copied .cuh files to ${CMAKE_BINARY_DIR}/include")
add_library(psb_cuda_C OBJECT ${cuda_source_C_files} ${cuda_source_cu_files})
# Create the main CUDA library
add_library(cuda ${cuda_source_files})
# Set properties for the CUDA library
set_target_properties(cuda
PROPERTIES
POSITION_INDEPENDENT_CODE TRUE
OUTPUT_NAME psb_cuda
VERSION ${VERSION} SOVERSION ${SOVERSION}
LINKER_LANGUAGE C)
# Include directories for the CUDA library
target_include_directories(cuda PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules> # Path for building
$<INSTALL_INTERFACE:modules> # Path for installation
#/opt/cuda/12.8/include
)
# Link with other necessary libraries
target_link_libraries(cuda PUBLIC base prec linsolve ext util)
endif()
#if(MPI_FOUND)
# Copy mpi.mod from the first available path in MPI_Fortran_INCLUDE_PATH
# set(MPI_MOD_COPIED FALSE)
# foreach(path IN LISTS MPI_Fortran_INCLUDE_PATH)
# Construct the full path to the mpi.mod file
# set(mpi_mod_path "${path}/mpi.mod")
# Check if the mpi.mod file exists
# if(EXISTS "${mpi_mod_path}")
# Copy the mpi.mod file to the module directory
# file(COPY "${mpi_mod_path}" DESTINATION "${CMAKE_Fortran_MODULE_DIRECTORY}")
#message(STATUS "Copied mpi.mod from ${mpi_mod_path} to ${CMAKE_Fortran_MODULE_DIRECTORY}")
#set(MPI_MOD_COPIED TRUE)
#break() # Exit the loop once we've copied the file
#endif()
#endforeach()
#if(NOT MPI_MOD_COPIED)
# message(WARNING "mpi.mod not found in any of the specified paths: ${MPI_Fortran_INCLUDE_PATH}")
#endif()
#foreach(lib base prec linsolve ext util cbind)
# target_link_libraries(${lib} PUBLIC ${MPI_C_LIBRARIES} ${MPI_Fortran_LIBRARIES})
#endforeach()
#endif()
if(OpenCoarrays_FOUND)
foreach(lib base prec linsolve ext util cbind) #TODO: check if cbind goes here!
target_link_libraries(${lib} PUBLIC OpenCoarrays::caf_mpi_static)
endforeach()
endif()
message(STATUS "\t\t ${CMAKE_INSTALL_LIBDIR}")
# Install the header files to the include directory
#install(FILES ${cbind_header_C_files}
# DESTINATION include
#)
#install(DIRECTORY "${CMAKE_BINARY_DIR}/include" DESTINATION "include"
# FILES_MATCHING PATTERN "*.h")
#install(DIRECTORY "${CMAKE_BINARY_DIR}/modules" DESTINATION "modules"
# FILES_MATCHING PATTERN "*.mod")
#install(DIRECTORY "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}" DESTINATION "include"
# FILES_MATCHING PATTERN "*.h")
#install(DIRECTORY "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_MODULDIR}" DESTINATION "modules"
# FILES_MATCHING PATTERN "*.mod")
# Install header files
install(DIRECTORY ${CMAKE_BINARY_DIR}/include/
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" # This will place headers in <prefix>/include
FILES_MATCHING PATTERN "*.h"
)
# Install module files
install(DIRECTORY ${CMAKE_BINARY_DIR}/modules/
DESTINATION "${CMAKE_INSTALL_MODULDIR}" # This will place .mod files in <prefix>/modules
FILES_MATCHING PATTERN "*.mod"
)
install(TARGETS base prec linsolve ext util cbind
EXPORT ${CMAKE_PROJECT_NAME}-targets
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
if(PSB_BUILD_CUDA)
install(TARGETS cuda
EXPORT ${CMAKE_PROJECT_NAME}-targets
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
endif()
if(WIN32)
install(TARGETS psb_base_C
EXPORT ${CMAKE_PROJECT_NAME}-targets
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
if(METIS_FOUND)
install(TARGETS psb_util_C
EXPORT ${CMAKE_PROJECT_NAME}-targets
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
endif()
endif()
#configure_package_config_file(
# INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}/cmake/psblas"
#)
#install(FILES
# "${CMAKE_CURRENT_BINARY_DIR}/psblasConfig.cmake"
# "${CMAKE_CURRENT_BINARY_DIR}/psblasConfigVersion.cmake"
# DESTINATION "${CMAKE_INSTALL_PREFIX}/cmake/psblas"
#)
export(
EXPORT ${CMAKE_PROJECT_NAME}-targets
FILE "${CMAKE_CURRENT_BINARY_DIR}/psblasTargets.cmake"
NAMESPACE ${CMAKE_PROJECT_NAME}::
)
# Set the installation directory for the test files
set(INSTALL_TEST_DIR "${CMAKE_INSTALL_PREFIX}/samples" CACHE PATH "Installation directory for sample files")
function(install_directory_recursive source_dir install_base_dir) # Function to install a directory and its subdirectories recursively
file(GLOB_RECURSE ALL_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/${source_dir}" "${source_dir}/*")
foreach(FILE_PATH IN LISTS ALL_FILES)
# Construct the full source and destination paths
set(FULL_SOURCE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${source_dir}/${FILE_PATH}")
set(FULL_INSTALL_PATH "${install_base_dir}/${FILE_PATH}")
# Check if it's a directory
if(IS_DIRECTORY "${FULL_SOURCE_PATH}")
# Create the directory in the install destination
file(MAKE_DIRECTORY "${FULL_INSTALL_PATH}")
else()
# Install the file
install(FILES "${FULL_SOURCE_PATH}" DESTINATION "${install_base_dir}" RENAME "${FILE_PATH}")
endif()
endforeach()
endfunction()
# Install cbind/test directory
install_directory_recursive(cbind/test "${INSTALL_TEST_DIR}/cbind")
# Install test/fileread directory
install_directory_recursive(test/fileread "${INSTALL_TEST_DIR}/fileread")
# Install test/pdegen directory
install_directory_recursive(test/pdegen "${INSTALL_TEST_DIR}/pdegen")
message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} - ${PSB_CMAKE_INSTALL_PREFIX};")
message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR} - ${PSB_CMAKE_INSTALL_LIBDIR};")
message(STATUS "CMAKE_INSTALL_INCLUDEDIR: ${CMAKE_INSTALL_INCLUDEDIR} - ${PSB_CMAKE_INSTALL_INCLUDEDIR};")
message(STATUS "CMAKE_INSTALL_MODULDIR: ${CMAKE_INSTALL_MODULDIR} - ${PSB_CMAKE_INSTALL_MODULDIR};")
#-----------------
# Add PSBLAS tests
#-----------------
# Unit tests targeting each function, argument, and branch of code
# add_mpi_test(initialize_mpi 2 initialize_mpi)