Android Studio 为不同的 ABI 链接共享库时出现问题

Android Studio problem with linking shared library for different 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()

我不知道如何解决这个问题。看起来我需要 link 任何 ABI 依赖库,但我不知道如何理解我需要哪个库。 "My" 库有很多文件,很难跟踪所有依赖项。那么我该如何解决这个问题(确保在构建 "my" 库后我拥有所有 ABI 的 *.so 并且我正在 link 使用 ${ANDROID_ABI} 将它们添加到主代码)?

我的 Android Studio 项目中有 2 个模块:库和应用程序。该库构建良好,但我不能 link 它到应用程序,因为 cmake 告诉我该库是一个不兼容的目标。更改 cmakes 后我摆脱了 ABI cmake 块,但库仍然不想 link.

应用程序 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 主 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}")

您不需要手动添加该 CMake 块(它也远未完成)。按照有关将 CMake 与 NDK 结合使用的文档进行操作,它将为您处理细节:https://developer.android.com/studio/projects/add-native-code

我终于做到了!在我重写 cmakes 文件后,我接近正确的决定。我想念 ABI 依赖。我稍微修正了我的 cmakes:

应用程序制作:

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(我删除了 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()