如何使用 cmake 将 C 库转换为不同的 ABI
How to convert C library to different ABIs using cmake
我正在尝试从 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' 创建共享库以创建 .so
库。
尝试的步骤:
将 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>)
- 在终端中打开了源目录
- 运行
cmake
- 运行
make
但是,无论我将 ANDROID_ARCH_ABI
设置为什么,在 运行 宁 cmake
之后 make
结果 .so
库的 ABI始终与 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
库总是:
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_*
变量。
有关可用标志的细分,请参阅 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
没有列在第一个 table 中,因为用户在通过 gradle 使用 CMake 时不必担心它,但它被进一步记录页)
如果您使用的是 r18 之前的 NDK(您不是,但可能其他登陆此处的人会使用)该页面上不再列出一些额外的标志(例如 ANDROID_TOOLCHAIN
).工具链文件本身的顶部有一条注释,其中列出了它支持的所有选项(如果您需要沿着这条路线走)。
我正在尝试从 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' 创建共享库以创建 .so
库。
尝试的步骤:
将
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>)
- 在终端中打开了源目录
- 运行
cmake
- 运行
make
但是,无论我将 ANDROID_ARCH_ABI
设置为什么,在 运行 宁 cmake
之后 make
结果 .so
库的 ABI始终与 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
库总是:
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_*
变量。
有关可用标志的细分,请参阅 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
没有列在第一个 table 中,因为用户在通过 gradle 使用 CMake 时不必担心它,但它被进一步记录页)
如果您使用的是 r18 之前的 NDK(您不是,但可能其他登陆此处的人会使用)该页面上不再列出一些额外的标志(例如 ANDROID_TOOLCHAIN
).工具链文件本身的顶部有一条注释,其中列出了它支持的所有选项(如果您需要沿着这条路线走)。