diff options
author | Elliott Sales de Andrade <quantum.analyst@gmail.com> | 2017-06-03 23:38:52 -0400 |
---|---|---|
committer | Elliott Sales de Andrade <quantum.analyst@gmail.com> | 2017-08-04 20:06:47 -0400 |
commit | 5a7e06a64f90f24b7cf642b43a81faf300bfc2fe (patch) | |
tree | b7611866f9c271abf5bf3c848046fa105bc98b48 | |
parent | 58bd1e83b4e24eaab3cf18deb635a057d6bfefb7 (diff) | |
download | meson-5a7e06a64f90f24b7cf642b43a81faf300bfc2fe.zip meson-5a7e06a64f90f24b7cf642b43a81faf300bfc2fe.tar.gz meson-5a7e06a64f90f24b7cf642b43a81faf300bfc2fe.tar.bz2 |
Add MPI dependency.
We prefer pkg-config files, though only OpenMPI supplies them.
Otherwise, check environment variables and search for wrappers and ask
them for what to do.
-rw-r--r-- | mesonbuild/dependencies/__init__.py | 3 | ||||
-rw-r--r-- | mesonbuild/dependencies/misc.py | 131 | ||||
-rw-r--r-- | test cases/common/157 mpi/main.c | 27 | ||||
-rw-r--r-- | test cases/common/157 mpi/main.cpp | 11 | ||||
-rw-r--r-- | test cases/common/157 mpi/main.f90 | 21 | ||||
-rw-r--r-- | test cases/common/157 mpi/meson.build | 24 |
6 files changed, 215 insertions, 2 deletions
diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py index f153b97..fb57e3d 100644 --- a/mesonbuild/dependencies/__init__.py +++ b/mesonbuild/dependencies/__init__.py @@ -17,7 +17,7 @@ from .base import ( # noqa: F401 ExternalDependency, ExternalLibrary, ExtraFrameworkDependency, InternalDependency, PkgConfigDependency, find_external_dependency, get_dep_identifier, packages) from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDependency -from .misc import BoostDependency, Python3Dependency, ThreadDependency +from .misc import (BoostDependency, MPIDependency, Python3Dependency, ThreadDependency) from .platform import AppleFrameworks from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency, VulkanDependency @@ -31,6 +31,7 @@ packages.update({ # From misc: 'boost': BoostDependency, + 'mpi': MPIDependency, 'python3': Python3Dependency, 'threads': ThreadDependency, diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 99df587..71f7369 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -16,6 +16,8 @@ import glob import os +import re +import shlex import stat import sysconfig @@ -24,7 +26,7 @@ from .. import mesonlib from ..environment import detect_cpu_family from .base import DependencyException, DependencyMethods -from .base import ExternalDependency, ExtraFrameworkDependency, PkgConfigDependency +from .base import ExternalDependency, ExternalProgram, ExtraFrameworkDependency, PkgConfigDependency class BoostDependency(ExternalDependency): @@ -277,6 +279,133 @@ class BoostDependency(ExternalDependency): return 'thread' in self.requested_modules +class MPIDependency(ExternalDependency): + def __init__(self, environment, kwargs): + language = kwargs.get('language', 'c') + super().__init__('mpi', environment, language, kwargs) + required = kwargs.pop('required', True) + kwargs['required'] = False + kwargs['silent'] = True + self.is_found = False + + # NOTE: Only OpenMPI supplies a pkg-config file at the moment. + if language == 'c': + env_vars = ['MPICC'] + pkgconfig_files = ['ompi-c'] + default_wrappers = ['mpicc'] + elif language == 'cpp': + env_vars = ['MPICXX'] + pkgconfig_files = ['ompi-cxx'] + default_wrappers = ['mpic++', 'mpicxx', 'mpiCC'] + elif language == 'fortran': + env_vars = ['MPIFC', 'MPIF90', 'MPIF77'] + pkgconfig_files = ['ompi-fort'] + default_wrappers = ['mpifort', 'mpif90', 'mpif77'] + else: + raise DependencyException('Language {} is not supported with MPI.'.format(language)) + + for pkg in pkgconfig_files: + try: + pkgdep = PkgConfigDependency(pkg, environment, kwargs) + if pkgdep.found(): + self.compile_args = pkgdep.get_compile_args() + self.link_args = pkgdep.get_link_args() + self.version = pkgdep.get_version() + self.is_found = True + break + except Exception: + pass + + if not self.is_found: + # Prefer environment. + for var in env_vars: + if var in os.environ: + wrappers = [os.environ[var]] + break + else: + # Or search for default wrappers. + wrappers = default_wrappers + + for prog in wrappers: + result = self._try_openmpi_wrapper(prog) + if result is not None: + self.is_found = True + self.version = result[0] + self.compile_args = result[1] + self.link_args = result[2] + break + result = self._try_other_wrapper(prog) + if result is not None: + self.is_found = True + self.version = result[0] + self.compile_args = result[1] + self.link_args = result[2] + break + + if self.is_found: + mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.green('YES'), self.version) + else: + mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.red('NO')) + if required: + raise DependencyException('MPI dependency {!r} not found'.format(self.name)) + + def _try_openmpi_wrapper(self, prog): + prog = ExternalProgram(prog, silent=True) + if prog.found(): + cmd = prog.get_command() + ['--showme:compile'] + p, o, e = mesonlib.Popen_safe(cmd) + p.wait() + if p.returncode != 0: + mlog.debug('Command', mlog.bold(cmd), 'failed to run:') + mlog.debug(mlog.bold('Standard output\n'), o) + mlog.debug(mlog.bold('Standard error\n'), e) + return + cargs = shlex.split(o) + + cmd = prog.get_command() + ['--showme:link'] + p, o, e = mesonlib.Popen_safe(cmd) + p.wait() + if p.returncode != 0: + mlog.debug('Command', mlog.bold(cmd), 'failed to run:') + mlog.debug(mlog.bold('Standard output\n'), o) + mlog.debug(mlog.bold('Standard error\n'), e) + return + libs = shlex.split(o) + + cmd = prog.get_command() + ['--showme:version'] + p, o, e = mesonlib.Popen_safe(cmd) + p.wait() + if p.returncode != 0: + mlog.debug('Command', mlog.bold(cmd), 'failed to run:') + mlog.debug(mlog.bold('Standard output\n'), o) + mlog.debug(mlog.bold('Standard error\n'), e) + return + version = re.search('\d+.\d+.\d+', o) + if version: + version = version.group(0) + else: + version = 'none' + + return version, cargs, libs + + def _try_other_wrapper(self, prog): + prog = ExternalProgram(prog, silent=True) + if prog.found(): + cmd = prog.get_command() + ['-show'] + p, o, e = mesonlib.Popen_safe(cmd) + p.wait() + if p.returncode != 0: + mlog.debug('Command', mlog.bold(cmd), 'failed to run:') + mlog.debug(mlog.bold('Standard output\n'), o) + mlog.debug(mlog.bold('Standard error\n'), e) + return + args = shlex.split(o) + + version = 'none' + + return version, args, args + + class ThreadDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('threads', environment, None, {}) diff --git a/test cases/common/157 mpi/main.c b/test cases/common/157 mpi/main.c new file mode 100644 index 0000000..e44357a --- /dev/null +++ b/test cases/common/157 mpi/main.c @@ -0,0 +1,27 @@ +#include <stdio.h> +#include <mpi.h> + +int main(int argc, char **argv) +{ + int ier, flag; + ier = MPI_Init(&argc, &argv); + if (ier) { + printf("Unable to initialize MPI: %d\n", ier); + return 1; + } + ier = MPI_Initialized(&flag); + if (ier) { + printf("Unable to check MPI initialization state: %d\n", ier); + return 1; + } + if (!flag) { + printf("MPI did not initialize!\n"); + return 1; + } + ier = MPI_Finalize(); + if (ier) { + printf("Unable to finalize MPI: %d\n", ier); + return 1; + } + return 0; +} diff --git a/test cases/common/157 mpi/main.cpp b/test cases/common/157 mpi/main.cpp new file mode 100644 index 0000000..0e0b621 --- /dev/null +++ b/test cases/common/157 mpi/main.cpp @@ -0,0 +1,11 @@ +#include <mpi.h> + +int main(int argc, char **argv) +{ + MPI::Init(argc, argv); + if (!MPI::Is_initialized()) { + printf("MPI did not initialize!\n"); + return 1; + } + MPI::Finalize(); +} diff --git a/test cases/common/157 mpi/main.f90 b/test cases/common/157 mpi/main.f90 new file mode 100644 index 0000000..d379e96 --- /dev/null +++ b/test cases/common/157 mpi/main.f90 @@ -0,0 +1,21 @@ +program mpitest + implicit none + include 'mpif.h' + logical :: flag + integer :: ier + call MPI_Init(ier) + if (ier /= 0) then + print *, 'Unable to initialize MPI: ', ier + stop 1 + endif + call MPI_Initialized(flag, ier) + if (ier /= 0) then + print *, 'Unable to check MPI initialization state: ', ier + stop 1 + endif + call MPI_Finalize(ier) + if (ier /= 0) then + print *, 'Unable to finalize MPI: ', ier + stop 1 + endif +end program mpitest diff --git a/test cases/common/157 mpi/meson.build b/test cases/common/157 mpi/meson.build new file mode 100644 index 0000000..f36b039 --- /dev/null +++ b/test cases/common/157 mpi/meson.build @@ -0,0 +1,24 @@ +project('mpi', 'c', 'cpp') + +mpic = dependency('mpi', language : 'c') +exec = executable('exec', + 'main.c', + dependencies : [mpic]) + +test('MPI C', exec) + +mpicpp = dependency('mpi', language : 'cpp') +execpp = executable('execpp', + 'main.cpp', + dependencies : [mpicpp]) + +test('MPI C++', execpp) + +if add_languages('fortran', required : false) + mpifort = dependency('mpi', language : 'fortran') + exef = executable('exef', + 'main.f90', + dependencies : [mpifort]) + + test('MPI Fortran', exef) +endif |