Merge branch 'QuLogic-mpi'
This commit is contained in:
commit
a19f906258
|
@ -76,6 +76,17 @@ install:
|
|||
- ps: If($Env:compiler -eq 'msys2-mingw') {(new-object Net.WebClient).DownloadFile('https://bootstrap.pypa.io/get-pip.py', 'C:\projects\meson\get-pip.py')}
|
||||
- cmd: if %compiler%==msys2-mingw ( %PYTHON% "C:\projects\meson\get-pip.py" )
|
||||
- cmd: if %compiler%==cygwin ( call ci\appveyor-install.bat )
|
||||
- ps: |
|
||||
If($Env:compiler -like 'msvc*') {
|
||||
(new-object net.webclient).DownloadFile(
|
||||
"https://download.microsoft.com/download/D/B/B/DBB64BA1-7B51-43DB-8BF1-D1FB45EACF7A/msmpisdk.msi",
|
||||
"C:\projects\msmpisdk.msi")
|
||||
c:\windows\system32\msiexec.exe /i C:\projects\msmpisdk.msi /quiet
|
||||
(new-object net.webclient).DownloadFile(
|
||||
"https://download.microsoft.com/download/D/B/B/DBB64BA1-7B51-43DB-8BF1-D1FB45EACF7A/MSMpiSetup.exe",
|
||||
"C:\projects\MSMpiSetup.exe")
|
||||
c:\projects\MSMpiSetup.exe -unattend -full
|
||||
}
|
||||
|
||||
# Install additional packages needed for all builds.
|
||||
- cmd: "%WRAPPER% %PYTHON% -m pip install codecov"
|
||||
|
|
|
@ -51,6 +51,21 @@ If your boost headers or libraries are in non-standard locations you can set the
|
|||
|
||||
GTest and GMock come as sources that must be compiled as part of your project. With Meson you don't have to care about the details, just pass `gtest` or `gmock` to `dependency` and it will do everything for you. If you want to use GMock, it is recommended to use GTest as well, as getting it to work standalone is tricky.
|
||||
|
||||
## MPI ##
|
||||
|
||||
MPI is supported for C, C++ and Fortran. Because dependencies are
|
||||
language-specific, you must specify the requested language using the
|
||||
`language` keyword argument, i.e.,
|
||||
* `dependency('mpi', language='c')` for the C MPI headers and libraries
|
||||
* `dependency('mpi', language='cpp')` for the C++ MPI headers and libraries
|
||||
* `dependency('mpi', language='fortran')` for the Fortran MPI headers and libraries
|
||||
|
||||
Meson prefers pkg-config for MPI, but if your MPI implementation does not
|
||||
provide them, it will search for the standard wrapper executables, `mpic`,
|
||||
`mpicxx`, `mpic++`, `mpifort`, `mpif90`, `mpif77`. If these are not in your
|
||||
path, they can be specified by setting the standard environment variables
|
||||
`MPICC`, `MPICXX`, `MPIFC`, `MPIF90`, or `MPIF77`, during configuration.
|
||||
|
||||
## Qt5 ##
|
||||
|
||||
Meson has native Qt5 support. Its usage is best demonstrated with an example.
|
||||
|
|
|
@ -193,6 +193,7 @@ Finds an external dependency with the given name with `pkg-config` if possible a
|
|||
- `fallback` specifies a subproject fallback to use in case the dependency is not found in the system. The value is an array `['subproj_name', 'subproj_dep']` where the first value is the name of the subproject and the second is the variable name in that subproject that contains the value of [`declare_dependency`](#declare_dependency).
|
||||
- `default_options` *(added 0.37.0)* an array of option values that override those set in the project's `default_options` invocation (like `default_options` in [`project()`](#project), they only have effect when Meson is run for the first time, and command line arguments override any default options in build files)
|
||||
- `method` defines the way the dependency is detected, the default is `auto` but can be overridden to be e.g. `qmake` for Qt development, and different dependencies support different values for this (though `auto` will work on all of them)
|
||||
- `language` *(added 0.42.0)* defines what language-specific dependency to find if it's available for multiple languages.
|
||||
|
||||
The returned object also has methods that are documented in the [object methods section](#dependency-object) below.
|
||||
|
||||
|
|
|
@ -104,3 +104,11 @@ By default Meson adds the current source and build directories to the
|
|||
header search path. On some rare occasions this is not desired. Setting
|
||||
the `implicit_include_directories` keyword argument to `false` these
|
||||
directories are not used.
|
||||
|
||||
## Support for MPI dependency
|
||||
|
||||
MPI is now supported as a dependency. Because dependencies are
|
||||
language-specific, you must specify the requested language with the `language`
|
||||
keyword, i.e., `dependency('mpi', language='c')` will request the C MPI headers
|
||||
and libraries. See [the MPI dependency](Dependencies.md#mpi) for more
|
||||
information.
|
||||
|
|
|
@ -120,6 +120,9 @@ end program prog
|
|||
def get_include_args(self, path, is_system):
|
||||
return ['-I' + path]
|
||||
|
||||
def get_module_incdir_args(self):
|
||||
return ('-I', )
|
||||
|
||||
def get_module_outdir_args(self, path):
|
||||
return ['-J' + path]
|
||||
|
||||
|
@ -209,6 +212,9 @@ class SunFortranCompiler(FortranCompiler):
|
|||
def get_warn_args(self, level):
|
||||
return []
|
||||
|
||||
def get_module_incdir_args(self):
|
||||
return ('-M', )
|
||||
|
||||
def get_module_outdir_args(self, path):
|
||||
return ['-moddir=' + path]
|
||||
|
||||
|
@ -251,6 +257,9 @@ class PGIFortranCompiler(FortranCompiler):
|
|||
super().__init__(exelist, version, is_cross, exe_wrapper=None)
|
||||
self.id = 'pgi'
|
||||
|
||||
def get_module_incdir_args(self):
|
||||
return ('-module', )
|
||||
|
||||
def get_module_outdir_args(self, path):
|
||||
return ['-module', path]
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
from .base import ( # noqa: F401
|
||||
Dependency, DependencyException, DependencyMethods, ExternalProgram,
|
||||
ExternalDependency, ExternalLibrary, ExtraFrameworkDependency, InternalDependency,
|
||||
PkgConfigDependency, find_external_dependency, get_dep_identifier, packages)
|
||||
PkgConfigDependency, find_external_dependency, get_dep_identifier, packages, _packages_accept_language)
|
||||
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,
|
||||
|
||||
|
@ -46,3 +47,6 @@ packages.update({
|
|||
'wxwidgets': WxDependency,
|
||||
'vulkan': VulkanDependency,
|
||||
})
|
||||
_packages_accept_language.update({
|
||||
'mpi',
|
||||
})
|
||||
|
|
|
@ -26,8 +26,9 @@ from .. import mesonlib
|
|||
from ..mesonlib import MesonException, Popen_safe, flatten, version_compare_many
|
||||
|
||||
|
||||
# This must be defined in this file to avoid cyclical references.
|
||||
# These must be defined in this file to avoid cyclical references.
|
||||
packages = {}
|
||||
_packages_accept_language = set()
|
||||
|
||||
|
||||
class DependencyException(MesonException):
|
||||
|
@ -610,10 +611,15 @@ def find_external_dependency(name, env, kwargs):
|
|||
raise DependencyException('Keyword "method" must be a string.')
|
||||
lname = name.lower()
|
||||
if lname in packages:
|
||||
if lname not in _packages_accept_language and 'language' in kwargs:
|
||||
raise DependencyException('%s dependency does not accept "language" keyword argument' % (lname, ))
|
||||
dep = packages[lname](env, kwargs)
|
||||
if required and not dep.found():
|
||||
raise DependencyException('Dependency "%s" not found' % name)
|
||||
return dep
|
||||
if 'language' in kwargs:
|
||||
# Remove check when PkgConfigDependency supports language.
|
||||
raise DependencyException('%s dependency does not accept "language" keyword argument' % (lname, ))
|
||||
pkg_exc = None
|
||||
pkgdep = None
|
||||
try:
|
||||
|
|
|
@ -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,210 @@ 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 = self._filter_compile_args(result[1])
|
||||
self.link_args = self._filter_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 = self._filter_compile_args(result[1])
|
||||
self.link_args = self._filter_link_args(result[2])
|
||||
break
|
||||
|
||||
if not self.is_found and mesonlib.is_windows():
|
||||
result = self._try_msmpi()
|
||||
if result is not None:
|
||||
self.is_found = True
|
||||
self.version, self.compile_args, self.link_args = result
|
||||
|
||||
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 _filter_compile_args(self, args):
|
||||
"""
|
||||
MPI wrappers return a bunch of garbage args.
|
||||
Drop -O2 and everything that is not needed.
|
||||
"""
|
||||
result = []
|
||||
multi_args = ('-I', )
|
||||
if self.language == 'fortran':
|
||||
fc = self.env.coredata.compilers['fortran']
|
||||
multi_args += fc.get_module_incdir_args()
|
||||
|
||||
include_next = False
|
||||
for f in args:
|
||||
if f.startswith(('-D', '-f') + multi_args) or f == '-pthread' \
|
||||
or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')):
|
||||
result.append(f)
|
||||
if f in multi_args:
|
||||
# Path is a separate argument.
|
||||
include_next = True
|
||||
elif include_next:
|
||||
include_next = False
|
||||
result.append(f)
|
||||
return result
|
||||
|
||||
def _filter_link_args(self, args):
|
||||
"""
|
||||
MPI wrappers return a bunch of garbage args.
|
||||
Drop -O2 and everything that is not needed.
|
||||
"""
|
||||
result = []
|
||||
include_next = False
|
||||
for f in args:
|
||||
if f.startswith(('-L', '-l', '-Xlinker')) or f == '-pthread' \
|
||||
or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')):
|
||||
result.append(f)
|
||||
if f in ('-L', '-Xlinker'):
|
||||
include_next = True
|
||||
elif include_next:
|
||||
include_next = False
|
||||
result.append(f)
|
||||
return result
|
||||
|
||||
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
|
||||
|
||||
def _try_msmpi(self):
|
||||
if self.language == 'cpp':
|
||||
# MS-MPI does not support the C++ version of MPI, only the standard C API.
|
||||
return
|
||||
if 'MSMPI_INC' not in os.environ:
|
||||
return
|
||||
incdir = os.environ['MSMPI_INC']
|
||||
arch = detect_cpu_family(self.env.coredata.compilers)
|
||||
if arch == 'x86':
|
||||
if 'MSMPI_LIB32' not in os.environ:
|
||||
return
|
||||
libdir = os.environ['MSMPI_LIB32']
|
||||
post = 'x86'
|
||||
elif arch == 'x86_64':
|
||||
if 'MSMPI_LIB64' not in os.environ:
|
||||
return
|
||||
libdir = os.environ['MSMPI_LIB64']
|
||||
post = 'x64'
|
||||
else:
|
||||
return
|
||||
if self.language == 'fortran':
|
||||
return ('none',
|
||||
['-I' + incdir, '-I' + os.path.join(incdir, post)],
|
||||
[os.path.join(libdir, 'msmpi.lib'), os.path.join(libdir, 'msmpifec.lib')])
|
||||
else:
|
||||
return ('none',
|
||||
['-I' + incdir, '-I' + os.path.join(incdir, post)],
|
||||
[os.path.join(libdir, 'msmpi.lib')])
|
||||
|
||||
|
||||
class ThreadDependency(ExternalDependency):
|
||||
def __init__(self, environment, kwargs):
|
||||
super().__init__('threads', environment, None, {})
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,33 @@
|
|||
project('mpi', 'c', 'cpp')
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
if build_machine.system() == 'windows' and cc.get_id() != 'msvc'
|
||||
error('MESON_SKIP_TEST: MPI not available on Windows without MSVC.')
|
||||
endif
|
||||
|
||||
mpic = dependency('mpi', language : 'c')
|
||||
exec = executable('exec',
|
||||
'main.c',
|
||||
dependencies : [mpic])
|
||||
|
||||
test('MPI C', exec)
|
||||
|
||||
if build_machine.system() != 'windows'
|
||||
# C++ MPI not supported by MS-MPI used on AppVeyor.
|
||||
mpicpp = dependency('mpi', language : 'cpp')
|
||||
execpp = executable('execpp',
|
||||
'main.cpp',
|
||||
dependencies : [mpicpp])
|
||||
|
||||
test('MPI C++', execpp)
|
||||
endif
|
||||
|
||||
if add_languages('fortran', required : false)
|
||||
mpifort = dependency('mpi', language : 'fortran')
|
||||
exef = executable('exef',
|
||||
'main.f90',
|
||||
dependencies : [mpifort])
|
||||
|
||||
test('MPI Fortran', exef)
|
||||
endif
|
Loading…
Reference in New Issue