diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index bbc92fc2582c..0fb9edef748b 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -105,3 +105,32 @@ were never turned on by Meson. [properties] bindgen_clang_arguments = ['--target', 'x86_64-linux-gnu'] ``` + +### proc_macro() + +```meson +rustmod.proc_macro(name, sources, ...) +``` + +*Since 1.3.0* + +This function creates a Rust `proc-macro` crate, similar to: +```meson +[[shared_library]](name, sources, + rust_crate_type: 'proc-macro', + native: true) +``` + +`proc-macro` targets can be passed to `link_with` keyword argument of other Rust +targets. + +Only a subset of [[shared_library]] keyword arguments are allowed: +- rust_args +- rust_dependency_map +- sources +- dependencies +- extra_files +- link_args +- link_depends +- link_with +- override_options diff --git a/docs/markdown/snippets/rust_crate_type.md b/docs/markdown/snippets/rust_crate_type.md new file mode 100644 index 000000000000..9b32f0ee86f2 --- /dev/null +++ b/docs/markdown/snippets/rust_crate_type.md @@ -0,0 +1,11 @@ +## Deprecated `rust_crate_type` and replaced by `rust_abi` + +The new `rust_abi` keyword argument is accepted by [[shared_library]], +[[static_library]], [[library]] and [[shared_module]] functions. It can be either +`'rust'` (the default) or `'c'` strings. + +`rust_crate_type` is now deprecated because Meson already knows if it's a shared +or static library, user only need to specify the ABI (Rust or C). + +`proc_macro` crates are now handled by the [`rust.proc_macro()`](Rust-module.md#proc_macro) +method. diff --git a/docs/yaml/functions/_build_target_base.yaml b/docs/yaml/functions/_build_target_base.yaml index 724b6a4ece12..3f0e88158c36 100644 --- a/docs/yaml/functions/_build_target_base.yaml +++ b/docs/yaml/functions/_build_target_base.yaml @@ -289,6 +289,7 @@ kwargs: rust_crate_type: type: str since: 0.42.0 + deprecated: 1.3.0 description: | Set the specific type of rust crate to compile (when compiling rust). @@ -306,6 +307,10 @@ kwargs: "proc-macro" is new in 0.62.0. + *Since 1.3.0* this is deprecated and replaced by "rust_abi" keyword argument. + `proc_macro` crates are now handled by the [`rust.proc_macro()`](Rust-module.md#proc_macro) + method. + rust_dependency_map: type: dict[str] since: 1.2.0 diff --git a/docs/yaml/functions/library.yaml b/docs/yaml/functions/library.yaml index f10ef8e88c84..f9e336b9b808 100644 --- a/docs/yaml/functions/library.yaml +++ b/docs/yaml/functions/library.yaml @@ -21,3 +21,14 @@ varargs_inherit: _build_target_base kwargs_inherit: - shared_library - static_library + +kwargs: + rust_abi: + type: str + since: 1.3.0 + description: | + Set the specific ABI to compile (when compiling rust). + - 'rust' (default): Create a "rlib" or "dylib" crate depending on the library + type being build. + - 'c': Create a "cdylib" or "staticlib" crate depending on the library + type being build. diff --git a/docs/yaml/functions/shared_library.yaml b/docs/yaml/functions/shared_library.yaml index 956fb2cb2ce1..5076b9341b2a 100644 --- a/docs/yaml/functions/shared_library.yaml +++ b/docs/yaml/functions/shared_library.yaml @@ -44,3 +44,11 @@ kwargs: description: | Specify a Microsoft module definition file for controlling symbol exports, etc., on platforms where that is possible (e.g. Windows). + + rust_abi: + type: str + since: 1.3.0 + description: | + Set the specific ABI to compile (when compiling rust). + - 'rust' (default): Create a "dylib" crate. + - 'c': Create a "cdylib" crate. diff --git a/docs/yaml/functions/shared_module.yaml b/docs/yaml/functions/shared_module.yaml index 20bd5c48802c..46086ba3096d 100644 --- a/docs/yaml/functions/shared_module.yaml +++ b/docs/yaml/functions/shared_module.yaml @@ -39,3 +39,11 @@ kwargs: description: | Specify a Microsoft module definition file for controlling symbol exports, etc., on platforms where that is possible (e.g. Windows). + + rust_abi: + type: str + since: 1.3.0 + description: | + Set the specific ABI to compile (when compiling rust). + - 'rust' (default): Create a "dylib" crate. + - 'c': Create a "cdylib" crate. diff --git a/docs/yaml/functions/static_library.yaml b/docs/yaml/functions/static_library.yaml index 1d42d600a4b6..615baa229976 100644 --- a/docs/yaml/functions/static_library.yaml +++ b/docs/yaml/functions/static_library.yaml @@ -23,3 +23,11 @@ kwargs: If `true` the object files in the target will be prelinked, meaning that it will contain only one prelinked object file rather than the individual object files. + + rust_abi: + type: str + since: 1.3.0 + description: | + Set the specific ABI to compile (when compiling rust). + - 'rust' (default): Create a "rlib" crate. + - 'c': Create a "staticlib" crate. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 491f2a63d834..3d3eefdcc733 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1937,16 +1937,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: if main_rust_file is None: raise RuntimeError('A Rust target has no Rust sources. This is weird. Also a bug. Please report') target_name = os.path.join(target.subdir, target.get_filename()) - if isinstance(target, build.Executable): - cratetype = 'bin' - elif hasattr(target, 'rust_crate_type'): - cratetype = target.rust_crate_type - elif isinstance(target, build.SharedLibrary): - cratetype = 'dylib' - elif isinstance(target, build.StaticLibrary): - cratetype = 'rlib' - else: - raise InvalidArguments('Unknown target type for rustc.') + cratetype = target.rust_crate_type args.extend(['--crate-type', cratetype]) # If we're dynamically linking, add those arguments @@ -1960,10 +1951,9 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: # Rustc replaces - with _. spaces or dots are not allowed, so we replace them with underscores args += ['--crate-name', target.name.replace('-', '_').replace(' ', '_').replace('.', '_')] depfile = os.path.join(target.subdir, target.name + '.d') - args += ['--emit', f'dep-info={depfile}', '--emit', 'link'] + args += ['--emit', f'dep-info={depfile}', '--emit', f'link={target_name}'] + args += ['--out-dir', self.get_target_private_dir(target)] args += target.get_extra_args('rust') - output = rustc.get_output_args(os.path.join(target.subdir, target.get_filename())) - args += output linkdirs = mesonlib.OrderedSet() external_deps = target.external_deps.copy() diff --git a/mesonbuild/build.py b/mesonbuild/build.py index fece0bebc8e2..c58447b55db8 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -115,9 +115,9 @@ cs_kwargs) known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie'} -known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'} -known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs'} -known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink'} +known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions', 'rust_abi'} +known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs', 'rust_abi'} +known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink', 'rust_abi'} known_jar_kwargs = known_exe_kwargs | {'main_class', 'java_resources'} def _process_install_tag(install_tag: T.Optional[T.List[T.Optional[str]]], @@ -1408,12 +1408,7 @@ def link(self, targets): msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) - if self.for_machine is not t.for_machine: - msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' - if self.environment.is_cross_build(): - raise InvalidArguments(msg + ' This is not possible in a cross build.') - else: - mlog.warning(msg + ' This will fail in cross build.') + self.check_can_link_together(t) self.link_targets.append(t) def link_whole(self, targets, promoted: bool = False): @@ -1429,12 +1424,7 @@ def link_whole(self, targets, promoted: bool = False): msg = f"Can't link non-PIC static library {t.name!r} into shared library {self.name!r}. " msg += "Use the 'pic' option to static_library to build with PIC." raise InvalidArguments(msg) - if self.for_machine is not t.for_machine: - msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' - if self.environment.is_cross_build(): - raise InvalidArguments(msg + ' This is not possible in a cross build.') - else: - mlog.warning(msg + ' This will fail in cross build.') + self.check_can_link_together(t) if isinstance(self, StaticLibrary) and not self.uses_rust(): # When we're a static library and we link_whole: to another static # library, we need to add that target's objects to ourselves. @@ -1480,6 +1470,17 @@ def check_can_extract_objects(self, t: T.Union[Target, CustomTargetIndex], origi f' and thus has to include objects from {t.name!r} to be usable.') raise InvalidArguments(m) + def check_can_link_together(self, t: BuildTargetTypes) -> None: + links_with_rust_abi = isinstance(t, BuildTarget) and t.uses_rust_abi() + if not self.uses_rust() and links_with_rust_abi: + raise InvalidArguments(f'Try to link Rust ABI library {t.name!r} with a non-Rust target {self.name!r}') + if self.for_machine is not t.for_machine and (not links_with_rust_abi or t.rust_crate_type != 'proc-macro'): + msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}' + if self.environment.is_cross_build(): + raise InvalidArguments(msg + ' This is not possible in a cross build.') + else: + mlog.warning(msg + ' This will fail in cross build.') + def add_pch(self, language: str, pchlist: T.List[str]) -> None: if not pchlist: return @@ -1645,6 +1646,9 @@ def get_used_stdlib_args(self, link_language: str) -> T.List[str]: def uses_rust(self) -> bool: return 'rust' in self.compilers + def uses_rust_abi(self) -> bool: + return self.uses_rust() and self.rust_crate_type in {'dylib', 'rlib', 'proc-macro'} + def uses_fortran(self) -> bool: return 'fortran' in self.compilers @@ -1980,6 +1984,13 @@ def post_init(self) -> None: if create_debug_file: self.debug_filename = self.name + '.pdb' + def process_kwargs(self, kwargs): + super().process_kwargs(kwargs) + + self.rust_crate_type = kwargs.get('rust_crate_type') or 'bin' + if self.rust_crate_type != 'bin': + raise InvalidArguments('Invalid rust_crate_type: must be "bin" for executables.') + def get_default_install_dir(self) -> T.Tuple[str, str]: return self.environment.get_bindir(), '{bindir}' @@ -2052,18 +2063,12 @@ def post_init(self) -> None: super().post_init() if 'cs' in self.compilers: raise InvalidArguments('Static libraries not supported for C#.') - if 'rust' in self.compilers: - # If no crate type is specified, or it's the generic lib type, use rlib - if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib': - mlog.debug('Defaulting Rust static library target crate type to rlib') - self.rust_crate_type = 'rlib' - # Don't let configuration proceed with a non-static crate type - elif self.rust_crate_type not in ['rlib', 'staticlib']: - raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for static libraries; must be "rlib" or "staticlib"') + if self.uses_rust(): # See https://github.com/rust-lang/rust/issues/110460 if self.rust_crate_type == 'rlib' and any(c in self.name for c in ['-', ' ', '.']): - raise InvalidArguments('Rust crate type "rlib" does not allow spaces, periods or dashes in the library name ' - 'due to a limitation of rustc. Replace them with underscores, for example') + raise InvalidArguments(f'Rust crate {self.name} type {self.rust_crate_type} does not allow spaces, ' + 'periods or dashes in the library name due to a limitation of rustc. ' + 'Replace them with underscores, for example') if self.rust_crate_type == 'staticlib': # FIXME: In the case of no-std we should not add those libraries, # but we have no way to know currently. @@ -2085,8 +2090,8 @@ def post_init(self) -> None: if not hasattr(self, 'prefix'): self.prefix = 'lib' if not hasattr(self, 'suffix'): - if 'rust' in self.compilers: - if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'rlib': + if self.uses_rust(): + if self.rust_crate_type == 'rlib': # default Rust static library suffix self.suffix = 'rlib' elif self.rust_crate_type == 'staticlib': @@ -2107,12 +2112,20 @@ def type_suffix(self): def process_kwargs(self, kwargs): super().process_kwargs(kwargs) - if 'rust_crate_type' in kwargs: - rust_crate_type = kwargs['rust_crate_type'] - if isinstance(rust_crate_type, str): + + rust_abi = kwargs.get('rust_abi') + rust_crate_type = kwargs.get('rust_crate_type') + if rust_crate_type: + if rust_abi: + raise InvalidArguments('rust_abi and rust_crate_type are mutually exclusive.') + if rust_crate_type == 'lib': + self.rust_crate_type = 'rlib' + elif rust_crate_type in {'rlib', 'staticlib'}: self.rust_crate_type = rust_crate_type else: - raise InvalidArguments(f'Invalid rust_crate_type "{rust_crate_type}": must be a string.') + raise InvalidArguments(f'Crate type {rust_crate_type!r} invalid for static libraries; must be "rlib" or "staticlib"') + else: + self.rust_crate_type = 'staticlib' if rust_abi == 'c' else 'rlib' def is_linkable_target(self): return True @@ -2153,18 +2166,12 @@ def __init__( def post_init(self) -> None: super().post_init() - if 'rust' in self.compilers: - # If no crate type is specified, or it's the generic lib type, use dylib - if not hasattr(self, 'rust_crate_type') or self.rust_crate_type == 'lib': - mlog.debug('Defaulting Rust dynamic library target crate type to "dylib"') - self.rust_crate_type = 'dylib' - # Don't let configuration proceed with a non-dynamic crate type - elif self.rust_crate_type not in ['dylib', 'cdylib', 'proc-macro']: - raise InvalidArguments(f'Crate type "{self.rust_crate_type}" invalid for dynamic libraries; must be "dylib", "cdylib", or "proc-macro"') + if self.uses_rust(): # See https://github.com/rust-lang/rust/issues/110460 if self.rust_crate_type != 'cdylib' and any(c in self.name for c in ['-', ' ', '.']): - raise InvalidArguments('Rust crate types "dylib" and "proc-macro" do not allow spaces, periods or dashes in the library name ' - 'due to a limitation of rustc. Replace them with underscores, for example') + raise InvalidArguments(f'Rust crate {self.name} type {self.rust_crate_type} does not allow spaces, ' + 'periods or dashes in the library name due to a limitation of rustc. ' + 'Replace them with underscores, for example') if not hasattr(self, 'prefix'): self.prefix = None @@ -2335,14 +2342,19 @@ def process_kwargs(self, kwargs): 'a file object or a Custom Target') self.process_link_depends(path) - if 'rust_crate_type' in kwargs: - rust_crate_type = kwargs['rust_crate_type'] - if isinstance(rust_crate_type, str): + rust_abi = kwargs.get('rust_abi') + rust_crate_type = kwargs.get('rust_crate_type') + if rust_crate_type: + if rust_abi: + raise InvalidArguments('rust_abi and rust_crate_type are mutually exclusive.') + if rust_crate_type == 'lib': + self.rust_crate_type = 'dylib' + elif rust_crate_type in {'dylib', 'cdylib', 'proc-macro'}: self.rust_crate_type = rust_crate_type else: - raise InvalidArguments(f'Invalid rust_crate_type "{rust_crate_type}": must be a string.') - if rust_crate_type == 'proc-macro': - FeatureNew.single_use('Rust crate type "proc-macro"', '0.62.0', self.subproject) + raise InvalidArguments(f'Crate type {rust_crate_type!r} invalid for shared libraries; must be "dylib", "cdylib" or "proc-macro"') + else: + self.rust_crate_type = 'cdylib' if rust_abi == 'c' else 'dylib' def get_import_filename(self) -> T.Optional[str]: """ diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index d722039d1ba2..b5e6a6a0c5a7 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -18,8 +18,8 @@ import re import typing as T -from .. import coredata, mlog -from ..mesonlib import EnvironmentException, MesonException, Popen_safe, OptionKey, join_args +from .. import coredata +from ..mesonlib import EnvironmentException, MesonException, Popen_safe_logged, OptionKey from .compilers import Compiler, rust_buildtype_args, clike_debug_args if T.TYPE_CHECKING: @@ -82,13 +82,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: ''')) cmdlist = self.exelist + ['-o', output_name, source_name] - pc, stdo, stde = Popen_safe(cmdlist, cwd=work_dir) - mlog.debug('Sanity check compiler command line:', join_args(cmdlist)) - mlog.debug('Sanity check compile stdout:') - mlog.debug(stdo) - mlog.debug('-----\nSanity check compile stderr:') - mlog.debug(stde) - mlog.debug('-----') + pc, stdo, stde = Popen_safe_logged(cmdlist, cwd=work_dir) if pc.returncode != 0: raise EnvironmentException(f'Rust compiler {self.name_string()} cannot compile programs.') if self.is_cross: @@ -104,7 +98,7 @@ def sanity_check(self, work_dir: str, environment: 'Environment') -> None: raise EnvironmentException(f'Executables created by Rust compiler {self.name_string()} are not runnable.') # Get libraries needed to link with a Rust staticlib cmdlist = self.exelist + ['--crate-type', 'staticlib', '--print', 'native-static-libs', source_name] - p, stdo, stde = Popen_safe(cmdlist, cwd=work_dir) + p, stdo, stde = Popen_safe_logged(cmdlist, cwd=work_dir) if p.returncode == 0: match = re.search('native-static-libs: (.*)$', stde, re.MULTILINE) if match: @@ -123,7 +117,7 @@ def get_buildtype_args(self, buildtype: str) -> T.List[str]: def get_sysroot(self) -> str: cmd = self.get_exelist(ccache=False) + ['--print', 'sysroot'] - p, stdo, stde = Popen_safe(cmd) + p, stdo, stde = Popen_safe_logged(cmd) return stdo.split('\n', maxsplit=1)[0] def get_debug_args(self, is_debug: bool) -> T.List[str]: diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 6fcefd14d6c8..a5c8a5a2d4aa 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -90,6 +90,7 @@ SHARED_LIB_KWS, SHARED_MOD_KWS, SOURCES_KW, + SOURCES_VARARGS, STATIC_LIB_KWS, VARIABLES_KW, TEST_KWS, @@ -121,6 +122,7 @@ from ..backend.backends import Backend from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs from ..programs import OverrideProgram + from .type_checking import SourcesVarargsType # Input source types passed to Targets SourceInputs = T.Union[mesonlib.File, build.GeneratedList, build.BuildTarget, build.BothLibraries, @@ -1446,23 +1448,28 @@ def func_debug(self, node, args, kwargs): def func_exception(self, node, args, kwargs): raise RuntimeError('unit test traceback :)') - @noKwargs @typed_pos_args('expect_error', str) + @typed_kwargs( + 'expect_error', + KwargInfo('how', str, default='literal', validator=in_set_validator({'literal', 're'})), + ) def func_expect_error(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs: TYPE_kwargs) -> ContextManagerObject: class ExpectErrorObject(ContextManagerObject): - def __init__(self, msg: str, subproject: str) -> None: + def __init__(self, msg: str, how: str, subproject: str) -> None: super().__init__(subproject) self.msg = msg + self.how = how def __exit__(self, exc_type, exc_val, exc_tb): if exc_val is None: raise InterpreterException('Expecting an error but code block succeeded') if isinstance(exc_val, mesonlib.MesonException): msg = str(exc_val) - if msg != self.msg: + if (self.how == 'literal' and self.msg != msg) or \ + (self.how == 're' and not re.match(self.msg, msg)): raise InterpreterException(f'Expecting error {self.msg!r} but got {msg!r}') return True - return ExpectErrorObject(args[0], self.subproject) + return ExpectErrorObject(args[0], kwargs['how'], self.subproject) def add_languages(self, args: T.List[str], required: bool, for_machine: MachineChoice) -> bool: success = self.add_languages_for(args, required, for_machine) @@ -1815,58 +1822,58 @@ def func_disabler(self, node, args, kwargs): @FeatureNewKwargs('executable', '0.42.0', ['implib']) @permittedKwargs(build.known_exe_kwargs) - @typed_pos_args('executable', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('executable', str, varargs=SOURCES_VARARGS) @typed_kwargs('executable', *EXECUTABLE_KWS, allow_unknown=True) def func_executable(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Executable) -> build.Executable: return self.build_target(node, args, kwargs, build.Executable) @permittedKwargs(build.known_stlib_kwargs) - @typed_pos_args('static_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('static_library', str, varargs=SOURCES_VARARGS) @typed_kwargs('static_library', *STATIC_LIB_KWS, allow_unknown=True) def func_static_lib(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.StaticLibrary) -> build.StaticLibrary: return self.build_target(node, args, kwargs, build.StaticLibrary) @permittedKwargs(build.known_shlib_kwargs) - @typed_pos_args('shared_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('shared_library', str, varargs=SOURCES_VARARGS) @typed_kwargs('shared_library', *SHARED_LIB_KWS, allow_unknown=True) def func_shared_lib(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.SharedLibrary) -> build.SharedLibrary: holder = self.build_target(node, args, kwargs, build.SharedLibrary) holder.shared_library_only = True return holder @permittedKwargs(known_library_kwargs) - @typed_pos_args('both_libraries', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('both_libraries', str, varargs=SOURCES_VARARGS) @typed_kwargs('both_libraries', *LIBRARY_KWS, allow_unknown=True) def func_both_lib(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.BothLibraries: return self.build_both_libraries(node, args, kwargs) @FeatureNew('shared_module', '0.37.0') @permittedKwargs(build.known_shmod_kwargs) - @typed_pos_args('shared_module', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('shared_module', str, varargs=SOURCES_VARARGS) @typed_kwargs('shared_module', *SHARED_MOD_KWS, allow_unknown=True) def func_shared_module(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.SharedModule) -> build.SharedModule: return self.build_target(node, args, kwargs, build.SharedModule) @permittedKwargs(known_library_kwargs) - @typed_pos_args('library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('library', str, varargs=SOURCES_VARARGS) @typed_kwargs('library', *LIBRARY_KWS, allow_unknown=True) def func_library(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.Executable: return self.build_library(node, args, kwargs) @permittedKwargs(build.known_jar_kwargs) - @typed_pos_args('jar', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('jar', str, varargs=SOURCES_VARARGS) @typed_kwargs('jar', *JAR_KWS, allow_unknown=True) def func_jar(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[str, mesonlib.File, build.GeneratedTypes]]], @@ -1875,10 +1882,10 @@ def func_jar(self, node: mparser.BaseNode, @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options']) @permittedKwargs(known_build_target_kwargs) - @typed_pos_args('build_target', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_pos_args('build_target', str, varargs=SOURCES_VARARGS) @typed_kwargs('build_target', *BUILD_TARGET_KWS, allow_unknown=True) def func_build_target(self, node: mparser.BaseNode, - args: T.Tuple[str, T.List[BuildTargetSource]], + args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.BuildTarget ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, build.SharedModule, build.BothLibraries, build.Jar]: @@ -3199,6 +3206,10 @@ def build_both_libraries(self, node, args, kwargs): # Feel free to submit patches to get this fixed if it is an # issue for you. reuse_object_files = False + elif shared_lib.uses_rust(): + # FIXME: rustc supports generating both libraries in a single invocation, + # but for now compile twice. + reuse_object_files = False else: reuse_object_files = static_lib.pic @@ -3240,6 +3251,10 @@ def build_target_decorator_caller(self, node, args, kwargs): name, sources = args for_machine = self.machine_from_native_kwarg(kwargs) + 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 if 'sources' in kwargs: sources += listify(kwargs['sources']) if any(isinstance(s, build.BuildTarget) for s in sources): diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 645b27363024..9a1904d57cb1 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -30,6 +30,7 @@ _FullEnvInitValueType = T.Union[EnvironmentVariables, T.List[str], T.List[T.List[str]], EnvInitValueType, str, None] PkgConfigDefineType = T.Optional[T.Tuple[str, str]] + SourcesVarargsType = T.List[T.Union[str, File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget]] def in_set_validator(choices: T.Set[str]) -> T.Callable[[str], T.Optional[str]]: @@ -464,6 +465,8 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus default=[], ) +SOURCES_VARARGS = (str, File, CustomTarget, CustomTargetIndex, GeneratedList, StructuredSources, ExtractedObjects, BuildTarget) + VARIABLES_KW: KwargInfo[T.Dict[str, str]] = KwargInfo( 'variables', # str is listified by validator/convertor, cannot use listify=True here because @@ -495,6 +498,21 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus KwargInfo('verbose', bool, default=False, since='0.62.0'), ] +# Cannot have a default value because we need to check that rust_crate_type and +# rust_abi are mutually exclusive. +RUST_CRATE_TYPE_KW: KwargInfo[T.Union[str, None]] = KwargInfo( + 'rust_crate_type', (str, NoneType), + since='0.42.0', + since_values={'proc-macro': '0.62.0'}, + deprecated='1.3.0', + deprecated_message='Use rust_abi or rust.proc_macro() instead.', + validator=in_set_validator({'bin', 'lib', 'rlib', 'dylib', 'cdylib', 'staticlib', 'proc-macro'})) + +RUST_ABI_KW: KwargInfo[T.Union[str, None]] = KwargInfo( + 'rust_abi', (str, NoneType), + since='1.3.0', + validator=in_set_validator({'rust', 'c'})) + # Applies to all build_target like classes _ALL_TARGET_KWS: T.List[KwargInfo] = [ OVERRIDE_OPTIONS_KW, @@ -503,6 +521,7 @@ def link_whole_validator(values: T.List[T.Union[StaticLibrary, CustomTarget, Cus # Applies to all build_target classes except jar _BUILD_TARGET_KWS: T.List[KwargInfo] = [ *_ALL_TARGET_KWS, + RUST_CRATE_TYPE_KW, ] def _validate_win_subsystem(value: T.Optional[str]) -> T.Optional[str]: @@ -572,6 +591,11 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup *_EXCLUSIVE_EXECUTABLE_KWS, ] +# Arguments exclusive to library types +_EXCLUSIVE_LIB_KWS: T.List[KwargInfo] = [ + RUST_ABI_KW, +] + # Arguments exclusive to StaticLibrary. These are separated to make integrating # them into build_target easier _EXCLUSIVE_STATIC_LIB_KWS: T.List[KwargInfo] = [] @@ -580,6 +604,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup STATIC_LIB_KWS = [ *_BUILD_TARGET_KWS, *_EXCLUSIVE_STATIC_LIB_KWS, + *_EXCLUSIVE_LIB_KWS, ] # Arguments exclusive to SharedLibrary. These are separated to make integrating @@ -594,6 +619,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup SHARED_LIB_KWS = [ *_BUILD_TARGET_KWS, *_EXCLUSIVE_SHARED_LIB_KWS, + *_EXCLUSIVE_LIB_KWS, ] # Arguments exclusive to SharedModule. These are separated to make integrating @@ -604,6 +630,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup SHARED_MOD_KWS = [ *_BUILD_TARGET_KWS, *_EXCLUSIVE_SHARED_MOD_KWS, + *_EXCLUSIVE_LIB_KWS, ] # Arguments exclusive to JAR. These are separated to make integrating @@ -622,6 +649,7 @@ def _convert_darwin_versions(val: T.List[T.Union[str, int]]) -> T.Optional[T.Tup # Arguments used by both_library and library LIBRARY_KWS = [ *_BUILD_TARGET_KWS, + *_EXCLUSIVE_LIB_KWS, *_EXCLUSIVE_SHARED_LIB_KWS, *_EXCLUSIVE_SHARED_MOD_KWS, *_EXCLUSIVE_STATIC_LIB_KWS, diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 0bda2c250bce..b6dd731491cc 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -15,13 +15,15 @@ import os import typing as T +from mesonbuild.interpreterbase.decorators import FeatureNew from . import ExtensionModule, ModuleReturnValue, ModuleInfo from .. import mlog -from ..build import BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, CustomTarget, InvalidArguments, Jar, StructuredSources +from ..build import (BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, + CustomTarget, InvalidArguments, Jar, StructuredSources, SharedLibrary) from ..compilers.compilers import are_asserts_disabled -from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES -from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs +from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, SHARED_LIB_KWS, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES, SOURCES_VARARGS +from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs from ..mesonlib import File if T.TYPE_CHECKING: @@ -32,6 +34,7 @@ from ..interpreter import kwargs as _kwargs from ..interpreter.interpreter import SourceInputs, SourceOutputs from ..programs import ExternalProgram, OverrideProgram + from ..interpreter.type_checking import SourcesVarargsType from typing_extensions import TypedDict @@ -64,6 +67,7 @@ def __init__(self, interpreter: Interpreter) -> None: self.methods.update({ 'test': self.test, 'bindgen': self.bindgen, + 'proc_macro': self.proc_macro, }) @typed_pos_args('rust.test', str, BuildTarget) @@ -268,6 +272,19 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu return ModuleReturnValue([target], [target]) + # Allow a limited set of kwargs, but still use the full set of typed_kwargs() + # because it could be setting required default values. + @FeatureNew('rust.proc_macro', '1.3.0') + @permittedKwargs({'rust_args', 'rust_dependency_map', 'sources', 'dependencies', 'extra_files', + 'link_args', 'link_depends', 'link_with', 'override_options'}) + @typed_pos_args('rust.proc_macro', str, varargs=SOURCES_VARARGS) + @typed_kwargs('rust.proc_macro', *SHARED_LIB_KWS, allow_unknown=True) + def proc_macro(self, state: ModuleState, args: T.Tuple[str, SourcesVarargsType], kwargs: T.Dict) -> SharedLibrary: + kwargs['native'] = True + kwargs['rust_crate_type'] = 'proc-macro' + target = state._interpreter.build_target(state.current_node, args, kwargs, SharedLibrary) + return T.cast('SharedLibrary', target) + def initialize(interp: Interpreter) -> RustModule: return RustModule(interp) diff --git a/test cases/failing/53 wrong shared crate type/foo.rs b/test cases/failing/53 wrong shared crate type/foo.rs deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/test cases/failing/53 wrong shared crate type/meson.build b/test cases/failing/53 wrong shared crate type/meson.build deleted file mode 100644 index 90020faf854b..000000000000 --- a/test cases/failing/53 wrong shared crate type/meson.build +++ /dev/null @@ -1,7 +0,0 @@ -project('test') - -if not add_languages('rust', required: false) - error('MESON_SKIP_TEST test requires rust compiler') -endif - -shared_library('mytest', 'foo.rs', rust_crate_type : 'staticlib') diff --git a/test cases/failing/53 wrong shared crate type/test.json b/test cases/failing/53 wrong shared crate type/test.json deleted file mode 100644 index 5faaece2b664..000000000000 --- a/test cases/failing/53 wrong shared crate type/test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "stdout": [ - { - "line": "test cases/failing/53 wrong shared crate type/meson.build:7:0: ERROR: Crate type \"staticlib\" invalid for dynamic libraries; must be \"dylib\", \"cdylib\", or \"proc-macro\"" - } - ] -} diff --git a/test cases/failing/54 wrong static crate type/foo.rs b/test cases/failing/54 wrong static crate type/foo.rs deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/test cases/failing/54 wrong static crate type/meson.build b/test cases/failing/54 wrong static crate type/meson.build deleted file mode 100644 index 179d7cd5365f..000000000000 --- a/test cases/failing/54 wrong static crate type/meson.build +++ /dev/null @@ -1,7 +0,0 @@ -project('test') - -if not add_languages('rust', required: false) - error('MESON_SKIP_TEST test requires rust compiler') -endif - -static_library('mytest', 'foo.rs', rust_crate_type : 'cdylib') diff --git a/test cases/failing/54 wrong static crate type/test.json b/test cases/failing/54 wrong static crate type/test.json deleted file mode 100644 index 83ae5e1b60bb..000000000000 --- a/test cases/failing/54 wrong static crate type/test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "stdout": [ - { - "line": "test cases/failing/54 wrong static crate type/meson.build:7:0: ERROR: Crate type \"cdylib\" invalid for static libraries; must be \"rlib\" or \"staticlib\"" - } - ] -} diff --git a/test cases/rust/18 proc-macro/meson.build b/test cases/rust/18 proc-macro/meson.build index 2958df1af6c1..c5f0dfc82aee 100644 --- a/test cases/rust/18 proc-macro/meson.build +++ b/test cases/rust/18 proc-macro/meson.build @@ -18,3 +18,16 @@ main = executable( ) test('main_test', main) + +rust = import('rust') + +pm = rust.proc_macro('proc_macro_examples2', 'proc.rs') + +main = executable( + 'main2', + 'use.rs', + link_with : pm, + rust_dependency_map : {'proc_macro_examples2' : 'proc_macro_examples'} +) + +test('main_test2', main) diff --git a/test cases/rust/4 polyglot/meson.build b/test cases/rust/4 polyglot/meson.build index 3601d5ed84d5..b2fd8f913a61 100644 --- a/test cases/rust/4 polyglot/meson.build +++ b/test cases/rust/4 polyglot/meson.build @@ -4,6 +4,52 @@ if host_machine.system() == 'darwin' error('MESON_SKIP_TEST: does not work right on macos, please fix!') endif -l = shared_library('stuff', 'stuff.rs', rust_crate_type: 'cdylib', install : true) -e = executable('prog', 'prog.c', link_with : l, install : true) -test('polyglottest', e) +cc = meson.get_compiler('c') + +# Test all combinations of crate and target types. +# - 'clib' gets translated to `rust_abi: 'c'` instead. +# - '' gets translated to no kwargs. +allowed_map = { + 'static_library': ['rlib', 'staticlib', 'lib', 'clib', ''], + 'shared_library': ['dylib', 'cdylib', 'lib', 'proc-macro', 'clib', ''], + 'both_libraries': ['lib', 'clib', ''], +} +foreach crate_type : ['lib', 'rlib', 'dylib', 'cdylib', 'staticlib', 'proc-macro', 'clib', '', 'invalid'] + foreach target_type, allowed : allowed_map + name = f'stuff_@crate_type@_@target_type@'.underscorify() + src = crate_type == 'proc-macro' ? 'proc.rs' : 'stuff.rs' + if crate_type not in allowed + # Note: in the both_libraries() case it is possible that the static part + # is still being built because the shared part raised an error but we + # don't rollback correctly. + testcase expect_error('(Crate type .* invalid for .*)|(.*must be one of.*not invalid)', how: 're') + build_target(name, src, + target_type: target_type, + rust_crate_type: crate_type, + install: true) + endtestcase + continue + endif + rust_kwargs = {} + if crate_type == 'clib' + rust_kwargs = {'rust_abi': 'c'} + elif crate_type != '' + rust_kwargs = {'rust_crate_type': crate_type} + endif + l = build_target(name, src, + target_type: target_type, + kwargs: rust_kwargs, + install: true) + if crate_type in ['cdylib', 'staticlib', 'clib'] + e = executable(f'prog-@name@', 'prog.c', + link_with: l, + rust_dependency_map: {name: 'stuff'}, + install: true) + test(f'polyglottest-@name@', e) + else + testcase expect_error('Try to link Rust ABI library .*', how: 're') + executable(f'prog-@name@', 'prog.c', link_with: l) + endtestcase + endif + endforeach +endforeach diff --git a/test cases/rust/4 polyglot/proc.rs b/test cases/rust/4 polyglot/proc.rs new file mode 100644 index 000000000000..53935e45d17f --- /dev/null +++ b/test cases/rust/4 polyglot/proc.rs @@ -0,0 +1,7 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn make_answer(_item: TokenStream) -> TokenStream { + "fn answer() -> u32 { 42 }".parse().unwrap() +} diff --git a/test cases/rust/4 polyglot/stuff.rs b/test cases/rust/4 polyglot/stuff.rs index ecf623c644e1..30c3a3624783 100644 --- a/test cases/rust/4 polyglot/stuff.rs +++ b/test cases/rust/4 polyglot/stuff.rs @@ -1,5 +1,3 @@ -#![crate_name = "stuff"] - #[no_mangle] pub extern fn f() { println!("Hello from Rust!"); diff --git a/test cases/rust/4 polyglot/test.json b/test cases/rust/4 polyglot/test.json index a8837a195f78..d963ad84064c 100644 --- a/test cases/rust/4 polyglot/test.json +++ b/test cases/rust/4 polyglot/test.json @@ -1,10 +1,92 @@ { "installed": [ - {"type": "exe", "file": "usr/bin/prog"}, - {"type": "pdb", "file": "usr/bin/prog"}, - {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff.so"}, - {"type": "file", "platform": "msvc", "file": "usr/bin/stuff.dll"}, - {"type": "file", "platform": "msvc", "file": "usr/lib/stuff.dll.lib"}, - {"type": "pdb", "file": "usr/bin/stuff"} + {"type": "exe", "file": "usr/bin/prog-stuff_clib_both_libraries"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_clib_both_libraries"}, + {"type": "pdb", "file": "usr/bin/stuff_clib_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_clib_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_clib_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_clib_both_libraries.dll.lib"}, + {"type": "file", "file": "usr/lib/libstuff_clib_both_libraries.a"}, + + {"type": "exe", "file": "usr/bin/prog-stuff_clib_shared_library"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_clib_shared_library"}, + {"type": "pdb", "file": "usr/bin/stuff_clib_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_clib_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_clib_shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_clib_shared_library.dll.lib"}, + + {"type": "exe", "file": "usr/bin/prog-stuff_clib_static_library"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_clib_static_library"}, + {"type": "file", "file": "usr/lib/libstuff_clib_static_library.a"}, + + {"type": "exe", "file": "usr/bin/prog-stuff_cdylib_shared_library"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_cdylib_shared_library"}, + {"type": "pdb", "file": "usr/bin/stuff_cdylib_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_cdylib_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_cdylib_shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_cdylib_shared_library.dll.lib"}, + + {"type": "exe", "file": "usr/bin/prog-stuff_staticlib_static_library"}, + {"type": "pdb", "file": "usr/bin/prog-stuff_staticlib_static_library"}, + {"type": "file", "file": "usr/lib/libstuff_staticlib_static_library.a"}, + + {"type": "pdb", "file": "usr/bin/stuff__both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff__both_libraries.so"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff__both_libraries.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff__both_libraries.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff__both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff__both_libraries.dll.lib"}, + + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff__static_library.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff__static_library.rlib"}, + + {"type": "pdb", "file": "usr/bin/stuff_proc_macro_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_proc_macro_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_proc_macro_shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_proc_macro_shared_library.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_lib_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_lib_both_libraries.rlib"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_lib_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_lib_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff_lib_both_libraries.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_lib_both_libraries.dll.lib"}, + + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_rlib_static_library.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff_rlib_static_library.rlib"}, + + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_lib_static_library.rlib"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/libstuff_lib_static_library.rlib"}, + + {"type": "pdb", "file": "usr/bin/stuff__shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff__shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff__shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff__shared_library.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_lib_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_lib_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_lib_shared_library.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_lib_shared_library.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_dylib_shared_library.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_dylib_shared_library.so"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_dylib_shared_library.dll.lib"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_dylib_shared_library.dll"}, + + {"type": "pdb", "file": "usr/bin/stuff_cdylib_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_cdylib_both_libraries.so"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_cdylib_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_cdylib_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_cdylib_both_libraries.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_proc_macro_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_proc_macro_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_proc_macro_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_proc_macro_both_libraries.dll.lib"}, + + {"type": "pdb", "file": "usr/bin/stuff_dylib_both_libraries.pdb"}, + {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff_dylib_both_libraries.so"}, + {"type": "file", "platform": "msvc", "file": "usr/bin/stuff_dylib_both_libraries.dll"}, + {"type": "file", "platform": "msvc", "file": "usr/lib/stuff_dylib_both_libraries.dll.lib"} ] }