diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2018-04-17 21:39:13 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-17 21:39:13 +0300 |
commit | 88ca3805e74e67d81499bcf02362d8935dd8ec7a (patch) | |
tree | 29bd531405a41e29ccabb9a3fb7c416b4ba3a977 | |
parent | 348248f0a19bdc80e8a184befb2faaa1d5e66f40 (diff) | |
parent | 46ccbe48e7dc902f699d0554055f89c49df4d415 (diff) | |
download | meson-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.md | 6 | ||||
-rw-r--r-- | mesonbuild/backend/backends.py | 2 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 2 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 15 | ||||
-rw-r--r-- | mesonbuild/compilers/c.py | 5 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 21 | ||||
-rw-r--r-- | mesonbuild/compilers/fortran.py | 19 | ||||
-rw-r--r-- | mesonbuild/dependencies/__init__.py | 4 | ||||
-rw-r--r-- | mesonbuild/dependencies/base.py | 3 | ||||
-rw-r--r-- | mesonbuild/dependencies/misc.py | 32 | ||||
-rw-r--r-- | mesonbuild/linkers.py | 6 | ||||
-rw-r--r-- | test cases/common/190 openmp/main.c | 16 | ||||
-rw-r--r-- | test cases/common/190 openmp/main.cpp | 16 | ||||
-rw-r--r-- | test cases/common/190 openmp/main.f90 | 8 | ||||
-rw-r--r-- | test cases/common/190 openmp/meson.build | 40 |
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 |