Проблема Android Studio со связыванием разделяемой библиотеки для разных ABI
В своем дипломном проекте я пытаюсь использовать Android Studio для переноса моего проекта C++ на Android. Мой C++ проект включает в себя мой собственный код и библиотеку, которая была разработана до меня. Сначала я попытался скомпилировать исходный код этой библиотеки в общую библиотеку Android. Я успешно сделал это. Но когда я компилирую код, который использует эту библиотеку, cmake говорит мне, что моя библиотека несовместима с архитектурой x86 (я думаю, что для других тоже будет). Когда я собирал библиотеку, я использую этот код для различных ABI, включая:
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()
Я не знаю, как это исправить. Похоже, мне нужно связать любую зависимую от ABI библиотеку, но я не знаю, как понять, какая библиотека мне нужна. В "моей" библиотеке много файлов, и было бы сложно просто проследить все зависимости. Итак, как я могу это исправить (конечно, после создания "моей" библиотеки у меня есть *.so для всех ABI, и я связываю их с основным кодом, используя ${ANDROID_ABI})?
У меня есть 2 модуля в моем проекте Android Studio: библиотека и приложение. Библиотека хорошо собирается, но я не могу связать ее с приложением, потому что cmake говорит мне, что библиотека является несовместимой целью. После изменения cmakes я избавился от блока ABI cmake, но библиотека все еще не хочет связываться.
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 другой 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}")
2 ответа
Я наконец сделал это! После того, как я переписал файлы cmakes, я был близок к правильному решению. Я скучаю по зависимости ABI. Я немного исправил свои 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 другой cmake (я удаляю блок MSVC только потому, что он бесполезен для сборки Android):
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()
Вам не нужно добавлять этот блок CMake вручную (он также далек от завершения). Следуйте документации по использованию CMake с NDK, и он будет обрабатывать детали для вас: https://developer.android.com/studio/projects/add-native-code