diff --git a/docs/markdown/snippets/rust-bindgen-cpp.md b/docs/markdown/snippets/rust-bindgen-cpp.md new file mode 100644 index 000000000..e12e0f966 --- /dev/null +++ b/docs/markdown/snippets/rust-bindgen-cpp.md @@ -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++ diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 96e1e6f16..caa1be296 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -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', diff --git a/test cases/rust/12 bindgen/meson.build b/test cases/rust/12 bindgen/meson.build index e36e9e2d1..840a8afab 100644 --- a/test cases/rust/12 bindgen/meson.build +++ b/test cases/rust/12 bindgen/meson.build @@ -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) diff --git a/test cases/rust/12 bindgen/src/cpp.rs b/test cases/rust/12 bindgen/src/cpp.rs new file mode 100644 index 000000000..51a594cc4 --- /dev/null +++ b/test cases/rust/12 bindgen/src/cpp.rs @@ -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::::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); +} diff --git a/test cases/rust/12 bindgen/src/header.hpp b/test cases/rust/12 bindgen/src/header.hpp new file mode 100644 index 000000000..3f01c5f7d --- /dev/null +++ b/test cases/rust/12 bindgen/src/header.hpp @@ -0,0 +1,9 @@ +#pragma once + +class MyClass { + public: + MyClass(); + int method() const; + private: + int val; +}; diff --git a/test cases/rust/12 bindgen/src/impl.cpp b/test cases/rust/12 bindgen/src/impl.cpp new file mode 100644 index 000000000..39c8f2ebe --- /dev/null +++ b/test cases/rust/12 bindgen/src/impl.cpp @@ -0,0 +1,7 @@ +#include "header.hpp" + +MyClass::MyClass() : val{7} {}; + +int MyClass::method() const { + return val; +}