Android NDK, CMake with other libraries - android-ndk

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.

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

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")
}

Related

msvc & cmake fully link static library with other static libraries (bundle) [duplicate]

I want to bundle five static libraries into one library in CMake. How can I proceed for this?
Like library a, b, c, d, and e should bundle into alpha_lib.
If you are using Visual Studio, you can take advantage of the Microsoft Library Manager (LIB.exe) to combine your static libraries into one. Your CMake could follow these steps:
Use find_program() to have CMake locate the MSVC lib.exe tool on your system. If you run cmake from the Visual Studio Command Prompt, find_program can locate lib.exe automatically, without using the optional PATHS argument to tell it where to look.
Use CMake's add_custom_target() command to call lib.exe using the syntax for merging libraries:
lib.exe /OUT:alpha_lib.lib a.lib b.lib c.lib d.lib e.lib
You can use target-dependent generator expressions in the custom target command to have CMake resolve the locations of your built libraries. The custom target will create a Project in your Visual Studio solution that can be run separately to merge all of the built static libraries into one library.
Your CMake could look something like this:
# Create the static libraries (a, b, c, d, and e)
add_library(a STATIC ${a_SOURCES})
...
add_library(e STATIC ${e_SOURCES})
# Tell CMake to locate the lib.exe tool.
find_program(MSVC_LIB_TOOL lib.exe)
# If the tool was found, create the custom target.
if(MSVC_LIB_TOOL)
add_custom_target(CombineStaticLibraries
COMMAND ${MSVC_LIB_TOOL} /OUT:$<TARGET_FILE_DIR:a>/alpha_lib.lib
$<TARGET_FILE:a>
$<TARGET_FILE:b>
$<TARGET_FILE:c>
$<TARGET_FILE:d>
$<TARGET_FILE:e>
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
endif()

CMake Precompiled Headers not including correctly for Visual Studio

So I've recently started using the "new" target_precompile_headers command for CMake to generate and include my precompiled headers.
But for some reason it doesn't seem to work at all the way I want it.
I do understand that the usage of this command is to provide the list of headers to include in your pch and that CMake itself generates the actual pch. This seem to work just fine as I can see the pchs generated for each config & project in my solution.
However looking at the project properties, and more specifically looking at the .cpp properties the /FI command is always empty, which means no files are force included.
This also means that none of my cpp catches that I am using pch at all and my compile fails.
Does anyone have any suggestions on what could be wrong?
// Example of a CMakeLists.txt which defines a static lib using PCH
file(GLOB ALL_SOURCE_FILES "*.cpp" "*.h")
add_library(MyLib STATIC ${ALL_SOURCE_FILES})
target_precompile_headers(MyLib PRIVATE MyHeader.h)
Below you see my own lib created with the snippet above. As you can see, no Forced Include file is added, thus no cpp files gets the PCH included.
I found this workaround: Adding the compiler option manually...
if(MSVC)
target_compile_options(YourProject PRIVATE "/FI${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}.dir/$<CONFIG>/cmake_pch.hxx")
endif()
(Currently using Cmake 3.24.1 with cmake_minimum_required(VERSION 3.18) in the file)

Whats the proper way to link Boost with CMake and Visual Studio in Windows?

I am trying to generate some Boost 1.58 libraries that I need (chrono, regex and thread) for Visual Studio 2012 and link the libraries with CMake. I have real problems for CMake and Visual Studio to find or link the libs, depending on the configuration I set.
I am finally using the following configuration:
bjam.exe --link=static --threading multi --variant=debug stage
But this doesn't seem to generate static libs.
How should I generate the libs and search them with CMake in order for Visual Studio to link them properly?
I finally came up with the solution and I think it is detailed enough to become a generic answer.
Visual Studio searches for dynamic libraries so we need to compile Boost libraries as shared, multithreaded, debug and release, and runtime-link shared. In windows using bjam.exe all commands have the prefix "--" except link, so the right way to build the libraries is:
bjam.exe link=shared --threading=multi --variant=debug --variant=release --with-chrono --with-regex --with-thread stage
This will generate the libs and DLLs in the folder Boost/stage/lib, so we need to set an environment variable Boost_LIBRARY_DIR C:/Boost/stage/lib, for example.
There are more options that may come in hand:
runtime-link = shared/static
toolset= msvc-11.0
The libraries will have a name like this for release:
boost_chrono-vc110-mt-1_58.lib
boost_chrono-vc110-mt-1_58.dll
And for debug:
boost_chrono-vc110-mt-gd-1_58.lib
boost_chrono-vc110-mt-gd-1_58.dll
In order for CMake to link them properly we need to write the following in the CMakeLists.txt:
add_definitions( -DBOOST_ALL_DYN_LINK ) //If not VS will give linking errors of redefinitions
set(Boost_USE_STATIC_LIBS OFF )
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost COMPONENTS thread chrono regex REQUIRED )
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES( ${PROJ_NAME} ${Boost_LIBRARIES} )
bjam.exe --link=static --threading multi --variant=debug stage
But this doesn't seem to generate static libs.
Building the special stage target places Boost library binaries in the stage\lib\ subdirectory of the Boost tree.
More about building Boost on Windows here
CMake:
SET (CMAKE_BUILD_TYPE Debug) # in order to link with boost debug libs you may need to set that to build your program in debug mode (or do that from command line)
FIND_PACKAGE (Boost 1.58 COMPONENTS "chrono" "regex" "thread" REQUIRED)
#ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK) # make sure you don't have this as it will try to link with boost .dll's
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
TARGET_LINK_LIBRARIES(${EXE_OR_LIB_NAME} ${Boost_LIBRARIES})

Integrating LibYUV to my Android Studio Project

I was wondering how do I include libyuv library to my Android Studio Project. I have the "libyuv_static.a" file which is a pre-compiled binary file but I did everything to include it in my project. I created a folder inside src/main named jniLibs and puted the binary file inside the folder but in runtime it doesn't load the library and it gives me this:
Caused by: java.lang.UnsatisfiedLinkError: Couldn't load libyuv2rgb
from loader
dalvik.system.PathClassLoader[dexPath=/data/app/com.example.myproject-1.apk,libraryPath=/data/app-lib/com.example.myproject-1]:
findLibrary returned null
. Could someone please share his/her experience.
In order to include a native library into an Android project, you have to get a .so file (shared library), not a .a (static library).
ie. you should end up with src/main/jniLibs/<abi>/libyuv_shared.so with <abi> being armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64 (any architecture your app and lib support).
There is an Android package now: https://github.com/crow-misia/libyuv-android, installable from mavenCentral:
dependencies {
implementation 'io.github.crow-misia.libyuv:libyuv-android:0.25.0'
}
For usage see https://github.com/crow-misia/libyuv-android/blob/main/sample/src/main/java/app/MainActivity.kt

Build boost.thread - lib file not found

I am trying to build the boost.thread library for Visual Studio 9.0. I used bjam to build the lib-files:
bjam toolset=msvc-9.0 variant=release threading=multi link=shared
The compilation succeeded and I got plenty of .lib and .dll files under boost/stage/lib.
Then I added include path and the above lib path to Visual Studio 9.0.
But when I try to compile some program, I always get the following error:
libboost_thread-vc90-mt-s-1_49.lib cannot be opened.
The lib file created by the build has slightly another name:
boost_thread-vc90-mt-1_49.lib
I tried to rename my file to match the expected name, but Visual Studio still cannot find the file.
It seems that the filename beeing seaarched depends on the project option "C/C++ / Code generation / runtime library". I need the option "Multithreaded /MT".
What am I doing wrong?
Thank you in advance.
You're trying to link statically with CRT, but dynamically - with Boost. This is not a good idea, but if you insist, you should define BOOST_ALL_DYN_LINK macro.
Better option would be to select /MD in your project options, or to set "link=static" when building boost.

Resources