Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

meson/rust: wrap bindgens wrap-static-fns functionality #12263

Merged
merged 2 commits into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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,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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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]
Expand Down Expand Up @@ -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,
karolherbst marked this conversation as resolved.
Show resolved Hide resolved
default='',
karolherbst marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -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']:
karolherbst marked this conversation as resolved.
Show resolved Hide resolved
# 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 @@ -302,15 +325,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
28 changes: 28 additions & 0 deletions test cases/rust/12 bindgen/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,34 @@ rust_bin2 = executable(

test('generated header', rust_bin2)

if prog_bindgen.version().version_compare('>= 0.65')
# Test generating a static inline wrapper
gen3 = rust.bindgen(
input : 'src/header3.h',
output : 'header3.rs',
output_inline_wrapper : 'header3.c',
include_directories : 'include',
)
c_inline_wrapper = static_library('c_wrapper', gen3[1])

f = configure_file(
input : 'src/main3.rs',
output : 'main3.rs',
copy : true,
)

rust_bin3 = executable(
'rust_bin3',
[f, gen3[0]],
link_with : [
c_lib,
c_inline_wrapper,
],
)

test('static inline wrapper', rust_bin3)
endif

subdir('sub')
subdir('dependencies')

Expand Down
12 changes: 12 additions & 0 deletions test cases/rust/12 bindgen/src/header3.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-license-identifer: Apache-2.0
// Copyright © 2023 Red Hat, Inc

#pragma once

#include "other.h"

int32_t add(const int32_t, const int32_t);

static inline int32_t sub(const int32_t a, const int32_t b) {
return a - b;
}
14 changes: 14 additions & 0 deletions test cases/rust/12 bindgen/src/main3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-license-identifer: Apache-2.0
// Copyright © 2023 Red Hat, Inc

#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

include!("header3.rs");

fn main() {
unsafe {
std::process::exit(add(0, sub(0, 0)));
};
}