aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/dependencies
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/dependencies')
-rw-r--r--mesonbuild/dependencies/base.py5
-rw-r--r--mesonbuild/dependencies/cuda.py74
-rw-r--r--mesonbuild/dependencies/detect.py10
-rw-r--r--mesonbuild/dependencies/python.py16
-rw-r--r--mesonbuild/dependencies/qt.py5
-rw-r--r--mesonbuild/dependencies/scalapack.py11
-rw-r--r--mesonbuild/dependencies/ui.py11
7 files changed, 83 insertions, 49 deletions
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 38bfc08..732bae5 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -143,6 +143,11 @@ class Dependency(HoldableObject):
def is_built(self) -> bool:
return False
+ def is_named(self) -> bool:
+ if self.name is None:
+ return False
+ return self.name != f'dep{self._id}'
+
def summary_value(self) -> T.Union[str, mlog.AnsiDecorator, mlog.AnsiText]:
if not self.found():
return mlog.red('NO')
diff --git a/mesonbuild/dependencies/cuda.py b/mesonbuild/dependencies/cuda.py
index 82bf5ad..cd97127 100644
--- a/mesonbuild/dependencies/cuda.py
+++ b/mesonbuild/dependencies/cuda.py
@@ -11,9 +11,9 @@ from pathlib import Path
from .. import mesonlib
from .. import mlog
-from ..environment import detect_cpu_family
from .base import DependencyException, SystemDependency
from .detect import packages
+from ..mesonlib import LibType
if T.TYPE_CHECKING:
@@ -27,8 +27,11 @@ class CudaDependency(SystemDependency):
supported_languages = ['cpp', 'c', 'cuda'] # see also _default_language
def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None:
- compilers = environment.coredata.compilers[self.get_for_machine_from_kwargs(kwargs)]
+ for_machine = self.get_for_machine_from_kwargs(kwargs)
+ compilers = environment.coredata.compilers[for_machine]
+ machine = environment.machines[for_machine]
language = self._detect_language(compilers)
+
if language not in self.supported_languages:
raise DependencyException(f'Language \'{language}\' is not supported by the CUDA Toolkit. Supported languages are {self.supported_languages}.')
@@ -50,16 +53,26 @@ class CudaDependency(SystemDependency):
if not os.path.isabs(self.cuda_path):
raise DependencyException(f'CUDA Toolkit path must be absolute, got \'{self.cuda_path}\'.')
+ # Cuda target directory relative to cuda path.
+ if machine.is_linux():
+ # E.g. targets/x86_64-linux
+ self.target_path = os.path.join('targets', f'{machine.cpu_family}-{machine.system}')
+ else:
+ self.target_path = '.'
+
# nvcc already knows where to find the CUDA Toolkit, but if we're compiling
# a mixed C/C++/CUDA project, we still need to make the include dir searchable
if self.language != 'cuda' or len(compilers) > 1:
- self.incdir = os.path.join(self.cuda_path, 'include')
+ self.incdir = os.path.join(self.cuda_path, self.target_path, 'include')
self.compile_args += [f'-I{self.incdir}']
arch_libdir = self._detect_arch_libdir()
- self.libdir = os.path.join(self.cuda_path, arch_libdir)
+ self.libdir = os.path.join(self.cuda_path, self.target_path, arch_libdir)
mlog.debug('CUDA library directory is', mlog.bold(self.libdir))
+ if 'static' not in kwargs:
+ self.libtype = LibType.PREFER_STATIC
+
self.is_found = self._find_requested_libraries()
@classmethod
@@ -211,8 +224,8 @@ class CudaDependency(SystemDependency):
return '.'.join(version.split('.')[:2])
def _detect_arch_libdir(self) -> str:
- arch = detect_cpu_family(self.env.coredata.compilers.host)
machine = self.env.machines[self.for_machine]
+ arch = machine.cpu_family
msg = '{} architecture is not supported in {} version of the CUDA Toolkit.'
if machine.is_windows():
libdirs = {'x86': 'Win32', 'x86_64': 'x64'}
@@ -220,10 +233,7 @@ class CudaDependency(SystemDependency):
raise DependencyException(msg.format(arch, 'Windows'))
return os.path.join('lib', libdirs[arch])
elif machine.is_linux():
- libdirs = {'x86_64': 'lib64', 'ppc64': 'lib', 'aarch64': 'lib64', 'loongarch64': 'lib64'}
- if arch not in libdirs:
- raise DependencyException(msg.format(arch, 'Linux'))
- return libdirs[arch]
+ return 'lib'
elif machine.is_darwin():
libdirs = {'x86_64': 'lib64'}
if arch not in libdirs:
@@ -236,13 +246,14 @@ class CudaDependency(SystemDependency):
all_found = True
for module in self.requested_modules:
- args = self.clib_compiler.find_library(module, self.env, [self.libdir])
- if module == 'cudart_static' and self.language != 'cuda':
- machine = self.env.machines[self.for_machine]
- if machine.is_linux():
- # extracted by running
- # nvcc -v foo.o
- args += ['-lrt', '-lpthread', '-ldl']
+ # You should only ever link to libraries inside the cuda tree, nothing outside of it.
+ # For instance, there is a
+ #
+ # - libnvidia-ml.so in stubs/ of the CUDA tree
+ # - libnvidia-ml.so in /usr/lib/ that is provided by the nvidia drivers
+ #
+ # Users should never link to the latter, since its ABI may change.
+ args = self.clib_compiler.find_library(module, self.env, [self.libdir, os.path.join(self.libdir, 'stubs')], self.libtype, ignore_system_dirs=True)
if args is None:
self._report_dependency_error(f'Couldn\'t find requested CUDA module \'{module}\'')
@@ -284,23 +295,26 @@ class CudaDependency(SystemDependency):
return candidates
def get_link_args(self, language: T.Optional[str] = None, raw: bool = False) -> T.List[str]:
+ # when using nvcc to link, we should instead use the native driver options
+ REWRITE_MODULES = {
+ 'cudart': ['-cudart', 'shared'],
+ 'cudart_static': ['-cudart', 'static'],
+ 'cudadevrt': ['-cudadevrt'],
+ }
+
args: T.List[str] = []
for lib in self.requested_modules:
link_args = self.lib_modules[lib]
- # Turn canonical arguments like
- # /opt/cuda/lib64/libcublas.so
- # back into
- # -lcublas
- # since this is how CUDA modules were passed to nvcc since time immemorial
- if language == 'cuda':
- if lib in frozenset(['cudart', 'cudart_static']):
- # nvcc always links these unconditionally
- mlog.debug(f'Not adding \'{lib}\' to dependency, since nvcc will link it implicitly')
- link_args = []
- elif link_args and link_args[0].startswith(self.libdir):
- # module included with CUDA, nvcc knows how to find these itself
- mlog.debug(f'CUDA module \'{lib}\' found in CUDA libdir')
- link_args = ['-l' + lib]
+ if language == 'cuda' and lib in REWRITE_MODULES:
+ link_args = REWRITE_MODULES[lib]
+ mlog.debug(f'Rewriting module \'{lib}\' to \'{link_args}\'')
+ elif lib == 'cudart_static':
+ machine = self.env.machines[self.for_machine]
+ if machine.is_linux():
+ # extracted by running
+ # nvcc -v foo.o
+ link_args += ['-lrt', '-lpthread', '-ldl']
+
args += link_args
return args
diff --git a/mesonbuild/dependencies/detect.py b/mesonbuild/dependencies/detect.py
index aa62c66..4cdf16d 100644
--- a/mesonbuild/dependencies/detect.py
+++ b/mesonbuild/dependencies/detect.py
@@ -15,7 +15,7 @@ if T.TYPE_CHECKING:
from ..environment import Environment
from .factory import DependencyFactory, WrappedFactoryFunc, DependencyGenerator
- TV_DepIDEntry = T.Union[str, bool, int, T.Tuple[str, ...]]
+ TV_DepIDEntry = T.Union[str, bool, int, None, T.Tuple[str, ...]]
TV_DepID = T.Tuple[T.Tuple[str, TV_DepIDEntry], ...]
PackageTypes = T.Union[T.Type[ExternalDependency], DependencyFactory, WrappedFactoryFunc]
@@ -40,10 +40,14 @@ _packages_accept_language: T.Set[str] = set()
def get_dep_identifier(name: str, kwargs: T.Dict[str, T.Any]) -> 'TV_DepID':
identifier: 'TV_DepID' = (('name', name), )
+ from ..interpreter.type_checking import DEPENDENCY_KWS
+ nkwargs = {k.name: k.default for k in DEPENDENCY_KWS}
+ nkwargs.update(kwargs)
+
from ..interpreter import permitted_dependency_kwargs
assert len(permitted_dependency_kwargs) == 19, \
'Extra kwargs have been added to dependency(), please review if it makes sense to handle it here'
- for key, value in kwargs.items():
+ for key, value in nkwargs.items():
# 'version' is irrelevant for caching; the caller must check version matches
# 'native' is handled above with `for_machine`
# 'required' is irrelevant for caching; the caller handles it separately
@@ -62,7 +66,7 @@ def get_dep_identifier(name: str, kwargs: T.Dict[str, T.Any]) -> 'TV_DepID':
assert isinstance(i, str), i
value = tuple(frozenset(listify(value)))
else:
- assert isinstance(value, (str, bool, int)), value
+ assert value is None or isinstance(value, (str, bool, int)), value
identifier = (*identifier, (key, value),)
return identifier
diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py
index 3dab31c..b028d9f 100644
--- a/mesonbuild/dependencies/python.py
+++ b/mesonbuild/dependencies/python.py
@@ -330,10 +330,12 @@ class PythonPkgConfigDependency(PkgConfigDependency, _PythonDependencyBase):
# But not Apple, because it's a framework
if self.env.machines.host.is_darwin() and 'PYTHONFRAMEWORKPREFIX' in self.variables:
framework_prefix = self.variables['PYTHONFRAMEWORKPREFIX']
- # Add rpath, will be de-duplicated if necessary
+ # Add rpath, will be de-duplicated if necessary
if framework_prefix.startswith('/Applications/Xcode.app/'):
self.link_args += ['-Wl,-rpath,' + framework_prefix]
- self.raw_link_args += ['-Wl,-rpath,' + framework_prefix]
+ if self.raw_link_args is not None:
+ # When None, self.link_args is used
+ self.raw_link_args += ['-Wl,-rpath,' + framework_prefix]
class PythonFrameworkDependency(ExtraFrameworkDependency, _PythonDependencyBase):
@@ -350,8 +352,14 @@ class PythonSystemDependency(SystemDependency, _PythonDependencyBase):
SystemDependency.__init__(self, name, environment, kwargs)
_PythonDependencyBase.__init__(self, installation, kwargs.get('embed', False))
- # match pkg-config behavior
- if self.link_libpython:
+ # For most platforms, match pkg-config behavior. iOS is a special case;
+ # check for that first, so that check takes priority over
+ # `link_libpython` (which *shouldn't* be set, but just in case)
+ if self.platform.startswith('ios-'):
+ # iOS doesn't use link_libpython - it links with the *framework*.
+ self.link_args = ['-framework', 'Python', '-F', self.variables.get('prefix')]
+ self.is_found = True
+ elif self.link_libpython:
# link args
if mesonlib.is_windows():
self.find_libpy_windows(environment, limited_api=False)
diff --git a/mesonbuild/dependencies/qt.py b/mesonbuild/dependencies/qt.py
index a3a9388..8bb269e 100644
--- a/mesonbuild/dependencies/qt.py
+++ b/mesonbuild/dependencies/qt.py
@@ -9,6 +9,7 @@ from __future__ import annotations
import abc
import re
import os
+from pathlib import Path
import typing as T
from .base import DependencyException, DependencyMethods
@@ -50,7 +51,7 @@ def _qt_get_private_includes(mod_inc_dir: str, module: str, mod_version: str) ->
if len(dirname.split('.')) == 3:
private_dir = dirname
break
- return [private_dir, os.path.join(private_dir, 'Qt' + module)]
+ return [private_dir, Path(private_dir, f'Qt{module}').as_posix()]
def get_qmake_host_bins(qvars: T.Dict[str, str]) -> str:
@@ -303,7 +304,7 @@ class QmakeQtDependency(_QtBase, ConfigToolDependency, metaclass=abc.ABCMeta):
modules_lib_suffix = _get_modules_lib_suffix(self.version, self.env.machines[self.for_machine], is_debug)
for module in self.requested_modules:
- mincdir = os.path.join(incdir, 'Qt' + module)
+ mincdir = Path(incdir, f'Qt{module}').as_posix()
self.compile_args.append('-I' + mincdir)
if module == 'QuickTest':
diff --git a/mesonbuild/dependencies/scalapack.py b/mesonbuild/dependencies/scalapack.py
index c04d1f5..f34692c 100644
--- a/mesonbuild/dependencies/scalapack.py
+++ b/mesonbuild/dependencies/scalapack.py
@@ -9,7 +9,7 @@ import os
import typing as T
from ..options import OptionKey
-from .base import DependencyMethods
+from .base import DependencyException, DependencyMethods
from .cmake import CMakeDependency
from .detect import packages
from .pkgconfig import PkgConfigDependency
@@ -65,8 +65,7 @@ class MKLPkgConfigDependency(PkgConfigDependency):
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')):
+ if 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
@@ -96,6 +95,9 @@ class MKLPkgConfigDependency(PkgConfigDependency):
self.version = v
def _set_libs(self) -> None:
+ if self.__mklroot is None:
+ raise DependencyException('MKLROOT not set')
+
super()._set_libs()
if self.env.machines[self.for_machine].is_windows():
@@ -133,6 +135,9 @@ class MKLPkgConfigDependency(PkgConfigDependency):
self.link_args.insert(i + 1, '-lmkl_blacs_intelmpi_lp64')
def _set_cargs(self) -> None:
+ if self.__mklroot is None:
+ raise DependencyException('MKLROOT not set')
+
allow_system = False
if self.language == 'fortran':
# gfortran doesn't appear to look in system paths for INCLUDE files,
diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py
index fc44037..1e80a77 100644
--- a/mesonbuild/dependencies/ui.py
+++ b/mesonbuild/dependencies/ui.py
@@ -187,12 +187,9 @@ class VulkanDependencySystem(SystemDependency):
def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any], language: T.Optional[str] = None) -> None:
super().__init__(name, environment, kwargs, language=language)
- try:
- self.vulkan_sdk = os.environ.get('VULKAN_SDK', os.environ['VK_SDK_PATH'])
- if not os.path.isabs(self.vulkan_sdk):
- raise DependencyException('VULKAN_SDK must be an absolute path.')
- except KeyError:
- self.vulkan_sdk = None
+ self.vulkan_sdk = os.environ.get('VULKAN_SDK', os.environ.get('VK_SDK_PATH'))
+ if self.vulkan_sdk and not os.path.isabs(self.vulkan_sdk):
+ raise DependencyException('VULKAN_SDK must be an absolute path.')
if self.vulkan_sdk:
# TODO: this config might not work on some platforms, fix bugs as reported
@@ -242,7 +239,7 @@ class VulkanDependencySystem(SystemDependency):
low=0, high=None, guess=e,
prefix='#include <vulkan/vulkan.h>',
env=environment,
- extra_args=None,
+ extra_args=self.compile_args,
dependencies=None))
# list containing vulkan version components and their expected value
for c, e in [('MAJOR', 1), ('MINOR', 3), ('PATCH', None)]]