Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android NDK, CMake with other libraries

So I am trying to build and test out a CMake with the Android NDK on Android Studio. I can get my library to compile, but it doesn't seem to want to pull any third-party dependencies over. I've been reading through the toolchain and looking for better documentations, with no luck. Can someone tell me if I am missing?

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)

Above is my CMakeLists.txt. I have done a little hacking to get it to compile with SFML with the paths, as I have not found good documentation with CMake and Android yet.

like image 387
ptDave Avatar asked Jun 13 '16 02:06

ptDave


2 Answers

May you add more info for: "but it doesn't seem to want to pull any third-party dependencies over."?

this one:
https://github.com/googlesamples/android-ndk/tree/master/hello-libs has static and shared 3rd party libs, you may try it.

For the shared dependent lib, you will need to pack them into APK, that is done inside gradle, cmake will not do it.
The above example shows that, basically they need to be copied into your app/src/main/jniLibs too so they will be packed into apk, and pushed to your android phone/tablet. At runtime they could be loaded.
I have tried to put a group of libraries into one directory, and use

  • link_directories(...)

then just put the lib names directly into

  • target_link_libraries(...)

also works. Make sure you have the right libs for the ABIs you intend to support for your app [looks like you are just building for one ABI].

like image 155
Gerry Avatar answered Nov 09 '22 01:11

Gerry


The process could be little long it will depend on your android skills.

An example could be similar to this process:

  • Crosscompile sfml.
  • Create your jni bridge
  • Generate with cmake the project and compile
  • Copy your files to android studio. create java loading library code.

I guess that you have crosscompiled sfml and you know how works crosscompiling process, if I am wrong check these link below:

Tutorial: https://github.com/SFML/SFML/wiki/Tutorial:-Building-SFML-for-Android

Source code: https://github.com/SFML/SFML

Toolchain: https://github.com/SFML/SFML/blob/master/cmake/toolchains/android.toolchain.cmake

Changes on your cmake: add this file

FIND_PACKAGE(SFML required)

In cmake put your SFML build directory and cmake will fills your VARIABLES automatically for instance this variables:

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) 

There are two ways to make android studio native apps:

Easy way: Create JNI bridge:

Crosscompile your cmake script and copy your lib to app/src/main/jniLibs

add library in execution time

code:

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

More complete way (it allows to debug library)

Create your ndk module in gradle example

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")
}
like image 33
uelordi Avatar answered Nov 09 '22 00:11

uelordi