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

864 lines
26 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)
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)
#TODO: check if it is needed an mpi compiler 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()
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")
#add define values for integer size (IPKx) and long size (LPKx)
CHECK_TYPE_SIZE("int" INT_SIZE LANGUAGE C)
CHECK_TYPE_SIZE("long" LONG_SIZE LANGUAGE C)
message(STATUS "INT SIZE ${INT_SIZE}")
add_compile_options(-DIPK${INT_SIZE})
add_compile_options(-DLPK${LONG_SIZE})
endif()
#-----------------------------------------
# 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)
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(-DHAVE_VOLATILE)
message(STATUS "-DHAVE_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(-DHAVE_ISO_FORTRAN_ENV)
message(STATUS "-DHAVE_ISO_FORTRAN_ENV")
endif()
CHECK_Fortran_SOURCE_COMPILES(
"flush(5); end"
HAVE_FLUSH_STMT
SRC_EXT f90
)
if(HAVE_FLUSH_STMT)
add_compile_options(-DHAVE_FLUSH_STMT)
message(STATUS "-DHAVE_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(-DHAVE_FINAL)
message(STATUS "-DHAVE_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(-DHAVE_MOLD)
message(STATUS "-DHAVE_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(-DHAVE_EXTENDS_TYPE_OF)
message(STATUS "-DHAVE_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(-DHAVE_SAME_TYPE_AS)
message(STATUS "-DHAVE_SAME_TYPE_AS")
endif()
#----------------------------------------------------------------------------
# Find MPI and set some flags so that FC and CC can point to gfortran and gcc
#----------------------------------------------------------------------------
find_package( MPI REQUIRED Fortran )
if(MPI_FOUND)
#-----------------------------------------------
# Work around an issue present on fedora systems
#-----------------------------------------------
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 is
known to cause segmentation faults for some Fortran codes. See, e.g.,
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71729 or
https://github.com/sourceryinstitute/OpenCoarrays/issues/317.
`noexecstack` is being replaced 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()
message(STATUS "Found MPI: ${MPI_C_LIBRARIES} ${MPI_Fortran_LIBRARIES}")
#----------------
# Setup MPI flags
#----------------
list(REMOVE_DUPLICATES 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})
include_directories(BEFORE ${MPI_C_INCLUDE_PATH} ${MPI_Fortran_INCLUDE_PATH})
message(STATUS "${MPI_C_INCLUDE_PATH}; ${MPI_Fortran_INCLUDE_PATH};; ${CMAKE_Fortran_LINK_FLAGS} ;")
if(MPI_Fortran_HAVE_F90_MODULE OR MPI_Fortran_HAVE_F08_MODULE)
add_compile_options(-DMPI_MOD)
message(STATUS "-DMPI_MOD")
#add_compile_options(-DSERIAL_MPI) # Is it right??
#message(STATUS "-DSERIAL_MPI")
endif()
set(SERIAL_MPI OFF)
else()
message(STATUS "MPI not found, serial ahead")
add_compile_options(-DSERIAL_MPI)
add_compile_options(-DMPI_MOD)
set(SERIAL_MPI ON)
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(-DHAVE_LAPACK)
#--------------------------------
# Find METIS partitioning library
#--------------------------------
include(${CMAKE_CURRENT_LIST_DIR}/cmake/FindMETIS.cmake)
find_package(METIS)
#---------------------------------------------------
# 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}/${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
#-----------------------------------
# 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 "${psblas_VERSION}"
COMPATIBILITY SameMajorVersion
)
configure_file("${CMAKE_SOURCE_DIR}/cmake/pkg/${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"
DESTINATION
"${CMAKE_INSTALL_LIBDIR}/cmake/psblas"
)
#------------------------------------------
# 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()
#---------------------------------------
# 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}")
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
)
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
)
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
)
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
)
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)
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()
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
)
target_include_directories(util PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/modules>
$<INSTALL_INTERFACE:modules>)
target_link_libraries(util PUBLIC base prec)
if(METIS_FOUND)
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
if (COMPILER_RESULT)
execute_process(COMMAND "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/test_size"
OUTPUT_VARIABLE type_size)
string(STRIP "${type_size}" type_size)
if (type_name STREQUAL "float")
set(METIS_REAL_32 "${type_size}")
add_definitions(-DMETIS_REAL_32)
elseif (type_name STREQUAL "double")
set(METIS_REAL_64 "${type_size}")
add_definitions(-DMETIS_REAL_64)
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(-DHAVE_METIS)
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 HAVE_METIS_)
target_compile_definitions(util
PUBLIC 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 ${base_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})
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
)
#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
#)
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(TARGETS base prec linsolve ext util cbind
EXPORT ${CMAKE_PROJECT_NAME}-targets
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
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()
# Step 2: Create the configuration file from the template
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/psblasConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/psblasConfig.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/psblas"
)
# Step 3: Install the generated config files
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/psblasConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/psblasConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/psblas"
)
# Step 4: Export targets so that the build directory can be used directly
export(
EXPORT ${CMAKE_PROJECT_NAME}-targets
FILE "${CMAKE_CURRENT_BINARY_DIR}/psblasTargets.cmake"
NAMESPACE psblas::
)
#-----------------
# Add PSBLAS tests
#-----------------
# Unit tests targeting each function, argument, and branch of code
# add_mpi_test(initialize_mpi 2 initialize_mpi)