modules/rust: Allow explicitly setting the language to bind

This may be of particular use when a header is .h but should be treated
as a C++ header instead of a C header.
pull/12263/head
Dylan Baker 1 year ago
parent 8ac4346943
commit 05d49c6990
  1. 3
      docs/markdown/Rust-module.md
  2. 5
      docs/markdown/snippets/rust-bindgen-language.md
  3. 21
      mesonbuild/modules/rust.py
  4. 19
      test cases/rust/12 bindgen/cpp/meson.build

@ -3,7 +3,7 @@ short-description: Rust language integration module
authors: authors:
- name: Dylan Baker - name: Dylan Baker
email: dylan@pnwbakers.com email: dylan@pnwbakers.com
years: [2020, 2021, 2022] years: [2020, 2021, 2022, 2024]
... ...
# Rust module # Rust module
@ -62,6 +62,7 @@ It takes the following keyword arguments
- `c_args`: a list of string arguments to pass to clang untouched - `c_args`: a list of string arguments to pass to clang untouched
- `args`: a list of string arguments to pass to `bindgen` untouched. - `args`: a list of string arguments to pass to `bindgen` untouched.
- `dependencies`: a list of `Dependency` objects to pass to the underlying clang call (*since 1.0.0*) - `dependencies`: a list of `Dependency` objects to pass to the underlying clang call (*since 1.0.0*)
- `language`: A literal string value of `c` or `cpp`. When set this will force bindgen to treat a source as the given language. Defaults to checking based on the input file extension. *(since 1.4.0)*
```meson ```meson
rust = import('unstable-rust') rust = import('unstable-rust')

@ -0,0 +1,5 @@
## Overriding bindgen language setting
Even though Meson will now tell bindgen to do the right thing in most cases,
there may still be cases where Meson does not have the intended behavior,
specifically with headers with a `.h` suffix, but are C++ headers.

@ -13,7 +13,10 @@ from .. import mlog
from ..build import (BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList, from ..build import (BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList,
CustomTarget, InvalidArguments, Jar, StructuredSources, SharedLibrary) CustomTarget, InvalidArguments, Jar, StructuredSources, SharedLibrary)
from ..compilers.compilers import are_asserts_disabled, lang_suffixes from ..compilers.compilers import are_asserts_disabled, lang_suffixes
from ..interpreter.type_checking import DEPENDENCIES_KW, LINK_WITH_KW, SHARED_LIB_KWS, TEST_KWS, OUTPUT_KW, INCLUDE_DIRECTORIES, SOURCES_VARARGS from ..interpreter.type_checking import (
DEPENDENCIES_KW, LINK_WITH_KW, SHARED_LIB_KWS, TEST_KWS, OUTPUT_KW,
INCLUDE_DIRECTORIES, SOURCES_VARARGS, NoneType, in_set_validator
)
from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs
from ..mesonlib import File from ..mesonlib import File
@ -27,7 +30,7 @@ if T.TYPE_CHECKING:
from ..programs import ExternalProgram, OverrideProgram from ..programs import ExternalProgram, OverrideProgram
from ..interpreter.type_checking import SourcesVarargsType from ..interpreter.type_checking import SourcesVarargsType
from typing_extensions import TypedDict from typing_extensions import TypedDict, Literal
class FuncTest(_kwargs.BaseTest): class FuncTest(_kwargs.BaseTest):
@ -44,6 +47,7 @@ if T.TYPE_CHECKING:
input: T.List[SourceInputs] input: T.List[SourceInputs]
output: str output: str
dependencies: T.List[T.Union[Dependency, ExternalLibrary]] dependencies: T.List[T.Union[Dependency, ExternalLibrary]]
language: T.Optional[Literal['c', 'cpp']]
class RustModule(ExtensionModule): class RustModule(ExtensionModule):
@ -187,6 +191,7 @@ class RustModule(ExtensionModule):
listify=True, listify=True,
required=True, required=True,
), ),
KwargInfo('language', (str, NoneType), since='1.4.0', validator=in_set_validator({'c', 'cpp'})),
INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '1.0.0'}), INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '1.0.0'}),
OUTPUT_KW, OUTPUT_KW,
DEPENDENCIES_KW.evolve(since='1.0.0'), DEPENDENCIES_KW.evolve(since='1.0.0'),
@ -243,7 +248,15 @@ class RustModule(ExtensionModule):
# bindgen assumes that C++ headers will be called .hpp. We want to # bindgen assumes that C++ headers will be called .hpp. We want to
# ensure that anything Meson considers a C++ header is treated as one. # ensure that anything Meson considers a C++ header is treated as one.
language = 'cpp' if os.path.splitext(name)[1][1:] in lang_suffixes['cpp'] else 'c' language = kwargs['language']
if language is None:
ext = os.path.splitext(name)[1][1:]
if ext in lang_suffixes['cpp']:
language = 'cpp'
elif ext == 'h':
language = 'c'
else:
raise InterpreterException(f'Unknown file type extension for: {name}')
# We only want include directories and defines, other things may not be valid # We only want include directories and defines, other things may not be valid
cargs = state.get_option('args', state.subproject, lang=language) cargs = state.get_option('args', state.subproject, lang=language)
@ -252,8 +265,6 @@ class RustModule(ExtensionModule):
if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')): if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')):
clang_args.append(a) clang_args.append(a)
# bindgen assumes that C++ headers will be called .hpp. We want to
# ensure that anything Meson considers a C++ header is treated as one.
if language == 'cpp': if language == 'cpp':
clang_args.extend(['-x', 'c++']) clang_args.extend(['-x', 'c++'])

@ -0,0 +1,19 @@
# SPDX-license-identifer: Apache-2.0
# Copyright © 2021-2023 Intel Corporation
fs = import('fs')
cpp_header = fs.copyfile('../src/header.hpp', 'cpp_header.h')
cpp_bind_override = rust.bindgen(
input : cpp_header,
output : 'generated-cpp.rs',
language : 'cpp',
)
cpp_exe2 = executable(
'cpp_exe2',
structured_sources(['../src/cpp.rs', cpp_bind_override]),
link_with : cpp_lib,
)
test('cpp-forced', cpp_exe2)
Loading…
Cancel
Save