aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2018-04-17 21:39:13 +0300
committerGitHub <noreply@github.com>2018-04-17 21:39:13 +0300
commit88ca3805e74e67d81499bcf02362d8935dd8ec7a (patch)
tree29bd531405a41e29ccabb9a3fb7c416b4ba3a977
parent348248f0a19bdc80e8a184befb2faaa1d5e66f40 (diff)
parent46ccbe48e7dc902f699d0554055f89c49df4d415 (diff)
downloadmeson-88ca3805e74e67d81499bcf02362d8935dd8ec7a.zip
meson-88ca3805e74e67d81499bcf02362d8935dd8ec7a.tar.gz
meson-88ca3805e74e67d81499bcf02362d8935dd8ec7a.tar.bz2
Merge pull request #1852 from QuLogic/openmp
Add an OpenMP dependency.
-rw-r--r--docs/markdown/snippets/openmp-dependency.md6
-rw-r--r--mesonbuild/backend/backends.py2
-rw-r--r--mesonbuild/backend/ninjabackend.py2
-rw-r--r--mesonbuild/backend/vs2010backend.py15
-rw-r--r--mesonbuild/compilers/c.py5
-rw-r--r--mesonbuild/compilers/compilers.py21
-rw-r--r--mesonbuild/compilers/fortran.py19
-rw-r--r--mesonbuild/dependencies/__init__.py4
-rw-r--r--mesonbuild/dependencies/base.py3
-rw-r--r--mesonbuild/dependencies/misc.py32
-rw-r--r--mesonbuild/linkers.py6
-rw-r--r--test cases/common/190 openmp/main.c16
-rw-r--r--test cases/common/190 openmp/main.cpp16
-rw-r--r--test cases/common/190 openmp/main.f908
-rw-r--r--test cases/common/190 openmp/meson.build40
15 files changed, 191 insertions, 4 deletions
diff --git a/docs/markdown/snippets/openmp-dependency.md b/docs/markdown/snippets/openmp-dependency.md
new file mode 100644
index 0000000..ad70011
--- /dev/null
+++ b/docs/markdown/snippets/openmp-dependency.md
@@ -0,0 +1,6 @@
+## Addition of OpenMP dependency
+
+An OpenMP dependency (`openmp`) has been added that encapsulates the various
+flags used by compilers to enable OpenMP and checks for the existence of the
+`omp.h` header. The `language` keyword may be passed to force the use of a
+specific compiler for the checks.
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 916f680..694700e 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -540,6 +540,8 @@ class Backend:
# pkg-config puts the thread flags itself via `Cflags:`
if dep.need_threads():
commands += compiler.thread_flags(self.environment)
+ elif dep.need_openmp():
+ commands += compiler.openmp_flags()
# Fortran requires extra include directives.
if compiler.language == 'fortran':
for lt in target.link_targets:
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 466a677..bc3a8ef 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2551,6 +2551,8 @@ rule FORTRAN_DEP_HACK
for d in target.external_deps:
if d.need_threads():
commands += linker.thread_link_flags(self.environment)
+ elif d.need_openmp():
+ commands += linker.openmp_flags()
# Only non-static built targets need link args and link dependencies
if not isinstance(target, build.StaticLibrary):
commands += target.link_args
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 3171451..22383dc 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -824,7 +824,10 @@ class Vs2010Backend(backends.Backend):
for d in reversed(target.get_external_deps()):
# Cflags required by external deps might have UNIX-specific flags,
# so filter them out if needed
- d_compile_args = compiler.unix_args_to_native(d.get_compile_args())
+ if isinstance(d, dependencies.OpenMPDependency):
+ d_compile_args = compiler.openmp_flags()
+ else:
+ d_compile_args = compiler.unix_args_to_native(d.get_compile_args())
for arg in d_compile_args:
if arg.startswith(('-D', '/D')):
define = arg[2:]
@@ -915,11 +918,17 @@ class Vs2010Backend(backends.Backend):
for dep in target.get_external_deps():
# Extend without reordering or de-dup to preserve `-L -l` sets
# https://github.com/mesonbuild/meson/issues/1718
- extra_link_args.extend_direct(dep.get_link_args())
+ if isinstance(dep, dependencies.OpenMPDependency):
+ extra_link_args.extend_direct(compiler.openmp_flags())
+ else:
+ extra_link_args.extend_direct(dep.get_link_args())
for d in target.get_dependencies():
if isinstance(d, build.StaticLibrary):
for dep in d.get_external_deps():
- extra_link_args.extend_direct(dep.get_link_args())
+ if isinstance(dep, dependencies.OpenMPDependency):
+ extra_link_args.extend_direct(compiler.openmp_flags())
+ else:
+ extra_link_args.extend_direct(dep.get_link_args())
# Add link args for c_* or cpp_* build options. Currently this only
# adds c_winlibs and cpp_winlibs when building for Windows. This needs
# to be after all internal and external libraries so that unresolved
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index a6bd0af..0e474e7 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -296,6 +296,8 @@ class CCompiler(Compiler):
args += d.get_compile_args()
if d.need_threads():
args += self.thread_flags(env)
+ elif d.need_openmp():
+ args += self.openmp_flags()
if mode == 'link':
# Add link flags needed to find dependencies
args += d.get_link_args()
@@ -1091,6 +1093,9 @@ class VisualStudioCCompiler(CCompiler):
def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
return []
+ def openmp_flags(self):
+ return ['/openmp']
+
# FIXME, no idea what these should be.
def thread_flags(self, env):
return []
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 99e9164..37326d8 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -937,6 +937,9 @@ class Compiler:
def thread_flags(self, env):
return []
+ def openmp_flags(self):
+ raise EnvironmentException('Language %s does not support OpenMP flags.' % self.get_display_language())
+
GCC_STANDARD = 0
GCC_OSX = 1
@@ -1152,6 +1155,9 @@ class GnuCompiler:
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)
+ def openmp_flags(self):
+ return ['-fopenmp']
+
class ElbrusCompiler(GnuCompiler):
# Elbrus compiler is nearly like GCC, but does not support
@@ -1270,6 +1276,15 @@ class ClangCompiler:
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)
+ def openmp_flags(self):
+ if version_compare(self.version, '>=3.8.0'):
+ return ['-fopenmp']
+ elif version_compare(self.version, '>=3.7.0'):
+ return ['-fopenmp=libomp']
+ else:
+ # Shouldn't work, but it'll be checked explicitly in the OpenMP dependency.
+ return []
+
# Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1
class IntelCompiler:
@@ -1332,6 +1347,12 @@ class IntelCompiler:
def get_default_include_dirs(self):
return gnulike_default_include_dirs(self.exelist, self.language)
+ def openmp_flags(self):
+ if version_compare(self.version, '>=15.0.0'):
+ return ['-qopenmp']
+ else:
+ return ['-openmp']
+
class ArmCompiler:
# Functionality that is common to all ARM family compilers.
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 5bb3ec9..9d3240f 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -180,6 +180,9 @@ class GnuFortranCompiler(FortranCompiler):
"""
return ['-Wl,--out-implib=' + implibname]
+ def openmp_flags(self):
+ return ['-fopenmp']
+
class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler):
def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
@@ -231,6 +234,9 @@ class SunFortranCompiler(FortranCompiler):
def get_module_outdir_args(self, path):
return ['-moddir=' + path]
+ def openmp_flags(self):
+ return ['-xopenmp']
+
class IntelFortranCompiler(IntelCompiler, FortranCompiler):
std_warn_args = ['-warn', 'all']
@@ -263,6 +269,10 @@ class PathScaleFortranCompiler(FortranCompiler):
def get_std_warn_args(self, level):
return PathScaleFortranCompiler.std_warn_args
+ def openmp_flags(self):
+ return ['-mp']
+
+
class PGIFortranCompiler(FortranCompiler):
std_warn_args = ['-Minform=inform']
@@ -282,6 +292,9 @@ class PGIFortranCompiler(FortranCompiler):
def get_no_warn_args(self):
return ['-silent']
+ def openmp_flags(self):
+ return ['-fopenmp']
+
class Open64FortranCompiler(FortranCompiler):
std_warn_args = ['-fullwarn']
@@ -296,6 +309,9 @@ class Open64FortranCompiler(FortranCompiler):
def get_warn_args(self, level):
return Open64FortranCompiler.std_warn_args
+ def openmp_flags(self):
+ return ['-mp']
+
class NAGFortranCompiler(FortranCompiler):
std_warn_args = []
@@ -309,3 +325,6 @@ class NAGFortranCompiler(FortranCompiler):
def get_warn_args(self, level):
return NAGFortranCompiler.std_warn_args
+
+ def openmp_flags(self):
+ return ['-openmp']
diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py
index 4796980..1c67311 100644
--- a/mesonbuild/dependencies/__init__.py
+++ b/mesonbuild/dependencies/__init__.py
@@ -18,7 +18,7 @@ from .base import ( # noqa: F401
ExternalDependency, ExternalLibrary, ExtraFrameworkDependency, InternalDependency,
PkgConfigDependency, find_external_dependency, get_dep_identifier, packages, _packages_accept_language)
from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDependency
-from .misc import (MPIDependency, Python3Dependency, ThreadDependency, PcapDependency, CupsDependency, LibWmfDependency)
+from .misc import (MPIDependency, OpenMPDependency, Python3Dependency, ThreadDependency, PcapDependency, CupsDependency, LibWmfDependency)
from .platform import AppleFrameworks
from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency, VulkanDependency
@@ -33,6 +33,7 @@ packages.update({
# From misc:
'boost': BoostDependency,
'mpi': MPIDependency,
+ 'openmp': OpenMPDependency,
'python3': Python3Dependency,
'threads': ThreadDependency,
'pcap': PcapDependency,
@@ -53,4 +54,5 @@ packages.update({
})
_packages_accept_language.update({
'mpi',
+ 'openmp',
})
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 4127081..2a19544 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -134,6 +134,9 @@ class Dependency:
def get_exe_args(self, compiler):
return []
+ def need_openmp(self):
+ return False
+
def need_threads(self):
return False
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 2a218be..d4525b1 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -237,6 +237,38 @@ class MPIDependency(ExternalDependency):
[os.path.join(libdir, 'msmpi.lib')])
+class OpenMPDependency(ExternalDependency):
+ # Map date of specification release (which is the macro value) to a version.
+ VERSIONS = {
+ '201511': '4.5',
+ '201307': '4.0',
+ '201107': '3.1',
+ '200805': '3.0',
+ '200505': '2.5',
+ '200203': '2.0',
+ '199810': '1.0',
+ }
+
+ def __init__(self, environment, kwargs):
+ language = kwargs.get('language')
+ super().__init__('openmp', environment, language, kwargs)
+ self.is_found = False
+ openmp_date = self.compiler.get_define('_OPENMP', '', self.env, [], [self])
+ if openmp_date:
+ self.version = self.VERSIONS[openmp_date]
+ if self.compiler.has_header('omp.h', '', self.env, dependencies=[self]):
+ self.is_found = True
+ else:
+ mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.')
+ if self.is_found:
+ mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.green('YES'), self.version)
+ else:
+ mlog.log('Dependency', mlog.bold(self.name), 'found:', mlog.red('NO'))
+
+ def need_openmp(self):
+ return True
+
+
class ThreadDependency(ExternalDependency):
def __init__(self, environment, kwargs):
super().__init__('threads', environment, None, {})
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index 8e491d9..cb07c5e 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -56,6 +56,9 @@ class VisualStudioLinker(StaticLinker):
def thread_link_flags(self, env):
return []
+ def openmp_flags(self):
+ return []
+
def get_option_link_args(self, options):
return []
@@ -114,6 +117,9 @@ class ArLinker(StaticLinker):
def thread_link_flags(self, env):
return []
+ def openmp_flags(self):
+ return []
+
def get_option_link_args(self, options):
return []
diff --git a/test cases/common/190 openmp/main.c b/test cases/common/190 openmp/main.c
new file mode 100644
index 0000000..cc81f48
--- /dev/null
+++ b/test cases/common/190 openmp/main.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <omp.h>
+
+int main(void) {
+#ifdef _OPENMP
+ if (omp_get_max_threads() == 2) {
+ return 0;
+ } else {
+ printf("Max threads is %d not 2.\n", omp_get_max_threads());
+ return 1;
+ }
+#else
+ printf("_OPENMP is not defined; is OpenMP compilation working?\n");
+ return 1;
+#endif
+}
diff --git a/test cases/common/190 openmp/main.cpp b/test cases/common/190 openmp/main.cpp
new file mode 100644
index 0000000..b12be3f
--- /dev/null
+++ b/test cases/common/190 openmp/main.cpp
@@ -0,0 +1,16 @@
+#include <iostream>
+#include <omp.h>
+
+int main(void) {
+#ifdef _OPENMP
+ if (omp_get_max_threads() == 2) {
+ return 0;
+ } else {
+ std::cout << "Max threads is " << omp_get_max_threads() << " not 2." << std::endl;
+ return 1;
+ }
+#else
+ printf("_OPENMP is not defined; is OpenMP compilation working?\n");
+ return 1;
+#endif
+}
diff --git a/test cases/common/190 openmp/main.f90 b/test cases/common/190 openmp/main.f90
new file mode 100644
index 0000000..c062d86
--- /dev/null
+++ b/test cases/common/190 openmp/main.f90
@@ -0,0 +1,8 @@
+program main
+ if (omp_get_max_threads() .eq. 2) then
+ stop 0
+ else
+ print *, 'Max threads is', omp_get_max_threads(), 'not 2.'
+ stop 1
+ endif
+end program main
diff --git a/test cases/common/190 openmp/meson.build b/test cases/common/190 openmp/meson.build
new file mode 100644
index 0000000..a05ca59
--- /dev/null
+++ b/test cases/common/190 openmp/meson.build
@@ -0,0 +1,40 @@
+project('openmp', 'c', 'cpp')
+
+cc = meson.get_compiler('c')
+if cc.get_id() == 'gcc' and cc.version().version_compare('<4.2.0')
+ error('MESON_SKIP_TEST gcc is too old to support OpenMP.')
+endif
+if cc.get_id() == 'clang' and cc.version().version_compare('<3.7.0')
+ error('MESON_SKIP_TEST clang is too old to support OpenMP.')
+endif
+if cc.get_id() == 'msvc' and cc.version().version_compare('<17')
+ error('MESON_SKIP_TEST msvc is too old to support OpenMP.')
+endif
+if host_machine.system() == 'darwin'
+ error('MESON_SKIP_TEST macOS does not support OpenMP.')
+endif
+
+openmp = dependency('openmp')
+
+exec = executable('exec',
+ 'main.c',
+ dependencies : [openmp])
+
+execpp = executable('execpp',
+ 'main.cpp',
+ dependencies : [openmp])
+
+env = environment()
+env.set('OMP_NUM_THREADS', '2')
+
+test('OpenMP C', exec, env : env)
+test('OpenMP C++', execpp, env : env)
+
+
+if add_languages('fortran', required : false)
+ exef = executable('exef',
+ 'main.f90',
+ dependencies : [openmp])
+
+ test('OpenMP Fortran', execpp, env : env)
+endif