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

@ -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]) dependencies: [scalapack, mpi_f])
test('scalapack_fortran', f_exe, timeout: 30) test('scalapack_fortran', f_exe, timeout: 30)
endif endif
scalapack_cmake = dependency('scalapack', method: 'cmake', cmake_module_path: 'cmake', required: false)

Loading…
Cancel
Save