Android Studio problem with linking shared library for different ABI - android-studio

For my diploma project, I'm trying to use Android Studio to port my c++ project to android. My c++ project includes my own code and library which was developed before me.
Firstly I was tried to compile the source code of this library to a shared android library. I successfully did it. But when I am compiling the code which uses this library, cmake tells me that my library is incompatible for x86 architecture (I think for others will be too).
When I was compiling the library I use this code for different ABI includes:
if (${ANDROID_ABI} STREQUAL "armeabi-v7a")
include_directories(${ANDROID_SYSROOT}/usr/include/arm-linux-androideabi)
elseif (${ANDROID_ABI} STREQUAL "x86_64")
include_directories(${ANDROID_SYSROOT}/usr/include/x86_64-linux-android)
elseif (${ANDROID_ABI} STREQUAL "x86")
include_directories(${ANDROID_SYSROOT}/usr/include/i686-linux-android)
elseif (${ANDROID_ABI} STREQUAL "arm64-v8a")
include_directories(${ANDROID_SYSROOT}/usr/include/aarch64-linux-android)
endif()
I don't know how to fix that. It looks like I need to link any ABI dependent library, but I don't know how I can understand which library I need. "My" library has many files and it would be hard to just trace all dependencies. So how I can fix that (sure after building "my" library I have *.so for all ABIs and I am linking they to main code using ${ANDROID_ABI})?
I have 2 modules in my Android Studio project: library and application. The library builds well, but I can't link it to the application because cmake tells me that library is an incompatible target. After changing cmakes I got rid of ABI cmake block, but the library still doesn't want to link.
App cmake:
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib
SHARED
src/main/cpp/native-lib.cpp )
find_library(log-lib
log )
add_library( libacheron SHARED IMPORTED )
set(lib_src_DIR ${CMAKE_CURRENT_LIST_DIR}/../acheron_lib/build/Debug/acheron)
set_target_properties(libacheron
PROPERTIES IMPORTED_LOCATION
${lib_src_DIR}/libacheron.so)
include_directories(${CMAKE_CURRENT_LIST_DIR}/../acheron_lib/temp/include)
target_link_libraries( native-lib
libacheron
${log-lib})
lib main cmake:
cmake_minimum_required(VERSION 3.3)
set(ACHERON_GLOBAL_ROOT ${CMAKE_CURRENT_LIST_DIR})
set(ACHERON_GLOBAL_BUILD_DIRECTORY "${ACHERON_GLOBAL_ROOT}/build")
function(acheron_add_subprojects proj_dir_list)
foreach(proj_dir ${proj_dir_list})
add_subdirectory(${proj_dir})
endforeach()
endfunction()
acheron_add_subprojects("${ACHERON_GLOBAL_ROOT}/src/main/acheron")
lib other cmake:
cmake_minimum_required(VERSION 3.3)
project(acheron)
set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
macro(acheron_set_build_directory build_dir)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${build_dir})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${build_dir})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${build_dir})
if(MSVC)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${build_dir})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${build_dir})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${build_dir})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${build_dir})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${build_dir})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${build_dir})
endif(MSVC)
endmacro()
acheron_set_build_directory(${ACHERON_GLOBAL_BUILD_DIRECTORY}/${CMAKE_BUILD_TYPE}/${PROJECT_NAME})
function(acheron_get_files_from_list out_file_list in_list)
set(file_list "")
foreach(in_item ${in_list})
if(NOT IS_DIRECTORY ${in_item})
list(APPEND file_list ${in_item})
endif()
endforeach()
set(${out_file_list} ${file_list} PARENT_SCOPE)
endfunction()
function(acheron_get_all_files_recursively out_file_list folder)
file(GLOB_RECURSE all_list ${folder}/*)
acheron_get_files_from_list(file_list "${all_list}")
set(${out_file_list} ${file_list} PARENT_SCOPE)
endfunction()
acheron_get_all_files_recursively(acheron_files ${CMAKE_CURRENT_SOURCE_DIR})
function(acheron_get_src_regex_pattern out_pattern)
set(${out_pattern} ".*\\.(((C|c)(P|p)(P|p)))$" PARENT_SCOPE)
endfunction()
acheron_get_src_regex_pattern(src_pattern)
function(acheron_get_filtered out_list regex_pattern in_list)
set(temp_list "")
foreach(in_item ${in_list})
if(${in_item} MATCHES ${regex_pattern})
list(APPEND temp_list ${in_item})
endif()
endforeach()
set(${out_list} ${temp_list} PARENT_SCOPE)
endfunction()
acheron_get_filtered(acheron_files ${src_pattern} "${acheron_files}")
function(acheron_add_source_groups root_dir src_list)
foreach(src_file ${src_list})
get_filename_component(src_name ${src_file} NAME)
string(REPLACE ${root_dir}/ "" group_name ${src_file})
string(REPLACE /${src_name} "" group_name ${group_name})
string(REPLACE "/" "\\" group_name ${group_name})
if(NOT ${group_name} STREQUAL ${src_name})
source_group(${group_name} FILES ${src_file})
endif()
endforeach()
endfunction()
acheron_add_source_groups(${CMAKE_CURRENT_SOURCE_DIR} "${acheron_files}")
add_library(${PROJECT_NAME} SHARED "${acheron_files}")

I finally did it! After I had rewritten cmakes files I was close to correct decision. I miss ABI dependence. I have a little corrected my cmakes:
app cmake:
set(lib_src_DIR ${CMAKE_CURRENT_LIST_DIR}/../acheron_lib/build/${CMAKE_BUILD_TYPE}/acheron)
set_target_properties(libacheron
PROPERTIES IMPORTED_LOCATION
${lib_src_DIR}/${ANDROID_ABI}/libacheron.so)
lib other cmake (I remove MSVC block just because of it useless for android build):
macro(acheron_set_build_directory build_dir)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${build_dir}/${ANDROID_ABI})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${build_dir}/${ANDROID_ABI})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${build_dir}/${ANDROID_ABI})
endmacro()

You don't need to add that block of CMake manually (it's also far from complete). Follow the docs on using CMake with the NDK and it'll handle handle the details for you: https://developer.android.com/studio/projects/add-native-code

Related

CMake Ubuntu set soname for shared object

How to set the SONAME for a shared library with CMake in Ubuntu?
With help of How to add linker flag for libraries with CMake? I have created a CMakeLists.txt:
project(mylib VERSION 1.2.3)
set(src_files_mylib
Client.cpp
Server.cpp
)
set(hdr_files_mylib
Client.h
Server.h
)
add_library(mylib SHARED ${src_files_mylib} ${hdr_files_mylib})
set_target_properties(mylib PROPERTIES PREFIX "")
set_target_properties(mylib PROPERTIES SUFFIX "")
set_target_properties(mylib PROPERTIES OUTPUT_NAME "mylib.so.${PROJECT_VERSION}")
add_link_options("LINKER: -l,soname,mylib.so.${PROJECT_VERSION_MAJOR}")
Using CMake 3.16 and out of source build. It produces the library named mylib.so.1.2.3 but it does not seem to have an SONAME in it. When executing ldconfig -n . in the library dir, it does not produce a link.
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,soname,mylib.so.${PROJECT_VERSION_MAJOR}")
instead of
add_link_options("LINKER: -l,soname,mylib.so.${PROJECT_VERSION_MAJOR}")
behaves the same to me.
When writing the Makefile manually, the target is built correctly with this (going ldconfig -n . like above produces a link):
(...)
MYLIB_SO=mylib.so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
MYLIB_SONAME=mylib.so.$(VERSION_MAJOR)
(...)
$(MYLIB_SO): $(OBJ_MYLIB)
$(CXX) $(SO_FLAGS) -Wl,-soname,$(MYLIB_SONAME) -o $(MYLIB_SO) $(DEBUGFLAGS) $(OBJ_MYLIB)
if libraries is called SoundTouch
project(SoundTouch VERSION 2.3.0 LANGUAGES CXX)
add_library(SoundTouch [SHARED]
sources/animation.cpp
sources/buffers.cpp
[...]
)
set_target_properties(SoundTouch PROPERTIES VERSION ${CMAKE_PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR} )

How do I write the cmake script for clion to include glfw?

cmake_minimum_required(VERSION 3.15)
project(hello)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
set(CMAKE_CXX_STANDARD 11)
add_executable(hello main.cpp)
INCLUDE_DIRECTORIES(${GLFW_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(hello ${GLFW_STATIC_LIBRARIES})
It tells me
CMake Error at /home/user/.local/share/JetBrains/Toolbox/apps/CLion/ch-0/193.5233.144/bin/cmake/linux/share/cmake-3.15/Modules/FindPkgConfig.cmake:696 (message):
None of the required 'glfw3' found
when I try to build it. My glfw folder is located at /usr/local/include/GLFW.
AFAIK, glfw3 is using CMake as the build system,
(src: packages.debian.org/fr/sid/amd64/libglfw3-dev/filelist)
which uses modern CMake, so you don't need GLFW_INCLUDE_DIRS etc...
Inside this file /usr/lib/cmake/glfw3/glfw3Targets.cmake (loaded by /usr/lib/cmake/glfw3/glfw3Config.cmake), you'll see:
...
# Create imported target glfw
add_library(glfw SHARED IMPORTED)
set_target_properties(glfw PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "GLFW_DLL"
INTERFACE_INCLUDE_DIRECTORIES "/usr/include"
)
...
So you can simply use:
find_package(glfw3 REQUIRED)
...
target_link_libraries(Foo glfw)
ps: same as my previous comment

CMake linking glfw3 lib error

i'm working with CLion, and I'm writing a program using the glfw3 lib.(http://www.glfw.org/docs/latest/)
I installed and did everything correctly for the lib i have the .a and .h files in:
/usr/local/lib/libglfw3.a
/usr/local/include/.h(all files)
I'm trying to use the library now, but i'm getting the linker error:
undefined reference to 'glViewport' etc. etc. all the functions i'm using
I added the lib path to the make file, I can't understand what i'm doing wrong, my CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.6)
project(testing)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp examples.h)
add_executable(testing ${SOURCE_FILES})
target_link_libraries(testing /usr/local/lib/libglfw3.a)
target_link_libraries(testing /usr/local/lib/libTest.a)
target_link_libraries(testing pthread)
any help will be appreciated.
Thanks!
You should not hard code absolute paths into your CMake files. This renders CMake useless.
In the documentation of GLFW on how to link against it, there it is explicitly written:
find_package(glfw3 3.2 REQUIRED)
find_package(OpenGL REQUIRED)
target_include_directories(myapp PUBLIC ${OPENGL_INCLUDE_DIR})
target_link_libraries(myapp
glfw
${OPENGL_gl_LIBRARY})
Moreover, you can replace
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
with
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
and CMake will figure out the correct compiler flag automatically depending on the compiler currently in use.

How to list target_link_libraries available on a system?

I'm trying to link with the Curl library in my CMakeLists.txt and I know that I should require the package add executable and link the library but I don't know how the variables names are called and where should I look for them, do you know where should I be looking for? Is there a way to list all the libraries in the system that I could be able to add in my project?
Here it's my CMakeLists (silly) attempt:
cmake_minimum_required(VERSION 3.3)
project(RadekClientRecon)
find_package(OpenCV REQUIRED)
find_package(CURL REQUIRED)
link_directories(/usr/lib/)
set(SOURCE_FILES main.cpp HttpManager.cpp)
add_executable(RadekClientRecon ${SOURCE_FILES})
target_link_libraries(RadekClientRecon ${OpenCV_LIBS} ${CURL_LIBRARIES})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
I've searched all "curl" named files in my computer if helps, I'm also using CLion if there's an automated way.
rinaldi#rinaldi-home:~/Projects/radekrecon$ sudo find / -name "*curl*" 2> /dev/null
/home/rinaldi/.atom/packages/atom-beautify/node_modules/jscs/lib/rules/disallow-curly-braces.js
/home/rinaldi/.atom/packages/atom-beautify/node_modules/jscs/lib/rules/require-curly-braces.js
/var/lib/dpkg/info/libcurl3:amd64.list
/var/lib/dpkg/info/python3-pycurl.md5sums
/var/lib/dpkg/info/libcurl3-gnutls:amd64.shlibs
/var/lib/dpkg/info/curl.md5sums
/var/lib/dpkg/info/libcurl3:amd64.postrm
/var/lib/dpkg/info/libcurl3:amd64.md5sums
/var/lib/dpkg/info/python3-pycurl.list
/var/lib/dpkg/info/libcurl3-gnutls:amd64.symbols
/var/lib/dpkg/info/libcurl3-gnutls:amd64.postrm
/var/lib/dpkg/info/libcurl3:amd64.symbols
/var/lib/dpkg/info/libcurl3-gnutls:amd64.md5sums
/var/lib/dpkg/info/libcurl3:amd64.postinst
/var/lib/dpkg/info/libcurl3:amd64.shlibs
/var/lib/dpkg/info/python3-pycurl.postinst
/var/lib/dpkg/info/curl.list
/var/lib/dpkg/info/python3-pycurl.prerm
/var/lib/dpkg/info/libcurl3-gnutls:amd64.postinst
/var/lib/dpkg/info/libcurl3-gnutls:amd64.list
/opt/clion-1.2.4/bin/cmake/doc/cmake-3.3/cmcurl
/opt/clion-1.2.4/bin/gdb/lib/python2.7/macurl2path.py
/usr/lib/python2.7/macurl2path.py
/usr/lib/python3.5/macurl2path.py
/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
/usr/lib/x86_64-linux-gnu/libcurl.so.4
/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3
/usr/lib/x86_64-linux-gnu/libcurl.so.3
/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.3.0
/usr/lib/x86_64-linux-gnu/gstreamer-0.10/libgstcurl.so
/usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0
/usr/lib/python3/dist-packages/pycurl.cpython-35m-x86_64-linux-gnu.so
/usr/lib/python3/dist-packages/curl
/usr/lib/python3/dist-packages/pycurl-7.19.5.1.egg-info
/usr/lib/python3/dist-packages/pycurl.cpython-34m-x86_64-linux-gnu.so
/usr/lib/python3.4/macurl2path.py
/usr/lib/gnupg/gpgkeys_curl
/usr/bin/curl
/usr/share/man/man1/curl.1.gz
/usr/share/lintian/overrides/libcurl3
/usr/share/lintian/overrides/libcurl3-gnutls
/usr/share/doc/libcurl3
/usr/share/doc/python3-pycurl
/usr/share/doc/libcurl3-gnutls
/usr/share/doc/curl
/usr/share/bash-completion/completions/curl
Apparently I needed to install some packages other than curl.
* libcurl4-gnutls-dev
* libcurl4-nss-dev
* libcurl4-openssl-dev
Those variables are named after their modules that can be found here.
My CMakeList.txt now it's creating the proper make file and looks like this:
cmake_minimum_required(VERSION 3.3)
project(RadekClientRecon)
find_package(OpenCV REQUIRED)
find_package(CURL REQUIRED)
link_directories(/usr/lib/)
link_directories(CURL_INCLUDE_DIRS)
set(SOURCE_FILES main.cpp HttpManager.cpp)
add_executable(RadekClientRecon ${SOURCE_FILES})
target_link_libraries(RadekClientRecon ${OpenCV_LIBS} ${CURL_LIBRARIES})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
After verifying the installation of curl, this is my CMakeLists.txt, which is running well on ubuntu 17.10
cmake_minimum_required(VERSION 2.8)
set(CURL_MIN_VERSION "7.55.1")
project(Downloader)
find_package(CURL REQUIRED)
link_directories(/usr/lib/x86_64-linux-gnu/)
add_executable(Downloader HTTPDownloaderExample.cpp HTTPDownloader.cpp)
target_link_libraries(Downloader curl)

Incorrect Dynamic Libraries linking after explicit set in Cmake

I've got a very frustrating issue a the moment. I'm attempting to build an executable that uses ROS and a compiled Matlab .so file. Due to what I believe is a boost conflict, I'm trying to build this exe using an earlier version of boost. Now, I've set up the cmakelist file, ran catkin_make (as its a ros project) and everything compiles, and the correct boost version is seen.
However, when running a ldd on the compiled exe, it still seems to be linking to the more recent version. Its rather annoying. I've posted the cmakelists file, and the ldd outcome. My system is Ubuntu 14.04 with ROS Indigo.
Any help would be really good, as I'm pulling my hair out trying to figure out what is wrong!
Many thanks in advance!
##CMAKE FILE
cmake_minimum_required(VERSION 2.8.3)
project(testmatlabdll)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wfatal-errors -O4 -march=native")
add_definitions(-std=c++11)
find_package(catkin REQUIRED)
find_package(PCL 1.7 REQUIRED)
link_directories(${PCL_LIBRARY_DIRS})
include_directories(${PCL_INCLUDE_DIRS})
add_definitions(${PCL_DEFINITIONS})
set(Boost_NO_SYSTEM_PATHS ON)
set(BOOST_ROOT /home/devbot/Downloads/boost_1_50_0)
set(BOOST_DIR /home/devbot/Downloads/boost_1_50_0)
set(Boost_INCLUDE_DIR /home/devbot/Downloads/boost_1_50_0)
set(BOOST_INCLUDEDIR /home/devbot/Downloads/boost_1_50_0)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
message(STATUS "BOOST_ROOT = ${BOOST_ROOT}")
message(STATUS "Boost_VERSION = ${Boost_VERSION}")
message(STATUS "Boost_LIB_VERSION = ${Boost_LIB_VERSION}")
message(STATUS "Boost_MAJOR_VERSION = ${Boost_MAJOR_VERSION}")
message(STATUS "Boost_MINOR_VERSION = ${Boost_MINOR_VERSION}")
message(STATUS "Boost_LIBRARIES = ${Boost_LIBRARIES}")
message(STATUS "Boost_INCLUDE_DIRS = ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost_LIBRARY_DIRS = ${Boost_LIBRARY_DIRS}")
find_package(Boost COMPONENTS REQUIRED
system filesystem thread date_time iostreams serialization chrono)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs message_generation image_transport cv_bridge)
find_package(OpenCV REQUIRED)
catkin_package(CATKIN_DEPENDS roscpp
std_msgs
pcl_ros
sensor_msgs
cv_bridge
message_runtime
LIBRARIES ${PROJECT_NAME}
DEPENDS system_lib)
include_directories(include ${catkin_INCLUDE_DIRS})
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(/usr/local/MATLAB/R2013b/extern/include/)
include_directories(/opt/matlab/extern/include)
include_directories(/home/devbot/catkin_ws/src/testmatlabdll/src)
link_directories(/home/devbot/catkin_ws/src/testmatlabdll/src)
add_library(mwmc SHARED IMPORTED)
set_property(TARGET mwmc PROPERTY IMPORTED_LOCATION /usr/local/MATLAB/MATLAB_Compiler_Runtime/v82/runtime/glnxa64/libmwmclmcrrt.so)
add_executable(testMatlab src/testMatlab.cpp)
target_link_libraries(testMatlab ${Boost_LIBRARIES} ${catkin_LIBRARIES} ${PCL_LIBRARIES} ${OpenCV_LIBRARIES})
target_link_libraries(testMatlab roughlib mwmc)
OUTPUT FROM LDD
ldd testMatlab | grep boost
libboost_system.so.1.50.0 => /home/devbot/Downloads/boost_1_50_0/stage/lib/libboost_system.so.1.50.0 (0x00007f7456f8a000)
libboost_system.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_system.so.1.54.0 (0x00007f7454662000)
libboost_thread.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.54.0 (0x00007f745444c000)
libboost_filesystem.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.54.0 (0x00007f7454018000)
libboost_regex.so.1.54.0 => /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.54.0 (0x00007f744d5d8000)

Resources