CMake find_library is failing to find a library - android

CMake is failing to find a library and I don't know why. This is the portion of my CMakeLists.txt that is supposed to find the library:
set(SODIUM_DIR ${PROJECT_SOURCE_DIR}/../../../deps/install/libsodium/android-${ANDROID_ABI}/lib)
message(STATUS SODIUM_DIR=${SODIUM_DIR})
find_library(sodium-lib
libsodium.a
PATHS ${SODIUM_DIR}
NO_DEFAULT_PATH)
Part of CMake's output is:
-- SODIUM_DIR=/Users/csimmons/Documents/repos/onedoclily/client/Android/app/../../../deps/install/libsodium/android-armeabi-v7a/lib
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
-- Configuring incomplete, errors occurred!
Please set them or make sure they are set and tested correctly in the CMake files:
See also "/Users/csimmons/Documents/repos/onedoclily/client/Android/app/.externalNativeBuild/cmake/debug/armeabi-v7a/CMakeFiles/CMakeOutput.log".
sodium-lib
linked by target "native-lib" in directory /Users/csimmons/Documents/repos/onedoclily/client/Android/app
Build command failed.
Running "ls" on SODIUM_DIR shows that the library is there:
$ ls /Users/csimmons/Documents/repos/onedoclily/client/Android/app/../../../deps/install/libsodium/android-armeabi-v7a/lib
libsodium.a libsodium.la libsodium.so pkgconfig

I believe that I've been able to solve the problem by using add_library and set_property instead of find_library.
set(SODIUM_PATH ${PROJECT_SOURCE_DIR}/../../../deps/install/libsodium/android-${ANDROID_ABI}/lib/libsodium.a)
add_library(sodium-lib STATIC IMPORTED)
set_property(TARGET sodium-lib PROPERTY IMPORTED_LOCATION ${SODIUM_PATH})
target_link_libraries( # My code's library.
native-lib
sodium-lib
)

The tag NAMES is missing before the list of possible names.
Fixed:
find_library(sodium-lib
NAMES libsodium.a
PATHS ${SODIUM_DIR}
NO_DEFAULT_PATH)
See How can I find a library name of .so file?

Related

CMake Error at CMakeLists.txt (target_link_libraries) when adding logs

I have an ndk project with a CMakeLists.txt that looks like so
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror")
add_library( # Specifies the name of the library.
main
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
main.c)
target_link_libraries(
android
log
)
it follows the pattern laid out in all of the NDK example projects listed on the googlesamples github repo. I keep getting CMake Error at CMakeLists.txt (target_link_libraries), and it seems like most people are solving it with this line
add_library(debug <files Name>)
but no one is adding that for logging. What am I doing wrong?
add below to your CMakeLists.txt above the line of target_link_libraries.
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 )
Then modify target_link_libraries as below for linking android log lib
target_link_libraries( # Specifies the target library.
main
# Links the target library to the log library
# included in the NDK.
${log-lib} )
1) in your code source folder, look for something like "Android.mk" or "project.mk", then remember the path of it.
2) go to android studio and click File ==> link c++ project with gradle ==> choose build system ndk-build , then look for the .mk file you found first.
click ok , and sync project.

Unable to link libCurl.a static library in CMake on Android

I am new to CMake and spent almost 2 weeks searching all over the internet trying to figure out why I am unable to link libcurl static libraries with my cpp sources in Cmake within my android project.
I found this repo: https://github.com/gcesarmza/curl-android-ios that I used to generate my static libraries for libcurl. It has dependencies with openssl and libz ( I dont know what else it's built with)
Here's my cmake:
cmake_minimum_required(VERSION 3.4.1)
include_directories(
${EXTERNAL}/libCurl/include/
#${EXTERNAL}/openssl/include/
)
add_library(
libcurl
STATIC IMPORTED SHARED
)
set_target_properties(
libcurl
PROPERTIES IMPORTED_LOCATION
${EXTERNAL}/libcurl/lib/android/libcurl.a
)
add_library(
libz
STATIC IMPORTED
)
set_target_properties(
libz
PROPERTIES IMPORTED_LOCATION
${EXTERNAL}/zlib/lib/armeabi-v7a/libz.a
)
set(WHARE_LIBRARY Whare_Native)
add_library(
${WHARE_LIBRARY}
SHARED
${CPP_SOURCE}/MyWebRequest.cpp
)
target_link_libraries(
${WHARE_LIBRARY}
libcurl
libz
)
I have a simple cpp implementation that makes curl calls such as curl_easy_init(). I am getting the following linker error when I build the project with this CMake file:
[9/9] Linking CXX shared library
../../../../build/intermediates/cmake/debug/obj/arm64-
v8a/libWhare_Native.so
FAILED: : && /Users/jay.nagar/Library/Android/sdk/ndk-
bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --
target=aarch64-none-linux-android --gcc-
.........
.........
.........
.........
WhareWebRequest.cpp:40: undefined reference to `curl_easy_init'
clang++: error: linker command failed with exit code 1 (use -v to see
invocation)
ninja: build stopped: subcommand failed.
I have spent days on Stackoverflow , GitHub and other sources and also tried many solutions that have been suggested, such as:
How to use libcurl as a static library with cmake?
and
Linking static libraries with c++/cmake
I also looked up CMake official documentation to understand the different properties. I experimented with CFLAGS, CURL_LIBRARY, find_library and what not. Like I said, I am a total newbie when it comes to Cmake configurations. Can anyone make sense of the type of error I am getting? I think its related to issues linking with the static libs but I am not sure. Can someone help debug this problem that I am deep into for days!
Thanks and help much appreciated!
https://imgur.com/a/gLN9ctq
libcutils.so is a private system library and is no longer allowed to be linked by app since API level 24.
See this link
How to solve UnsatisfiedLinkError?
---- Edit ----
You need to specify the correct static lib path for each Android ABI using CMake variable ${ANDROID_ABI}.
Change below code
set_target_properties(
libcurl
PROPERTIES IMPORTED_LOCATION
${EXTERNAL}/libcurl/lib/android/libcurl.a
)
to
set_target_properties(
libcurl
PROPERTIES IMPORTED_LOCATION
${EXTERNAL}/libcurl/lib/android/${ANDROID_ABI}/libcurl.a
)
And ensure that you have all the needed architectures (ABI) of your libcurl.a, e.g. armeabi-v7a, arm64-v8a, x86, x86_64
The issue was with incorrectly generated libs for the libcurl static libraries. I found some prebuilt .a files here that worked for me: https://github.com/gcesarmza/curl-android-ios/tree/master/prebuilt-with-ssl/android
and
https://github.com/djp952/prebuilt-libz
It was just pure luck that I found something out of several prebuilt libs that just happened to work. I would be happier if I could generate those myself but in any case, at least I am not blocked :)

Link .so library in android studio project

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)

Adding sub directory in cmake not working

I'm trying to add another cmake project which has CMakeLists.txt file as a compilation dependency which i can use in another .cpp file.
Location of project which i want to add: Users/brainfreak/Downloads/assimp-master/
Location of main project: /Users/brainfreak/AndroidStudioProjects/ModelShow/app/src/main/cpp/hellojni.cpp
This is used as a native code in a Android Studio project. I followed the tutorial in https://developer.android.com/studio/projects/add-native-code.html#create-cmake-script under "Include other CMake projects"
This is the main CMakeLists.txt that i came up with:
/Users/brainfreak/AndroidStudioProjects/ModelShow/app/src/main/cpp/CMakeLists.txt
cmake_minimum_required( VERSION 2.6 )
add_library(model-lib SHARED hellojni.cpp)
set (src_dir Users/brainfreak/Downloads/assimp-master/)
set (output_dir Users/brainfreak/Downloads/assimp-master/output)
file(MAKE_DIRECTORY ${output_dir})
add_subdirectory(${src_dir} ${output_dir})
add_library(assimp STATIC IMPORTED)
set_target_properties( assimp PROPERTIES IMPORTED_LOCATION
${output_dir}/${ANDROID_ABI}/assimp)
include_directories(${src_dir}/include)
target_link_libraries(model-lib assimp)
The error i always get:
Execution failed for task ':app:externalNativeBuildDebug'.
> Build command failed.
Error while executing process /Users/brainfreak/Android/sdk/cmake/3.6.3155560/bin/cmake with arguments {--build /Users/brainfreak/AndroidStudioProjects/ModelShow/app/.externalNativeBuild/cmake/debug/x86 --target model-lib}
ninja: error: 'Users/brainfreak/Downloads/assimp-master/output/x86/assimp', needed by '/Users/brainfreak/AndroidStudioProjects/ModelShow/app/build/intermediates/cmake/debug/obj/x86/libmodel-lib.so', missing and no known rule to make it
I don't know what file to place under "${output_dir}/${ANDROID_ABI}/" for the script to find. Can you tell where i'm going wrong?
Assuming that you got one of the latest releases from https://github.com/assimp and followed the instructions (note that this was tested with NDK r14, available for download from https://developer.android.com/ndk/downloads/older_releases), you have produced file libassimp.so inside project "Code" folder. Make sure that you build the x86 version of the library.
Copy this file to /Users/brainfreak/Downloads/assimp-master/output/x86/, and prepare your CMakeLists.txt:
cmake_minimum_required( VERSION 2.6 )
add_library(model-lib SHARED hellojni.cpp)
set (src_dir /Users/brainfreak/Downloads/assimp-master/)
set (output_dir /Users/brainfreak/Downloads/assimp-master/output)
file(MAKE_DIRECTORY ${output_dir})
add_subdirectory(${src_dir} ${output_dir})
add_library(assimp STATIC IMPORTED)
set_target_properties( assimp PROPERTIES IMPORTED_LOCATION
${output_dir}/${ANDROID_ABI}/libassimp.so)
include_directories(${src_dir}/include)
target_link_libraries(model-lib assimp)
Note that the file that your script was missing slash (/) before Users which could cause the confusion.
Don't forget to set abiFilters in your app/build.gradle:
ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your APK.
abiFilters 'x86'
}

How to dependency to Android native code using CMake?

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 !

Categories

Resources