aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/build.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/build.py')
-rw-r--r--mesonbuild/build.py65
1 files changed, 37 insertions, 28 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 7320b88..72d376d 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -33,7 +33,7 @@ from .compilers import (
is_header, is_object, is_source, clink_langs, sort_clink, all_languages,
is_known_suffix, detect_static_linker
)
-from .interpreterbase import FeatureNew, FeatureDeprecated
+from .interpreterbase import FeatureNew, FeatureDeprecated, UnknownValue
if T.TYPE_CHECKING:
from typing_extensions import Literal, TypedDict
@@ -275,7 +275,7 @@ class Build:
self.stdlibs = PerMachine({}, {})
self.test_setups: T.Dict[str, TestSetup] = {}
self.test_setup_default_name = None
- self.find_overrides: T.Dict[str, T.Union['Executable', programs.ExternalProgram, programs.OverrideProgram]] = {}
+ self.find_overrides: T.Dict[str, T.Union['OverrideExecutable', programs.ExternalProgram, programs.OverrideProgram]] = {}
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
@@ -648,7 +648,7 @@ class Target(HoldableObject, metaclass=abc.ABCMeta):
def process_kwargs_base(self, kwargs: T.Dict[str, T.Any]) -> None:
if 'build_by_default' in kwargs:
self.build_by_default = kwargs['build_by_default']
- if not isinstance(self.build_by_default, bool):
+ if not isinstance(self.build_by_default, (bool, UnknownValue)):
raise InvalidArguments('build_by_default must be a boolean value.')
if not self.build_by_default and kwargs.get('install', False):
@@ -656,29 +656,11 @@ class Target(HoldableObject, metaclass=abc.ABCMeta):
# set, use the value of 'install' if it's enabled.
self.build_by_default = True
- self.raw_overrides = self.parse_overrides(kwargs)
+ self.raw_overrides = kwargs.get('override_options', {})
def get_override(self, name: str) -> T.Optional[str]:
return self.raw_overrides.get(name, None)
- @staticmethod
- def parse_overrides(kwargs: T.Dict[str, T.Any]) -> T.Dict[str, str]:
- opts = kwargs.get('override_options', [])
-
- # In this case we have an already parsed and ready to go dictionary
- # provided by typed_kwargs
- if isinstance(opts, dict):
- return T.cast('T.Dict[OptionKey, str]', opts)
-
- result: T.Dict[str, str] = {}
- overrides = stringlistify(opts)
- for o in overrides:
- if '=' not in o:
- raise InvalidArguments('Overrides must be of form "key=value"')
- k, v = o.split('=', 1)
- result[k] = v
- return result
-
def is_linkable_target(self) -> bool:
return False
@@ -1375,6 +1357,10 @@ class BuildTarget(Target):
deps = listify(deps)
for dep in deps:
if dep in self.added_deps:
+ # Prefer to add dependencies to added_deps which have a name
+ if dep.is_named():
+ self.added_deps.remove(dep)
+ self.added_deps.add(dep)
continue
if isinstance(dep, dependencies.InternalDependency):
@@ -2199,10 +2185,16 @@ class StaticLibrary(BuildTarget):
elif self.rust_crate_type == 'staticlib':
self.suffix = 'a'
else:
- if 'c' in self.compilers and self.compilers['c'].get_id() == 'tasking':
- self.suffix = 'ma' if self.options.get_value('b_lto') and not self.prelink else 'a'
- else:
- self.suffix = 'a'
+ self.suffix = 'a'
+ if 'c' in self.compilers and self.compilers['c'].get_id() == 'tasking' and not self.prelink:
+ key = OptionKey('b_lto', self.subproject, self.for_machine)
+ try:
+ v = self.environment.coredata.get_option_for_target(self, key)
+ except KeyError:
+ v = self.environment.coredata.optstore.get_value_for(key)
+ assert isinstance(v, bool), 'for mypy'
+ if v:
+ self.suffix = 'ma'
self.filename = self.prefix + self.name + '.' + self.suffix
self.outputs[0] = self.filename
@@ -2594,7 +2586,7 @@ class CommandBase:
subproject: str
def flatten_command(self, cmd: T.Sequence[T.Union[str, File, programs.ExternalProgram, BuildTargetTypes]]) -> \
- T.List[T.Union[str, File, BuildTarget, 'CustomTarget']]:
+ T.List[T.Union[str, File, BuildTarget, CustomTarget, programs.ExternalProgram]]:
cmd = listify(cmd)
final_cmd: T.List[T.Union[str, File, BuildTarget, 'CustomTarget']] = []
for c in cmd:
@@ -2611,7 +2603,8 @@ class CommandBase:
# Can only add a dependency on an external program which we
# know the absolute path of
self.depend_files.append(File.from_absolute_file(path))
- final_cmd += c.get_command()
+ # Do NOT flatten -- it is needed for later parsing
+ final_cmd.append(c)
elif isinstance(c, (BuildTarget, CustomTarget)):
self.dependencies.append(c)
final_cmd.append(c)
@@ -2681,6 +2674,7 @@ class CustomTarget(Target, CustomTargetBase, CommandBase):
install_dir: T.Optional[T.List[T.Union[str, Literal[False]]]] = None,
install_mode: T.Optional[FileMode] = None,
install_tag: T.Optional[T.List[T.Optional[str]]] = None,
+ rspable: bool = False,
absolute_paths: bool = False,
backend: T.Optional['Backend'] = None,
description: str = 'Generating {} with a custom command',
@@ -2713,6 +2707,9 @@ class CustomTarget(Target, CustomTargetBase, CommandBase):
# Whether to use absolute paths for all files on the commandline
self.absolute_paths = absolute_paths
+ # Whether to enable using response files for the underlying tool
+ self.rspable = rspable
+
def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, None]]:
return None, None
@@ -3129,6 +3126,18 @@ class ConfigurationData(HoldableObject):
def keys(self) -> T.Iterator[str]:
return self.values.keys()
+class OverrideExecutable(Executable):
+ def __init__(self, executable: Executable, version: str):
+ self._executable = executable
+ self._version = version
+
+ def __getattr__(self, name: str) -> T.Any:
+ _executable = object.__getattribute__(self, '_executable')
+ return getattr(_executable, name)
+
+ def get_version(self, interpreter: T.Optional[Interpreter] = None) -> str:
+ return self._version
+
# A bit poorly named, but this represents plain data files to copy
# during install.
@dataclass(eq=False)