I'm in the process of attempting to use bindgen
to generate Rust bindings for a large library (DPDK, but it doesn't really matter). I'm starting small and importing specific header files and building up the set of bindings iteratively. At some point, I reach a header that bindgen
cannot handle for whatever reason (one example is Atomics, for example). The error message is too vague and doesn't leave any breadcrumbs to the problematic symbol.
--- stderr
clang diag: warning: argument unused during compilation: '-L/nix/store/e3b0c44298fc1c149afbf4c8996fb924-dpdk-24.07/lib' [-Wunused-command-line-argument]
thread 'main' panicked at build.rs:336:6:
Unable to generate bindings: Codegen(Serialize { msg: "Cannot serialize type kind Opaque", loc: "builtin definitions" })
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
I'd like to attach a debugger to the execution of the build.rs script so that I can step into the bindgen
utility and see if I can find some context about what it is choking on. The only advice I can find about debugging the build.rs
script is to put println!
statements in. That advice is not appropriate in this case because (a) this is a complex issue not suitable for println debugging and (b) the issue exists in bindgen
, which would not lend itself to adding new println statements.
How might someone go about attaching a debugger (ideally, an IDE debugger like RustRover) to the build.rs script?
You can find the path to the compiled executable for the build script with:
cargo build -v 2>&1 | grep build-script-build
You can load and run it in a debugger like any normal executable.
I found that the build.rs makes hard assumptions on the environments variables that Cargo exports when invoking the build script. I opted to just capture the entire environment of the build.rs by putting a std::thread::sleep(std::time::Duration::from_secs(u64::MAX))
and then dumping /proc/$(pgrep -f build-script-build)/environ
and using it.
Once GDB was loaded, I added in the directory holding the build.rs
and a few directories from the crates index to the source search path. However, debugging Rust in gdb
is an absolute pain. For example, I know the source code location of the error that eventually surfaces, but can't set a break point on it by file:line. If I search for the symbol, I get all the various impls and closures:
(gdb) info func CSerialize
All functions matching regular expression "CSerialize":
Non-debugging symbols:
0x000000000016f1b0 core::ptr::drop_in_place<core::iter::adapters::map::Map<alloc::vec::into_iter::IntoIter<(alloc::string::String,bindgen::ir::context::TypeId)>,<bindgen::ir::function::Function as bindgen::codegen::serialize::CSerialize>::serialize<alloc::vec::Vec<u8>>::{{closure}}>>
0x00000000001a8070 <bindgen::ir::function::Function as bindgen::codegen::serialize::CSerialize>::serialize::{{closure}}
0x00000000001a8080 <bindgen::ir::function::Function as bindgen::codegen::serialize::CSerialize>::serialize::{{closure}}
0x00000000001a8230 <bindgen::ir::function::Function as bindgen::codegen::serialize::CSerialize>::serialize::{{closure}}::{{closure}}
0x00000000001a8390 <bindgen::ir::function::Function as bindgen::codegen::serialize::CSerialize>::serialize::{{closure}}
0x00000000001a83b0 <bindgen::ir::function::Function as bindgen::codegen::serialize::CSerialize>::serialize::{{closure}}
0x00000000001a8460 <bindgen::ir::ty::Type as bindgen::codegen::serialize::CSerialize>::serialize::{{closure}}
0x00000000001d8330 <bindgen::ir::context::TypeId as bindgen::codegen::serialize::CSerialize>::serialize
0x00000000001fd170 <bindgen::ir::ty::Type as bindgen::codegen::serialize::CSerialize>::serialize
0x000000000029dad0 <bindgen::ir::item::Item as bindgen::codegen::serialize::CSerialize>::serialize
0x000000000029dce0 <bindgen::ir::function::Function as bindgen::codegen::serialize::CSerialize>::serialize
....
Thread 1 "build-script-bu" hit Breakpoint 2, 0x0000555555751170 in <bindgen::ir::ty::Type as bindgen::codegen::serialize::CSerialize>::serialize ()
(gdb) list .
Insufficient debug info for showing source lines at current PC (0x555555751170).
(gdb) info locals
No symbol table info available.
It seems like the build-script-build
binary is not build a way that is condusive to debugging.
Attaching the RustRover debugger was less useful, as it could not figure out how to associate the build.rs source to the executable (this is something I will raise with JetBrains as a feature request).
After adding the below snippet to Cargo.toml
and doing a clean
+ build
, RustRover was able to attach to the build-script-build
process if I manually invoked it.
[profile.dev.build-override]
debug = true