build: Use typed_kwargs for language args

This also moves the repacking into the interpreter, making the build
implementation simpler and removing a layering violation. This also
makes use a defaultdict to remove the need to call `.get()`
pull/12331/head
Dylan Baker 2 years ago committed by Eli Schwartz
parent cbca191948
commit 523a27c6f0
  1. 4
      mesonbuild/backend/ninjabackend.py
  2. 26
      mesonbuild/build.py
  3. 13
      mesonbuild/interpreter/interpreter.py
  4. 16
      mesonbuild/interpreter/kwargs.py
  5. 17
      mesonbuild/interpreter/type_checking.py
  6. 7
      mesonbuild/modules/rust.py

@ -1068,7 +1068,7 @@ class NinjaBackend(backends.Backend):
return True
if 'cpp' not in target.compilers:
return False
if '-fmodules-ts' in target.extra_args.get('cpp', []):
if '-fmodules-ts' in target.extra_args['cpp']:
return True
# Currently only the preview version of Visual Studio is supported.
cpp = target.compilers['cpp']
@ -1462,7 +1462,7 @@ class NinjaBackend(backends.Backend):
compiler = target.compilers['cs']
rel_srcs = [os.path.normpath(s.rel_to_builddir(self.build_to_src)) for s in src_list]
deps = []
commands = compiler.compiler_args(target.extra_args.get('cs', []))
commands = compiler.compiler_args(target.extra_args['cs'])
commands += compiler.get_buildtype_args(buildtype)
commands += compiler.get_optimization_args(target.get_option(OptionKey('optimization')))
commands += compiler.get_debug_args(target.get_option(OptionKey('debug')))

@ -724,7 +724,7 @@ class BuildTarget(Target):
objects: T.List[ObjectTypes],
environment: environment.Environment,
compilers: T.Dict[str, 'Compiler'],
kwargs):
kwargs: T.Dict[str, T.Any]):
super().__init__(name, subdir, subproject, True, for_machine, environment, install=kwargs.get('install', False))
self.all_compilers = compilers
self.compilers: OrderedDict[str, Compiler] = OrderedDict()
@ -747,7 +747,7 @@ class BuildTarget(Target):
# as Vala which generates .vapi and .h besides the compiled output.
self.outputs = [self.filename]
self.pch: T.Dict[str, T.List[str]] = {}
self.extra_args: T.Dict[str, T.List[str]] = {}
self.extra_args: T.DefaultDict[str, T.List[str]] = kwargs.get('language_args', defaultdict(list))
self.sources: T.List[File] = []
self.generated: T.List['GeneratedTypes'] = []
self.extra_files: T.List[File] = []
@ -831,6 +831,8 @@ class BuildTarget(Target):
def check_unknown_kwargs_int(self, kwargs, known_kwargs):
unknowns = []
for k in kwargs:
if k == 'language_args':
continue
if k not in known_kwargs:
unknowns.append(k)
if len(unknowns) > 0:
@ -1104,10 +1106,6 @@ class BuildTarget(Target):
self.process_kwargs_base(kwargs)
self.original_kwargs = kwargs
for lang in all_languages:
lang_args = extract_as_list(kwargs, f'{lang}_args')
self.add_compiler_args(lang, lang_args)
self.add_pch('c', extract_as_list(kwargs, 'c_pch'))
self.add_pch('cpp', extract_as_list(kwargs, 'cpp_pch'))
@ -1279,8 +1277,8 @@ class BuildTarget(Target):
def get_outputs(self) -> T.List[str]:
return self.outputs
def get_extra_args(self, language) -> T.List[str]:
return self.extra_args.get(language, [])
def get_extra_args(self, language: str) -> T.List[str]:
return self.extra_args[language]
@lru_cache(maxsize=None)
def get_dependencies(self) -> OrderedSet[Target]:
@ -1539,16 +1537,6 @@ class BuildTarget(Target):
ids = [IncludeDirs(x.get_curdir(), x.get_incdirs(), is_system, x.get_extra_build_dirs()) for x in ids]
self.include_dirs += ids
def add_compiler_args(self, language: str, args: T.List['FileOrString']) -> None:
args = listify(args)
for a in args:
if not isinstance(a, (str, File)):
raise InvalidArguments('A non-string passed to compiler args.')
if language in self.extra_args:
self.extra_args[language] += args
else:
self.extra_args[language] = args
def get_aliases(self) -> T.List[T.Tuple[str, str, str]]:
return []
@ -2876,7 +2864,7 @@ class Jar(BuildTarget):
raise InvalidArguments('structured sources are not supported in Java targets.')
self.filename = self.name + '.jar'
self.outputs = [self.filename]
self.java_args = kwargs.get('java_args', [])
self.java_args = self.extra_args['java']
self.main_class = kwargs.get('main_class', '')
self.java_resources: T.Optional[StructuredSources] = kwargs.get('java_resources', None)

@ -3230,7 +3230,7 @@ class Interpreter(InterpreterBase, HoldableObject):
else:
raise InterpreterException(f'Unknown default_library value: {default_library}.')
def __convert_file_args(self, raw: T.List[mesonlib.FileOrString], allow_file: bool) -> T.Tuple[T.List[mesonlib.File], T.List[str]]:
def __convert_file_args(self, raw: T.List[mesonlib.FileOrString]) -> T.Tuple[T.List[mesonlib.File], T.List[str]]:
"""Convert raw target arguments from File | str to File.
This removes files from the command line and replaces them with string
@ -3246,8 +3246,6 @@ class Interpreter(InterpreterBase, HoldableObject):
for a in raw:
if isinstance(a, mesonlib.File):
if not allow_file:
raise InvalidArguments('File type arguments are only allowed for vala')
depend_files.append(a)
args.append(a.rel_to_builddir(build_to_source))
else:
@ -3264,11 +3262,13 @@ class Interpreter(InterpreterBase, HoldableObject):
them for the IR.
"""
d = kwargs.setdefault('depend_files', [])
new_args: T.DefaultDict[str, T.List[str]] = collections.defaultdict(list)
for l in compilers.all_languages:
deps, args = self.__convert_file_args(kwargs[f'{l}_args'], l == 'vala')
kwargs[f'{l}_args'] = args
deps, args = self.__convert_file_args(kwargs[f'{l}_args'])
new_args[l] = args
d.extend(deps)
kwargs['language_args'] = new_args
@T.overload
def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType],
@ -3295,7 +3295,6 @@ class Interpreter(InterpreterBase, HoldableObject):
targetclass: T.Type[T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]]
) -> T.Union[build.Executable, build.StaticLibrary, build.SharedModule, build.SharedLibrary, build.Jar]:
@FeatureNewKwargs('build target', '0.42.0', ['build_rpath', 'implicit_include_directories'])
@FeatureNewKwargs('build target', '0.41.0', ['rust_args'])
@FeatureNewKwargs('build target', '0.38.0', ['build_by_default'])
@FeatureNewKwargs('build target', '0.48.0', ['gnu_symbol_visibility'])
def build_target_decorator_caller(self, node, args, kwargs):
@ -3339,7 +3338,7 @@ class Interpreter(InterpreterBase, HoldableObject):
# Filter out kwargs from other target types. For example 'soversion'
# passed to library() when default_library == 'static'.
kwargs = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs}
kwargs = {k: v for k, v in kwargs.items() if k in targetclass.known_kwargs | {'language_args'}}
srcs: T.List['SourceInputs'] = []
struct: T.Optional[build.StructuredSources] = build.StructuredSources()

@ -335,12 +335,27 @@ class _BuildTarget(_BaseBuildTarget):
rust_dependency_map: T.Dict[str, str]
sources: SourcesVarargsType
c_args: T.List[str]
cpp_args: T.List[str]
cuda_args: T.List[str]
fortran_args: T.List[str]
d_args: T.List[str]
objc_args: T.List[str]
objcpp_args: T.List[str]
rust_args: T.List[str]
vala_args: T.List[T.Union[str, File]] # Yes, Vala is really special
cs_args: T.List[str]
swift_args: T.List[str]
cython_args: T.List[str]
nasm_args: T.List[str]
masm_args: T.List[str]
class _LibraryMixin(TypedDict):
rust_abi: T.Optional[Literal['c', 'rust']]
class Executable(_BuildTarget):
export_dynamic: T.Optional[bool]
@ -394,6 +409,7 @@ class Jar(_BaseBuildTarget):
main_class: str
java_resources: T.Optional[build.StructuredSources]
sources: T.Union[str, File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget]
java_args: T.List[str]
class FuncDeclareDependency(TypedDict):

@ -526,8 +526,25 @@ _VS_MODULE_DEFS_KW: KwargInfo[T.Optional[T.Union[str, File, CustomTarget, Custom
since_values={CustomTargetIndex: '1.3.0'}
)
_BASE_LANG_KW: KwargInfo[T.List[str]] = KwargInfo(
'UNKNOWN',
ContainerTypeInfo(list, (str)),
listify=True,
default=[],
)
_LANGUAGE_KWS: T.List[KwargInfo[T.List[str]]] = [
_BASE_LANG_KW.evolve(name=f'{lang}_args')
for lang in compilers.all_languages - {'rust', 'vala'}
]
# Cannot use _BASE_LANG_KW here because Vala is special for types
_LANGUAGE_KWS.append(KwargInfo(
'vala_args', ContainerTypeInfo(list, (str, File)), listify=True, default=[]))
_LANGUAGE_KWS.append(_BASE_LANG_KW.evolve(name='rust_args', since='0.41.0'))
# Applies to all build_target like classes
_ALL_TARGET_KWS: T.List[KwargInfo] = [
*_LANGUAGE_KWS,
OVERRIDE_OPTIONS_KW,
]

@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
import os
import typing as T
from mesonbuild.interpreterbase.decorators import FeatureNew
@ -160,12 +159,14 @@ class RustModule(ExtensionModule):
new_target_kwargs = base_target.original_kwargs.copy()
# Don't mutate the shallow copied list, instead replace it with a new
# one
new_target_kwargs['rust_args'] = \
new_target_kwargs.get('rust_args', []) + kwargs['rust_args'] + ['--test']
new_target_kwargs['install'] = False
new_target_kwargs['dependencies'] = new_target_kwargs.get('dependencies', []) + kwargs['dependencies']
new_target_kwargs['link_with'] = new_target_kwargs.get('link_with', []) + kwargs['link_with']
lang_args = base_target.extra_args.copy()
lang_args['rust'] = base_target.extra_args['rust'] + kwargs['rust_args'] + ['--test']
new_target_kwargs['language_args'] = lang_args
sources = T.cast('T.List[SourceOutputs]', base_target.sources.copy())
sources.extend(base_target.generated)

Loading…
Cancel
Save