scalapack: allow specifying find method

pull/6228/head
Michael Hirsch, Ph.D 5 years ago
parent 3120481d77
commit e209dd2607
No known key found for this signature in database
GPG Key ID: 6D23CDADAB0294F9
  1. 173
      mesonbuild/dependencies/scalapack.py
  2. 223
      test cases/frameworks/30 scalapack/cmake/FindSCALAPACK.cmake
  3. 2
      test cases/frameworks/30 scalapack/meson.build

@ -16,106 +16,105 @@ from pathlib import Path
import os
from .. import mesonlib
from .base import (CMakeDependency, ExternalDependency, PkgConfigDependency)
from .base import CMakeDependency, DependencyMethods, ExternalDependency, PkgConfigDependency
class ScalapackDependency(ExternalDependency):
def __init__(self, environment, kwargs: dict):
language = kwargs.get('language')
super().__init__('scalapack', environment, language, kwargs)
methods = mesonlib.listify(kwargs.get('method', 'auto'))
super().__init__('scalapack', environment, None, kwargs)
kwargs['required'] = False
kwargs['silent'] = True
self.is_found = False
self.static = kwargs.get('static', False)
# 1. try pkg-config
pkgconfig_files = []
mklroot = None
is_gcc = None
if language == 'fortran':
is_gcc = environment.detect_fortran_compiler(self.for_machine).get_id() == 'gcc'
elif language == 'c':
is_gcc = environment.detect_c_compiler(self.for_machine).get_id() == 'gcc'
elif language == 'cpp':
is_gcc = environment.detect_cpp_compiler(self.for_machine).get_id() == 'gcc'
# Intel MKL works with non-Intel compilers too -- but not gcc on windows
if 'MKLROOT' in os.environ and not (mesonlib.is_windows() and is_gcc):
try:
mklroot = Path(os.environ['MKLROOT']).resolve()
except Exception:
pass
if mklroot is not None:
# MKL pkg-config is a start, but you have to add / change stuff
# https://software.intel.com/en-us/articles/intel-math-kernel-library-intel-mkl-and-pkg-config-tool
pkgconfig_files = (
['mkl-static-lp64-iomp'] if self.static else ['mkl-dynamic-lp64-iomp']
)
if mesonlib.is_windows():
suffix = '.lib'
elif self.static:
suffix = '.a'
else:
suffix = ''
libdir = mklroot / 'lib/intel64'
# Intel compiler might not have Parallel Suite
pkgconfig_files += ['scalapack-openmpi', 'scalapack']
if set(methods).intersection(['auto', 'pkg-config']):
pkgconfig_files = []
mklroot = None
is_gcc = self.clib_compiler.get_id() == 'gcc'
# Intel MKL works with non-Intel compilers too -- but not gcc on windows
if 'MKLROOT' in os.environ and not (mesonlib.is_windows() and is_gcc):
try:
mklroot = Path(os.environ['MKLROOT']).resolve()
except Exception:
pass
if mklroot is not None:
# MKL pkg-config is a start, but you have to add / change stuff
# https://software.intel.com/en-us/articles/intel-math-kernel-library-intel-mkl-and-pkg-config-tool
pkgconfig_files = (
['mkl-static-lp64-iomp'] if self.static else ['mkl-dynamic-lp64-iomp']
)
if mesonlib.is_windows():
suffix = '.lib'
elif self.static:
suffix = '.a'
else:
suffix = ''
libdir = mklroot / 'lib/intel64'
# Intel compiler might not have Parallel Suite
pkgconfig_files += ['scalapack-openmpi', 'scalapack']
for pkg in pkgconfig_files:
pkgdep = PkgConfigDependency(
pkg, environment, kwargs, language=self.language
)
if pkgdep.found():
self.compile_args = pkgdep.get_compile_args()
if mklroot:
link_args = pkgdep.get_link_args()
if is_gcc:
for i, a in enumerate(link_args):
if 'mkl_intel_lp64' in a:
link_args[i] = a.replace('intel', 'gf')
for pkg in pkgconfig_files:
pkgdep = PkgConfigDependency(
pkg, environment, kwargs, language=self.language
)
if pkgdep.found():
self.compile_args = pkgdep.get_compile_args()
if mklroot:
link_args = pkgdep.get_link_args()
if is_gcc:
for i, a in enumerate(link_args):
if 'mkl_intel_lp64' in a:
link_args[i] = a.replace('intel', 'gf')
break
# MKL pkg-config omits scalapack
# be sure "-L" and "-Wl" are first if present
i = 0
for j, a in enumerate(link_args):
if a.startswith(('-L', '-Wl')):
i = j + 1
elif j > 3:
break
# MKL pkg-config omits scalapack
# be sure "-L" and "-Wl" are first if present
i = 0
for j, a in enumerate(link_args):
if a.startswith(('-L', '-Wl')):
i = j + 1
elif j > 3:
break
if mesonlib.is_windows() or self.static:
link_args.insert(
i, str(libdir / ('mkl_scalapack_lp64' + suffix))
)
link_args.insert(
i + 1, str(libdir / ('mkl_blacs_intelmpi_lp64' + suffix))
)
if mesonlib.is_windows() or self.static:
link_args.insert(
i, str(libdir / ('mkl_scalapack_lp64' + suffix))
)
link_args.insert(
i + 1, str(libdir / ('mkl_blacs_intelmpi_lp64' + suffix))
)
else:
link_args.insert(i, '-lmkl_scalapack_lp64')
link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64')
else:
link_args.insert(i, '-lmkl_scalapack_lp64')
link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64')
else:
link_args = pkgdep.get_link_args()
self.link_args = link_args
link_args = pkgdep.get_link_args()
self.link_args = link_args
self.version = pkgdep.get_version()
if self.version == 'unknown' and mklroot:
try:
v = (
mklroot.as_posix()
.split('compilers_and_libraries_')[1]
.split('/', 1)[0]
)
if v:
self.version = v
except IndexError:
pass
self.version = pkgdep.get_version()
if self.version == 'unknown' and mklroot:
try:
v = (
mklroot.as_posix()
.split('compilers_and_libraries_')[1]
.split('/', 1)[0]
)
if v:
self.version = v
except IndexError:
pass
self.is_found = True
self.pcdep = pkgdep
return
if set(methods).intersection(['auto', 'cmake']):
cmakedep = CMakeDependency('Scalapack', environment, kwargs)
if cmakedep.found():
self.compile_args = cmakedep.get_compile_args()
self.link_args = cmakedep.get_link_args()
self.version = cmakedep.get_version()
self.is_found = True
self.pcdep = pkgdep
return
# 2. try CMake
cmakedep = CMakeDependency('Scalapack', environment, kwargs)
if cmakedep.found():
self.compile_args = cmakedep.get_compile_args()
self.link_args = cmakedep.get_link_args()
self.version = cmakedep.get_version()
self.is_found = True
return
@staticmethod
def get_methods():
return [DependencyMethods.AUTO, DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE]

@ -0,0 +1,223 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindSCALAPACK
-------------
* Michael Hirsch, Ph.D. www.scivision.dev
Let Michael know if there are more MKL / Lapack / compiler combination you want.
Refer to https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor
Finds SCALAPACK libraries for MKL, OpenMPI and MPICH.
Intel MKL relies on having environment variable MKLROOT set, typically by sourcing
mklvars.sh beforehand.
This also uses our FindLAPACK.cmake to deduplicate code.
Parameters
^^^^^^^^^^
``MKL``
Intel MKL for MSVC, ICL, ICC, GCC and PGCC. Working with IntelMPI (default Window, Linux), MPICH (default Mac) or OpenMPI (Linux only).
``IntelMPI``
MKL BLACS IntelMPI
``MKL64``
MKL only: 64-bit integers (default is 32-bit integers)
``OpenMPI``
SCALAPACK + OpenMPI
``MPICH``
SCALAPACK + MPICH
Result Variables
^^^^^^^^^^^^^^^^
``SCALAPACK_FOUND``
SCALapack libraries were found
``SCALAPACK_<component>_FOUND``
SCALAPACK <component> specified was found
``SCALAPACK_LIBRARIES``
SCALapack library files
``SCALAPACK_INCLUDE_DIRS``
SCALapack include directories
References
^^^^^^^^^^
* Pkg-Config and MKL: https://software.intel.com/en-us/articles/intel-math-kernel-library-intel-mkl-and-pkg-config-tool
* MKL for Windows: https://software.intel.com/en-us/mkl-windows-developer-guide-static-libraries-in-the-lib-intel64-win-directory
* MKL Windows directories: https://software.intel.com/en-us/mkl-windows-developer-guide-high-level-directory-structure
#]=======================================================================]
#===== functions
function(mkl_scala)
set(_mkl_libs ${ARGV})
foreach(s ${_mkl_libs})
find_library(SCALAPACK_${s}_LIBRARY
NAMES ${s}
PATHS ENV MKLROOT ENV I_MPI_ROOT ENV TBBROOT
PATH_SUFFIXES
lib/intel64 lib/intel64_win
intel64/lib/release
lib/intel64/gcc4.7 ../tbb/lib/intel64/gcc4.7
lib/intel64/vc_mt ../tbb/lib/intel64/vc_mt
../compiler/lib/intel64
HINTS ${MKL_LIBRARY_DIRS} ${MKL_LIBDIR}
NO_DEFAULT_PATH)
if(NOT SCALAPACK_${s}_LIBRARY)
message(WARNING "MKL component not found: " ${s})
return()
endif()
list(APPEND SCALAPACK_LIB ${SCALAPACK_${s}_LIBRARY})
endforeach()
find_path(SCALAPACK_INCLUDE_DIR
NAMES mkl_scalapack.h
PATHS ENV MKLROOT ENV I_MPI_ROOT ENV TBBROOT
PATH_SUFFIXES
include
include/intel64/${_mkl_bitflag}lp64
HINTS ${MKL_INCLUDE_DIRS})
if(NOT SCALAPACK_INCLUDE_DIR)
message(WARNING "MKL Include Dir not found")
return()
endif()
list(APPEND SCALAPACK_INCLUDE_DIR
${MKL_INCLUDE_DIRS})
set(SCALAPACK_LIBRARY ${SCALAPACK_LIB} PARENT_SCOPE)
set(SCALAPACK_INCLUDE_DIR ${SCALAPACK_INCLUDE_DIR} PARENT_SCOPE)
endfunction(mkl_scala)
#==== main program
cmake_policy(VERSION 3.11)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
cmake_policy(SET CMP0074 NEW)
cmake_policy(SET CMP0075 NEW)
endif()
if(NOT (OpenMPI IN_LIST SCALAPACK_FIND_COMPONENTS
OR MPICH IN_LIST SCALAPACK_FIND_COMPONENTS
OR MKL IN_LIST SCALAPACK_FIND_COMPONENTS))
if(DEFINED ENV{MKLROOT})
if(APPLE)
list(APPEND SCALAPACK_FIND_COMPONENTS MKL MPICH)
else()
list(APPEND SCALAPACK_FIND_COMPONENTS MKL IntelMPI)
endif()
else()
list(APPEND SCALAPACK_FIND_COMPONENTS OpenMPI)
endif()
endif()
find_package(PkgConfig)
if(NOT WIN32)
find_package(Threads) # not required--for example Flang
endif()
if(MKL IN_LIST SCALAPACK_FIND_COMPONENTS)
if(BUILD_SHARED_LIBS)
set(_mkltype dynamic)
else()
set(_mkltype static)
endif()
if(MKL64 IN_LIST SCALAPACK_FIND_COMPONENTS)
set(_mkl_bitflag i)
else()
set(_mkl_bitflag)
endif()
if(WIN32)
set(_impi impi)
else()
unset(_impi)
endif()
pkg_check_modules(MKL mkl-${_mkltype}-${_mkl_bitflag}lp64-iomp)
if(OpenMPI IN_LIST SCALAPACK_FIND_COMPONENTS)
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_openmpi_${_mkl_bitflag}lp64)
if(SCALAPACK_LIBRARY)
set(SCALAPACK_OpenMPI_FOUND true)
endif()
elseif(MPICH IN_LIST SCALAPACK_FIND_COMPONENTS)
if(APPLE)
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_mpich_${_mkl_bitflag}lp64)
elseif(WIN32)
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_mpich2_${_mkl_bitflag}lp64.lib mpi.lib fmpich2.lib)
else() # linux, yes it's just like IntelMPI
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_intelmpi_${_mkl_bitflag}lp64)
endif()
if(SCALAPACK_LIBRARY)
set(SCALAPACK_MPICH_FOUND true)
endif()
else() # IntelMPI
mkl_scala(mkl_scalapack_${_mkl_bitflag}lp64 mkl_blacs_intelmpi_${_mkl_bitflag}lp64 ${_impi})
if(SCALAPACK_LIBRARY)
set(SCALAPACK_IntelMPI_FOUND true)
endif()
endif()
if(SCALAPACK_LIBRARY)
set(SCALAPACK_MKL_FOUND true)
endif()
elseif(OpenMPI IN_LIST SCALAPACK_FIND_COMPONENTS)
pkg_check_modules(SCALAPACK scalapack-openmpi)
find_library(SCALAPACK_LIBRARY
NAMES scalapack scalapack-openmpi
HINTS ${SCALAPACK_LIBRARY_DIRS} ${SCALAPACK_LIBDIR})
if(SCALAPACK_LIBRARY)
set(SCALAPACK_OpenMPI_FOUND true)
endif()
elseif(MPICH IN_LIST SCALAPACK_FIND_COMPONENTS)
find_library(SCALAPACK_LIBRARY
NAMES scalapack-mpich scalapack-mpich2)
if(SCALAPACK_LIBRARY)
set(SCALAPACK_MPICH_FOUND true)
endif()
endif()
# Finalize
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
SCALAPACK
REQUIRED_VARS SCALAPACK_LIBRARY
HANDLE_COMPONENTS)
if(SCALAPACK_FOUND)
set(SCALAPACK_LIBRARIES ${SCALAPACK_LIBRARY})
set(SCALAPACK_INCLUDE_DIRS ${SCALAPACK_INCLUDE_DIR})
endif()
mark_as_advanced(SCALAPACK_LIBRARY SCALAPACK_INCLUDE_DIR)

@ -25,3 +25,5 @@ if add_languages('fortran')
dependencies: [scalapack, mpi_f])
test('scalapack_fortran', f_exe, timeout: 30)
endif
scalapack_cmake = dependency('scalapack', method: 'cmake', cmake_module_path: 'cmake', required: false)

Loading…
Cancel
Save