Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to cross-compile to Android #49

Open
Michael-F-Bryan opened this issue Jul 1, 2021 · 7 comments
Open

Unable to cross-compile to Android #49

Michael-F-Bryan opened this issue Jul 1, 2021 · 7 comments

Comments

@Michael-F-Bryan
Copy link

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
Copy link
Author

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
Copy link

fzyzcjy commented Sep 28, 2021

Did you solved it?

@Michael-F-Bryan
Copy link
Author

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
Copy link

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
Copy link
Author

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

@MichaelMcCulloch
Copy link

MichaelMcCulloch commented Nov 26, 2022

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
Copy link

milewski commented Sep 14, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants