From 92b77cb3210280315c47d18f3c87cdd2c59021bc Mon Sep 17 00:00:00 2001 From: "Michael Hirsch, Ph.D" Date: Sun, 24 Nov 2019 00:13:54 -0500 Subject: deps: add scalapack Scalapack uses a library stack that can be challenging to manage. Not least of all since many Scalapacks ship with broken / incomplete pkg-config files and CMake FindScalapack.cmake This resolves those issues for typical Scalapack setups including: * Linux: Intel MKL or OpenMPI + Netlib * MacOS: Intel MKL or OpenMPI + Netlib * Windows: Intel MKL (OpenMPI not available on Windows) --- mesonbuild/dependencies/scalapack.py | 121 +++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 mesonbuild/dependencies/scalapack.py (limited to 'mesonbuild/dependencies/scalapack.py') diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py new file mode 100644 index 0000000..4057091 --- /dev/null +++ b/mesonbuild/dependencies/scalapack.py @@ -0,0 +1,121 @@ +# Copyright 2013-2019 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pathlib import Path +import os + +from .. import mesonlib +from .base import (CMakeDependency, ExternalDependency, PkgConfigDependency) + + +class ScalapackDependency(ExternalDependency): + def __init__(self, environment, kwargs: dict): + language = kwargs.get('language') + super().__init__('scalapack', environment, language, 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'] + + 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 + 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 = 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.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 -- cgit v1.1 From e209dd2607c775cf8705c3b6ef70389c85a782e3 Mon Sep 17 00:00:00 2001 From: "Michael Hirsch, Ph.D" Date: Sat, 30 Nov 2019 22:16:40 -0500 Subject: scalapack: allow specifying find method --- mesonbuild/dependencies/scalapack.py | 173 +++++++++++++++++------------------ 1 file changed, 86 insertions(+), 87 deletions(-) (limited to 'mesonbuild/dependencies/scalapack.py') diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py index 4057091..36bfd66 100644 --- a/mesonbuild/dependencies/scalapack.py +++ b/mesonbuild/dependencies/scalapack.py @@ -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] -- cgit v1.1