mozilla / cbindgen

A project for generating C bindings from Rust code
Mozilla Public License 2.0
2.38k stars 305 forks source link

cbindgen panics parsing sodiumoxide crate #381

Closed eliaslevy closed 4 years ago

eliaslevy commented 5 years ago
tmp $ cargo new --lib sodiumoxide-ffi
    Created library `sodiumoxide-ffi` package
tmp $ cd sodiumoxide-ffi/
sodiumoxide-ffi $ cat <<EOF > src/lib.rs 
> use sodiumoxide::crypto::box_::{PublicKey, SecretKey};
> #[no_mangle]
> pub extern fn test(pk: &PublicKey, sk: &SecretKey) {}
> EOF
sodiumoxide-ffi $ cbindgen --version
cbindgen 0.9.0
sodiumoxide-ffi $ RUST_BACKTRACE=1 cbindgen -d
thread 'main' panicked at 'error parsing dependency's target metadata: Error("unexpected token")', src/libcore/result.rs:999:5
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
   1: std::sys_common::backtrace::_print
   2: std::panicking::default_hook::{{closure}}
   3: std::panicking::default_hook
   4: std::panicking::rust_panic_with_hook
   5: std::panicking::continue_panic_fmt
   6: rust_begin_unwind
   7: core::panicking::panic_fmt
   8: core::result::unwrap_failed
   9: cbindgen::bindgen::ir::cfg::Cfg::load_metadata
  10: <core::iter::adapters::Map<I,F> as core::iter::traits::iterator::Iterator>::fold
  11: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T,I>>::from_iter
  12: cbindgen::bindgen::cargo::cargo::Cargo::dependencies
  13: cbindgen::bindgen::parser::Parser::parse_crate
  14: cbindgen::bindgen::parser::Parser::parse_crate
  15: cbindgen::bindgen::parser::Parser::parse_crate
  16: cbindgen::bindgen::parser::Parser::parse_crate
  17: cbindgen::bindgen::parser::Parser::parse_crate
  18: cbindgen::bindgen::parser::Parser::parse_crate
  19: cbindgen::bindgen::parser::parse_lib
  20: cbindgen::bindgen::builder::Builder::generate
  21: cbindgen::main
  22: std::rt::lang_start::{{closure}}
  23: std::panicking::try::do_call
  24: __rust_maybe_catch_panic
  25: std::rt::lang_start_internal
  26: main
sodiumoxide-ffi $ 
emilio commented 5 years ago

Sorry, I missed this one. We should probably look into it. This is cbindgen failing to parse the Cargo.toml of a dependency as valid toml. Which is a bit weird.

Benlitz commented 4 years ago

Hello, I was going to fill another issue but it's probably the same problem, I got the same error with cgmath. I did a bit of investigation and it seems that it comes from winapi that specifies target-specific dependencies this way:

[target.i686-pc-windows-gnu.dependencies.winapi-i686-pc-windows-gnu]
version = "0.4"
[target.x86_64-pc-windows-gnu.dependencies.winapi-x86_64-pc-windows-gnu]
version = "0.4"

According to cargo documentation this is valid:

In addition to #[cfg] syntax, Cargo also supports listing out the full target the dependencies would apply to:

[target.x86_64-pc-windows-gnu.dependencies]
winhttp = "0.4.0"
[target.i686-unknown-linux-gnu.dependencies]
openssl = "1.0.1"

But the way this is parsed is using this:

syn::parse_str::<syn::Meta>(target)

which does not accept such a token, if my understanding is correct.

The best way to fix this issue is probably to modify load_metadata so it can handle the token properly - my knowledge of syn and cbindgen is not good enough yet to propose a fix directly but I could write hacky code to work around the issue and it seems to be fine.