Android ndk Android NDK、CMake和其他库

Android ndk Android NDK、CMake和其他库,android-ndk,cmake,Android Ndk,Cmake,所以我尝试在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_N

所以我尝试在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的好文档。

这个过程可能有点长,这取决于您的Android技能

示例可能与此过程类似:

  • 交叉编译sfml
  • 创建您的jni桥
  • 使用cmake生成项目并编译
  • 将文件复制到android studio。创建java加载库代码
我猜您已经交叉编译了sfml,并且您知道交叉编译过程是如何工作的,如果我错了,请检查以下链接:

教程:

源代码:

工具链:

您的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脚本并将lib复制到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模块 范例

您是否可以为以下内容添加更多信息: “但它似乎不想改变任何第三方依赖关系。”

这个:
有静态和共享的第三方LIB,您可以试试

对于共享依赖库,您需要将它们打包到APK中,这是在gradle中完成的,cmake不会这样做。
上面的例子表明,基本上它们也需要复制到你的app/src/main/jniLibs中,这样它们就会被打包到apk中,并被推送到你的android手机/平板电脑上。在运行时可以加载它们。
我尝试将一组库放在一个目录中,并使用

  • 链接目录(…)
然后直接将库名称放入

  • 目标链接库(…)

同样有效。确保你的应用程序准备支持的ABI具有正确的LIB[看起来你只是在为一个ABI构建]。

因此,这是我的build.gradle。我一直在遵循这一点:我听起来很奇怪。你的.gradle文件,我只对第三方交叉编译元素使用了cmake。假设您的sfm库是从armv7或任何其他体系结构交叉编译而来的,您应该创建ndk模块。语法将取决于gradle版本使用的是什么,在我的例子中,我使用的是0.4.0 Expermental。如果你为多个ABI编译,你在jniLibs下面有合适的子目录吗?你的第二种方法是关于编辑CMakeLists.txt吗?是的,在CMakeLists.txtI中,我不确定AS是否用于自动生成app/src/main/jniLibs dir,但它似乎没有任何其他链接已经损坏。
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")
}