android - 如何使用 cmake 将 C 库转换为不同的 ABI

标签 android c cmake android-ndk cross-compiling

我正在尝试从 c_speech_features C library 创建共享库针对不同的 Android ABI。我已经下载了 Android NDK 并尝试按照 'Cross Compiling for Android' 的 cmake 说明进行操作创建 .so 库。

尝试的步骤:

  1. 已下载 the library source code

  2. CMakeLists.txt 文件更改为

    cmake_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>)
    
  3. 在终端打开源目录
  4. 运行 cmake
  5. 运行 make

但是,无论我将 ANDROID_ARCH_ABI 设置为什么,在运行 cmake 然后 make 之后生成 的 ABI。 so 库始终与未在 CMakeLists.txt 文件中设置上述变量时相同。这是结果:

~$ readelf -h libc_speech_features.so | grep 'Class\|File\|Machine'
  Class:                             ELF64
  Machine:                           Advanced Micro Devices X86-64

我已尝试在库存储库的新下载上执行此操作,因此我认为这不是缓存 CMake 文件的问题。

是否可以通过这种方式为不同的 ABI 架构创建 .so 库?如果是这样,我应该如何改变我的方法?如果有其他编译库的方法,我也很乐意尝试。以下是我所做的一些其他尝试。

在 Tsyvarev 评论后编辑

我已经从 CMakeLists.txt 文件中删除了设置变量,现在正尝试通过运行命令来使用工具链文件

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 \
.

然后我运行 make 来构建 .so 文件。但是现在生成的 .so lib 总是:

  Class:                             ELF32
  Machine:                           ARM

我是否错误地设置了所需的架构?使用 cmake 工具链时应该如何改变架构?

其他尝试

我看到有许多其他方法可以在 Android 应用程序中包含 C 库:

  • 我直接添加 C 代码并构建 使用 Android Studio ( docs description ) 的库,因为我不能 访问任何方法。我确信这种方式可行,但现在已经了解如何包含和使用预先存在的 .so 库,因此创建一个库可能更容易。

  • Android NDK standalone toolchains我还没明白怎么办 在此 C 库上运行,其 CMakeLists.txt 定义了如何 建库

  • 我看过 android-cmake经常提到,我可能是愚蠢的 在这里,但可以从 README 中看到如何使用它(它也很旧 所以可能并不比直接使用 cmake 好)。

  • 我认为使用 Android.mk 并不容易,因为我有一个库 已经有了 CMakeLists.txt 文件,所以转换它似乎 喜欢更多的工作

最佳答案

Am I incorrectly setting the desired architecture? How is one supposed to alter the architecture when using the cmake toolchain?

是的。不幸的是,Android 和 CMake 同时添加了对另一个的支持,因此有两个工作流程,您正在混合和匹配它们。

为了获得对新 NDK 的最佳支持,您想使用 NDK 的内置支持(工具链文件,就像您正在使用的一样),但您需要使用 ANDROID_* 变量而不是CMAKE_ANDROID_* 变量。

有关可用标志的 segmentation ,请参阅 CMake 的 Android 文档:https://developer.android.com/ndk/guides/cmake .

要修复您的特定调用,您需要:

$ cmake -DCMAKE_TOOLCHAIN_FILE=/path_to/android-ndk-r18b/build/cmake/android.toolchain.cmake \
      -DANDROID_PLATFORM=android-24 -DANDROID_ABI=x86 \
      .

(显然 ANDROID_ABI 没有列在第一个表中,因为它不是用户在通过 gradle 使用 CMake 时必须担心的事情,但它在页面下方有记录)

如果您使用的是 r18 之前的 NDK(您不是,但也许其他人会使用)该页面上不再列出一些额外的标志(例如 ANDROID_TOOLCHAIN).工具链文件本身的顶部有一条注释,其中列出了它支持的所有选项(如果您需要沿着这条路线走)。

关于android - 如何使用 cmake 将 C 库转换为不同的 ABI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53064837/

相关文章:

cmake - 设置 CMake OBJECT 库的输出目录

android - 如何使用存储在 SDCARD 中的 JPG 将 JPG 文件作为 BITMAP 打开?

java - 如何处理网络状态变化时的在线媒体播放器(网络在 WiFi 或移动数据之间切换)?

cmake - 将带空格的参数传递给 CMake ExternalProject_Add BUILD_COMMAND

c - 当尝试从 bmp 文件中提取 RGB 分量时,为什么我的代码段出现错误?

c - 删除C BST中的节点

c++ - CMake 未将 boost 目录包含在其生成的项目中

java - 最后 onNext() 执行完成的 RxJava 回调

Android Studio 多个 dex 文件 gradle 错误

c - 试图扫描到二维 malloc'd 数组 c 编程