diff --git a/mesonbuild/build.py b/mesonbuild/build.py index a43709342dd4..b9d0abee0761 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -363,7 +363,7 @@ def __init__(self, environment: Environment): self.stdlibs = PerMachine({}, {}) self.test_setups: T.Dict[str, TestSetup] = {} self.test_setup_default_name = None - self.find_overrides: T.Dict[str, T.Union['OverrideExecutable', programs.ExternalProgram, programs.OverrideProgram]] = {} + self.find_overrides: T.Dict[str, programs.AnyProgram] = {} self.searched_programs: T.Set[str] = set() # The list of all programs that have been searched for. # If we are doing a cross build we need two caches, if we're doing a @@ -2850,7 +2850,7 @@ def __init__(self, environment: Environment, command: T.Sequence[T.Union[ str, BuildTargetTypes, GeneratedList, - programs.ExternalProgram, File]], + programs.AnyProgram, File]], sources: T.Sequence[T.Union[ str, File, BuildTargetTypes, ExtractedObjects, GeneratedList, programs.ExternalProgram]], diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index f3382d20e37d..6bc36569a6ec 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -119,7 +119,7 @@ from ..backend.backends import Backend from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs from ..options import OptionDict - from ..programs import OverrideProgram + from ..programs import AnyProgram from .type_checking import SourcesVarargsType # Input source types passed to Targets @@ -131,7 +131,7 @@ BuildTargetSource = T.Union[mesonlib.FileOrString, build.GeneratedTypes, build.StructuredSources] - ProgramVersionFunc = T.Callable[[T.Union[ExternalProgram, build.Executable, OverrideProgram]], str] + ProgramVersionFunc = T.Callable[[AnyProgram], str] TestClass = T.TypeVar('TestClass', bound=Test) @@ -1585,7 +1585,7 @@ def program_from_system(self, args: T.List[mesonlib.FileOrString], search_dirs: def program_from_overrides(self, command_names: T.List[mesonlib.FileOrString], extra_info: T.List['mlog.TV_Loggable'] - ) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.OverrideExecutable]]: + ) -> T.Optional[AnyProgram]: for name in command_names: if not isinstance(name, str): continue @@ -1600,7 +1600,7 @@ def store_name_lookups(self, command_names: T.List[mesonlib.FileOrString]) -> No if isinstance(name, str): self.build.searched_programs.add(name) - def add_find_program_override(self, name: str, exe: T.Union[build.OverrideExecutable, ExternalProgram, 'OverrideProgram']) -> None: + def add_find_program_override(self, name: str, exe: AnyProgram) -> None: if name in self.build.searched_programs: raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.') if name in self.build.find_overrides: @@ -1625,7 +1625,7 @@ def find_program_impl(self, args: T.List[mesonlib.FileOrString], search_dirs: T.Optional[T.List[str]] = None, version_arg: T.Optional[str] = '', version_func: T.Optional[ProgramVersionFunc] = None - ) -> T.Union['ExternalProgram', 'build.OverrideExecutable', 'OverrideProgram']: + ) -> AnyProgram: args = mesonlib.listify(args) extra_info: T.List[mlog.TV_Loggable] = [] @@ -1657,7 +1657,7 @@ def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: Machi version_arg: T.Optional[str], version_func: T.Optional[ProgramVersionFunc], extra_info: T.List[mlog.TV_Loggable] - ) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: + ) -> T.Optional[AnyProgram]: progobj = self.program_from_overrides(args, extra_info) if progobj: return progobj @@ -1693,7 +1693,7 @@ def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: Machi return progobj - def check_program_version(self, progobj: T.Union[ExternalProgram, build.Executable, OverrideProgram], + def check_program_version(self, progobj: AnyProgram, wanted: T.Union[str, T.List[str]], version_func: T.Optional[ProgramVersionFunc], extra_info: T.List[mlog.TV_Loggable]) -> bool: @@ -1720,7 +1720,7 @@ def check_program_version(self, progobj: T.Union[ExternalProgram, build.Executab def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrString], default_options: OptionDict, required: bool, extra_info: T.List[mlog.TV_Loggable] - ) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: + ) -> AnyProgram: mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program', mlog.bold(' '.join(args))) sp_kwargs: kwtypes.DoSubproject = { @@ -1747,7 +1747,7 @@ def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrStrin @disablerIfNotFound def func_find_program(self, node: mparser.BaseNode, args: T.Tuple[T.List[mesonlib.FileOrString]], kwargs: 'kwtypes.FindProgram', - ) -> T.Union['build.Executable', ExternalProgram, 'OverrideProgram']: + ) -> AnyProgram: disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) if disabled: mlog.log('Program', mlog.bold(' '.join(args[0])), 'skipped: feature', mlog.bold(feature), 'disabled') diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 3ff9368d907f..6c1f59f096a3 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -18,7 +18,7 @@ from ..interpreter import Interpreter from ..interpreter.interpreter import ProgramVersionFunc from ..interpreterbase import TYPE_var, TYPE_kwargs - from ..programs import OverrideProgram + from ..programs import AnyProgram from ..dependencies import Dependency from ..options import ElementaryOptionValues @@ -75,14 +75,14 @@ def find_program(self, prog: T.Union[mesonlib.FileOrString, T.List[mesonlib.File required: bool = True, version_func: T.Optional[ProgramVersionFunc] = None, wanted: T.Union[str, T.List[str]] = '', silent: bool = False, - for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, build.OverrideExecutable, OverrideProgram]: + for_machine: MachineChoice = MachineChoice.HOST) -> AnyProgram: if not isinstance(prog, list): prog = [prog] return self._interpreter.find_program_impl(prog, required=required, version_func=version_func, 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']: + wanted: T.Optional[str] = None) -> AnyProgram: # Look in overrides in case it's built as subproject progobj = self._interpreter.program_from_overrides([name], []) if progobj is not None: diff --git a/mesonbuild/modules/_qt.py b/mesonbuild/modules/_qt.py index b75169e4b2b0..e0ed3edee92d 100644 --- a/mesonbuild/modules/_qt.py +++ b/mesonbuild/modules/_qt.py @@ -28,7 +28,7 @@ from ..interpreter import Interpreter from ..interpreter import kwargs from ..mesonlib import FileOrString - from ..programs import ExternalProgram + from ..programs import AnyProgram, CommandList from typing_extensions import Literal QtDependencyType = T.Union[QtPkgConfigDependency, QmakeQtDependency] @@ -208,8 +208,8 @@ def __init__(self, interpreter: Interpreter, qt_version: int = 5): ExtensionModule.__init__(self, interpreter) self.qt_version = qt_version # It is important that this list does not change order as the order of - # the returned ExternalPrograms will change as well - self.tools: T.Dict[str, T.Union[ExternalProgram, build.Executable]] = { + # the returned program will change as well + self.tools: T.Dict[str, AnyProgram] = { tool: NonExistingExternalProgram(tool) for tool in self._set_of_qt_tools } self.methods.update({ @@ -251,7 +251,7 @@ def gen_bins() -> T.Generator[T.Tuple[str, str], None, None]: arg = ['-v'] # Ensure that the version of qt and each tool are the same - def get_version(p: T.Union[ExternalProgram, build.Executable]) -> str: + def get_version(p: AnyProgram) -> str: _, out, err = Popen_safe(p.get_command() + arg) if name == 'lrelease' or not qt_dep.version.startswith('4'): care = out @@ -727,7 +727,7 @@ def compile_translations(self, state: ModuleState, args: T.Tuple, kwargs: Compil ts = os.path.basename(ts) else: outdir = state.subdir - cmd: T.List[T.Union[ExternalProgram, build.Executable, str]] = [self.tools['lrelease'], '@INPUT@', '-qm', '@OUTPUT@'] + cmd: CommandList = [self.tools['lrelease'], '@INPUT@', '-qm', '@OUTPUT@'] lrelease_target = build.CustomTarget( f'qt{self.qt_version}-compile-{ts}', outdir, diff --git a/mesonbuild/modules/codegen.py b/mesonbuild/modules/codegen.py index c1daa91c59c3..0b9b6a1d9d35 100644 --- a/mesonbuild/modules/codegen.py +++ b/mesonbuild/modules/codegen.py @@ -21,18 +21,16 @@ from .. import mlog if T.TYPE_CHECKING: - from typing_extensions import Literal, TypeAlias, TypedDict + from typing_extensions import Literal, TypedDict from . import ModuleState from .._typing import ImmutableListProtocol - from ..build import Executable from ..interpreter import Interpreter from ..interpreter.kwargs import ExtractRequired from ..interpreterbase import TYPE_var, TYPE_kwargs from ..mesonlib import MachineChoice - from ..programs import OverrideProgram + from ..programs import AnyProgram, CommandList - Program: TypeAlias = T.Union[Executable, ExternalProgram, OverrideProgram] LexImpls = Literal['lex', 'flex', 'reflex', 'win_flex'] YaccImpls = Literal['yacc', 'byacc', 'bison', 'win_bison'] @@ -87,12 +85,11 @@ def inner(check: T.List[str]) -> T.Optional[str]: class _CodeGenerator(HoldableObject): name: str - program: Program + program: AnyProgram arguments: ImmutableListProtocol[str] = dataclasses.field(default_factory=list) - def command(self) -> T.List[T.Union[Program, str]]: - return (T.cast('T.List[T.Union[Program, str]]', [self.program]) + - T.cast('T.List[T.Union[Program, str]]', self.arguments)) + def command(self) -> CommandList: + return T.cast('CommandList', [self.program]) + T.cast('CommandList', self.arguments) def found(self) -> bool: return self.program.found() diff --git a/mesonbuild/modules/dlang.py b/mesonbuild/modules/dlang.py index 35ce86be81f1..b60ad0481621 100644 --- a/mesonbuild/modules/dlang.py +++ b/mesonbuild/modules/dlang.py @@ -22,20 +22,18 @@ from typing_extensions import Literal, TypeAlias from . import ModuleState - from ..build import OverrideExecutable from ..interpreter.interpreter import Interpreter from ..interpreterbase.baseobjects import TYPE_kwargs - from ..programs import ExternalProgram, OverrideProgram + from ..programs import AnyProgram - _AnyProgram: TypeAlias = T.Union[OverrideExecutable, ExternalProgram, OverrideProgram] _JSONTypes: TypeAlias = T.Union[str, int, bool, None, T.List['_JSONTypes'], T.Dict[str, '_JSONTypes']] class DlangModule(ExtensionModule): - class_dubbin: T.Union[_AnyProgram, Literal[False], None] = None + class_dubbin: T.Union[AnyProgram, Literal[False], None] = None init_dub = False - dubbin: T.Union[_AnyProgram, Literal[False], None] + dubbin: T.Union[AnyProgram, Literal[False], None] INFO = ModuleInfo('dlang', '0.48.0') @@ -122,7 +120,7 @@ def _call_dubbin(self, args: T.List[str], env: T.Optional[T.Mapping[str, str]] = p, out = Popen_safe(self.dubbin.get_command() + args, env=env)[0:2] return p.returncode, out.strip() - def check_dub(self, state: ModuleState) -> T.Union[_AnyProgram, Literal[False]]: + def check_dub(self, state: ModuleState) -> T.Union[AnyProgram, Literal[False]]: dubbin = state.find_program('dub', silent=True) if dubbin.found(): try: diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index d6f56b9fa65d..9e444db8b813 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -37,7 +37,7 @@ from ..scripts.gettext import read_linguas if T.TYPE_CHECKING: - from typing_extensions import Literal, TypeAlias, TypedDict + from typing_extensions import Literal, TypedDict from . import ModuleState from ..build import BuildTarget @@ -45,7 +45,7 @@ from ..interpreter import Interpreter from ..interpreterbase import TYPE_var, TYPE_kwargs from ..mesonlib import FileOrString - from ..programs import ExternalProgram + from ..programs import AnyProgram, CommandList, CommandListEntry, ExternalProgram class PostInstall(TypedDict): glib_compile_schemas: bool @@ -198,8 +198,6 @@ class MkEnums(_MkEnumsCommon): vtail: T.Optional[str] depends: T.List[T.Union[BuildTarget, CustomTarget, CustomTargetIndex]] - ToolType: TypeAlias = T.Union[Executable, ExternalProgram, OverrideProgram] - # Differs from the CustomTarget version in that it straight defaults to True _BUILD_BY_DEFAULT: KwargInfo[bool] = KwargInfo( @@ -256,8 +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[ToolType] = None - self.gicompiler: T.Optional[ToolType] = None + self.giscanner: T.Optional[AnyProgram] = None + self.gicompiler: T.Optional[AnyProgram] = 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 @@ def _print_gdbus_warning() -> None: once=True, fatal=False) @staticmethod - def _find_tool(state: 'ModuleState', tool: str) -> 'ToolType': + def _find_tool(state: 'ModuleState', tool: str) -> 'AnyProgram': tool_map = { 'gio-querymodules': 'gio-2.0', 'glib-compile-schemas': 'gio-2.0', @@ -398,7 +396,7 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri glib_version = self._get_native_glib_version(state) glib_compile_resources = self._find_tool(state, 'glib-compile-resources') - cmd: T.List[T.Union['ToolType', str]] = [glib_compile_resources, '@INPUT@'] + cmd: T.List[T.Union['AnyProgram', str]] = [glib_compile_resources, '@INPUT@'] source_dirs = kwargs['source_dir'] dependencies = kwargs['dependencies'] @@ -496,7 +494,7 @@ def compile_resources(self, state: 'ModuleState', args: T.Tuple[str, 'FileOrStri raise MesonException('GResource header is installed yet export is not enabled') depfile: T.Optional[str] = None - target_cmd: T.List[T.Union['ToolType', str]] + target_cmd: T.List[T.Union['AnyProgram', str]] if not mesonlib.version_compare(glib_version, gresource_dep_needed_version): # This will eventually go out of sync if dependencies are added target_cmd = cmd @@ -789,8 +787,7 @@ def postconf_hook(self, b: build.Build) -> None: 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']]: + def _get_gir_dep(self, state: 'ModuleState') -> T.Tuple[Dependency, AnyProgram, AnyProgram]: if not self.gir_dep: self.gir_dep = state.dependency('gobject-introspection-1.0') self.giscanner = self._find_tool(state, 'g-ir-scanner') @@ -971,7 +968,7 @@ def _make_gir_target( self, state: 'ModuleState', girfile: str, - scan_command: T.Sequence[T.Union['FileOrString', Executable, ExternalProgram, OverrideProgram]], + scan_command: T.Sequence[T.Union['FileOrString', Executable, AnyProgram]], generated_files: T.Sequence[T.Union[str, mesonlib.File, build.GeneratedTypes]], depends: T.Sequence[T.Union['FileOrString', build.BuildTarget, 'build.GeneratedTypes', build.StructuredSources]], env_flags: T.Sequence[str], @@ -1194,7 +1191,8 @@ def generate_gir(self, state: 'ModuleState', args: T.Tuple[T.List[T.Union[Execut gir_inc_dirs: T.List[str] = [] - scan_command: T.List[T.Union[str, Executable, 'ExternalProgram', 'OverrideProgram']] = [giscanner] + # Executables are passed as indexes other than 0 in this List + scan_command: T.List[T.Union[CommandListEntry, Executable]] = [giscanner] scan_command += ['--quiet'] scan_command += ['--no-libtool'] scan_command += ['--namespace=' + ns, '--nsversion=' + nsversion] @@ -1267,7 +1265,7 @@ def compile_schemas(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs srcdir = os.path.join(state.build_to_src, state.subdir) outdir = state.subdir - cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'glib-compile-schemas'), '--targetdir', outdir, srcdir] + cmd: T.List[T.Union['AnyProgram', str]] = [self._find_tool(state, 'glib-compile-schemas'), '--targetdir', outdir, srcdir] if state.subdir == '': targetname = 'gsettings-compile' else: @@ -1347,7 +1345,7 @@ def yelp(self, state: 'ModuleState', args: T.Tuple[str, T.List[str]], kwargs: 'Y pot_file = os.path.join('@SOURCE_ROOT@', state.subdir, 'C', project_id + '.pot') pot_sources = [os.path.join('@SOURCE_ROOT@', state.subdir, 'C', s) for s in sources] - pot_args: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [itstool, '-o', pot_file] + pot_args: CommandList = [itstool, '-o', pot_file] pot_args.extend(pot_sources) pottarget = build.RunTarget(f'help-{project_id}-pot', pot_args, [], os.path.join(state.subdir, 'C'), state.subproject, @@ -1379,7 +1377,7 @@ def yelp(self, state: 'ModuleState', args: T.Tuple[str, T.List[str]], kwargs: 'Y targets.append(l_data) po_file = l + '.po' - po_args: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] = [ + po_args: CommandList = [ msgmerge, '-q', '-o', os.path.join('@SOURCE_ROOT@', l_subdir, po_file), os.path.join('@SOURCE_ROOT@', l_subdir, po_file), pot_file] @@ -1644,7 +1642,7 @@ def gdbus_codegen(self, state: 'ModuleState', args: T.Tuple[str, T.Optional[T.Un kwargs: 'GdbusCodegen') -> ModuleReturnValue: namebase = args[0] xml_files: T.List[T.Union['FileOrString', build.GeneratedTypes]] = [args[1]] if args[1] else [] - cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'gdbus-codegen')] + cmd: T.List[T.Union['AnyProgram', str]] = [self._find_tool(state, 'gdbus-codegen')] cmd.extend(kwargs['extra_args']) # Autocleanup supported? @@ -2049,7 +2047,7 @@ def _make_mkenum_impl( install_dir: T.Optional[T.Sequence[T.Union[str, bool]]] = None, depends: T.Optional[T.Sequence[build.BuildTargetTypes]] = None ) -> build.CustomTarget: - real_cmd: T.List[T.Union[str, 'ToolType']] = [self._find_tool(state, 'glib-mkenums')] + real_cmd: T.List[T.Union[str, 'AnyProgram']] = [self._find_tool(state, 'glib-mkenums')] real_cmd.extend(cmd) _install_dir = install_dir or state.environment.coredata.optstore.get_value_for(OptionKey('includedir')) assert isinstance(_install_dir, str), 'for mypy' @@ -2095,7 +2093,7 @@ def genmarshal(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GenMarsh new_genmarshal = mesonlib.version_compare(self._get_native_glib_version(state), '>= 2.53.3') - cmd: T.List[T.Union['ToolType', str]] = [self._find_tool(state, 'glib-genmarshal'), '--quiet'] + cmd: T.List[T.Union['AnyProgram', str]] = [self._find_tool(state, 'glib-genmarshal'), '--quiet'] if kwargs['prefix']: cmd.extend(['--prefix', kwargs['prefix']]) if kwargs['extra_args']: @@ -2242,8 +2240,7 @@ def generate_vapi(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gener build_dir = os.path.join(state.environment.get_build_dir(), state.subdir) source_dir = os.path.join(state.environment.get_source_dir(), state.subdir) pkg_cmd, vapi_depends, vapi_packages, vapi_includes, packages = self._extract_vapi_packages(state, kwargs['packages']) - cmd: T.List[T.Union[ExternalProgram, Executable, OverrideProgram, str]] - cmd = [state.find_program('vapigen'), '--quiet', f'--library={library}', f'--directory={build_dir}'] + cmd: CommandList = [state.find_program('vapigen'), '--quiet', f'--library={library}', f'--directory={build_dir}'] cmd.extend([f'--vapidir={d}' for d in kwargs['vapi_dirs']]) cmd.extend([f'--metadatadir={d}' for d in kwargs['metadata_dirs']]) cmd.extend([f'--girdir={d}' for d in kwargs['gir_dirs']]) diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index a22c4317e2bf..f96efbbbe75d 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -33,7 +33,7 @@ from ..interpreter import kwargs as _kwargs from ..interpreter.interpreter import SourceInputs, SourceOutputs from ..interpreter.interpreterobjects import Test - from ..programs import OverrideProgram + from ..programs import AnyProgram from ..interpreter.type_checking import SourcesVarargsType from typing_extensions import TypedDict, Literal @@ -91,7 +91,7 @@ class RustModule(ExtensionModule): def __init__(self, interpreter: Interpreter) -> None: super().__init__(interpreter) - self._bindgen_bin: T.Optional[T.Union[ExternalProgram, Executable, OverrideProgram]] = None + self._bindgen_bin: T.Optional[AnyProgram] = None if 'rust' in interpreter.compilers.host: rustc = T.cast('RustCompiler', interpreter.compilers.host['rust']) self._bindgen_rust_target = 'nightly' if rustc.is_nightly else rustc.version diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index 3250c072ca9a..4df975c5e3af 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -23,6 +23,7 @@ from ..compilers import Compiler from ..interpreter import Interpreter from ..interpreter.interpreter import SourceOutputs + from ..programs import AnyProgram, CommandList from typing_extensions import TypedDict @@ -62,7 +63,7 @@ def detect_compiler(self, compilers: T.Dict[str, 'Compiler']) -> 'Compiler': return compilers[l] raise MesonException('Resource compilation requires a C or C++ compiler.') - def _find_resource_compiler(self, state: 'ModuleState') -> T.Tuple[ExternalProgram, ResourceCompilerType]: + def _find_resource_compiler(self, state: 'ModuleState') -> T.Tuple[AnyProgram, ResourceCompilerType]: # FIXME: Does not handle `native: true` executables, see # See https://github.com/mesonbuild/meson/issues/1531 # Take a parameter instead of the hardcoded definition below @@ -71,24 +72,17 @@ def _find_resource_compiler(self, state: 'ModuleState') -> T.Tuple[ExternalProgr if self._rescomp: return self._rescomp - # Will try cross / native file and then env var - rescomp = ExternalProgram.from_bin_list(state.environment, for_machine, 'windres') - - if not rescomp or not rescomp.found(): - def search_programs(names: T.List[str]) -> T.Optional[ExternalProgram]: - for name in names: - program = ExternalProgram(name, silent=True) - if program.found(): - return program - return None + comp = self.detect_compiler(state.environment.coredata.compilers[for_machine]) + rescomp_names: T.List[mesonlib.FileOrString] + if comp.id in {'msvc', 'clang-cl', 'intel-cl'} or (comp.linker and comp.linker.id in {'link', 'lld-link'}): + rescomp_names = ['rc', 'llvm-rc'] + else: + rescomp_names = ['windres', 'llvm-windres'] - comp = self.detect_compiler(state.environment.coredata.compilers[for_machine]) - if comp.id in {'msvc', 'clang-cl', 'intel-cl'} or (comp.linker and comp.linker.id in {'link', 'lld-link'}): - rescomp = search_programs(['rc', 'llvm-rc']) - else: - rescomp = search_programs(['windres', 'llvm-windres']) + rescomp = state.find_program( + rescomp_names, silent=True, required=False, for_machine=for_machine) - if not rescomp: + if not rescomp.found(): raise MesonException('Could not find Windows resource compiler') for (arg, match, rc_type) in [ @@ -208,8 +202,7 @@ def get_names() -> T.Iterable[T.Tuple[str, str, T.Union[str, mesonlib.File, buil name = name.replace('/', '_').replace('\\', '_').replace(':', '_') name_formatted = name_formatted.replace('/', '_').replace('\\', '_').replace(':', '_') output = f'{name}_@BASENAME@.{suffix}' - command: T.List[T.Union[str, ExternalProgram]] = [] - command.append(rescomp) + command: CommandList = [rescomp] command.extend(res_args) depfile: T.Optional[str] = None extra_depends = wrc_depends.copy() diff --git a/mesonbuild/programs.py b/mesonbuild/programs.py index a1cfc06e98a2..ecb6f19ce667 100644 --- a/mesonbuild/programs.py +++ b/mesonbuild/programs.py @@ -19,9 +19,16 @@ from .mesonlib import MachineChoice, OrderedSet if T.TYPE_CHECKING: + from typing_extensions import TypeAlias + + from .build import OverrideExecutable from .environment import Environment from .interpreter import Interpreter + AnyProgram: TypeAlias = T.Union[OverrideExecutable, 'ExternalProgram', 'OverrideProgram'] + CommandListEntry: TypeAlias = T.Union[str, AnyProgram] + CommandList: TypeAlias = T.List[CommandListEntry] + class ExternalProgram(mesonlib.HoldableObject):