rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

bindgen fails to generate __bindgen_padding in some situations on AVR

Open mutantbob opened this issue 3 years ago • 0 comments

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,
}

mutantbob avatar Mar 04 '22 17:03 mutantbob