boncheolgu / tflite-rs

Apache License 2.0
114 stars 54 forks source link

Unable to cross-compile to Android #49

Open Michael-F-Bryan opened 3 years ago

Michael-F-Bryan commented 3 years ago

I'm trying to use the tflite crate on Android and iOS, but have been having issues getting it to compile. For some reason it doesn't look like bindgen can find the C++ STL when it tries to generate bindings.

$ RUST_BACKTRACE=1 cargo build --target aarch64-linux-android
   Compiling tflite v0.9.5 (/tmp/tflite-rs)
error: failed to run custom build command for `tflite v0.9.5 (/tmp/tflite-rs)`

Caused by:
  process didn't exit successfully: `/tmp/tflite-rs/target/debug/build/tflite-764e91f18045bab8/build-script-build` (exit status: 101)
  --- stderr
  csrc/stl_wrapper.hpp:1:10: fatal error: 'memory' file not found
  csrc/stl_wrapper.hpp:1:10: fatal error: 'memory' file not found, err: true
  thread 'main' panicked at 'Unable to generate STL bindings: ()', build.rs:299:10
  stack backtrace:
     0: rust_begin_unwind
               at /rustc/1c6868aa21981b37cbd3fc95828ee3b0ac22d494/library/std/src/panicking.rs:515:5
     1: core::panicking::panic_fmt
               at /rustc/1c6868aa21981b37cbd3fc95828ee3b0ac22d494/library/core/src/panicking.rs:92:14
     2: core::result::unwrap_failed
               at /rustc/1c6868aa21981b37cbd3fc95828ee3b0ac22d494/library/core/src/result.rs:1355:5
     3: core::result::Result<T,E>::expect
               at /rustc/1c6868aa21981b37cbd3fc95828ee3b0ac22d494/library/core/src/result.rs:997:23
     4: build_script_build::import_stl_types
               at ./build.rs:282:20
     5: build_script_build::main
               at ./build.rs:530:5
     6: core::ops::function::FnOnce::call_once
               at /rustc/1c6868aa21981b37cbd3fc95828ee3b0ac22d494/library/core/src/ops/function.rs:227:5
  note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Do you have any suggestions for resolving this?

Full Steps to Reproduce

First, clone the tflite crate:

$ cd /tmp
$ git clone https://github.com/boncheolgu/tflite-rs
$ cd tflite-rs
$ git log -1
commit b206241826e92005ad2155b20f04b6c293892372 (HEAD -> master, origin/master, origin/HEAD)
Author: Boncheol Gu <boncheol.gu@gmail.com>
Date:   Sat Mar 20 17:19:51 2021 +0900

    Bump version to v0.9.5

Next we need to add set up our environment for cross-compiling. This involves adding the aarch64-linux-android target and telling cargo where our C compiler and archiver is.

$ rustup target add aarch64-linux-android
$ rustc --version --verbose
rustc 1.54.0-nightly (1c6868aa2 2021-05-27)
binary: rustc
commit-hash: 1c6868aa21981b37cbd3fc95828ee3b0ac22d494
commit-date: 2021-05-27
host: x86_64-unknown-linux-gnu
release: 1.54.0-nightly
LLVM version: 12.0.1

$ echo $ANDROID_HOME
/home/michael/Android/Sdk
$ echo $NDK_HOME
/home/michael/Android/Sdk/ndk/22.1.7171670

$ cat ~/.cargo/config
[target.aarch64-linux-android]
ar = "/home/michael/Android/Sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar"
linker = "/home/michael/Android/Sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang"

I had the same issue using the tf_v2.4.1 branch, although I needed to tell cc where the C compiler and archiver is.

$ git checkout tf_v2.4.1
$ git log -1
commit 59894c2ad99bbccc1944d935b97e2863f61f71a4 (HEAD -> tf_v2.4.1, origin/tf_v2.4.1)
Author: Tyler Hawkes <tyler.hawkes@vivint.com>
Date:   Mon May 24 23:44:05 2021 +0000

    Adding send/sync implementations
$ export CXX_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++
$ export CC_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang
$ export AR_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar

$ cargo build --target aarch64-linux-android
   Compiling tflite v0.10.1 (/tmp/tflite-rs)
error: failed to run custom build command for `tflite v0.10.1 (/tmp/tflite-rs)`

Caused by:
  process didn't exit successfully: `/tmp/tflite-rs/target/debug/build/tflite-e5d8c2c5e7f7c2ae/build-script-build` (exit status: 101)
  --- stderr
  csrc/stl_wrapper.hpp:1:10: fatal error: 'memory' file not found
  csrc/stl_wrapper.hpp:1:10: fatal error: 'memory' file not found, err: true
  thread 'main' panicked at 'Unable to generate STL bindings: ()', build.rs:328:10
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Michael-F-Bryan commented 3 years ago

On Discord, @bkirwi pointed out you can use the BINDGEN_EXTRA_CLANG_ARGS environment variable to point bindgen at the STL for your Android NDK so I've now moved on to a different compilation error.

$ export AR_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar
$ export CC_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang
$ export CXX_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++
$ export BINDGEN_EXTRA_CLANG_ARGS=-I$NDK_HOME/sources/cxx-stl/llvm-libc++/include/

$ cargo build --target aarch64-linux-android
   ...
   Compiling tflite v0.9.6
error: failed to run custom build command for `tflite v0.9.6`

Caused by:
  process didn't exit successfully: `/home/michael/Documents/hotg-ai/rune/target/debug/build/tflite-e86bb924f15fa979/build-script-build` (exit status: 101)
  --- stderr
  /home/michael/Android/Sdk/ndk/22.1.7171670/sources/cxx-stl/llvm-libc++/include/typeinfo:222:16: error: reinterpret_cast from 'std::__type_info_implementations::__non_unique_arm_rtti_bit_impl::__type_name_t' (aka 'unsigned int') to 'size_t' (aka 'unsigned long') is not allowed
  /home/michael/Android/Sdk/ndk/22.1.7171670/sources/cxx-stl/llvm-libc++/include/typeinfo:222:16: error: reinterpret_cast from 'std::__type_info_implementations::__non_unique_arm_rtti_bit_impl::__type_name_t' (aka 'unsigned int') to 'size_t' (aka 'unsigned long') is not allowed, err: true
  thread 'main' panicked at 'Unable to generate STL bindings: ()', /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/tflite-0.9.6/build.rs:280:10
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed

It seems like tflite's build script isn't telling bindgen that it is targeting a 64-bit platform because it thinks __type_name_t is an unsigned int instead of a unsigned long.

fzyzcjy commented 3 years ago

Did you solved it?

Michael-F-Bryan commented 3 years ago

Our solution was to create our own library which builds TensorFlow Lite and exposes just enough functionality to suit our needs while also (cross-)compiling to our target devices (Android, iOS, x86/ARM linux, x86 MacOS, Windows, etc.).

MichaelMcCulloch commented 1 year ago

On Discord, @bkirwi pointed out you can use the BINDGEN_EXTRA_CLANG_ARGS environment variable to point bindgen at the STL for your Android NDK so I've now moved on to a different compilation error.

$ export AR_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar
$ export CC_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang
$ export CXX_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++
$ export BINDGEN_EXTRA_CLANG_ARGS=-I$NDK_HOME/sources/cxx-stl/llvm-libc++/include/

$ cargo build --target aarch64-linux-android
   ...
   Compiling tflite v0.9.6
error: failed to run custom build command for `tflite v0.9.6`

Caused by:
  process didn't exit successfully: `/home/michael/Documents/hotg-ai/rune/target/debug/build/tflite-e86bb924f15fa979/build-script-build` (exit status: 101)
  --- stderr
  /home/michael/Android/Sdk/ndk/22.1.7171670/sources/cxx-stl/llvm-libc++/include/typeinfo:222:16: error: reinterpret_cast from 'std::__type_info_implementations::__non_unique_arm_rtti_bit_impl::__type_name_t' (aka 'unsigned int') to 'size_t' (aka 'unsigned long') is not allowed
  /home/michael/Android/Sdk/ndk/22.1.7171670/sources/cxx-stl/llvm-libc++/include/typeinfo:222:16: error: reinterpret_cast from 'std::__type_info_implementations::__non_unique_arm_rtti_bit_impl::__type_name_t' (aka 'unsigned int') to 'size_t' (aka 'unsigned long') is not allowed, err: true
  thread 'main' panicked at 'Unable to generate STL bindings: ()', /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/tflite-0.9.6/build.rs:280:10
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed

It seems like tflite's build script isn't telling bindgen that it is targeting a 64-bit platform because it thinks __type_name_t is an unsigned int instead of a unsigned long.

I hope I'm not wrong to ask this here on such an old thread. But I have exactly the same blocker. I'm wondering if you happen to know what I would have to do to correct bindgen such that it targets a 64 bit platform?

Michael-F-Bryan commented 1 year ago

Sorry, I can't really help you there. We ended up moving away from the tflite-rs crate.

MichaelMcCulloch commented 1 year ago

I don't want to be that guy who found a solution but left no update, so here goes:

Take a look at my solution

I would suggest to build tflitec-rs with a empty (except for the tflitec dependency) cargo project with all the settings configured for Android NDK 21. you'll need bazelisk , android studio and cargo-ndk installed. Take a look at the this folder in this commit in my solution and you'll find the necessary environment variables. There's even a script. I hope it helps. Once you've succeeded in building your project for all platforms, you'll find the built artifact under the /target/-linux-android(eabi)/release/build/tflitec-bl4hbl4hblah/out/libtensorflowlite_c.so. Copy them to the android project jniLibs dir in the appropriate folder, and set the TFLITEC_PREBUILT_PATH_PLAT_FORM_TRIPLET appropriately so you can build again without the hassle. You can then update your project to ndk api 30 as I did in the following commits.

If you're really suffering, you can just grab the 64-bit libs here

milewski commented 1 year ago

And very importantly, make sure you use rust 1.67.1 or BELLOW! since version 1.6.8 rust does not compile with NDK lower than 25

Compatibility Notes # Only support Android NDK 25 or newer