rust/bindgen: Use Meson rules for C++ headers

Bindgen natively only considers .hpp to be C++ headers, but Meson
considers some additional extensions including .hh and .hxx to be C++.
pull/12263/head
Dylan Baker 1 year ago
parent 2c7833b1c9
commit 6a8330af59
  1. 6
      docs/markdown/snippets/rust-bindgen-cpp.md
  2. 25
      mesonbuild/modules/rust.py
  3. 16
      test cases/rust/12 bindgen/meson.build
  4. 19
      test cases/rust/12 bindgen/src/cpp.rs
  5. 9
      test cases/rust/12 bindgen/src/header.hpp
  6. 7
      test cases/rust/12 bindgen/src/impl.cpp

@ -0,0 +1,6 @@
## Bindgen will now use Meson's hueristic for what is a C++ header
Bindgen natively assumes that a file with the extension `.cpp` is a C++ header,
but that everything else is a C header. Meson has a whole list of extensions it
considers to be C++, and now will automatically look for those extensions and
set bindgen to treat those as C++

@ -12,7 +12,7 @@ from . import ExtensionModule, ModuleReturnValue, ModuleInfo
from .. import mlog
from ..build import (BothLibraries, BuildTarget, CustomTargetIndex, Executable, ExtractedObjects, GeneratedList,
CustomTarget, InvalidArguments, Jar, StructuredSources, SharedLibrary)
from ..compilers.compilers import are_asserts_disabled
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 ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs
from ..mesonlib import File
@ -230,13 +230,6 @@ class RustModule(ExtensionModule):
elif isinstance(s, CustomTarget):
depends.append(s)
# We only want include directories and defines, other things may not be valid
cargs = state.get_option('args', state.subproject, lang='c')
assert isinstance(cargs, list), 'for mypy'
for a in itertools.chain(state.global_args.get('c', []), state.project_args.get('c', []), cargs):
if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')):
clang_args.append(a)
if self._bindgen_bin is None:
self._bindgen_bin = state.find_program('bindgen')
@ -248,6 +241,22 @@ class RustModule(ExtensionModule):
else:
name = header.get_outputs()[0]
# bindgen assumes that C++ headers will be called .hpp. We want to
# 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'
# We only want include directories and defines, other things may not be valid
cargs = state.get_option('args', state.subproject, lang=language)
assert isinstance(cargs, list), 'for mypy'
for a in itertools.chain(state.global_args.get(language, []), state.project_args.get(language, []), cargs):
if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')):
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':
clang_args.extend(['-x', 'c++'])
cmd = self._bindgen_bin.get_command() + \
[
'@INPUT@', '--output',

@ -1,7 +1,7 @@
# SPDX-license-identifer: Apache-2.0
# Copyright © 2021-2022 Intel Corporation
project('rustmod bindgen', ['c', 'rust'], meson_version : '>= 0.63')
project('rustmod bindgen', ['c', 'cpp', 'rust'], meson_version : '>= 0.63')
prog_bindgen = find_program('bindgen', required : false)
if not prog_bindgen.found()
@ -107,3 +107,17 @@ gp_exe = executable(
)
test('global and project arguments', gp_exe)
cpp_lib = static_library('cpplib', 'src/impl.cpp')
cpp_bind = rust.bindgen(
input : 'src/header.hpp',
output : 'generated-cpp.rs',
)
cpp_exe = executable(
'cpp_exe',
structured_sources(['src/cpp.rs', cpp_bind]),
link_with : cpp_lib,
)
test('cpp', cpp_exe)

@ -0,0 +1,19 @@
// SPDX-license-identifer: Apache-2.0
// Copyright © 2023 Intel Corporation
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!("generated-cpp.rs");
fn main() {
let mut instance = std::mem::MaybeUninit::<MyClass>::uninit();
let val: i32;
unsafe {
MyClass_MyClass(instance.as_mut_ptr());
val = instance.assume_init_mut().method();
}
let success = val == 7;
std::process::exit(!success as i32);
}

@ -0,0 +1,9 @@
#pragma once
class MyClass {
public:
MyClass();
int method() const;
private:
int val;
};

@ -0,0 +1,7 @@
#include "header.hpp"
MyClass::MyClass() : val{7} {};
int MyClass::method() const {
return val;
}
Loading…
Cancel
Save