How to cross compile when you have native dependency?


#1

I’m looking to use Rust for bluetooth comms, I found this library (https://github.com/ChangSpivey/bluetooth-serial-port) which works on my laptop. I want to run it on raspberry pi - I’ve got basics setup as mentioned in rust-cross project and the basic “hello world” works on ARM but whenever I build my project with “extern crate bluetooth_serial_port” in my main.rs I get the following error,

✔ ~/projects/rust-playground/bt-test [master L|…5] 
17:15 $ cargo build --target=arm-unknown-linux-gnueabihf
   Compiling bt-test v0.1.0 (file:///home/opensourcegeek/projects/rust-playground/bt-test)
error: linking with `arm-linux-gnueabihf-gcc` failed: exit code: 1
  |
  = note: "arm-linux-gnueabihf-gcc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-L" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/bt_test.0.o" "-o" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/bt_test" "-Wl,--gc-sections" "-pie" "-nodefaultlibs" "-L" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps" "-L" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libbluetooth_serial_port-f23155f1a81f0bc5.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libenum_primitive-77b731c79b5cdf4e.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libnum-1fa4854b44bb6a54.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libnum_iter-50df698bc905252c.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libmio-d8a3ebfe89185cdb.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/liblog-bf16bb9a4912b11d.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libnix-56d9e0b660233faa.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libvoid-2cc31605fcb01ba1.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libbitflags-75746cc7f0e9d928.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libslab-69010361762af86e.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/liblazycell-d53b754addaf1d91.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libnum_integer-52fdddf28cd8e924.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libnum_traits-92bb90166cd1857c.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libnet2-755d3e4f87237d0e.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/libcfg_if-72c1f992b13d5087.rlib" "/home/opensourcegeek/projects/rust-playground/bt-test/target/arm-unknown-linux-gnueabihf/debug/deps/liblibc-e1db4c5f3a4f3c2f.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/libstd-2057375968b67ddb.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/libpanic_unwind-20b62febd4f8b14e.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/libunwind-70c006235637ffa1.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/librand-eee0071785e97554.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/libcollections-29e32f0fcc1aa9f2.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/librustc_unicode-08e94cce686650ba.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/liballoc-2c56955b22137f5f.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/liballoc_jemalloc-fdcec0246f2c2a65.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/liblibc-50aa47411c753e02.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/libcore-d096a56044617aca.rlib" "/home/opensourcegeek/.rustup/toolchains/1.14.0-x86_64-unknown-linux-gnu/lib/rustlib/arm-unknown-linux-gnueabihf/lib/libcompiler_builtins-7da46c38d3cea97a.rlib" "-l" "bluetooth" "-l" "bluetooth" "-l" "util" "-l" "dl" "-l" "rt" "-l" "pthread" "-l" "gcc_s" "-l" "pthread" "-l" "c" "-l" "m" "-l" "rt" "-l" "util"
  = note: /home/opensourcegeek/projects/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lbluetooth
/home/opensourcegeek/projects/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/../lib/gcc/arm-linux-gnueabihf/4.8.3/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lbluetooth
collect2: error: ld returned 1 exit status

The bluetooth (libbluetooth.so) library is in /usr/lib64 however I’m not sure how cross compiling works when you have an external dependency for a module. So how to compile my binary with a dependency on an external crate which has a native dependency? Please let me know if you require more details.


#2

The libbluetooth.so in /usr/lib64 is compiled for the x86-64 processor. When you cross compile/link you need to provide a path to the ARM-compiled libbluetooth.so file.

You use the -L option on the linker command line to specify library search paths, and -l to specify libraries to search for.

If you use the “file” command on the .so file you can determine if its an x86 or ARM flavored library.

I believe that you can install foreign architectures so that you can install the armhf version of libbluetooth-dev on your dev machine, or you can install libbluetooth-dev on your RPi and copy the files over to you dev machine.


#3

Many crates that provide some native dependency have a cargo build script, build.rs, which makes the build more customizable (depending on the build script, you may be able to specify the exact location of a cross-compiled library etc.) The build script passes some info to cargo, which in turn passes that to rustc. However, the crate you linked doesn’t seem to provide that.

I’d send an issue, and possibly a pull request.

Here’s some info about build scripts: http://doc.crates.io/build-script.html
If the crate supported them and had a links attribute, you would be also able to override the lib location in your Cargo.toml. (But I guess it’s better for the build script to be flexible than to be forced to use override.) You can fork the repo, try to implement a build script, send a PR, and while waiting, use your fork in your Cargo.toml.