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

Cross-compile to Android does not work #4

Closed
AxelNennker opened this issue May 23, 2019 · 17 comments
Closed

Cross-compile to Android does not work #4

AxelNennker opened this issue May 23, 2019 · 17 comments
Labels
bug Something isn't working cross-compilation

Comments

@AxelNennker
Copy link

I could not get this crate to work for cargo build --target=aarch64-linux-android

Even if I tell cargo which compilers to use. The following does not work:
ANDROID_API=28 PATH=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH CC=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android28-clang CXX=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android28-clang++ cargo build --target=aarch64-linux-android

The value for $NDK is set using

export HOST_TAG=linux-x86_64
export NDK=$HOME/Android/Sdk/ndk-bundle

I suggest to use zeromq's own build system in this crate, that is basically
cd vendor && ./autogen.sh && HOST_TAG=linux-x86_64 NDK=$HOME/Android/Sdk/ndk-bundle LIBZMQ_SYS_STATIC=1 PATH=$NDK/toolchains/llvm/prebuilt/HOST_TAG/bin:$PATH CC=$NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android28-clang CXX=$NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android28-clang++ ./configure --target= --host=x86_64-linux-gnu --enable-static --disable-shared --prefix=/usr/local/aarch64-linux-android && make

If you are not on Linux you have to use the correct HOST_TAG for your system.
Just see what is there after installing Android Studio.

I wouldn't mind you get cmake do the job but a PR doing this with ./configure is #3

@jean-airoldie
Copy link
Owner

jean-airoldie commented May 23, 2019

Could you submit the stacktrace that you get when trying to compile using cmake?

I'm not sure I understand your point about using zeromq's build system. What would be the advantage of using your method vs. statically cross-compiling libzmq outside of cargo (e.g. using autogen & make) then telling cargo where the compiled lib is?

@AxelNennker
Copy link
Author

I am building a library for Android that uses zeromq.
https://github.com/hyperledger/indy-sdk/tree/master/libindy
Currently I have to compile several libraries and then tell that cargo where the three other libraries are.
openssl, libsodium, zeromq

We have built some scripts that somewhat automate the process but currently we are stuck with NDK r16

To simplify the process I would like that these other libraries are build using cargo.
So in libindy I like to call cargo build --target=aarch64-linux-android and want that the crates used by libindy magically compile for this target.

This seems to work for openssl (feature vendored) and for sodiumoxide but not for zmq.

  • sodiumoxide
ignisvulpis@namenlos:~/development/sodiumoxide$ HOST_TAG=linux-x86_64 LIBZMQ_SYS_STATIC=1 PATH=$NDK/toolchains/llvm/prebuilt/HOST_TAG/bin:$PATH CC=$NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android28-clang CXX=$NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android28-clang++ cargo build --target=aarch64-linux-android 
    Updating crates.io index
   Compiling libc v0.2.54
   Compiling byteorder v1.3.1
   Compiling crc32fast v1.2.0
   Compiling cfg-if v0.1.7
   Compiling adler32 v1.0.3
   Compiling pkg-config v0.3.14
   Compiling cc v1.0.36
   Compiling serde v1.0.90
   Compiling filetime v0.2.5
   Compiling xattr v0.2.2
   Compiling libflate v0.1.22
   Compiling tar v0.4.24
   Compiling libsodium-sys v0.2.2 (/home/ignisvulpis/development/sodiumoxide/libsodium-sys)
   Compiling sodiumoxide v0.2.2 (/home/ignisvulpis/development/sodiumoxide)
    Finished dev [unoptimized + debuginfo] target(s) in 31.42s
ignisvulpis@namenlos:~/development/sodiumoxide$ 

Regarding the stacktrace: I seems that zeromq-src-rs is not building any library. Maybe I am using it wrong.

ignisvulpis@namenlos:/tmp/zeromq-src-rs$ cargo clean && cargo build --target=aarch64-linux-android
   Compiling cc v1.0.37
   Compiling cmake v0.1.40
   Compiling zeromq-src v0.1.1 (/tmp/zeromq-src-rs)
    Finished dev [unoptimized + debuginfo] target(s) in 1.62s
ignisvulpis@namenlos:/tmp/zeromq-src-rs$ find target -name lib\*
target/aarch64-linux-android/debug/libzeromq_src.rlib
target/aarch64-linux-android/debug/deps/libcmake-9820f53154040bb2.rlib
target/aarch64-linux-android/debug/deps/libzeromq_src-08db56fb795a94e1.rlib
target/aarch64-linux-android/debug/deps/libcc-6254c2c529020aab.rlib
target/aarch64-linux-android/debug/.fingerprint/cmake-9820f53154040bb2/lib-cmake-9820f53154040bb2.json
target/aarch64-linux-android/debug/.fingerprint/cmake-9820f53154040bb2/lib-cmake-9820f53154040bb2
target/aarch64-linux-android/debug/.fingerprint/cc-6254c2c529020aab/lib-cc-6254c2c529020aab
target/aarch64-linux-android/debug/.fingerprint/cc-6254c2c529020aab/lib-cc-6254c2c529020aab.json
target/aarch64-linux-android/debug/.fingerprint/zeromq-src-08db56fb795a94e1/lib-zeromq_src-08db56fb795a94e1.json
target/aarch64-linux-android/debug/.fingerprint/zeromq-src-08db56fb795a94e1/lib-zeromq_src-08db56fb795a94e1
target/aarch64-linux-android/debug/libzeromq_src.d
ignisvulpis@namenlos:/tmp/zeromq-src-rs$ 

There is no libzmq.a nor a libzmq.so

@jean-airoldie
Copy link
Owner

jean-airoldie commented May 23, 2019

Understood.

Can you run cargo test --all --target=aarch64-linux-android? If the test does not fail then the lib has indeed compiled. In itself the crate does not compile the lib, it merely gives the tools required to do so. But running the tests will compile the testcrate which calls these tools to compile, link and run a test script.

@AxelNennker
Copy link
Author

The first naive try does not find the compiler.

ignisvulpis@namenlos:/tmp/zeromq-src-rs$ cargo clean && cargo test --all --target=aarch64-linux-android
   Compiling cc v1.0.37
   Compiling cmake v0.1.40
   Compiling zeromq-src v0.1.1 (/tmp/zeromq-src-rs)
   Compiling testcrate v0.1.0 (/tmp/zeromq-src-rs/testcrate)
error: failed to run custom build command for `testcrate v0.1.0 (/tmp/zeromq-src-rs/testcrate)`
process didn't exit successfully: `/tmp/zeromq-src-rs/target/debug/build/testcrate-7a6d0b4f4a531c39/build-script-build` (exit code: 101)
--- stdout
cargo:rerun-if-changed=build.rs
running: "cmake" "/tmp/zeromq-src-rs/vendor" "-DENABLE_DRAFTS=OFF" "-DCMAKE_BUILD_TYPE=Release" "-DWITH_PERF_TOOL=OFF" "-DBUILD_SHARED=OFF" "-DBUILD_STATIC=ON" "-DCMAKE_INSTALL_PREFIX=/tmp/zeromq-src-rs/target/aarch64-linux-android/debug/build/testcrate-0f017105baa04b79/out" "-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC --target=aarch64-linux-android" "-DCMAKE_C_COMPILER=aarch64-linux-android-clang" "-DCMAKE_CXX_FLAGS= -ffunction-sections -fdata-sections -fPIC --target=aarch64-linux-android" "-DCMAKE_CXX_COMPILER=aarch64-linux-android-clang++"
-- The C compiler identification is unknown
-- The CXX compiler identification is unknown
-- Configuring incomplete, errors occurred!
See also "/tmp/zeromq-src-rs/target/aarch64-linux-android/debug/build/testcrate-0f017105baa04b79/out/build/CMakeFiles/CMakeOutput.log".
See also "/tmp/zeromq-src-rs/target/aarch64-linux-android/debug/build/testcrate-0f017105baa04b79/out/build/CMakeFiles/CMakeError.log".

--- stderr
CMake Error at CMakeLists.txt:2 (project):
  The CMAKE_C_COMPILER:

    aarch64-linux-android-clang

  is not a full path and was not found in the PATH.

  Tell CMake where to find the compiler by setting either the environment
  variable "CC" or the CMake cache entry CMAKE_C_COMPILER to the full path to
  the compiler, or to the compiler name if it is in the PATH.


CMake Error at CMakeLists.txt:2 (project):
  The CMAKE_CXX_COMPILER:

    aarch64-linux-android-clang++

  is not a full path and was not found in the PATH.

  Tell CMake where to find the compiler by setting either the environment
  variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
  to the compiler, or to the compiler name if it is in the PATH.


thread 'main' panicked at '
command did not execute successfully, got: exit code: 1

build script failed, must exit now', /home/ignisvulpis/.cargo/registry/src/github.com-1ecc6299db9ec823/cmake-0.1.40/src/lib.rs:832:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

ignisvulpis@namenlos:/tmp/zeromq-src-rs$ 

and cmake suggest the 'wrong' compiler. Current Android clang compilers have the Android-API in their name.
So setting the environment as suggested by the error message.

ignisvulpis@namenlos:/tmp/zeromq-src-rs$ cargo clean && ANDROID_API=28 HOST_TAG=linux-x86_64 NDK=$HOME/Android/Sdk/ndk-bundle CC=$NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android28-clang CXX=$NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android28-clang++ cargo test --all --target=aarch64-linux-android

cmake-output.txt

@jean-airoldie
Copy link
Owner

From what I understand cmake is running a test to check if the supplied compilers are working. But since you are cross compiling you can't actually run an executable on host.

From what I understand the solution would be to disable these tests. We can do so by passing CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY. I will make a PR to add a cross-compiling method to the Build that will set this define.

@AxelNennker
Copy link
Author

I think the linker is failing because it is not finding some file like e.g. crtend_android.o
Most of the times this means that sysroot is not found.
Don't know why cmake fails to find them. Usually it is the job of the compiler or linker to find them.
I tried to add --sysroot to CFLAGS but no success

@jean-airoldie
Copy link
Owner

jean-airoldie commented May 23, 2019

I added the ability to pass abitrary cmake definitions in this WIP PR #5. I'm passing CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY.

Please run cargo test --all against this PR and tell me if it helps.

edit: Nevermind I forgot to cargo clean, this PR does not even compile.

@AxelNennker
Copy link
Author

Please see attached file for the output. No change, I think.

cmake-cross-compilation.txt

@jean-airoldie
Copy link
Owner

No change indeed.

Sorry I can't help much. This seems to be an issue related to the cmake configuration and I don't have any experience using cmake in a cross-compiling context.

@jean-airoldie jean-airoldie added bug Something isn't working cross-compilation and removed bug Something isn't working labels May 23, 2019
@AxelNennker
Copy link
Author

Then maybe use my PR which doesn't use cmake but configure && make?

@jean-airoldie
Copy link
Owner

I don't really think it makes sense to merge that PR considering it doesn't have any proper linking logic (which is why it doesn't compile in the first place). The purpose of this crate is to be able to use libzmq without having to install / compile it as a dependency. It lets cargo handle the compilation and linking. I am not against using configure && make but they are not well integrated into the rust ecosystem (properly linking for every system would be a real headache). If I merge your PR, this repo would basically be the equivalent of a sh script with a git submodule that compiles the lib. I don't think it would be particularly reliable.

Does that make sense?

@AxelNennker
Copy link
Author

I agree on the purpose of this crate. It should be integrated in libzmq-rs and rust-zmq behind a feature flag 'vendored'

I think it a good idea to follow the example of the openssl source crate openssl-src
https://github.com/alexcrichton/openssl-src-rs/blob/master/src/lib.rs#L80

Which calls openssl's ./Configure script.

I think the PR brings this crate forward.
The PR does not finish the work to integrate the crate into libzmqrs or rust-zmq.

Regarding reliability, I think that ./Configure is THE way to build openssl from source.

@jean-airoldie
Copy link
Owner

Yes I don't disagree with using configure and make, I'm more worried about the linking procedure. As you can see in the crate that you link, making it work for multiple arch seems like a real headache.

The reason openssl is not build using cmake is because there is no support for it (i.e. no `CMakeLists.txt anywhere in the project).

I can't really merge the PR as is since it as no linking logic currently. But I saw that it is now a WIP.

@jean-airoldie jean-airoldie added the bug Something isn't working label May 24, 2019
@oblique
Copy link

oblique commented May 26, 2019

I can compile for Android using cmake without any problem. These are the full steps:

Download and unzip Android NDK.

Now run:

cd android-ndk-r19c
./build/tools/make-standalone-toolchain.sh --arch=arm64 --platform=android-28 --install-dir=android-toolchain
export PATH="$PATH:$PWD/android-toolchain/bin"
cd /path/to/zeromq-src-rs
cargo build --all --target=aarch64-linux-android

So the key to this is to use make-standalone-toolchain.sh to generate the toolchain in a directory.

@AxelNennker
Copy link
Author

Works for me too. Thanks for checking this out. I thought that make-standalone-toolchain.sh was deprecated by Google/Android.
Anyway, great this works.

@oblique
Copy link

oblique commented May 26, 2019

I manage to build it without standalone toolchain.

Create android.cmake and put the following in:

set(ANDROID_PLATFORM android-28)
set(ANDROID_ABI arm64-v8a)
string(REPLACE "--target=aarch64-linux-android" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REPLACE "--target=aarch64-linux-android" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
unset(CMAKE_C_COMPILER CACHE)
unset(CMAKE_CXX_COMPILER CACHE)
include("$ENV{ANDROID_NDK_PATH}/build/cmake/android.toolchain.cmake")

Now you can build with:

export ANDROID_NDK_PATH=/path/to/android-ndk-r19c
export CMAKE_TOOLCHAIN_FILE=/path/to/android.cmake
cargo build --target=aarch64-linux-android --all

Of-course we can avoid all the above by improving cmake-rs.

@AxelNennker
Copy link
Author

There is an issue for that here: rust-lang/cmake-rs#80

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working cross-compilation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants