Im using prebuilt android native library: libcrypto.a.
Library is compiled for armeabi, armeabi-v7a and x86.
Structure:
-app
- CMakeLists.txt
- libs
- armeabi
- armeabi-v7a
- x86
Each folder (armeabi, armeabi-v7a and x86) contains folders lib(contains libcrypto.a) and include (contains header files).
CMake code:
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
add_library(crypto STATIC IMPORTED)
set_target_properties(crypto
PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/lib/libcrypto.a)
target_link_libraries( # Specifies the target library.
native-lib
crypto
# Links the target library to the log library
# included in the NDK.
${log-lib})
In my own native-lib i wanna use libcrypto.a. But when i wanna import header file f.e. #include "openssl/md5.h" android studio does not see that file.
And offer me to include one of THREE files from different abis:
"../../../libs/x86/include/openssl/md5.h"
"../../../libs/armeabi/include/openssl/md5.h"
"../../../libs/armeabi-v7a/include/openssl/md5.h"
Is there any way to create one version of my library (native-lib), include only 1 header and let android studio to choose abi automatically?
Smth like:
#include "openssl/md5.h"
but in the same time use 3 abi version.
Or i should use prebuilt included libraries not like that?
#EDIT1
target_include_directories(crypto INTERFACE ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/include)
Not working, getting CMake error.
Before that i have used
target_include_directories(${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/include/)
You need to add an include directory so that the compiler can find openssl/md5.h.
The most idiomatic way to do this would be:
target_include_directories(crypto INTERFACE
${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/include)
Unfortunately, CMake is silly, and doesn't actually let you do this yet on imported library targets, so you have to set the property manually, like so:
set_target_properties(crypto
PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/lib/libcrypto.a
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/include
)
That adds that include directory to the interface of crypto, which means it also gets used when building native-lib, as properties which are preceded with INTERFACE are propagated to the users of that target. Using INTERFACE properties is the natural way in CMake to propagate usage requirements to consumers of a library.
Could you please try to one of the codes below:
include_directories("${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/include")
Or
target_include_directories(native-lib "${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/include")
If I'm not wrong, target_include_directories include files to a specific target. Since you are importing the header file in your native-lib files, target_include_directories must aim the native-lib.. and not crypto.. Those header files are not necessary to crypto... but to native-lib.
For any case, you can set include_directories which will add those header files to all targets (native-lib and crypto).
Also, remember:
1 - Edit your CMakeLists.txt
2 - Perform a project sync
3 - Only after that, open your native-lib.cpp file and try to import the file header file again.
Related
Hello I am beginner in Android NDK programming and I need some help getting freetype library to work with my project. I've been trying for 3 hours straight to somehow import freetype to my Android Studio project. I searched on the internet and could not find any solution that was working. I downloaded the library and put it in my cpp folder of the project.But I don't know how to include freetype. Any help would be appreaciated!
This is how my CMakeLists.txt look and for the files that I have added it works for them:
cmake_minimum_required(VERSION 3.10.2)
project("firstnative")
include_directories(stb/stb_lib
GoldFlow/Core
GoldFlow/Graphics
GoldFlow/Math
GoldFlow/glm
GoldFlow/glm/gtc
GoldFlow/entt
GoldFlow/physics
GoldFlow/scripts
GoldFlow/freetype/include
GoldFlow/freetype/include/freetype/
GoldFlow/freetype/include/freetype/config
GoldFlow/freetype/include/freetype/internal
GoldFlow/freetype/include/freetype/internal/services
)
add_library(
Native
SHARED
GoldFlow/Math/GoldMath.cpp
GoldFlow/Graphics/Shader.cpp
GoldFlow/Graphics/Renderer2D.cpp
GoldFlow/Graphics/Camera.cpp
GoldFlow/Graphics/Texture.cpp
GoldFlow/Graphics/SpriteSheet.cpp
GoldFlow/Core/Scene.cpp
GoldFlow/Core/GameObject.cpp
GoldFlow/Core/Application.cpp
GoldFlow/Core/Controls.cpp
GoldFlow/Core/Timer.cpp
GoldFlow/physics/AABB.cpp
GoldFlow/physics/Objects.cpp
GoldFlow/scripts/ControllerScript.cpp
GoldFlow/scripts/CharacterMovingScript.cpp
native.cpp)
add_library(
Freetype
SHARED
GoldFlow/freetype/src/autofit/autofit.c
GoldFlow/freetype/src/base/ftbase.c
GoldFlow/freetype/src/base/ftbbox.c
GoldFlow/freetype/src/base/ftbdf.c
GoldFlow/freetype/src/base/ftbitmap.c
GoldFlow/freetype/src/base/ftcid.c
GoldFlow/freetype/src/base/ftfstype.c
GoldFlow/freetype/src/base/ftgasp.c
GoldFlow/freetype/src/base/ftglyph.c
GoldFlow/freetype/src/base/ftgxval.c
GoldFlow/freetype/src/base/ftinit.c
GoldFlow/freetype/src/base/ftmm.c
GoldFlow/freetype/src/base/ftotval.c
GoldFlow/freetype/src/base/ftpatent.c
GoldFlow/freetype/src/base/ftpfr.c
GoldFlow/freetype/src/base/ftstroke.c
GoldFlow/freetype/src/base/ftsynth.c
GoldFlow/freetype/src/base/fttype1.c
GoldFlow/freetype/src/base/ftwinfnt.c
GoldFlow/freetype/src/bdf/bdf.c
GoldFlow/freetype/src/bzip2/ftbzip2.c
GoldFlow/freetype/src/cache/ftcache.c
GoldFlow/freetype/src/cff/cff.c
GoldFlow/freetype/src/cid/type1cid.c
GoldFlow/freetype/src/gzip/ftgzip.c
GoldFlow/freetype/src/lzw/ftlzw.c
GoldFlow/freetype/src/pcf/pcf.c
GoldFlow/freetype/src/pfr/pfr.c
GoldFlow/freetype/src/psaux/psaux.c
GoldFlow/freetype/src/pshinter/pshinter.c
GoldFlow/freetype/src/psnames/psnames.c
GoldFlow/freetype/src/raster/raster.c
GoldFlow/freetype/src/sfnt/sfnt.c
GoldFlow/freetype/src/smooth/smooth.c
GoldFlow/freetype/src/truetype/truetype.c
GoldFlow/freetype/src/type1/type1.c
GoldFlow/freetype/src/type42/type42.c
GoldFlow/freetype/src/winfonts/winfnt.c
)
find_library(
log-lib
log )
find_library(GLES-lib
GLESv3)
target_link_libraries(
Native
${log-lib}
${GLES-lib}
${Freetype}
)
The error I am getting now is this: C:\Users\infer\AndroidStudioProjects\FirstNative\app\src\main\cpp\GoldFlow\freetype\src\base\ftbdf.c:40:14: error: use of undeclared identifier 'FT_ERR_PREFIXInvalid_Face_Handle'; did you mean 'FT_Err_Invalid_Face_Handle'?
Ok the solution was very simple. All I did actually was I created directory in cpp folder named freetype and in that dir I've put every freetype file and just added that folder as sub directory in CMake and linked at the end and now eveyrthing works. Here is my CMake:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.10.2)
# Declares and names the project.
project("firstnative")
include_directories(stb/stb_lib
GoldFlow/Core
GoldFlow/Graphics
GoldFlow/Math
GoldFlow/glm
GoldFlow/glm/gtc
GoldFlow/entt
GoldFlow/physics
GoldFlow/scripts
GoldFlow/text
)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
Native
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
GoldFlow/Math/GoldMath.cpp
GoldFlow/Graphics/Shader.cpp
GoldFlow/Graphics/Renderer2D.cpp
GoldFlow/Graphics/Camera.cpp
GoldFlow/Graphics/Texture.cpp
GoldFlow/Graphics/SpriteSheet.cpp
GoldFlow/Core/Scene.cpp
GoldFlow/Core/GameObject.cpp
GoldFlow/Core/Application.cpp
GoldFlow/Core/Controls.cpp
GoldFlow/Core/Timer.cpp
GoldFlow/physics/AABB.cpp
GoldFlow/physics/Objects.cpp
GoldFlow/scripts/ControllerScript.cpp
GoldFlow/scripts/CharacterMovingScript.cpp
GoldFlow/text/TextRenderer.cpp
native.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
#sd
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
find_library(GLES-lib
GLESv3)
add_subdirectory(freetype)
target_link_libraries( # Specifies the target library.
Native
# Links the target library to the log and gl es library
# included in the NDK.
${log-lib}
${GLES-lib}
freetype
)
I got some C code I have to integrate into my Android project. It depends on a library (.so), and I also have the .h files.
I copied the libs and include directories into the project's cpp package to make them easier to find.
To make it easier I tried starting with the HelloJNI project Android Studio offers and followed the instructions here.
This is the CMakeLists.txt:
#given from HelloJNI
cmake_minimum_required(VERSION 3.4.1)
add_library(hello-jni SHARED
hello-jni.c)
# Include libraries needed for hello-jni lib
target_link_libraries(hello-jni
android
log)
#my own additions now:
add_library( # Specifies the name of the library.
libgdndk
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
IMPORTED)
set_target_properties( # Specifies the target library.
libgdndk
# Specifies the parameter you want to define.
PROPERTIES IMPORTED_LOCATION
# Provides the path to the library you want to import.
${CMAKE_BINARY_DIR}/libs/${ANDROID_ABI}/libgdndk.so )
include_directories(${CMAKE_BINARY_DIR}/inc/)
target_link_libraries( hello-jni libgdndk app-glue ${libgdndk} )
This results in an error:
ninja: error: 'libs/armeabi-v7a/libgdndk.so', needed by 'C:/workspace/android/HelloJNI/app/build/intermediates/cmake/arm7/debug/obj/armeabi-v7a/libhello-jni.so', missing and no known rule to make it
You seem to be linking your imported library to the hello-jni target twice. Also, using ${} in the target_link_libraries() command for the libgdndk library is not necessary. You have already defined a CMake target libgdndk for the library, so you can just do this:
target_link_libraries( hello-jni libgdndk app-glue )
I finally got some help from the publisher of the lib, the (working) result looks quite similar to the code i tried, so maybe it was just the location of the library that was at fault.
add_library( gdndk SHARED IMPORTED )
include_directories( $ENV{userprofile}/AppData/Local/Android/sdk/extras/blackberry/dynamics_sdk/sdk/libs/handheld/gd/inc)
set_target_properties(gdndk PROPERTIES IMPORTED_LOCATION $ENV{userprofile}/AppData/Local/Android/sdk/extras/blackberry/dynamics_sdk/sdk/libs/handheld/gd/libs/${ANDROID_ABI}/libgdndk.so )
target_link_libraries( hello-jni gdndk )
As the title suggests I am trying to link a native .so to an android studio project. I have gone through the docs in android developer website and some more articles but unsuccessful in connecting the .so file with the project.
Whenever I try to run the code I get the following error
CMake Error: The following variables are used in this project, but
they are set to NOTFOUND. Please set them or make sure they are set
and tested correctly in the CMake files: testlib
Here is my CMake file
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
add_library(testlib SHARED IMPORTED)
set_property(TARGET testlib PROPERTY IMPORTED_LOCATION "E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/libremotedesktop_client.so")
#find_path(testlib E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/RemoteDesktop.h)
find_library(testlib E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/libremotedesktop_client.so)
#add_library(remote SHARED IMPORTED)
#set_target_properties(remote PROPERTIES IMPORTED_LOCATION libs/${ANDROID_ABI}/libremotedesktop_client.so )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib}
${testlib})
target_include_directories()
I have four .so files each for arm64, armeabi, armeabi-v7a, x86. I have harcoded the armeabi-v7a lib in the path, android studio is throwing the above mentioned error when I do that. My actual aim is to dynamically load the library based on the chip in the phone. I am pretty sure that my current code is not achieving that.
Here are my queries
How to solve the error that I am getting? I have tried giving both relative and absolute path but to no avail I am getting the same error.
How do I add a .so and a .h file into a native android studio project? That has variations based on the chip on which the code is running?
When I directly add the .h file to the native folder I can reference the classes and functions in that header in my C code but I am unable to run the code. I have a getInstance() method in the .h file. Whenever I call the
getInstance() function it says undefined refernce to getInstance(). What I understand from that is the '.h' file is linked correctly but the definition of the function of the .h files which are actually present in the .so files are not linked. I believe this will be solved if question 1 and 2 are answered.
Is it necessary for all native android projects to have a .mk file? I didn't add one to my project and think it might be one of the cause for the error that I am getting.
You don't need find_library in your case. For log, the library is resolved by NDK for you; for libremotedesktop_client.so, you know the exact path.
Here is the CMakeLists.txt that will work for you:
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
add_library(remote SHARED IMPORTED)
set_property(TARGET remote PROPERTY IMPORTED_LOCATION "E:/project/Remote_Native/remote_attempt_1/app/libs/${ANDROID_ABI}/libremotedesktop_client.so")
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
log
remote)
Note that using full path (E:/project…) in CMake script is not the best practice; you probably can express the path to this library somehow relative to the path of your CMakeLists.txt, which is ${CMAKE_CURRENT_SOURCE_DIR}.
1-2). First of all, add set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) at the start of your CMakeLists.txt (just after cmake_minimum_required(...)) to allow another search paths for libraries. After this you can find lib just using standard find_library:
find_library(FOO_LIBRARY
foo # Lib's full name in this case - libfoo.so
PATHS path/to/lib/)
if (NOT FOO_LIBRARY)
message(FATAL_ERROR "Foo lib not found!")
endif()
You can use variable ANDROID_ABI to get particular library version, if directory with libraries organised in this way:
- path/to/lib
- armeabi-v7a
- libfoo.so
- arm64-v8a
- libfoo.so
- x86
- libfoo.so
- x86_64
- libfoo.so
So, search path in this case:path/to/lib/${ANDROID_ABI}/
To include headers in project just use include_directories:
include_directories(path/to/headers)
4). .mk files only needed if you use ndk-build (so you don't need any)
I am using Android Studio 2.2.2 with cmake and Android NDK. I have a problem linking .a library (Static lib).
Here is my cmake:
# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.
add_library(lib_webp SHARED IMPORTED )
set_target_properties(lib_webp PROPERTIES IMPORTED_LOCATION
src/main/jni/${ANDROID_ABI}/libwebp.so)
add_library( # Sets the name of the library.
game-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# Associated headers in the same location as their source
# file are automatically included.
src/main/cpp/main.cpp
src/main/cpp/android_native_app_glue.c
)
target_include_directories(game-lib PRIVATE
../../../../libs/headers/android
)
include_directories($ENV{NDK_MODULE_PATH}/sources/android/native_app_glue/)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
game-lib
# Links the target library to the log library
# included in the NDK.
# ${log-lib}
# Specifies the name of the NDK library that
# you want CMake to locate.
log
android
OpenSLES
z
GLESv2
EGL
dl
)
add_definitions(-g -DANDROID -Wno-write-strings -fsigned-char -Wno-conversion-null)
TARGET_LINK_LIBRARIES(game-lib libtheoraplayer.a)
My linker reports an error
arm-linux-androideabi/bin\ld: error: cannot find -ltheoraplayer
error: undefined reference to 'TheoraVideoManager::TheoraVideoManager(int)'
which is a part of libtheoraplayer.a. Did anyone had similar problem? Any idea how to solve this?
I have the Static lib libtheoraplayer.a present at that location. I even have the Shared lib also, libtheoraplayer.so but I can`t link it either.
Any advice would be appreciated.
Cheers.
To post the answer. As Tsyvarev said, the problem with non-absolute file name for library. When I used absoulte path it worked like a charm.
Thank you.
Cheers.
I am currently writing JNI code for an Android application to use some legacy native code. I chose to use CMake to give it a try (this is my first time using it).
I would like to serialize a quite complex C structure to JSON format using Jansson library. This would to make it more simple to expose it to Java.
Here is my question: How is it possible to import Jansson in my project as a dependency for my own code ?
I tried to import Jansson in my own sources and use a add_subdirectory clause to make it build. As a result, I can see some intermediates CMake files in the output but no actual compiled file.
Here is what my CMake file looks like :
cmake_minimum_required(VERSION 3.4.1)
include_directories(
src/main/cpp/xxx/Include
)
add_subdirectory("src/main/cpp/jansson")
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# Associated headers in the same location as their source
# file are automatically included.
src/main/cpp/xxx/file1.c
src/main/cpp/xxx/file2.c
src/main/cpp/xxx/file3.c
src/main/cpp/xxx/file4.c
src/main/cpp/native-lib.cpp )
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
Any help will be welcomed !!
Okay, so I was just missing to declare the dependency of my library on Jansson. This is made by adding its project name to the existing target_link_library clause.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
jansson
${log-lib} )
In case someone else (well maybe my future self) stumbles on the same problem, here are all the necessary steps to add a native dependency in an Android CMake file:
Find a library already supporting CMake
Import library code in your project (I used git submodule)
Add add_subdirectory clause that points to the folder containing the library CMake file
Add include files to include_directories (hopefully, the imported library set a variable for that, such as JANSSON_INCLUDE_DIRS in my case
Add dependency by adding the library project name to the target_link_libraries clause
Once this is done: poof ! magic ! everything works fine !