From d6bddafa265ce8f6a1d1194c284acc39f4188e46 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 12 Apr 2024 10:53:52 -0700 Subject: [PATCH] compilers: Add support for OpenMP from homebrew with AppleClang Which requires injecting some extra paths and the `-Xpreprocess` flag, as well as extra search paths for libomp and the headers. Fixes: #7435 --- mesonbuild/_typing.py | 2 +- mesonbuild/compilers/c.py | 3 +- mesonbuild/compilers/cpp.py | 3 +- mesonbuild/compilers/mixins/apple.py | 57 ++++++++++++++++++++++++ test cases/common/184 openmp/meson.build | 3 -- 5 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 mesonbuild/compilers/mixins/apple.py diff --git a/mesonbuild/_typing.py b/mesonbuild/_typing.py index 05ff2b3da..8336c46bd 100644 --- a/mesonbuild/_typing.py +++ b/mesonbuild/_typing.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2020 The Meson development team -# Copyright © 2020-2023 Intel Corporation +# Copyright © 2020-2024 Intel Corporation """Meson specific typing helpers. diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 8fda3a5a5..cbc1bea95 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -10,6 +10,7 @@ from .. import options from .. import mlog from ..mesonlib import MesonException, version_compare from .c_function_attributes import C_FUNC_ATTRIBUTES +from .mixins.apple import AppleCompilerMixin from .mixins.clike import CLikeCompiler from .mixins.ccrx import CcrxCompiler from .mixins.xc16 import Xc16Compiler @@ -187,7 +188,7 @@ class ArmLtdClangCCompiler(ClangCCompiler): id = 'armltdclang' -class AppleClangCCompiler(ClangCCompiler): +class AppleClangCCompiler(AppleCompilerMixin, ClangCCompiler): """Handle the differences between Apple Clang and Vanilla Clang. diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 9467a35c5..5e8947bce 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -19,6 +19,7 @@ from .compilers import ( CompileCheckMode, ) from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES +from .mixins.apple import AppleCompilerMixin from .mixins.clike import CLikeCompiler from .mixins.ccrx import CcrxCompiler from .mixins.ti import TICompiler @@ -337,7 +338,7 @@ class ArmLtdClangCPPCompiler(ClangCPPCompiler): id = 'armltdclang' -class AppleClangCPPCompiler(ClangCPPCompiler): +class AppleClangCPPCompiler(AppleCompilerMixin, ClangCPPCompiler): _CPP23_VERSION = '>=13.0.0' # TODO: We don't know which XCode version will include LLVM 17 yet, so diff --git a/mesonbuild/compilers/mixins/apple.py b/mesonbuild/compilers/mixins/apple.py new file mode 100644 index 000000000..98c4bfa1a --- /dev/null +++ b/mesonbuild/compilers/mixins/apple.py @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2024 Intel Corporation + +"""Provides mixins for Apple compilers.""" + +from __future__ import annotations +import typing as T + +from ...mesonlib import MesonException + +if T.TYPE_CHECKING: + from ..._typing import ImmutableListProtocol + from ...environment import Environment + from ..compilers import Compiler +else: + # This is a bit clever, for mypy we pretend that these mixins descend from + # Compiler, so we get all of the methods and attributes defined for us, but + # for runtime we make them descend from object (which all classes normally + # do). This gives up DRYer type checking, with no runtime impact + Compiler = object + + +class AppleCompilerMixin(Compiler): + + """Handle differences between Vanilla Clang and the Clang shipped with XCode.""" + + __BASE_OMP_FLAGS: ImmutableListProtocol[str] = ['-Xpreprocessor', '-fopenmp'] + + def openmp_flags(self, env: Environment) -> T.List[str]: + """Flags required to compile with OpenMP on Apple. + + The Apple Clang Compiler doesn't have builtin support for OpenMP, it + must be provided separately. As such, we need to add the -Xpreprocessor + argument so that an external OpenMP can be found. + + :return: A list of arguments + """ + m = env.machines[self.for_machine] + assert m is not None, 'for mypy' + if m.cpu_family.startswith('x86'): + root = '/usr/local' + else: + root = '/opt/homebrew' + return self.__BASE_OMP_FLAGS + [f'-I{root}/opt/libomp/include'] + + def openmp_link_flags(self, env: Environment) -> T.List[str]: + m = env.machines[self.for_machine] + assert m is not None, 'for mypy' + if m.cpu_family.startswith('x86'): + root = '/usr/local' + else: + root = '/opt/homebrew' + + link = self.find_library('omp', env, [f'{root}/opt/libomp/lib']) + if not link: + raise MesonException("Couldn't find libomp") + return self.__BASE_OMP_FLAGS + link diff --git a/test cases/common/184 openmp/meson.build b/test cases/common/184 openmp/meson.build index 4cbe80616..ab09b2c48 100644 --- a/test cases/common/184 openmp/meson.build +++ b/test cases/common/184 openmp/meson.build @@ -16,9 +16,6 @@ endif if cc.get_id() == 'clang' and host_machine.system() == 'windows' error('MESON_SKIP_TEST Windows clang does not support OpenMP.') endif -if host_machine.system() == 'darwin' - error('MESON_SKIP_TEST macOS does not support OpenMP.') -endif openmp = dependency('openmp') env = environment()