rust-lang / rust-lang/rust-bindgen
bindgen fails to generate __bindgen_padding in some situations on AVR
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 5.3k
- Forks
- 829
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 15
Description
This bug report has an example repo to aid in reproduction of the problem:
https://github.com/mutantbob/bindgen-malfunction
It does not seem to malfunction when generating in the native environment, but instead malfunctions when cross-compiling for AVR.
headers
base.h:
#ifndef Base_h_
#define Base_h_
class Base
{
private:
int maple;
public:
Base() : maple(7) {}
virtual int f() =0;
};
#endif Base_h_
alpha.h:
#include "base.h"
class Alpha: Base
{
#ifdef MALFUNCTION
int bar;
#else
short bar;
short bacon;
#endif
public:
int f() { return bar; }
};
Bindgen Invocation
use std::env;
use std::path::PathBuf;
use bindgen;
use bindgen::Builder;
pub trait BlocklistFileMulti {
fn blocklist_file_multi<T: AsRef<str>, I: IntoIterator<Item = T>>(self, iter: I) -> Self;
}
impl BlocklistFileMulti for bindgen::Builder {
fn blocklist_file_multi<T: AsRef<str>, I: IntoIterator<Item = T>>(self, iter: I) -> Self {
let mut builder = self;
for file in iter {
println!("# blocking file {}", file.as_ref());
builder = builder.blocklist_file(file)
}
builder
}
}
fn generate_bindings_generic<T: AsRef<str>, I: IntoIterator<Item = T>>(header: &str, out_basename: &str, excludes: I, malfunction:bool) {
println!("cargo:rerun-if-changed={}", header);
let bindings = make_builder_for(header)
.blocklist_file_multi(excludes)
.clang_args(if malfunction {
vec!["-DMALFUNCTION=1"]
} else {
vec![]
})
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let bindings_out_file = out_path.join(out_basename);
bindings
.write_to_file(bindings_out_file)
.expect("Couldn't write bindings!");
}
fn make_builder_for(header: &str) -> Builder {
bindgen::Builder::default()
.header(header)
.clang_args(&[
"-x",
"c++",
])
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.ctypes_prefix("cty")
.rustfmt_bindings(true)
}
fn main()
{
let blank : [&str;0] = [];
generate_bindings_generic("src-cpp/mixed.h", "mixed.rs", &blank, false);
generate_bindings_generic("src-cpp/alpha.h", "alpha.rs", &blank, false);
generate_bindings_generic("src-cpp/alpha.h", "alpha-minus.rs", vec!["src-cpp/base.h"], false);
generate_bindings_generic("src-cpp/alpha.h", "alpha-wrong.rs", vec!["src-cpp/base.h"], true);
}
Actual Results
#[repr(C)]
pub struct Alpha__bindgen_vtable(cty::c_void);
#[repr(C, packed)]
pub struct Alpha {
pub vtable_: *const Alpha__bindgen_vtable,
pub bar: cty::c_int,
}
Expected Results
#[repr(C)]
pub struct Alpha__bindgen_vtable(cty::c_void);
#[repr(C)]
pub struct Alpha {
pub vtable_: *const Alpha__bindgen_vtable,
pub __bindgen_padding_0: u16,
pub bar: cty::c_int,
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue using the linked bindgen-malfunction repository, starting with src-cpp/base.h and src-cpp/alpha.h and the shown Builder invocation. Compare alpha-wrong.rs with the expected Alpha layout, then trace padding generation for the AVR cross-compilation case; done means the generated struct uses repr(C) and includes the required __bindgen_padding_0 field.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, rust
- Domain
- embedded-iot, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100