Android NDK,使用CMake与其他库

15

所以我正在尝试在Android Studio上使用Android NDK构建和测试一个带有CMake的项目。我已经成功编译了我的库,但它似乎不想拉取任何第三方依赖项。我一直在阅读工具链并寻找更好的文档,但都没有任何进展。请问是否有人能告诉我是否有什么地方出了问题?

cmake_minimum_required(VERSION 3.4.1)

set(SFML_PATH ${ANDROID_NDK}/sources/sfml)
set(SFML_LIB_PATH ${SFML_PATH}/lib/${ANDROID_NDK_ABI_NAME})

set(SFML_LIB_SYSTEM ${SFML_LIB_PATH}/libsfml-system.so)
set(SFML_LIB_AUDIO ${SFML_LIB_PATH}/libsfml-audio.so)
set(SFML_LIB_GRAPHICS ${SFML_LIB_PATH}/libsfml-graphics.so)
set(SFML_LIB_NETWORK ${SFML_LIB_PATH}/libsfml-network.so)
set(SFML_LIB_WINDOW ${SFML_LIB_PATH}/libsfml-window.so)
set(SFML_LIB_ACTIVITY ${SFML_LIB_PATH}/libsfml-activity.so)
set(SFML_LIB_MAIN ${SFML_LIB_PATH}/libsfml-main.a)


set(SFML_LIBS ${SFML_LIB_SYSTEM} ${SFML_LIB_GRAPHICS} ${SFML_LIB_AUDIO} ${SFML_LIB_WINDOW} ${SFML_LIB_ACTIVITY})

include_directories(${SFML_PATH}/include)
link_directories(${SFML_LIB_PATH})

add_library(native-lib SHARED
    src/main/cpp/native-lib.cpp)

target_link_libraries(native-lib log ${SFML_LIBS})

#file(COPY ${SFML_LIBS} DESTINATION ${__android_install_path})
FOREACH(SFML_LIB ${SFML_LIB})
    execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${SFML_LIB}" "${LIBRARY_OUTPUT_PATH}/${SFML_LIB}" RESULT_VARIABLE __fileCopyProcess )
    MESSAGE("Lib: ${SFML_LIB}")
ENDFOREACH(SFML_LIB)

下面是我的CMakeLists.txt文件。为了让它与SFML一起编译,我已经做了一些修改,包括路径方面的调整,因为我还没有找到关于CMake和Android的好文档。

2个回答

6

请问您需要对以下内容进行补充翻译吗:"但它似乎不想拉取任何第三方依赖项。"?

这个示例https://github.com/googlesamples/android-ndk/tree/master/hello-libs包含静态和共享的第三方库,您可以尝试使用。

对于共享依赖库,您需要将它们打包到APK中,在gradle中完成,而cmake则无法完成此操作。
上面的示例显示,它们基本上需要被复制到您的app/src/main/jniLibs目录中,以便它们被打包到apk并推送到您的Android手机/平板电脑中。在运行时,它们可以被加载。
我曾经尝试将一组库放入一个目录中,并使用

  • link_directories(...)

然后直接将库名称放入

  • target_link_libraries(...)

也可以正常工作。请确保您为应用程序支持的ABI选择了正确的库[看起来您只是为一个ABI构建]。


如果您正在为多个ABI编译,请确保在jniLibs下有适当的子目录。 - bph
你的第二种方法是指编辑CMakeLists.txt吗? - bph
是的,在CMakeLists.txt文件中。 - Gerry
我不确定AS以前是否会自动生成app/src/main/jniLibs目录,但现在似乎不再这样了。 - bph
链接已失效。 - Jon McClung

3
这个过程可能会比较漫长,取决于您的 Android 技能。
一个例子可以类似于这个过程:
1. 交叉编译 sfml。 2. 创建您的 jni 桥接。 3. 使用 cmake 生成项目并编译。 4. 将文件复制到 Android Studio。创建 Java 加载库代码。
我猜你已经交叉编译了 sfml 并且知道交叉编译的过程是如何工作的,如果我错了,请参考下面的链接:
教程: https://github.com/SFML/SFML/wiki/Tutorial:-Building-SFML-for-Android 源代码: https://github.com/SFML/SFML 工具链: https://github.com/SFML/SFML/blob/master/cmake/toolchains/android.toolchain.cmake 更改您的 cmake: 添加此文件。
FIND_PACKAGE(SFML required)

在CMake中,放置您的SFML构建目录,CMake会自动填充您的变量。例如,这些变量:
set(SFML_PATH ${ANDROID_NDK}/sources/sfml)
set(SFML_LIB_PATH ${SFML_PATH}/lib/${ANDROID_NDK_ABI_NAME})

set(SFML_LIB_SYSTEM ${SFML_LIB_PATH}/libsfml-system.so)
set(SFML_LIB_AUDIO ${SFML_LIB_PATH}/libsfml-audio.so)
set(SFML_LIB_GRAPHICS ${SFML_LIB_PATH}/libsfml-graphics.so)
set(SFML_LIB_NETWORK ${SFML_LIB_PATH}/libsfml-network.so)
set(SFML_LIB_WINDOW ${SFML_LIB_PATH}/libsfml-window.so)
set(SFML_LIB_ACTIVITY ${SFML_LIB_PATH}/libsfml-activity.so)
set(SFML_LIB_MAIN ${SFML_LIB_PATH}/libsfml-main.a) 

制作Android Studio原生应用有两种方法:

简单方法:创建JNI桥接:

交叉编译您的CMake脚本并将库复制到app/src/main/jniLibs

在执行时添加库

代码:

try
{
  Log.v(LOG_TAG, "adding your library");
  System.loadLibrary(your_library);
}
catch(UnsatisfiedLinkError e)
{
 Log.e(LOG_TAG,e.getMessage());
}

更全面的方式(它允许调试库)

在gradle中创建你的ndk模块 示例

android.ndk {
    moduleName = "your_library"
    cppFlags.add("-fexceptions")
    //cppFlags.add("-std=c++11")
    //cFlags.add("-fopenmp")
    cppFlags.add("-I" + file("src/main/jni").absolutePath)
    stl = "gnustl_shared" // Which STL library to use: gnustl or stlport
    ldLibs.addAll(["android", "EGL", "GLESv2", "dl", "log", "z"])
    String libsDir = curDir.absolutePath + "/src/main/jniLibs/armeabi/"
    ldLibs.add(libsDir + "your_native_lib.so")
}

这是我的 build.gradle 文件: http://pastebin.com/K3r54H3b我一直在遵循这个链接的指导:http://tools.android.com/tech-docs/external-c-builds - ptDave
你的.gradle文件让我感到奇怪,我只使用cmake来进行第三方交叉编译元素。假设你的sfm库是从armv7或其他架构进行交叉编译的,那么你应该创建一个NDK模块。语法将取决于你使用的gradle版本,在我的情况下,我使用的是0.4.0实验版。 - uelordi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接