diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index 11966ca8ccea..ee095e9d6da1 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -57,6 +57,9 @@ It takes the following keyword arguments - `input`: a list of Files, Strings, or CustomTargets. The first element is the header bindgen will parse, additional elements are dependencies. - `output`: the name of the output rust file +- `output_inline_wrapper`: the name of the optional output c file containing + wrappers for static inline function. This requires `bindgen-0.65` or + newer (*since 1.3.0*). - `include_directories`: A list of `include_directories` or `string` objects, these are passed to clang as `-I` arguments *(string since 1.0.0)* - `c_args`: a list of string arguments to pass to clang untouched diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index fb8528088142..73ac032afb21 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -9,7 +9,7 @@ from mesonbuild.interpreterbase.decorators import FeatureNew from . import ExtensionModule, ModuleReturnValue, ModuleInfo -from .. import mlog +from .. import mesonlib, mlog from ..build import (BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, CustomTarget, InvalidArguments, Jar, StructuredSources, SharedLibrary) from ..compilers.compilers import are_asserts_disabled, lang_suffixes @@ -19,6 +19,7 @@ ) from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs from ..mesonlib import File +from ..programs import ExternalProgram if T.TYPE_CHECKING: from . import ModuleState @@ -27,7 +28,7 @@ from ..interpreter import Interpreter from ..interpreter import kwargs as _kwargs from ..interpreter.interpreter import SourceInputs, SourceOutputs - from ..programs import ExternalProgram, OverrideProgram + from ..programs import OverrideProgram from ..interpreter.type_checking import SourcesVarargsType from typing_extensions import TypedDict, Literal @@ -46,6 +47,7 @@ class FuncBindgen(TypedDict): include_directories: T.List[IncludeDirs] input: T.List[SourceInputs] output: str + output_inline_wrapper: str dependencies: T.List[T.Union[Dependency, ExternalLibrary]] language: T.Optional[Literal['c', 'cpp']] bindgen_version: T.List[str] @@ -196,6 +198,12 @@ def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: Func KwargInfo('bindgen_version', ContainerTypeInfo(list, str), default=[], listify=True, since='1.4.0'), INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '1.0.0'}), OUTPUT_KW, + KwargInfo( + 'output_inline_wrapper', + str, + default='', + since='1.3.0', + ), DEPENDENCIES_KW.evolve(since='1.0.0'), ) def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> ModuleReturnValue: @@ -287,12 +295,27 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu if std != 'none': clang_args.append(f'-std={std}') + inline_wrapper_args: T.List[str] = [] + outputs = [kwargs['output']] + if kwargs['output_inline_wrapper']: + # Todo drop this isinstance once Executable supports version_compare + if isinstance(self._bindgen_bin, ExternalProgram): + if mesonlib.version_compare(self._bindgen_bin.get_version(), '< 0.65'): + raise InterpreterException('\'output_inline_wrapper\' parameter of rust.bindgen requires bindgen-0.65 or newer') + + outputs.append(kwargs['output_inline_wrapper']) + inline_wrapper_args = [ + '--experimental', '--wrap-static-fns', + '--wrap-static-fns-path', os.path.join(state.environment.build_dir, '@OUTPUT1@') + ] + cmd = self._bindgen_bin.get_command() + \ [ '@INPUT@', '--output', - os.path.join(state.environment.build_dir, '@OUTPUT@') + os.path.join(state.environment.build_dir, '@OUTPUT0@') ] + \ - kwargs['args'] + ['--'] + kwargs['c_args'] + clang_args + \ + kwargs['args'] + inline_wrapper_args + ['--'] + \ + kwargs['c_args'] + clang_args + \ ['-MD', '-MQ', '@INPUT@', '-MF', '@DEPFILE@'] target = CustomTarget( @@ -302,7 +325,7 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu state.environment, cmd, [header], - [kwargs['output']], + outputs, depfile='@PLAINNAME@.d', extra_depends=depends, depend_files=depend_files, @@ -310,7 +333,7 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu description='Generating bindings for Rust {}', ) - return ModuleReturnValue([target], [target]) + 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.