The Meson Build System http://mesonbuild.com/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
5.3 KiB

# SPDX-License-Identifier: Apache-2.0
# Copyright 2013-2020 The Meson development team
from __future__ import annotations
from pathlib import Path
import functools
import os
import typing as T
from ..mesonlib import OptionKey
from .base import DependencyMethods
from .cmake import CMakeDependency
from .detect import packages
from .pkgconfig import PkgConfigDependency
from .factory import factory_methods
if T.TYPE_CHECKING:
from ..environment import Environment
from ..mesonlib import MachineChoice
from .factory import DependencyGenerator
@factory_methods({DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE})
def scalapack_factory(env: 'Environment', for_machine: 'MachineChoice',
kwargs: T.Dict[str, T.Any],
methods: T.List[DependencyMethods]) -> T.List['DependencyGenerator']:
candidates: T.List['DependencyGenerator'] = []
if DependencyMethods.PKGCONFIG in methods:
static_opt = kwargs.get('static', env.coredata.get_option(OptionKey('prefer_static')))
mkl = 'mkl-static-lp64-iomp' if static_opt else 'mkl-dynamic-lp64-iomp'
candidates.append(functools.partial(
MKLPkgConfigDependency, mkl, env, kwargs))
for pkg in ['scalapack-openmpi', 'scalapack']:
candidates.append(functools.partial(
PkgConfigDependency, pkg, env, kwargs))
if DependencyMethods.CMAKE in methods:
candidates.append(functools.partial(
CMakeDependency, 'Scalapack', env, kwargs))
return candidates
packages['scalapack'] = scalapack_factory
class MKLPkgConfigDependency(PkgConfigDependency):
"""PkgConfigDependency for Intel MKL.
MKL's pkg-config is pretty much borked in every way. We need to apply a
bunch of fixups to make it work correctly.
"""
def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any],
language: T.Optional[str] = None):
_m = os.environ.get('MKLROOT')
self.__mklroot = Path(_m).resolve() if _m else None
# We need to call down into the normal super() method even if we don't
# find mklroot, otherwise we won't have all of the instance variables
# initialized that meson expects.
super().__init__(name, env, kwargs, language=language)
# Doesn't work with gcc on windows, but does on Linux
if (not self.__mklroot or (env.machines[self.for_machine].is_windows()
and self.clib_compiler.id == 'gcc')):
self.is_found = False
# This can happen either because we're using GCC, we couldn't find the
# mklroot, or the pkg-config couldn't find it.
if not self.is_found:
return
assert self.version != '', 'This should not happen if we didn\'t return above'
if self.version == 'unknown':
# At least by 2020 the version is in the pkg-config, just not with
# the correct name
v = self.get_variable(pkgconfig='Version', default_value='')
if not v and self.__mklroot:
try:
v = (
self.__mklroot.as_posix()
.split('compilers_and_libraries_')[1]
.split('/', 1)[0]
)
except IndexError:
pass
if v:
assert isinstance(v, str)
self.version = v
def _set_libs(self) -> None:
super()._set_libs()
if self.env.machines[self.for_machine].is_windows():
suffix = '.lib'
elif self.static:
suffix = '.a'
else:
suffix = ''
libdir = self.__mklroot / 'lib/intel64'
if self.clib_compiler.id == 'gcc':
for i, a in enumerate(self.link_args):
# only replace in filename, not in directory names
dirname, basename = os.path.split(a)
if 'mkl_intel_lp64' in basename:
basename = basename.replace('intel', 'gf')
self.link_args[i] = '/' + os.path.join(dirname, basename)
# MKL pkg-config omits scalapack
# be sure "-L" and "-Wl" are first if present
i = 0
for j, a in enumerate(self.link_args):
if a.startswith(('-L', '-Wl')):
i = j + 1
elif j > 3:
break
if self.env.machines[self.for_machine].is_windows() or self.static:
self.link_args.insert(
i, str(libdir / ('mkl_scalapack_lp64' + suffix))
)
self.link_args.insert(
i + 1, str(libdir / ('mkl_blacs_intelmpi_lp64' + suffix))
)
else:
self.link_args.insert(i, '-lmkl_scalapack_lp64')
self.link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64')
def _set_cargs(self) -> None:
allow_system = False
if self.language == 'fortran':
# gfortran doesn't appear to look in system paths for INCLUDE files,
# so don't allow pkg-config to suppress -I flags for system paths
allow_system = True
dependencies: allow get_variable to define multiple pkgconfig defines It was previously impossible to do this: ``` dep.get_pkgconfig_variable( 'foo', define_variable: ['prefix', '/usr', 'datadir', '/usr/share'], ) ``` since get_pkgconfig_variable mandated exactly two (if any) arguments. However, you could do this: ``` dep.get_variable( 'foo', pkgconfig_define: ['prefix', '/usr', 'datadir', '/usr/share'], ) ``` It would silently do the wrong thing, by defining "prefix" as `/usr=datadir=/usr/share`, which might not "matter" if only datadir was used in the "foo" variable as the unmodified value might be adequate. The actual intention of anyone writing such a meson.build is that they aren't sure whether the .pc file uses ${prefix} or ${datadir} (or which one gets used, might have changed between versions of that .pc file, even). A recent refactor made this into a hard error, which broke some projects that were doing this and inadvertently depending on some .pc file that only used the second variable. (This was "fine" since the result was essentially meaningful, and even resulted in behavior identical to the intended behavior if both projects were installed into the same prefix -- in which case there's nothing to remap.) Re-allow this. There are two ways we could re-allow this: - ignore it with a warning - add a new feature to allow actually doing this Since the use case which triggered this bug actually has a pretty good reason to want to do this, it makes sense to add the new feature. Fixes https://bugs.gentoo.org/916576 Fixes https://github.com/containers/bubblewrap/issues/609
1 year ago
cflags = self.pkgconfig.cflags(self.name, allow_system, define_variable=(('prefix', self.__mklroot.as_posix()),))
self.compile_args = self._convert_mingw_paths(cflags)