diff options
Diffstat (limited to 'mesonbuild/dependencies')
-rw-r--r-- | mesonbuild/dependencies/base.py | 5 | ||||
-rw-r--r-- | mesonbuild/dependencies/cuda.py | 74 | ||||
-rw-r--r-- | mesonbuild/dependencies/detect.py | 10 | ||||
-rw-r--r-- | mesonbuild/dependencies/python.py | 16 | ||||
-rw-r--r-- | mesonbuild/dependencies/qt.py | 5 | ||||
-rw-r--r-- | mesonbuild/dependencies/scalapack.py | 11 | ||||
-rw-r--r-- | mesonbuild/dependencies/ui.py | 11 |
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)]] |