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 :)
Related
For my project, I am trying to integrate a c++ library into an Android app. This library uses PyTorch.
For the first test implementation I used the example from https://github.com/ademar111190/CppAndroidIosExample and try to add my PyTorch Lib.
Building it outside of Android Studio worked, but as soon as I build it internally the error comes up:
Your installed Caffe2 version uses CUDA but I cannot find the CUDA
libraries. Please set the proper CUDA prefixes and / or install CUDA.
Call Stack (most recent call first):
C:/DEV/libtorch/share/cmake/Torch/TorchConfig.cmake:40 (find_package)
CMakeLists.txt:16 (find_package)
I compared both builds in the cmake-gui and found that the Android build was missing the CUDA_TOOLKIT_ROOT_DIR entry.
Solution attempts
1:
I tried to enter the whole thing via the GUI, however when generating outside of Android Studio the error came up:
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:
log-lib
linked by target "native-lib" in directory
2:
I try to add the PATH to Windows, but it did not work
3:
I try to add to CMakeLists.txt:
set(CUDA_TOOLKIT_ROOT_DIR "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.2")
System: Win 10 64
CUDA Version: 11.2
CMAKE Version: 3.19.2
Changed Files
./Android/app/CMakeLists.txt:
cmake_minimum_required(VERSION 3.4.1)
project(native-lib)
list(APPEND CMAKE_PREFIX_PATH C:/DEV/libtorch)
set(Torch_DIR C:/DEV/libtorch/share/cmake/Torch)
set(Caffe2_DIR C:/DEV/libtorch/share/cmake/Caffe2)
set(CMAKE_CUDA_COMPILER "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v11.2/bin/nvcc")
find_package(Torch REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
include_directories (
../../CPP/
)
add_library(
native-lib
SHARED
src/main/cpp/native-lib.cpp
../../CPP/Core.h
../../CPP/Core.cpp
)
find_library(
log-lib
log
)
target_link_libraries(
native-lib
${log-lib}
${TORCH_LIBRARIES}
)
set_property(TARGET native-lib PROPERTY CXX_STANDARD 14)
if (MSVC)
file(GLOB TORCH_DLLS "${TORCH_INSTALL_PREFIX}/lib/*.dll")
add_custom_command(TARGET native-lib
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${TORCH_DLLS}
$<TARGET_FILE_DIR:native-lib>)
endif (MSVC)
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 )
First of all, this is my error.
Build command failed.
Error while executing process /Users/{user}/Library/Android/sdk/cmake/3.6.4111459/bin/cmake with arguments {--build /Users/{user}/Desktop/android/app/.externalNativeBuild/cmake/debug/arm64-v8a --target native-lib}
ninja: error: 'src/main/jniLibs/zlib/arm64-v8a/lib/libz.a', needed by '../../../../build/intermediates/cmake/debug/obj/arm64-v8a/libnative-lib.so', missing and no known rule to make it
I have a statically linked prebuilt zlib.a library for every ARCHs (armeabi, armeabi-v7a, arm64-v8a, x86, x86_64) and placed the library like this.
app/src/main/jniLibs/zlib/${ANDROID_ABI}/include/zlib.h
app/src/main/jniLibs/zlib/${ANDROID_ABI}/lib/libz.a
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib SHARED src/main/cpp/native-lib.cpp)
add_library(libz STATIC IMPORTED)
set_target_properties(libz PROPERTIES IMPORTED_LOCATION src/main/jniLibs/zlib/${ANDROID_ABI}/lib/libz.a)
include_directories(src/main/jniLibs/zlib/${ANDROID_ABI}/include)
find_library(log-lib log)
target_link_libraries(native-lib libz ${log-lib})
in a Java file,
static {
System.loadLibrary("libz");
System.loadLibrary("native-lib");
}
I don't have no idea about this issue. It seems okay. I don't touch build.gradle, should I? What am I missing? What is problem?
Property IMPORTED_LOCATION should be an absolute path.
Use ${CMAKE_CURRENT_SOURCE_DIR} for refer to the directory with currently processed CMakeLists.txt:
set_target_properties(libz PROPERTIES
IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/zlib/${ANDROID_ABI}/lib/libz.a)
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)
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?