diff options
Diffstat (limited to 'mesonbuild/modules')
-rw-r--r-- | mesonbuild/modules/__init__.py | 18 | ||||
-rw-r--r-- | mesonbuild/modules/fs.py | 121 | ||||
-rw-r--r-- | mesonbuild/modules/gnome.py | 85 | ||||
-rw-r--r-- | mesonbuild/modules/pkgconfig.py | 8 | ||||
-rw-r--r-- | mesonbuild/modules/python.py | 3 | ||||
-rw-r--r-- | mesonbuild/modules/rust.py | 4 |
6 files changed, 151 insertions, 88 deletions
diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 87892e6..3938101 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -82,19 +82,21 @@ class ModuleState: wanted=wanted, silent=silent, for_machine=for_machine) def find_tool(self, name: str, depname: str, varname: str, required: bool = True, - wanted: T.Optional[str] = None) -> T.Union[build.OverrideExecutable, ExternalProgram, 'OverrideProgram']: - # Look in overrides in case it's built as subproject - progobj = self._interpreter.program_from_overrides([name], []) - if progobj is not None: - return progobj + wanted: T.Optional[str] = None, for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[build.OverrideExecutable, ExternalProgram, 'OverrideProgram']: + if for_machine is MachineChoice.HOST: + # Look in overrides in case it's built as subproject + progobj = self._interpreter.program_from_overrides([name], []) + if progobj is not None: + return progobj # Look in machine file - prog_list = self.environment.lookup_binary_entry(MachineChoice.HOST, name) + prog_list = self.environment.lookup_binary_entry(for_machine, name) if prog_list is not None: return ExternalProgram.from_entry(name, prog_list) # Check if pkgconfig has a variable - dep = self.dependency(depname, native=True, required=False, wanted=wanted) + dep = self.dependency(depname, native=for_machine is MachineChoice.BUILD, + required=False, wanted=wanted) if dep.found() and dep.type_name == 'pkgconfig': value = dep.get_variable(pkgconfig=varname) if value: @@ -106,7 +108,7 @@ class ModuleState: return progobj # Normal program lookup - return self.find_program(name, required=required, wanted=wanted) + return self.find_program(name, required=required, wanted=wanted, for_machine=for_machine) def dependency(self, depname: str, native: bool = False, required: bool = True, wanted: T.Optional[str] = None) -> 'Dependency': diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 1fa368e..57a6b6d 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -2,7 +2,9 @@ # Copyright 2019 The Meson development team from __future__ import annotations -from pathlib import Path, PurePath, PureWindowsPath +from ntpath import sep as ntsep +from pathlib import Path +from posixpath import sep as posixsep import hashlib import os import typing as T @@ -12,7 +14,7 @@ from .. import mlog from ..build import BuildTarget, CustomTarget, CustomTargetIndex, InvalidArguments from ..interpreter.type_checking import INSTALL_KW, INSTALL_MODE_KW, INSTALL_TAG_KW, NoneType from ..interpreterbase import FeatureNew, KwargInfo, typed_kwargs, typed_pos_args, noKwargs -from ..mesonlib import File, MesonException, has_path_sep, path_is_in_root, relpath +from ..mesonlib import File, MesonException, has_path_sep, is_windows, path_is_in_root, relpath if T.TYPE_CHECKING: from . import ModuleState @@ -42,7 +44,7 @@ class FSModule(ExtensionModule): INFO = ModuleInfo('fs', '0.53.0') - def __init__(self, interpreter: 'Interpreter') -> None: + def __init__(self, interpreter: Interpreter) -> None: super().__init__(interpreter) self.methods.update({ 'as_posix': self.as_posix, @@ -62,29 +64,30 @@ class FSModule(ExtensionModule): 'replace_suffix': self.replace_suffix, 'size': self.size, 'stem': self.stem, + 'suffix': self.suffix, }) - def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: + def _absolute_dir(self, state: ModuleState, arg: FileOrString) -> str: """ make an absolute path from a relative path, WITHOUT resolving symlinks """ if isinstance(arg, File): - return Path(arg.absolute_path(state.source_root, state.environment.get_build_dir())) - return Path(state.source_root) / Path(state.subdir) / Path(arg).expanduser() + return arg.absolute_path(state.source_root, state.environment.get_build_dir()) + return os.path.join(state.source_root, state.subdir, os.path.expanduser(arg)) @staticmethod - def _obj_to_path(feature_new_prefix: str, obj: T.Union[FileOrString, BuildTargetTypes], state: ModuleState) -> PurePath: + def _obj_to_pathstr(feature_new_prefix: str, obj: T.Union[FileOrString, BuildTargetTypes], state: ModuleState) -> str: if isinstance(obj, str): - return PurePath(obj) + return obj if isinstance(obj, File): FeatureNew(f'{feature_new_prefix} with file', '0.59.0').use(state.subproject, location=state.current_node) - return PurePath(str(obj)) + return str(obj) FeatureNew(f'{feature_new_prefix} with build_tgt, custom_tgt, and custom_idx', '1.4.0').use(state.subproject, location=state.current_node) - return PurePath(state.backend.get_target_filename(obj)) + return state.backend.get_target_filename(obj) - def _resolve_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path: + def _resolve_dir(self, state: ModuleState, arg: FileOrString) -> str: """ resolves symlinks and makes absolute a directory relative to calling meson.build, if not already absolute @@ -92,7 +95,7 @@ class FSModule(ExtensionModule): path = self._absolute_dir(state, arg) try: # accommodate unresolvable paths e.g. symlink loops - path = path.resolve() + path = os.path.realpath(path) except Exception: # return the best we could do pass @@ -101,123 +104,139 @@ class FSModule(ExtensionModule): @noKwargs @FeatureNew('fs.expanduser', '0.54.0') @typed_pos_args('fs.expanduser', str) - def expanduser(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str: - return str(Path(args[0]).expanduser()) + def expanduser(self, state: ModuleState, args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str: + return os.path.expanduser(args[0]) @noKwargs @FeatureNew('fs.is_absolute', '0.54.0') @typed_pos_args('fs.is_absolute', (str, File)) - def is_absolute(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: - if isinstance(args[0], File): + def is_absolute(self, state: ModuleState, args: T.Tuple[FileOrString], kwargs: T.Dict[str, T.Any]) -> bool: + path = args[0] + if isinstance(path, File): FeatureNew('fs.is_absolute with file', '0.59.0').use(state.subproject, location=state.current_node) - return PurePath(str(args[0])).is_absolute() + path = str(path) + if is_windows(): + # os.path.isabs was broken for Windows before Python 3.13, so we implement it ourselves + path = path[:3].replace(posixsep, ntsep) + return path.startswith(ntsep * 2) or path.startswith(':' + ntsep, 1) + return path.startswith(posixsep) @noKwargs @FeatureNew('fs.as_posix', '0.54.0') @typed_pos_args('fs.as_posix', str) - def as_posix(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str: + def as_posix(self, state: ModuleState, args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str: r""" this function assumes you are passing a Windows path, even if on a Unix-like system and so ALL '\' are turned to '/', even if you meant to escape a character """ - return PureWindowsPath(args[0]).as_posix() + return args[0].replace(ntsep, posixsep) @noKwargs @typed_pos_args('fs.exists', str) - def exists(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool: - return self._resolve_dir(state, args[0]).exists() + def exists(self, state: ModuleState, args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool: + return os.path.exists(self._resolve_dir(state, args[0])) @noKwargs @typed_pos_args('fs.is_symlink', (str, File)) - def is_symlink(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: + def is_symlink(self, state: ModuleState, args: T.Tuple[FileOrString], kwargs: T.Dict[str, T.Any]) -> bool: if isinstance(args[0], File): FeatureNew('fs.is_symlink with file', '0.59.0').use(state.subproject, location=state.current_node) - return self._absolute_dir(state, args[0]).is_symlink() + return os.path.islink(self._absolute_dir(state, args[0])) @noKwargs @typed_pos_args('fs.is_file', str) - def is_file(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool: - return self._resolve_dir(state, args[0]).is_file() + def is_file(self, state: ModuleState, args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool: + return os.path.isfile(self._resolve_dir(state, args[0])) @noKwargs @typed_pos_args('fs.is_dir', str) - def is_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool: - return self._resolve_dir(state, args[0]).is_dir() + def is_dir(self, state: ModuleState, args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool: + return os.path.isdir(self._resolve_dir(state, args[0])) @noKwargs @typed_pos_args('fs.hash', (str, File), str) - def hash(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str: + def hash(self, state: ModuleState, args: T.Tuple[FileOrString, str], kwargs: T.Dict[str, T.Any]) -> str: if isinstance(args[0], File): FeatureNew('fs.hash with file', '0.59.0').use(state.subproject, location=state.current_node) file = self._resolve_dir(state, args[0]) - if not file.is_file(): + if not os.path.isfile(file): raise MesonException(f'{file} is not a file and therefore cannot be hashed') try: h = hashlib.new(args[1]) except ValueError: raise MesonException('hash algorithm {} is not available'.format(args[1])) - mlog.debug('computing {} sum of {} size {} bytes'.format(args[1], file, file.stat().st_size)) - h.update(file.read_bytes()) + mlog.debug('computing {} sum of {} size {} bytes'.format(args[1], file, os.stat(file).st_size)) + with open(file, mode='rb', buffering=0) as f: + h.update(f.read()) return h.hexdigest() @noKwargs @typed_pos_args('fs.size', (str, File)) - def size(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> int: + def size(self, state: ModuleState, args: T.Tuple[FileOrString], kwargs: T.Dict[str, T.Any]) -> int: if isinstance(args[0], File): FeatureNew('fs.size with file', '0.59.0').use(state.subproject, location=state.current_node) file = self._resolve_dir(state, args[0]) - if not file.is_file(): + if not os.path.isfile(file): raise MesonException(f'{file} is not a file and therefore cannot be sized') try: - return file.stat().st_size + return os.stat(file).st_size except ValueError: raise MesonException('{} size could not be determined'.format(args[0])) @noKwargs @typed_pos_args('fs.is_samepath', (str, File), (str, File)) - def is_samepath(self, state: 'ModuleState', args: T.Tuple['FileOrString', 'FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool: + def is_samepath(self, state: ModuleState, args: T.Tuple[FileOrString, FileOrString], kwargs: T.Dict[str, T.Any]) -> bool: if isinstance(args[0], File) or isinstance(args[1], File): FeatureNew('fs.is_samepath with file', '0.59.0').use(state.subproject, location=state.current_node) file1 = self._resolve_dir(state, args[0]) file2 = self._resolve_dir(state, args[1]) - if not file1.exists(): + if not os.path.exists(file1): return False - if not file2.exists(): + if not os.path.exists(file2): return False try: - return file1.samefile(file2) + return os.path.samefile(file1, file2) except OSError: return False @noKwargs @typed_pos_args('fs.replace_suffix', (str, File, CustomTarget, CustomTargetIndex, BuildTarget), str) - def replace_suffix(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes], str], kwargs: T.Dict[str, T.Any]) -> str: - path = self._obj_to_path('fs.replace_suffix', args[0], state) - return str(path.with_suffix(args[1])) + def replace_suffix(self, state: ModuleState, args: T.Tuple[T.Union[FileOrString, BuildTargetTypes], str], kwargs: T.Dict[str, T.Any]) -> str: + if args[1] and not args[1].startswith('.'): + raise ValueError(f"Invalid suffix {args[1]!r}") + path = self._obj_to_pathstr('fs.replace_suffix', args[0], state) + return os.path.splitext(path)[0] + args[1] @noKwargs @typed_pos_args('fs.parent', (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) - def parent(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: - path = self._obj_to_path('fs.parent', args[0], state) - return str(path.parent) + def parent(self, state: ModuleState, args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: + path = self._obj_to_pathstr('fs.parent', args[0], state) + return os.path.split(path)[0] or '.' @noKwargs @typed_pos_args('fs.name', (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) - def name(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: - path = self._obj_to_path('fs.name', args[0], state) - return str(path.name) + def name(self, state: ModuleState, args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: + path = self._obj_to_pathstr('fs.name', args[0], state) + return os.path.basename(path) @noKwargs @typed_pos_args('fs.stem', (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) @FeatureNew('fs.stem', '0.54.0') - def stem(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: - path = self._obj_to_path('fs.stem', args[0], state) - return str(path.stem) + def stem(self, state: ModuleState, args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: + path = self._obj_to_pathstr('fs.name', args[0], state) + return os.path.splitext(os.path.basename(path))[0] + + @noKwargs + @typed_pos_args('fs.suffix', (str, File, CustomTarget, CustomTargetIndex, BuildTarget)) + @FeatureNew('fs.suffix', '1.9.0') + def suffix(self, state: ModuleState, args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str: + path = self._obj_to_pathstr('fs.suffix', args[0], state) + return os.path.splitext(path)[1] @FeatureNew('fs.read', '0.57.0') @typed_pos_args('fs.read', (str, File)) @typed_kwargs('fs.read', KwargInfo('encoding', str, default='utf-8')) - def read(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: 'ReadKwArgs') -> str: + def read(self, state: ModuleState, args: T.Tuple[FileOrString], kwargs: ReadKwArgs) -> str: """Read a file from the source tree and return its value as a decoded string. diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 9f955ae..53919bc 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -22,7 +22,7 @@ from .. import build from .. import interpreter from .. import mesonlib from .. import mlog -from ..build import CustomTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments +from ..build import CustomTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments, OverrideExecutable from ..dependencies import Dependency, InternalDependency from ..dependencies.pkgconfig import PkgConfigDependency, PkgConfigInterface from ..interpreter.type_checking import DEPENDS_KW, DEPEND_FILES_KW, ENV_KW, INSTALL_DIR_KW, INSTALL_KW, NoneType, DEPENDENCY_SOURCES_KW, in_set_validator @@ -33,11 +33,11 @@ from ..mesonlib import ( MachineChoice, MesonException, OrderedSet, Popen_safe, join_args, quote_arg ) from ..options import OptionKey -from ..programs import OverrideProgram +from ..programs import ExternalProgram, OverrideProgram from ..scripts.gettext import read_linguas if T.TYPE_CHECKING: - from typing_extensions import Literal, TypedDict + from typing_extensions import Literal, TypeAlias, TypedDict from . import ModuleState from ..build import BuildTarget @@ -45,7 +45,6 @@ if T.TYPE_CHECKING: from ..interpreter import Interpreter from ..interpreterbase import TYPE_var, TYPE_kwargs from ..mesonlib import FileOrString - from ..programs import ExternalProgram class PostInstall(TypedDict): glib_compile_schemas: bool @@ -198,7 +197,7 @@ if T.TYPE_CHECKING: vtail: T.Optional[str] depends: T.List[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]] - ToolType = T.Union[Executable, ExternalProgram, OverrideProgram] + ToolType: TypeAlias = T.Union[OverrideExecutable, ExternalProgram, OverrideProgram] # Differs from the CustomTarget version in that it straight defaults to True @@ -255,9 +254,8 @@ class GnomeModule(ExtensionModule): def __init__(self, interpreter: 'Interpreter') -> None: super().__init__(interpreter) - self.gir_dep: T.Optional[Dependency] = None - self.giscanner: T.Optional[T.Union[ExternalProgram, Executable, OverrideProgram]] = None - self.gicompiler: T.Optional[T.Union[ExternalProgram, Executable, OverrideProgram]] = None + self.giscanner: T.Optional[ToolType] = None + self.gicompiler: T.Optional[ToolType] = None self.install_glib_compile_schemas = False self.install_gio_querymodules: T.List[str] = [] self.install_gtk_update_icon_cache = False @@ -309,7 +307,7 @@ class GnomeModule(ExtensionModule): once=True, fatal=False) @staticmethod - def _find_tool(state: 'ModuleState', tool: str) -> 'ToolType': + def _find_tool(state: 'ModuleState', tool: str, for_machine: MachineChoice = MachineChoice.HOST) -> 'ToolType': tool_map = { 'gio-querymodules': 'gio-2.0', 'glib-compile-schemas': 'gio-2.0', @@ -322,7 +320,7 @@ class GnomeModule(ExtensionModule): } depname = tool_map[tool] varname = tool.replace('-', '_') - return state.find_tool(tool, depname, varname) + return state.find_tool(tool, depname, varname, for_machine=for_machine) @typed_kwargs( 'gnome.post_install', @@ -636,7 +634,7 @@ class GnomeModule(ExtensionModule): # https://github.com/mesonbuild/meson/issues/1911 # However, g-ir-scanner does not understand -Wl,-rpath # so we need to use -L instead - for d in state.backend.determine_rpath_dirs(lib): + for d in lib.determine_rpath_dirs(): d = os.path.join(state.environment.get_build_dir(), d) link_command.append('-L' + d) if include_rpath: @@ -775,9 +773,7 @@ class GnomeModule(ExtensionModule): STATIC_BUILD_REQUIRED_VERSION = ">=1.58.1" if isinstance(girtarget, (build.StaticLibrary)) and \ - not mesonlib.version_compare( - self._get_gir_dep(state)[0].get_version(), - STATIC_BUILD_REQUIRED_VERSION): + not self._giscanner_version_compare(state, STATIC_BUILD_REQUIRED_VERSION): raise MesonException('Static libraries can only be introspected with GObject-Introspection ' + STATIC_BUILD_REQUIRED_VERSION) return girtarget @@ -791,18 +787,26 @@ class GnomeModule(ExtensionModule): if self.devenv is not None: b.devenv.append(self.devenv) - def _get_gir_dep(self, state: 'ModuleState') -> T.Tuple[Dependency, T.Union[Executable, 'ExternalProgram', 'OverrideProgram'], - T.Union[Executable, 'ExternalProgram', 'OverrideProgram']]: - if not self.gir_dep: - self.gir_dep = state.dependency('gobject-introspection-1.0') - self.giscanner = self._find_tool(state, 'g-ir-scanner') - self.gicompiler = self._find_tool(state, 'g-ir-compiler') - return self.gir_dep, self.giscanner, self.gicompiler + def _get_gi(self, state: 'ModuleState') -> T.Tuple[ToolType, ToolType]: + if not self.giscanner: + self.giscanner = self._find_tool(state, 'g-ir-scanner', for_machine=MachineChoice.BUILD) + self.gicompiler = self._find_tool(state, 'g-ir-compiler', for_machine=MachineChoice.HOST) + return self.giscanner, self.gicompiler + + def _giscanner_version_compare(self, state: 'ModuleState', cmp: str) -> bool: + # Support for --version was introduced in g-i 1.58, but Ubuntu + # Bionic shipped 1.56.1. As all our version checks are greater + # than 1.58, we can just return False if get_version fails. + try: + giscanner, _ = self._get_gi(state) + return mesonlib.version_compare(giscanner.get_version(), cmp) + except MesonException: + return False @functools.lru_cache(maxsize=None) def _gir_has_option(self, option: str) -> bool: exe = self.giscanner - if isinstance(exe, OverrideProgram): + if isinstance(exe, (Executable, OverrideProgram)): # Handle overridden g-ir-scanner assert option in {'--extra-library', '--sources-top-dirs'} return True @@ -867,7 +871,7 @@ class GnomeModule(ExtensionModule): # https://github.com/mesonbuild/meson/issues/1911 # However, g-ir-scanner does not understand -Wl,-rpath # so we need to use -L instead - for d in state.backend.determine_rpath_dirs(girtarget): + for d in girtarget.determine_rpath_dirs(): d = os.path.join(state.environment.get_build_dir(), d) ret.append('-L' + d) @@ -990,10 +994,10 @@ class GnomeModule(ExtensionModule): run_env.set('CFLAGS', [quote_arg(x) for x in env_flags], ' ') run_env.merge(kwargs['env']) - gir_dep, _, _ = self._get_gir_dep(state) + giscanner, _ = self._get_gi(state) # response file supported? - rspable = mesonlib.version_compare(gir_dep.get_version(), '>= 1.85.0') + rspable = self._giscanner_version_compare(state, '>= 1.85.0') return GirTarget( girfile, @@ -1145,7 +1149,7 @@ class GnomeModule(ExtensionModule): if len(girtargets) > 1 and any(isinstance(el, Executable) for el in girtargets): raise MesonException('generate_gir only accepts a single argument when one of the arguments is an executable') - gir_dep, giscanner, gicompiler = self._get_gir_dep(state) + giscanner, gicompiler = self._get_gi(state) ns = kwargs['namespace'] nsversion = kwargs['nsversion'] @@ -1156,14 +1160,13 @@ class GnomeModule(ExtensionModule): builddir = os.path.join(state.environment.get_build_dir(), state.subdir) depends: T.List[T.Union['FileOrString', 'build.GeneratedTypes', build.BuildTarget, build.StructuredSources]] = [] - depends.extend(gir_dep.sources) depends.extend(girtargets) langs_compilers = self._get_girtargets_langs_compilers(girtargets) cflags, internal_ldflags, external_ldflags = self._get_langs_compilers_flags(state, langs_compilers) deps = self._get_gir_targets_deps(girtargets) deps += kwargs['dependencies'] - deps += [gir_dep] + deps += [state.dependency('glib-2.0'), state.dependency('gobject-2.0'), state.dependency('gmodule-2.0'), state.dependency('gio-2.0')] typelib_includes, depends = self._gather_typelib_includes_and_update_depends(state, deps, depends) # ldflags will be misinterpreted by gir scanner (showing # spurious dependencies) but building GStreamer fails if they @@ -1190,6 +1193,32 @@ class GnomeModule(ExtensionModule): scan_command: T.List[T.Union[str, Executable, 'ExternalProgram', 'OverrideProgram']] = [giscanner] scan_command += ['--quiet'] + + if state.environment.is_cross_build() and state.environment.need_exe_wrapper(): + if not state.environment.has_exe_wrapper(): + mlog.error('generate_gir requires exe_wrapper') + + binary_wrapper = state.environment.get_exe_wrapper().get_command() + ldd = state.environment.lookup_binary_entry(MachineChoice.HOST, 'ldd') + if ldd is None: + ldd_wrapper = ['ldd'] + else: + ldd_wrapper = ExternalProgram.from_bin_list(state.environment, MachineChoice.HOST, 'ldd').get_command() + + WRAPPER_ARGS_REQUIRED_VERSION = ">=1.85.0" + if not self._giscanner_version_compare(state, WRAPPER_ARGS_REQUIRED_VERSION): + msg = ('Use of gnome.generate_gir during cross compilation requires' + f'g-ir-scanner {WRAPPER_ARGS_REQUIRED_VERSION}') + raise MesonException(msg) + else: + scan_command += ['--use-binary-wrapper', binary_wrapper[0]] + if len(binary_wrapper) > 1: + scan_command += ['--binary-wrapper-args-begin', *binary_wrapper[1:], '--binary-wrapper-args-end'] + + scan_command += ['--use-ldd-wrapper', ldd_wrapper[0]] + if len(ldd_wrapper) > 1: + scan_command += ['--ldd-wrapper-args-begin', *ldd_wrapper[1:], '--ldd-wrapper-args-end'] + scan_command += ['--no-libtool'] scan_command += ['--namespace=' + ns, '--nsversion=' + nsversion] scan_command += ['--warn-all'] diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index e3f7a97..bef14e9 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -156,6 +156,14 @@ class DependenciesHelper: pass elif isinstance(obj, dependencies.ExternalDependency) and obj.name == 'threads': pass + elif isinstance(obj, dependencies.InternalDependency) and all(lib.get_id() in self.metadata for lib in obj.libraries): + # Ensure BothLibraries are resolved: + if self.pub_libs and isinstance(self.pub_libs[0], build.StaticLibrary): + obj = obj.get_as_static(recursive=True) + else: + obj = obj.get_as_shared(recursive=True) + for lib in obj.libraries: + processed_reqs.append(self.metadata[lib.get_id()].filebase) else: raise mesonlib.MesonException('requires argument not a string, ' 'library with pkgconfig-generated file ' diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 8d82a33..3c07960 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -16,7 +16,7 @@ from ..dependencies.detect import get_dep_identifier, find_external_dependency from ..dependencies.python import BasicPythonExternalProgram, python_factory, _PythonDependencyBase from ..interpreter import extract_required_kwarg, permitted_dependency_kwargs, primitives as P_OBJ from ..interpreter.interpreterobjects import _ExternalProgramHolder -from ..interpreter.type_checking import NoneType, PRESERVE_PATH_KW, SHARED_MOD_KWS +from ..interpreter.type_checking import NoneType, DEPENDENCY_KWS, PRESERVE_PATH_KW, SHARED_MOD_KWS from ..interpreterbase import ( noPosargs, noKwargs, permittedKwargs, ContainerTypeInfo, InvalidArguments, typed_pos_args, typed_kwargs, KwargInfo, @@ -256,6 +256,7 @@ class PythonInstallation(_ExternalProgramHolder['PythonExternalProgram']): @permittedKwargs(permitted_dependency_kwargs | {'embed'}) @FeatureNewKwargs('python_installation.dependency', '0.53.0', ['embed']) @noPosargs + @typed_kwargs('python_installation.dependency', *DEPENDENCY_KWS, allow_unknown=True) @InterpreterObject.method('dependency') def dependency_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> 'Dependency': disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index c5f18e8..d0e8091 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -242,6 +242,10 @@ class RustModule(ExtensionModule): def doctest(self, state: ModuleState, args: T.Tuple[str, T.Union[SharedLibrary, StaticLibrary]], kwargs: FuncDoctest) -> ModuleReturnValue: name, base_target = args + if not base_target.uses_rust(): + raise MesonException('doc tests are only supported for Rust targets') + if not base_target.uses_rust_abi(): + raise MesonException("doc tests are not supported for rust_abi: 'c'") if state.environment.is_cross_build() and state.environment.need_exe_wrapper(base_target.for_machine): mlog.notice('skipping Rust doctests due to cross compilation', once=True) return ModuleReturnValue(None, []) |