aboutsummaryrefslogtreecommitdiffstats
path: root/meson/mesonbuild/interpreter/mesonmain.py
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /meson/mesonbuild/interpreter/mesonmain.py
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'meson/mesonbuild/interpreter/mesonmain.py')
-rw-r--r--meson/mesonbuild/interpreter/mesonmain.py382
1 files changed, 382 insertions, 0 deletions
diff --git a/meson/mesonbuild/interpreter/mesonmain.py b/meson/mesonbuild/interpreter/mesonmain.py
new file mode 100644
index 000000000..97a695b9d
--- /dev/null
+++ b/meson/mesonbuild/interpreter/mesonmain.py
@@ -0,0 +1,382 @@
+import os
+
+from .. import mesonlib
+from .. import dependencies
+from .. import build
+from .. import mlog
+
+from ..mesonlib import MachineChoice, OptionKey
+from ..programs import OverrideProgram, ExternalProgram
+from ..interpreterbase import (MesonInterpreterObject, FeatureNewKwargs, FeatureNew, FeatureDeprecated,
+ typed_pos_args, permittedKwargs, noArgsFlattening, noPosargs, noKwargs,
+ MesonVersionString, InterpreterException)
+
+from .interpreterobjects import (ExecutableHolder, ExternalProgramHolder,
+ CustomTargetHolder, CustomTargetIndexHolder,
+ EnvironmentVariablesObject)
+
+import typing as T
+
+if T.TYPE_CHECKING:
+ from .interpreter import Interpreter
+
+class MesonMain(MesonInterpreterObject):
+ def __init__(self, build: 'build.Build', interpreter: 'Interpreter'):
+ super().__init__(subproject=interpreter.subproject)
+ self.build = build
+ self.interpreter = interpreter
+ self.methods.update({'get_compiler': self.get_compiler_method,
+ 'is_cross_build': self.is_cross_build_method,
+ 'has_exe_wrapper': self.has_exe_wrapper_method,
+ 'can_run_host_binaries': self.can_run_host_binaries_method,
+ 'is_unity': self.is_unity_method,
+ 'is_subproject': self.is_subproject_method,
+ 'current_source_dir': self.current_source_dir_method,
+ 'current_build_dir': self.current_build_dir_method,
+ 'source_root': self.source_root_method,
+ 'build_root': self.build_root_method,
+ 'project_source_root': self.project_source_root_method,
+ 'project_build_root': self.project_build_root_method,
+ 'global_source_root': self.global_source_root_method,
+ 'global_build_root': self.global_build_root_method,
+ 'add_install_script': self.add_install_script_method,
+ 'add_postconf_script': self.add_postconf_script_method,
+ 'add_dist_script': self.add_dist_script_method,
+ 'install_dependency_manifest': self.install_dependency_manifest_method,
+ 'override_dependency': self.override_dependency_method,
+ 'override_find_program': self.override_find_program_method,
+ 'project_version': self.project_version_method,
+ 'project_license': self.project_license_method,
+ 'version': self.version_method,
+ 'project_name': self.project_name_method,
+ 'get_cross_property': self.get_cross_property_method,
+ 'get_external_property': self.get_external_property_method,
+ 'has_external_property': self.has_external_property_method,
+ 'backend': self.backend_method,
+ 'add_devenv': self.add_devenv_method,
+ })
+
+ def _find_source_script(self, prog: T.Union[str, mesonlib.File, build.Executable, ExternalProgram], args):
+
+ if isinstance(prog, (build.Executable, ExternalProgram)):
+ return self.interpreter.backend.get_executable_serialisation([prog] + args)
+ found = self.interpreter.func_find_program({}, prog, {})
+ es = self.interpreter.backend.get_executable_serialisation([found] + args)
+ es.subproject = self.interpreter.subproject
+ return es
+
+ def _process_script_args(
+ self, name: str, args: T.List[T.Union[
+ str, mesonlib.File, CustomTargetHolder,
+ CustomTargetIndexHolder,
+ ExternalProgramHolder, ExecutableHolder,
+ ]], allow_built: bool = False) -> T.List[str]:
+ script_args = [] # T.List[str]
+ new = False
+ for a in args:
+ if isinstance(a, str):
+ script_args.append(a)
+ elif isinstance(a, mesonlib.File):
+ new = True
+ script_args.append(a.rel_to_builddir(self.interpreter.environment.source_dir))
+ elif isinstance(a, (build.BuildTarget, build.CustomTarget, build.CustomTargetIndex)):
+ if not allow_built:
+ raise InterpreterException(f'Arguments to {name} cannot be built')
+ new = True
+ script_args.extend([os.path.join(a.get_subdir(), o) for o in a.get_outputs()])
+
+ # This feels really hacky, but I'm not sure how else to fix
+ # this without completely rewriting install script handling.
+ # This is complicated by the fact that the install target
+ # depends on all.
+ if isinstance(a, build.CustomTargetIndex):
+ a.target.build_by_default = True
+ else:
+ a.build_by_default = True
+ elif isinstance(a, ExternalProgram):
+ script_args.extend(a.command)
+ new = True
+ else:
+ raise InterpreterException(
+ f'Arguments to {name} must be strings, Files, or CustomTargets, '
+ 'Indexes of CustomTargets')
+ if new:
+ FeatureNew.single_use(
+ f'Calling "{name}" with File, CustomTaget, Index of CustomTarget, '
+ 'Executable, or ExternalProgram',
+ '0.55.0', self.interpreter.subproject)
+ return script_args
+
+ @FeatureNewKwargs('add_install_script', '0.57.0', ['skip_if_destdir'])
+ @permittedKwargs({'skip_if_destdir'})
+ def add_install_script_method(self, args: 'T.Tuple[T.Union[str, mesonlib.File, ExecutableHolder], T.Union[str, mesonlib.File, CustomTargetHolder, CustomTargetIndexHolder], ...]', kwargs):
+ if len(args) < 1:
+ raise InterpreterException('add_install_script takes one or more arguments')
+ if isinstance(args[0], mesonlib.File):
+ FeatureNew.single_use('Passing file object to script parameter of add_install_script',
+ '0.57.0', self.interpreter.subproject)
+ skip_if_destdir = kwargs.get('skip_if_destdir', False)
+ if not isinstance(skip_if_destdir, bool):
+ raise InterpreterException('skip_if_destdir keyword argument must be boolean')
+ script_args = self._process_script_args('add_install_script', args[1:], allow_built=True)
+ script = self._find_source_script(args[0], script_args)
+ script.skip_if_destdir = skip_if_destdir
+ self.build.install_scripts.append(script)
+
+ @permittedKwargs(set())
+ def add_postconf_script_method(self, args, kwargs):
+ if len(args) < 1:
+ raise InterpreterException('add_postconf_script takes one or more arguments')
+ if isinstance(args[0], mesonlib.File):
+ FeatureNew.single_use('Passing file object to script parameter of add_postconf_script',
+ '0.57.0', self.interpreter.subproject)
+ script_args = self._process_script_args('add_postconf_script', args[1:], allow_built=True)
+ script = self._find_source_script(args[0], script_args)
+ self.build.postconf_scripts.append(script)
+
+ @permittedKwargs(set())
+ def add_dist_script_method(self, args, kwargs):
+ if len(args) < 1:
+ raise InterpreterException('add_dist_script takes one or more arguments')
+ if len(args) > 1:
+ FeatureNew.single_use('Calling "add_dist_script" with multiple arguments',
+ '0.49.0', self.interpreter.subproject)
+ if isinstance(args[0], mesonlib.File):
+ FeatureNew.single_use('Passing file object to script parameter of add_dist_script',
+ '0.57.0', self.interpreter.subproject)
+ if self.interpreter.subproject != '':
+ FeatureNew.single_use('Calling "add_dist_script" in a subproject',
+ '0.58.0', self.interpreter.subproject)
+ script_args = self._process_script_args('add_dist_script', args[1:], allow_built=True)
+ script = self._find_source_script(args[0], script_args)
+ self.build.dist_scripts.append(script)
+
+ @noPosargs
+ @permittedKwargs({})
+ def current_source_dir_method(self, args, kwargs):
+ src = self.interpreter.environment.source_dir
+ sub = self.interpreter.subdir
+ if sub == '':
+ return src
+ return os.path.join(src, sub)
+
+ @noPosargs
+ @permittedKwargs({})
+ def current_build_dir_method(self, args, kwargs):
+ src = self.interpreter.environment.build_dir
+ sub = self.interpreter.subdir
+ if sub == '':
+ return src
+ return os.path.join(src, sub)
+
+ @noPosargs
+ @permittedKwargs({})
+ def backend_method(self, args, kwargs):
+ return self.interpreter.backend.name
+
+ @noPosargs
+ @permittedKwargs({})
+ @FeatureDeprecated('meson.source_root', '0.56.0', 'use meson.project_source_root() or meson.global_source_root() instead.')
+ def source_root_method(self, args, kwargs):
+ return self.interpreter.environment.source_dir
+
+ @noPosargs
+ @permittedKwargs({})
+ @FeatureDeprecated('meson.build_root', '0.56.0', 'use meson.project_build_root() or meson.global_build_root() instead.')
+ def build_root_method(self, args, kwargs):
+ return self.interpreter.environment.build_dir
+
+ @noPosargs
+ @permittedKwargs({})
+ @FeatureNew('meson.project_source_root', '0.56.0')
+ def project_source_root_method(self, args, kwargs):
+ src = self.interpreter.environment.source_dir
+ sub = self.interpreter.root_subdir
+ if sub == '':
+ return src
+ return os.path.join(src, sub)
+
+ @noPosargs
+ @permittedKwargs({})
+ @FeatureNew('meson.project_build_root', '0.56.0')
+ def project_build_root_method(self, args, kwargs):
+ src = self.interpreter.environment.build_dir
+ sub = self.interpreter.root_subdir
+ if sub == '':
+ return src
+ return os.path.join(src, sub)
+
+ @noPosargs
+ @noKwargs
+ @FeatureNew('meson.global_source_root', '0.58.0')
+ def global_source_root_method(self, args, kwargs):
+ return self.interpreter.environment.source_dir
+
+ @noPosargs
+ @noKwargs
+ @FeatureNew('meson.global_build_root', '0.58.0')
+ def global_build_root_method(self, args, kwargs):
+ return self.interpreter.environment.build_dir
+
+ @noPosargs
+ @permittedKwargs({})
+ @FeatureDeprecated('meson.has_exe_wrapper', '0.55.0', 'use meson.can_run_host_binaries instead.')
+ def has_exe_wrapper_method(self, args: T.Tuple[object, ...], kwargs: T.Dict[str, object]) -> bool:
+ return self.can_run_host_binaries_impl(args, kwargs)
+
+ @noPosargs
+ @permittedKwargs({})
+ @FeatureNew('meson.can_run_host_binaries', '0.55.0')
+ def can_run_host_binaries_method(self, args: T.Tuple[object, ...], kwargs: T.Dict[str, object]) -> bool:
+ return self.can_run_host_binaries_impl(args, kwargs)
+
+ def can_run_host_binaries_impl(self, args, kwargs):
+ if (self.is_cross_build_method(None, None) and
+ self.build.environment.need_exe_wrapper()):
+ if self.build.environment.exe_wrapper is None:
+ return False
+ # We return True when exe_wrap is defined, when it's not needed, and
+ # when we're compiling natively. The last two are semantically confusing.
+ # Need to revisit this.
+ return True
+
+ @noPosargs
+ @permittedKwargs({})
+ def is_cross_build_method(self, args, kwargs):
+ return self.build.environment.is_cross_build()
+
+ @permittedKwargs({'native'})
+ def get_compiler_method(self, args, kwargs):
+ if len(args) != 1:
+ raise InterpreterException('get_compiler_method must have one and only one argument.')
+ cname = args[0]
+ for_machine = self.interpreter.machine_from_native_kwarg(kwargs)
+ clist = self.interpreter.coredata.compilers[for_machine]
+ if cname in clist:
+ return clist[cname]
+ raise InterpreterException(f'Tried to access compiler for language "{cname}", not specified for {for_machine.get_lower_case_name()} machine.')
+
+ @noPosargs
+ @permittedKwargs({})
+ def is_unity_method(self, args, kwargs):
+ optval = self.interpreter.environment.coredata.get_option(OptionKey('unity'))
+ if optval == 'on' or (optval == 'subprojects' and self.interpreter.is_subproject()):
+ return True
+ return False
+
+ @noPosargs
+ @permittedKwargs({})
+ def is_subproject_method(self, args, kwargs):
+ return self.interpreter.is_subproject()
+
+ @permittedKwargs({})
+ def install_dependency_manifest_method(self, args, kwargs):
+ if len(args) != 1:
+ raise InterpreterException('Must specify manifest install file name')
+ if not isinstance(args[0], str):
+ raise InterpreterException('Argument must be a string.')
+ self.build.dep_manifest_name = args[0]
+
+ @FeatureNew('meson.override_find_program', '0.46.0')
+ @permittedKwargs({})
+ def override_find_program_method(self, args, kwargs):
+ if len(args) != 2:
+ raise InterpreterException('Override needs two arguments')
+ name, exe = args
+ if not isinstance(name, str):
+ raise InterpreterException('First argument must be a string')
+ if isinstance(exe, mesonlib.File):
+ abspath = exe.absolute_path(self.interpreter.environment.source_dir,
+ self.interpreter.environment.build_dir)
+ if not os.path.exists(abspath):
+ raise InterpreterException('Tried to override %s with a file that does not exist.' % name)
+ exe = OverrideProgram(name, abspath)
+ if not isinstance(exe, (ExternalProgram, build.Executable)):
+ raise InterpreterException('Second argument must be an external program or executable.')
+ self.interpreter.add_find_program_override(name, exe)
+
+ @FeatureNew('meson.override_dependency', '0.54.0')
+ @permittedKwargs({'native'})
+ def override_dependency_method(self, args, kwargs):
+ if len(args) != 2:
+ raise InterpreterException('Override needs two arguments')
+ name = args[0]
+ dep = args[1]
+ if not isinstance(name, str) or not name:
+ raise InterpreterException('First argument must be a string and cannot be empty')
+ if not isinstance(dep, dependencies.Dependency):
+ raise InterpreterException('Second argument must be a dependency object')
+ identifier = dependencies.get_dep_identifier(name, kwargs)
+ for_machine = self.interpreter.machine_from_native_kwarg(kwargs)
+ override = self.build.dependency_overrides[for_machine].get(identifier)
+ if override:
+ m = 'Tried to override dependency {!r} which has already been resolved or overridden at {}'
+ location = mlog.get_error_location_string(override.node.filename, override.node.lineno)
+ raise InterpreterException(m.format(name, location))
+ self.build.dependency_overrides[for_machine][identifier] = \
+ build.DependencyOverride(dep, self.interpreter.current_node)
+
+ @noPosargs
+ @permittedKwargs({})
+ def project_version_method(self, args, kwargs):
+ return self.build.dep_manifest[self.interpreter.active_projectname]['version']
+
+ @FeatureNew('meson.project_license()', '0.45.0')
+ @noPosargs
+ @permittedKwargs({})
+ def project_license_method(self, args, kwargs):
+ return self.build.dep_manifest[self.interpreter.active_projectname]['license']
+
+ @noPosargs
+ @permittedKwargs({})
+ def version_method(self, args, kwargs):
+ return MesonVersionString(self.interpreter.coredata.version)
+
+ @noPosargs
+ @permittedKwargs({})
+ def project_name_method(self, args, kwargs):
+ return self.interpreter.active_projectname
+
+ def __get_external_property_impl(self, propname: str, fallback: T.Optional[object], machine: MachineChoice) -> object:
+ """Shared implementation for get_cross_property and get_external_property."""
+ try:
+ return self.interpreter.environment.properties[machine][propname]
+ except KeyError:
+ if fallback is not None:
+ return fallback
+ raise InterpreterException(f'Unknown property for {machine.get_lower_case_name()} machine: {propname}')
+
+ @noArgsFlattening
+ @permittedKwargs({})
+ @FeatureDeprecated('meson.get_cross_property', '0.58.0', 'Use meson.get_external_property() instead')
+ @typed_pos_args('meson.get_cross_property', str, optargs=[object])
+ def get_cross_property_method(self, args: T.Tuple[str, T.Optional[object]], kwargs: T.Dict[str, T.Any]) -> object:
+ propname, fallback = args
+ return self.__get_external_property_impl(propname, fallback, MachineChoice.HOST)
+
+ @noArgsFlattening
+ @permittedKwargs({'native'})
+ @FeatureNew('meson.get_external_property', '0.54.0')
+ @typed_pos_args('meson.get_external_property', str, optargs=[object])
+ def get_external_property_method(self, args: T.Tuple[str, T.Optional[object]], kwargs: T.Dict[str, T.Any]) -> object:
+ propname, fallback = args
+ machine = self.interpreter.machine_from_native_kwarg(kwargs)
+ return self.__get_external_property_impl(propname, fallback, machine)
+
+
+ @permittedKwargs({'native'})
+ @FeatureNew('meson.has_external_property', '0.58.0')
+ @typed_pos_args('meson.has_external_property', str)
+ def has_external_property_method(self, args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str:
+ prop_name = args[0]
+ for_machine = self.interpreter.machine_from_native_kwarg(kwargs)
+ return prop_name in self.interpreter.environment.properties[for_machine]
+
+ @FeatureNew('add_devenv', '0.58.0')
+ @noKwargs
+ @typed_pos_args('add_devenv', (str, list, dict, EnvironmentVariablesObject))
+ def add_devenv_method(self, args: T.Union[str, list, dict, EnvironmentVariablesObject], kwargs: T.Dict[str, T.Any]) -> None:
+ env = args[0]
+ if isinstance(env, (str, list, dict)):
+ env = EnvironmentVariablesObject(env)
+ self.build.devenv.append(env.vars)