type is redefined
Input C/C++ Header
Header
#include "AeronArchive.h"
the actual header can be found here https://github.com/real-logic/aeron/blob/1.41.4/aeron-archive/src/main/cpp/client/AeronArchive.h
Bindgen Invocation
bindgen code
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=bindings.h");
let aeron_path = canonicalize(Path::new("./aeron")).unwrap();
let header_path = aeron_path.join("aeron-archive/src/main/cpp/client");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let cmake_output = Config::new(&aeron_path)
.build();
let base_lib_dir = cmake_output.join("build");
println!(
"cargo:rustc-link-search=native={}",
base_lib_dir.join("lib").display()
);
// Because the `cmake_output` path is different for debug/release, we're not worried
// about accidentally linking the Debug library when this is a release build or vice-versa
println!(
"cargo:rustc-link-search=native={}",
base_lib_dir.join("lib/Debug").display()
);
println!(
"cargo:rustc-link-search=native={}",
base_lib_dir.join("binaries/Debug").display()
);
println!(
"cargo:rustc-link-search=native={}",
base_lib_dir.join("lib/Release").display()
);
println!(
"cargo:rustc-link-search=native={}",
base_lib_dir.join("binaries/Release").display()
);
println!("cargo:rustc-link-lib=static=aeron_archive_client");
println!("cargo:rustc-link-lib=static=aeron_archive_client_wrapper");
println!("cargo:rustc-link-lib=stdc++");
println!("cargo:include={}", header_path.display());
let bindings = bindgen::Builder::default()
.clang_arg(format!("-I{}", header_path.display()))
.clang_arg(format!(
"-I{}",
aeron_path.join("aeron-client/src/main/c").display()
))
.header("bindings.h")
.enable_cxx_namespaces()
// enable C++
.clang_args(&["-x", "c++", "--std=c++14"])
.opaque_type("std::.*")
.constified_enum_module("aeron_.*_enum")
.derive_debug(false)
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate aeron bindings");
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
Actual Results
error
error[E0428]: the name `this_t` is defined multiple times
--> /home/alex/workspaces/personal/aeron-lib/target/debug/build/libaeron_archive-sys-0a7352ee9f461a4a/out/bindings.rs:10595:5
|
10115 | pub type this_t = root::aeron::concurrent::logbuffer::BufferClaim;
| ------------------------------------------------------------------ previous definition of the type `this_t` here
...
10595 | pub type this_t = root::aeron::ChannelUri;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `this_t` redefined here
|
= note: `this_t` must be defined only once in the type namespace of this module
error[E0428]: the name `this_t` is defined multiple times
--> /home/alex/workspaces/personal/aeron-lib/target/debug/build/libaeron_archive-sys-0a7352ee9f461a4a/out/bindings.rs:10597:5
|
10115 | pub type this_t = root::aeron::concurrent::logbuffer::BufferClaim;
| ------------------------------------------------------------------ previous definition of the type `this_t` here
...
10597 | pub type this_t = root::aeron::archive::client::Context;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `this_t` redefined here
|
= note: `this_t` must be defined only once in the type namespace of this module
error[E0428]: the name `this_t` is defined multiple times
--> /home/alex/workspaces/personal/aeron-lib/target/debug/build/libaeron_archive-sys-0a7352ee9f461a4a/out/bindings.rs:10598:5
|
10115 | pub type this_t = root::aeron::concurrent::logbuffer::BufferClaim;
| ------------------------------------------------------------------ previous definition of the type `this_t` here
...
10598 | pub type this_t = root::aeron::BufferBuilder;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `this_t` redefined here
|
= note: `this_t` must be defined only once in the type namespace of this module
generated file
// skip other line....
pub type this_t = root::aeron::ChannelUri;
pub type this_t = root::aeron::archive::client::Context;
pub type this_t = root::aeron::BufferBuilder;
}
Expected Results
no redefined type
This sounds like another of those C++ template issues where we don't have a straight solution and it is mostly caused by how libclang exposes the information of the templates. There's not much we can do about how clang exposes this and using other tools like libtooling is not viable due to distribution issues.
I wanted to get creduced test cases even if there might not be a solution soon.
Here is the preprocessed header output. __bindgen.hpp.gz
I grepped for 3 things in the interestingness tests for creduce when running rustc --test on the bindings
- previous definition of the type
- erroneous constant encountered
- cycle detected when expanding type alias
test-case1.hpp
typedef long a;
template <typename = int> class b {
typedef int bu;
typedef b bv;
bv &bw(bu *, a, bu);
};
template <> b<> &b<>::bw(bu *, a, bu);
template <> b<wchar_t> &b<wchar_t>::bw(bu *, a, bu);
test-case1.rs
/* automatically generated by rust-bindgen 0.69.4 */
pub type a = ::std::os::raw::c_long;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct b {
pub _address: u8,
}
pub type b_bu = ::std::os::raw::c_int;
pub type b_bv = b;
pub type bu = ::std::os::raw::c_int;
pub type bu = ::std::os::raw::c_int;
test-case2.hpp
template <typename, typename a> class d { a ay; };
template <typename, typename, typename, typename b> using bf = d<b, int>;
template <typename b> class e { bf<int, int, int, b> bh; };
e<int> c;
test-case2.rs
/* automatically generated by rust-bindgen 0.69.4 */
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct d<a> {
pub ay: a,
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<a>>,
}
pub type bf = d<a>;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct e {
pub bh: bf,
}
#[test]
fn __bindgen_test_layout_e_open0_int_close0_instantiation() {
assert_eq!(
::std::mem::size_of::<e>(),
4usize,
concat!("Size of template specialization: ", stringify!(e))
);
assert_eq!(
::std::mem::align_of::<e>(),
4usize,
concat!("Alignment of template specialization: ", stringify!(e))
);
}
extern "C" {
pub static mut c: e;
}
test-case3.hpp
typedef struct a b;
template <typename, typename = a> class bk;
template <typename> struct c { typedef int bm; };
struct a : c<int> {};
template <typename, typename bu> class bk {
typedef typename bu::bm bm;
typedef bk by;
by &ca(b, bm);
};
template <> bk<wchar_t> &bk<wchar_t>::ca(b, bm);
test-case3.rs
pub struct c {
pub _address: u8,
}
pub type c_bm = ::std::os::raw::c_int;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct a {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_a() {
assert_eq!(
::std::mem::size_of::<a>(),
1usize,
concat!("Size of: ", stringify!(a))
);
assert_eq!(
::std::mem::align_of::<a>(),
1usize,
concat!("Alignment of ", stringify!(a))
);
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct bk {
pub _address: u8,
}
pub type bk_bm = [u8; 0usize];
pub type bk_by = bk;
#[test]
fn __bindgen_test_layout_c_open0_int_close0_instantiation() {
assert_eq!(
::std::mem::size_of::<c>(),
1usize,
concat!("Size of template specialization: ", stringify!(c))
);
assert_eq!(
::std::mem::align_of::<c>(),
1usize,
concat!("Alignment of template specialization: ", stringify!(c))
);
}
pub type bm = bm;
pub type bm = ::std::os::raw::c_int;