Issue
I am trying to create shared libraries from the c_speech_features C library for the different Android ABIs. I have downloaded the Android NDK and have tried to follow the cmake instructions for 'Cross Compiling for Android' to create the .so
library.
Steps Tried:
Downloaded the library source code
Altered the
CMakeLists.txt
file tocmake_minimum_required (VERSION 3.6) project (c_speech_features) include(GNUInstallDirs) ### I ADDED THESE VARIABLES TO COMPILE FOR ANDROID ### set(CMAKE_SYSTEM_NAME Android) set(CMAKE_SYSTEM_VERSION 23) set(CMAKE_ANDROID_ARCH_ABI armeabi-v7a) set(CMAKE_ANDROID_NDK /path_to/android-ndk-r18b/) option (ENABLE_DOUBLE "Enable double-precision floats" OFF) if (ENABLE_DOUBLE) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dkiss_fft_scalar=double") endif () configure_file ("c_speech_features_config.h.in" "c_speech_features_config.h") add_library (objlib OBJECT c_speech_features.c kiss_fft130/kiss_fft.c kiss_fft130/tools/kiss_fftr.c) set_property (TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1) include_directories (kiss_fft130 kiss_fft130/tools) add_library (c_speech_features SHARED $<TARGET_OBJECTS:objlib>) add_library (c_speech_features_static STATIC $<TARGET_OBJECTS:objlib>)
- opened the source directory in terminal
- ran
cmake
- ran
make
However, no matter what I set the ANDROID_ARCH_ABI
to, after running cmake
and then make
the ABI of the resulting .so
library is always the same as when the above variables are not set in the CMakeLists.txt
file. This is the result:
~$ readelf -h libc_speech_features.so | grep 'Class\|File\|Machine'
Class: ELF64
Machine: Advanced Micro Devices X86-64
I have attempted to do this on fresh downloads of the library repository and so do not think it is a problem with cached CMake files.
Is it possible to create the .so
library for the different ABI architectures in this way? If so how should I alter my approach? If there is some other way to compile the libraries I would also be happy to try. Below are some other attempts I made.
Edit after Tsyvarev comment
I have removed the set variables from the CMakeLists.txt
file and am now attempting to use the toolchain file by running the command
cmake -DCMAKE_TOOLCHAIN_FILE=/path_to/android-ndk-r18b/build/cmake/android.toolchain.cmake \
-DCMAKE_ANDROID_NDK=/path_to/android-ndk-r18b \
-DANDROID_PLATFORM=android-24 -DCMAKE_ANDROID_ARCH_ABI=x86 \
.
I then run make
to build the .so
file. However now the resulting .so
lib is always:
Class: ELF32
Machine: ARM
Am I incorrectly setting the desired architecture? How is one supposed to alter the architecture when using the cmake toolchain?
Other Attempts
I have seen there are a number of other ways to include a C library in an Android application:
I was unsuccessful in adding the C code directly and building the library using Android Studio (docs description) as I could not access any of the methods. I'm sure its possible this way, but have now understood how to include and use pre-existing
.so
libs so creating one may be easier.Android NDK standalone toolchains I have not understood how to run on this C library with its
CMakeLists.txt
that defines how the library is builtI've seen android-cmake mentioned often and I may be being dumb here but could see how to use it from the README (its also quite old so may not be better than directly using cmake).
I do not think using Android.mk is easier seeing as I have a library with the
CMakeLists.txt
file already and so converting it seems like more work
Solution
Am I incorrectly setting the desired architecture? How is one supposed to alter the architecture when using the cmake toolchain?
Yes. Unfortunately both Android and CMake added support for the other at the same time, so there are two workflows for this, and you're mixing and matching them.
For the best support for new NDKs, you want to use the NDK's builtin support (the toolchain file, like you're using), but you need to use the ANDROID_*
variables rather than the CMAKE_ANDROID_*
variables.
See the Android docs for CMake for a breakdown of the available flags: https://developer.android.com/ndk/guides/cmake.
To fix your specific invocation, you want:
$ cmake -DCMAKE_TOOLCHAIN_FILE=/path_to/android-ndk-r18b/build/cmake/android.toolchain.cmake \
-DANDROID_PLATFORM=android-24 -DANDROID_ABI=x86 \
.
(apparently ANDROID_ABI
isn't listed in the first table since it's not something the user has to worry about when using CMake via gradle, but it is documented further down the page)
If you're using a pre-r18 NDK (you're not, but maybe someone else landing here will be) there are a few additional flags no longer listed on that page (such as ANDROID_TOOLCHAIN
). There's a comment at the top of the toolchain file itself that lists all the options it supports if you need to go down that route.
Answered By - Dan Albert
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.