diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index c117d0149889..83da888c5158 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -3210,7 +3210,8 @@ def generate_single_compile(self, target: build.BuildTarget, src, compiler_name = self.compiler_to_rule_name(compiler) else: compiler_name = self.compiler_to_rule_name(compiler) - extra_deps = [] + extra_deps: T.List[str] = [] + extra_deps.extend(self.get_target_depend_files(target)) if compiler.get_language() == 'fortran': # Can't read source file to scan for deps if it's generated later # at build-time. Skip scanning for deps, and just set the module diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 69797e04b49c..4969446499b6 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -47,6 +47,7 @@ from .linkers.linkers import StaticLinker from .mesonlib import ExecutableSerialisation, FileMode, FileOrString from .mparser import BaseNode + from .options import ElementaryOptionValues GeneratedTypes: TypeAlias = T.Union['CustomTarget', 'CustomTargetIndex', 'GeneratedList'] LibTypes: TypeAlias = T.Union['SharedLibrary', 'StaticLibrary', 'CustomTarget', 'CustomTargetIndex'] @@ -70,6 +71,7 @@ class BuildTargetKeywordArguments(TypedDict, total=False): build_by_default: bool build_rpath: str + build_subdir: str c_pch: T.Optional[T.Tuple[str, T.Optional[str]]] cpp_pch: T.Optional[T.Tuple[str, T.Optional[str]]] d_debug: T.List[T.Union[str, int]] @@ -77,6 +79,7 @@ class BuildTargetKeywordArguments(TypedDict, total=False): d_module_versions: T.List[T.Union[str, int]] d_unittest: bool dependencies: T.List[dependencies.Dependency] + depend_files: T.List[File] extra_files: T.List[File] gnu_symbol_visibility: Literal['default', 'internal', 'hidden', 'protected', 'inlineshidden', ''] implicit_include_directories: bool @@ -88,14 +91,14 @@ class BuildTargetKeywordArguments(TypedDict, total=False): install_tag: T.List[T.Optional[str]] language_args: T.DefaultDict[Language, T.List[str]] link_args: T.List[str] - link_depends: T.List[T.Union[str, File, CustomTarget, CustomTargetIndex]] + link_depends: T.List[T.Union[File, BuildTargetTypes]] link_language: Language link_whole: T.List[StaticTargetTypes] link_with: T.List[BuildTargetTypes] name_prefix: T.Optional[str] name_suffix: T.Optional[str] native: MachineChoice - override_options: T.Dict[OptionKey, str] + override_options: T.Dict[str, ElementaryOptionValues] resources: T.List[str] swift_interoperability_mode: Literal['c', 'cpp'] swift_module_name: str @@ -104,7 +107,6 @@ class BuildTargetKeywordArguments(TypedDict, total=False): vala_gir: T.Optional[str] vala_header: T.Optional[str] vala_vapi: T.Optional[str] - win_subsystem: str _allow_no_sources: bool @@ -115,6 +117,7 @@ class ExecutableKeywordArguments(BuildTargetKeywordArguments, total=False): export_dynamic: bool pie: bool vs_module_defs: T.Union[str, File, CustomTarget, CustomTargetIndex] + win_subsystem: str class SharedModuleKeywordArguments(BuildTargetKeywordArguments, total=False): @@ -132,6 +135,13 @@ class StaticLibraryKeywordArguments(BuildTargetKeywordArguments, total=False): pic: bool prelink: bool + class JarKeywordArguments(BuildTargetKeywordArguments, total=False): + + java_args: T.List[str] + java_resources: T.Optional[StructuredSources] + main_class: str + + _T = T.TypeVar('_T') DEFAULT_STATIC_LIBRARY_NAMES: T.Mapping[str, T.Tuple[str, str]] = { @@ -788,7 +798,7 @@ def id(self) -> str: def get_id(self) -> str: return self.id - def get_override(self, name: str) -> T.Optional[str]: + def get_override(self, name: str) -> T.Optional[ElementaryOptionValues]: return self.raw_overrides.get(name, None) def is_linkable_target(self) -> bool: @@ -837,7 +847,7 @@ def __init__( self.link_language: T.Optional[Language] = kwargs.get('link_language') self.link_targets: T.List[BuildTargetTypes] = [] self.link_whole_targets: T.List[StaticTargetTypes] = [] - self.depend_files: T.List[File] = [] + self.depend_files = kwargs.get('depend_files', []) self.link_depends: T.List[T.Union[File, BuildTargetTypes]] = [] self.added_deps = set() self.name_prefix_set = False @@ -896,7 +906,6 @@ def __init__( mlog.warning(f'Build target {name} has no sources. ' 'This was never supposed to be allowed but did because of a bug, ' 'support will be removed in a future release of Meson') - self.check_unknown_kwargs(kwargs) self.validate_install() self.check_module_linking() @@ -952,21 +961,6 @@ def validate_install(self): else: mlog.warning('Installing target build for the build machine. This will fail in a cross build.') - def check_unknown_kwargs(self, kwargs: BuildTargetKeywordArguments) -> None: - # Override this method in derived classes that have more - # keywords. - self.check_unknown_kwargs_int(kwargs, self.known_kwargs) - - def check_unknown_kwargs_int(self, kwargs: BuildTargetKeywordArguments, known_kwargs: T.Set[str]) -> None: - unknowns = [] - for k in kwargs: - if k == 'language_args': - continue - if k not in known_kwargs: - unknowns.append(k) - if len(unknowns) > 0: - mlog.warning('Unknown keyword argument(s) in target {}: {}.'.format(self.name, ', '.join(unknowns))) - def process_objectlist(self, objects): assert isinstance(objects, list) deprecated_non_objects = [] @@ -3187,7 +3181,7 @@ class Jar(BuildTarget): def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice, sources: T.List[SourceOutputs], structured_sources: T.Optional['StructuredSources'], objects, environment: Environment, compilers: CompilerDict, - kwargs): + kwargs: JarKeywordArguments): super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects, environment, compilers, kwargs) for s in self.sources: diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index d18d7f5f280b..55f0ec841c19 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -19,7 +19,7 @@ from .. import mesonlib from ..mesonlib import (EnvironmentVariables, ExecutableSerialisation, MesonBugException, MesonException, HoldableObject, FileMode, MachineChoice, is_parent_path, listify, - extract_as_list, has_path_sep, path_has_root, path_is_in_root, PerMachine) + has_path_sep, path_has_root, path_is_in_root, PerMachine) from ..options import OptionKey from ..programs import ExternalProgram, NonExistingExternalProgram, Program from ..dependencies import Dependency @@ -3189,9 +3189,16 @@ def source_strings_to_files(self, sources: T.List['mesonlib.FileOrString'], stri @T.overload def source_strings_to_files(self, sources: T.List['mesonlib.FileOrString'], strict: bool = False) -> T.List['mesonlib.FileOrString']: ... # noqa: F811 + @T.overload + def source_strings_to_files(self, sources: T.List[T.Union[mesonlib.FileOrString, build.BuildTargetTypes]]) -> T.List[T.Union[mesonlib.File, build.BuildTargetTypes]]: ... + @T.overload def source_strings_to_files(self, sources: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]]) -> T.List[T.Union[mesonlib.File, build.GeneratedTypes]]: ... # noqa: F811 + @T.overload + def source_strings_to_files(self, sources: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes, build.StructuredSources]] + ) -> T.List[T.Union[mesonlib.File, build.GeneratedTypes, build.StructuredSources]]: ... # noqa: F811 + @T.overload def source_strings_to_files(self, sources: T.List['SourceInputs'], strict: bool = True) -> T.List['SourceOutputs']: ... # noqa: F811 @@ -3372,7 +3379,8 @@ def __convert_file_args(self, raw: T.List[mesonlib.FileOrString]) -> T.Tuple[T.L return depend_files, args - def __process_language_args(self, kwargs: T.Dict[str, T.List[mesonlib.FileOrString]]) -> None: + def __process_language_args(self, kwargs: kwtypes.BuildTarget + ) -> T.Tuple[T.DefaultDict[Language, T.List[str]], T.List[mesonlib.File]]: """Convert split language args into a combined dictionary. The Meson DSL takes arguments in the form `_args : args`, but in the @@ -3380,14 +3388,14 @@ def __process_language_args(self, kwargs: T.Dict[str, T.List[mesonlib.FileOrStri This function extracts the arguments from the DSL format and prepares them for the IR. """ - d = kwargs.setdefault('depend_files', []) - new_args: T.DefaultDict[str, T.List[str]] = collections.defaultdict(list) + deps: T.List[mesonlib.File] = [] + new_args: T.DefaultDict[Language, T.List[str]] = collections.defaultdict(list) for l in compilers.all_languages: - deps, args = self.__convert_file_args(kwargs[f'{l}_args']) + deps, args = self.__convert_file_args(kwargs[f'{l}_args']) # type: ignore[literal-required] new_args[l] = args - d.extend(deps) - kwargs['language_args'] = new_args + deps.extend(deps) + return new_args, deps @staticmethod def _handle_rust_abi(abi: T.Optional[Literal['c', 'rust']], @@ -3423,6 +3431,219 @@ def _handle_rust_abi(abi: T.Optional[Literal['c', 'rust']], crate_type = default_rust_type return crate_type + def __convert_build_target_base_kwargs(self, kwargs: kwtypes.BuildTarget, final: build.BuildTargetKeywordArguments) -> None: + """Convert shared arguments for BuildTargets to the Build layer form. + + This takes the raw DSL form, and builds a new dict in the form that the BuildTarget expects + + :param kwargs: The arguments in raw DSL form + :param final: A new dictionary to fill in with the Build layer + :raises InvalidArguments: If one the PCH files doesn't exit + """ + # copy common arguments directly + for arg in ('build_by_default', 'build_rpath', 'build_subdir', 'c_pch', + 'cpp_pch', 'd_debug', 'd_module_versions', 'd_unittest', + 'dependencies', 'gnu_symbol_visibility', 'install', + 'install_mode', 'install_rpath', + 'implicit_include_directories', 'link_args', + 'link_language', 'link_with', 'link_whole', 'name_prefix', + 'name_suffix', 'native', 'resources', 'vala_header', + 'vala_gir', 'vala_vapi', 'swift_interoperability_mode', + 'swift_module_name', 'rust_crate_type', + 'rust_dependency_map', 'override_options'): + final[arg] = kwargs[arg] + + # this is not accessable from the DSL, so we need to initialize it + # ourselves + final['depend_files'] = [] + + # Check for non-existant PCH files + missing: T.List[str] = [] + for each in itertools.chain(kwargs['c_pch'] or [], kwargs['cpp_pch'] or []): + if each is not None: + if not os.path.isfile(os.path.join(self.environment.source_dir, self.subdir, each)): + missing.append(os.path.join(self.subdir, each)) + if missing: + raise InvalidArguments('The following PCH files do not exist: {}'.format(', '.join(missing))) + + # The build layer and interpreter don't agree here, and it's not clear + # that we're hanlding this correctly + final['install_dir'] = kwargs['install_dir'] # type: ignore[typeddict-item] + final['link_depends'] = self.source_strings_to_files(kwargs['link_depends']) + final['install_tag'] = [kwargs['install_tag']] + final['extra_files'] = mesonlib.unique_list(self.source_strings_to_files(kwargs['extra_files'])) + + # Convert into IncludeDirs objects + final['include_directories'] = self.extract_incdirs(kwargs['include_directories']) + final['d_import_dirs'] = self.extract_incdirs(kwargs['d_import_dirs'], True) + + # Convert language arguments + lang_args, deps = self.__process_language_args(kwargs) + final['language_args'] = lang_args + final['depend_files'].extend(deps) + + def __convert_executable_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.Executable) -> build.ExecutableKeywordArguments: + """Convert Executable arguments from DSL form to the build layer form. + + :param node: The Node being evaluated + :param kwargs: The DSL keyword arguments + :raises InvalidArguments: If both gui_app and win_subsystem are set + :raises InvalidArguments: If implib is false and export_dynamic is true + :raises InvalidArguments: If the rust_crate_type is set to anything except bin + :return: The keyword arguments as the Build layer expects + """ + final: build.ExecutableKeywordArguments = {} + self.__convert_build_target_base_kwargs(kwargs, final) + + # Exe exclusive arguments + for exe_arg in ('android_exe_type', 'pie', 'vs_module_defs'): + final[exe_arg] = kwargs[exe_arg] + + # rewrite `gui_app` to `win_subsystem` + if kwargs['gui_app'] is not None: + if kwargs['win_subsystem'] is not None: + raise InvalidArguments.from_node( + 'Executable got both "gui_app", and "win_subsystem" arguments, which are mutually exclusive', + node=node) + final['win_subsystem'] = 'windows' + elif kwargs['win_subsystem'] is not None: + final['win_subsystem'] = kwargs['win_subsystem'] + else: + final['win_subsystem'] = 'console' + + # handle interactions between implib and export_dynamic + if kwargs['implib']: + if kwargs['export_dynamic'] is False: + FeatureDeprecated.single_use( + 'implib overrides explicit export_dynamic off', '1.3.0', self.subproject, + 'Do not set ths if want export_dynamic disabled if implib is enabled', + location=node) + kwargs['export_dynamic'] = True + elif kwargs['export_dynamic']: + if kwargs['implib'] is False: + raise InvalidArguments.from_node( + '"implib" keyword" must not be false if "export_dynamic" is set and not false.', + node=node) + if kwargs['export_dynamic'] is None: + kwargs['export_dynamic'] = False + if isinstance(kwargs['implib'], bool): + final['implib'] = None + else: + final['implib'] = kwargs['implib'] + final['export_dynamic'] = kwargs['export_dynamic'] + + # Handle executable speicific rust_crate_type + if kwargs['rust_crate_type'] not in {None, 'bin'}: + raise InvalidArguments.from_node( + 'Crate type for executable must be "bin"', node=node) + final['rust_crate_type'] = 'bin' + + return final + + def __convert_static_library_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.StaticLibrary) -> build.StaticLibraryKeywordArguments: + """Convert StaticLibrary arguments to the Build format. + + :param node: The Node currently be evaluated. + :param kwargs: The DSL form of the keyword arguments. + :return: The arguments in Build layer format. + """ + final: build.StaticLibraryKeywordArguments = {} + self.__convert_build_target_base_kwargs(kwargs, final) + + for arg in ('pic', 'prelink'): + final[arg] = kwargs[arg] + + for lang in compilers.all_languages - {'java'}: + deps, args = self.__convert_file_args(kwargs.get(f'{lang}_static_args', [])) # type: ignore[arg-type] + final['language_args'][lang].extend(args) + final['depend_files'].extend(deps) + final['rust_crate_type'] = self._handle_rust_abi( + kwargs['rust_abi'], kwargs['rust_crate_type'], 'rlib', 'staticlib', + build.StaticLibrary.typename) + + return final + + def __convert_shared_library_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.SharedLibrary) -> build.SharedLibraryKeywordArguments: + """Convert SharedLibrary arguments to the Build format. + + :param node: The Node currently be evaluated. + :param kwargs: The DSL form of the keyword arguments. + :return: The arguments in Build layer format. + """ + final: build.SharedLibraryKeywordArguments = {} + self.__convert_build_target_base_kwargs(kwargs, final) + + for arg in ('version', 'soversion', 'darwin_versions', 'shortname'): + final[arg] = kwargs[arg] + + for lang in compilers.all_languages - {'java'}: + deps, args = self.__convert_file_args(kwargs.get(f'{lang}_shared_args', [])) # type: ignore[arg-type] + final['language_args'][lang].extend(args) + final['depend_files'].extend(deps) + final['rust_crate_type'] = self._handle_rust_abi( + kwargs['rust_abi'], kwargs['rust_crate_type'], 'dylib', 'cdylib', + build.SharedLibrary.typename, extra_valid_types={'proc-macro'}) + + return final + + def __convert_shared_module_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.SharedModule) -> build.SharedModuleKeywordArguments: + """Convert SharedModule arguments to the Build format. + + :param node: The Node currently be evaluated. + :param kwargs: The DSL form of the keyword arguments. + :return: The arguments in Build layer format. + """ + final: build.SharedModuleKeywordArguments = {} + self.__convert_build_target_base_kwargs(kwargs, final) + + for arg in ('vs_module_defs', ): + final[arg] = kwargs[arg] + + for lang in compilers.all_languages - {'java'}: + deps, args = self.__convert_file_args(kwargs.get(f'{lang}_shared_args', [])) # type: ignore[arg-type] + final['language_args'][lang].extend(args) + final['depend_files'].extend(deps) + final['rust_crate_type'] = self._handle_rust_abi( + kwargs['rust_abi'], kwargs['rust_crate_type'], 'dylib', 'cdylib', + build.SharedModule.typename, extra_valid_types={'proc-macro'}) + + return final + + def __convert_jar_kwargs(self, node: mparser.BaseNode, kwargs: kwtypes.Jar) -> build.JarKeywordArguments: + """Convert Jar arguments to the Build format. + + :param node: The Node currently be evaluated. + :param kwargs: The DSL form of the keyword arguments. + :return: The arguments in Build layer format. + """ + final: build.JarKeywordArguments = {} + + # copy common arguments directly + for arg in ('build_by_default', 'build_subdir', 'dependencies', + 'install', 'install_mode', 'implicit_include_directories', + 'link_with', 'java_args', 'java_resources', 'main_class'): + final[arg] = kwargs[arg] + + # this is not accessable from the DSL, so we need to initialize it + # ourselves + final['depend_files'] = [] + + # The build layer and interpreter don't agree here, and it's not clear + # that we're hanlding this correctly + final['install_dir'] = kwargs['install_dir'] # type: ignore[typeddict-item] + final['install_tag'] = [kwargs['install_tag']] + final['extra_files'] = mesonlib.unique_list(self.source_strings_to_files(kwargs['extra_files'])) + + # Convert into IncludeDirs objects + final['include_directories'] = self.extract_incdirs(kwargs['include_directories']) + + # Convert language arguments + lang_args, deps = self.__process_language_args(kwargs) + final['language_args'] = lang_args + final['depend_files'].extend(deps) + + return final + @T.overload def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Executable, targetclass: T.Type[build.Executable]) -> build.Executable: ... @@ -3451,76 +3672,28 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs mlog.debug('Unknown target type:', str(targetclass)) raise RuntimeError('Unreachable code') - # Because who owns this isn't clear - kwargs = kwargs.copy() - - name, sources = args + name, raw_sources = args for_machine = kwargs['native'] if kwargs.get('rust_crate_type') == 'proc-macro': # Silently force to native because that's the only sensible value # and rust_crate_type is deprecated any way. for_machine = MachineChoice.BUILD # Avoid mutating, since there could be other references to sources - sources = sources + kwargs['sources'] - if any(isinstance(s, build.BuildTarget) for s in sources): + raw_sources = raw_sources + T.cast('SourcesVarargsType', kwargs['sources']) + if any(isinstance(s, build.BuildTarget) for s in raw_sources): FeatureBroken.single_use('passing references to built targets as a source file', '1.1.0', self.subproject, 'Consider using `link_with` or `link_whole` if you meant to link, or dropping them as otherwise they are ignored.', node) - if any(isinstance(s, build.ExtractedObjects) for s in sources): + if any(isinstance(s, build.ExtractedObjects) for s in raw_sources): FeatureBroken.single_use('passing object files as sources', '1.1.0', self.subproject, 'Pass these to the `objects` keyword instead, they are ignored when passed as sources.', node) # Go ahead and drop these here, since they're only allowed through for # backwards compatibility anyway - sources = [s for s in sources - if not isinstance(s, (build.BuildTarget, build.ExtractedObjects))] - sources = self.source_strings_to_files(sources) + self.check_sources_exist(os.path.join(self.source_root, self.subdir), raw_sources) + sources = self.source_strings_to_files([ + s for s in raw_sources if not isinstance(s, (build.BuildTarget, build.ExtractedObjects))]) objs = kwargs['objects'] - kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies') - # TODO: When we can do strings -> Files in the typed_kwargs validator, do this there too - kwargs['extra_files'] = mesonlib.unique_list(self.source_strings_to_files(kwargs['extra_files'])) - self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources) - self.__process_language_args(kwargs) - if targetclass is build.StaticLibrary: - kwargs = T.cast('kwtypes.StaticLibrary', kwargs) - for lang in compilers.all_languages - {'java'}: - deps, args = self.__convert_file_args(kwargs.get(f'{lang}_static_args', [])) - kwargs['language_args'][lang].extend(args) - kwargs['depend_files'].extend(deps) - kwargs['rust_crate_type'] = self._handle_rust_abi( - kwargs['rust_abi'], kwargs['rust_crate_type'], 'rlib', 'staticlib', targetclass.typename) - - elif targetclass is build.SharedLibrary: - kwargs = T.cast('kwtypes.SharedLibrary', kwargs) - for lang in compilers.all_languages - {'java'}: - deps, args = self.__convert_file_args(kwargs.get(f'{lang}_shared_args', [])) - kwargs['language_args'][lang].extend(args) - kwargs['depend_files'].extend(deps) - kwargs['rust_crate_type'] = self._handle_rust_abi( - kwargs['rust_abi'], kwargs['rust_crate_type'], 'dylib', 'cdylib', targetclass.typename, - extra_valid_types={'proc-macro'}) - - elif targetclass is build.Executable: - kwargs = T.cast('kwtypes.Executable', kwargs) - if kwargs['rust_crate_type'] not in {None, 'bin'}: - raise InvalidArguments('Crate type for executable must be "bin"') - kwargs['rust_crate_type'] = 'bin' - - if targetclass is not build.Jar: - self.check_for_jar_sources(sources, targetclass) - kwargs['include_directories'] = self.extract_incdirs(kwargs['include_directories']) - kwargs['d_import_dirs'] = self.extract_incdirs(kwargs['d_import_dirs'], True) - missing: T.List[str] = [] - for each in itertools.chain(kwargs['c_pch'] or [], kwargs['cpp_pch'] or []): - if each is not None: - if not os.path.isfile(os.path.join(self.environment.source_dir, self.subdir, each)): - missing.append(os.path.join(self.subdir, each)) - if missing: - raise InvalidArguments('The following PCH files do not exist: {}'.format(', '.join(missing))) - - # 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 | {'language_args'}} srcs: T.List['SourceInputs'] = [] struct: T.Optional[build.StructuredSources] = build.StructuredSources() @@ -3554,35 +3727,18 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs outputs.update(o) if targetclass is build.Executable: - kwargs = T.cast('kwtypes.Executable', kwargs) - if kwargs['gui_app'] is not None: - if kwargs['win_subsystem'] is not None: - raise InvalidArguments.from_node( - 'Executable got both "gui_app", and "win_subsystem" arguments, which are mutually exclusive', - node=node) - if kwargs['gui_app']: - kwargs['win_subsystem'] = 'windows' - if kwargs['win_subsystem'] is None: - kwargs['win_subsystem'] = 'console' - - if kwargs['implib']: - if kwargs['export_dynamic'] is False: - FeatureDeprecated.single_use('implib overrides explicit export_dynamic off', '1.3.0', self.subproject, - 'Do not set ths if want export_dynamic disabled if implib is enabled', - location=node) - kwargs['export_dynamic'] = True - elif kwargs['export_dynamic']: - if kwargs['implib'] is False: - raise InvalidArguments('"implib" keyword" must not be false if "export_dynamic" is set and not false.') - if kwargs['export_dynamic'] is None: - kwargs['export_dynamic'] = False - if isinstance(kwargs['implib'], bool): - kwargs['implib'] = None - - kwargs['install_tag'] = [kwargs['install_tag']] + nkwargs = self.__convert_executable_kwargs(node, kwargs) + elif targetclass is build.StaticLibrary: + nkwargs = self.__convert_static_library_kwargs(node, kwargs) + elif targetclass is build.SharedLibrary: + nkwargs = self.__convert_shared_library_kwargs(node, kwargs) + elif targetclass is build.SharedModule: + nkwargs = self.__convert_shared_module_kwargs(node, kwargs) + else: + nkwargs = self.__convert_jar_kwargs(node, kwargs) target = targetclass(name, self.subdir, self.subproject, for_machine, srcs, struct, objs, - self.environment, self.compilers[for_machine], kwargs) + self.environment, self.compilers[for_machine], nkwargs) if objs and target.uses_rust(): FeatureNew.single_use('objects in Rust targets', '1.8.0', self.subproject) @@ -3596,7 +3752,7 @@ def add_stdlib_info(self, target): if dep: target.add_deps([dep]) - def check_sources_exist(self, subdir, sources): + def check_sources_exist(self, subdir: str, sources: SourcesVarargsType) -> None: for s in sources: if not isinstance(s, str): continue # This means a generated source and they always exist. diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 402f1afd8fa2..4acf93ae99ea 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -338,16 +338,17 @@ class _BaseBuildTarget(TypedDict): build_by_default: bool build_rpath: str + build_subdir: str dependencies: T.List[Dependency] extra_files: T.List[FileOrString] gnu_symbol_visibility: str - include_directories: T.List[build.IncludeDirs] + include_directories: T.List[T.Union[str, build.IncludeDirs]] install: bool install_mode: FileMode install_tag: T.Optional[str] install_rpath: str implicit_include_directories: bool - link_depends: T.List[T.Union[str, File, build.GeneratedTypes]] + link_depends: T.List[T.Union[str, File, build.BuildTargetTypes]] link_language: T.Optional[Language] link_whole: T.List[build.StaticTargetTypes] link_with: T.List[build.BuildTargetTypes] @@ -363,7 +364,7 @@ class _BaseBuildTarget(TypedDict): vala_gir: T.Optional[str] -class _BuildTarget(_BaseBuildTarget): +class BuildTarget(_BaseBuildTarget): """Arguments shared by non-JAR functions""" @@ -378,8 +379,8 @@ class _BuildTarget(_BaseBuildTarget): swift_module_name: str sources: SourcesVarargsType link_args: T.List[str] - c_pch: T.List[str] - cpp_pch: T.List[str] + c_pch: T.Optional[T.Tuple[str, T.Optional[str]]] + cpp_pch: T.Optional[T.Tuple[str, T.Optional[str]]] c_args: T.List[str] cpp_args: T.List[str] cuda_args: T.List[str] @@ -401,7 +402,7 @@ class _LibraryMixin(TypedDict): rust_abi: T.Optional[RustAbi] -class Executable(_BuildTarget): +class Executable(BuildTarget): export_dynamic: T.Optional[bool] gui_app: T.Optional[bool] @@ -418,7 +419,7 @@ class _StaticLibMixin(TypedDict): pic: T.Optional[bool] -class StaticLibrary(_BuildTarget, _StaticLibMixin, _LibraryMixin): +class StaticLibrary(BuildTarget, _StaticLibMixin, _LibraryMixin): pass @@ -428,18 +429,19 @@ class _SharedLibMixin(TypedDict): soversion: T.Optional[str] version: T.Optional[str] vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex]] + shortname: str -class SharedLibrary(_BuildTarget, _SharedLibMixin, _LibraryMixin): +class SharedLibrary(BuildTarget, _SharedLibMixin, _LibraryMixin): pass -class SharedModule(_BuildTarget, _LibraryMixin): +class SharedModule(BuildTarget, _LibraryMixin): vs_module_defs: T.Optional[T.Union[str, File, build.CustomTarget, build.CustomTargetIndex]] -class Library(_BuildTarget, _SharedLibMixin, _StaticLibMixin, _LibraryMixin): +class Library(BuildTarget, _SharedLibMixin, _StaticLibMixin, _LibraryMixin): """For library, both_library, and as a base for build_target""" diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 04abe09506ab..a15b08bc2621 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -988,6 +988,7 @@ def _shortname_validator(shortname: T.Optional[str]) -> T.Optional[str]: *_EXCLUSIVE_STATIC_LIB_KWS, *EXCLUSIVE_EXECUTABLE_KWS, *_SHARED_STATIC_ARGS, + _VS_MODULE_DEFS_KW, RUST_ABI_KW.evolve(since='1.10.0'), *[a.evolve(deprecated='1.3.0', deprecated_message='The use of "jar" in "build_target()" is deprecated, and this argument is only used by jar()') for a in _EXCLUSIVE_JAR_KWS],