Skip to content

Commit

Permalink
meson/rust: wrap bindgens wrap-static-fns functionality
Browse files Browse the repository at this point in the history
This way the `rust.bindgen` can generate a second output being a C file,
which contains wrapper functions for static inline ones.

This output file can then be compiled via C targets.
  • Loading branch information
karolherbst authored and dcbaker committed Feb 23, 2024
1 parent 39e1bf1 commit 0f73401
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
3 changes: 3 additions & 0 deletions docs/markdown/Rust-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 29 additions & 6 deletions mesonbuild/modules/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
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
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
from ..programs import ExternalProgram

if T.TYPE_CHECKING:
from . import ModuleState
Expand All @@ -24,7 +25,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
Expand All @@ -43,6 +44,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]]


Expand Down Expand Up @@ -189,6 +191,12 @@ def test(self, state: ModuleState, args: T.Tuple[str, BuildTarget], kwargs: Func
),
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:
Expand Down Expand Up @@ -248,12 +256,27 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu
else:
name = header.get_outputs()[0]

inline_wrapper_args = []
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(
Expand All @@ -263,15 +286,15 @@ 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,
backend=state.backend,
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.
Expand Down

0 comments on commit 0f73401

Please sign in to comment.