【问题标题】:Android Studio problem with linking shared library for different ABI为不同 ABI 链接共享库的 Android Studio 问题
【发布时间】:2018-10-15 20:15:58
【问题描述】:

对于我的文凭项目,我正在尝试使用 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 依赖库,但我不知道如何理解我需要哪个库。 “我的”库有很多文件,很难跟踪所有依赖项。那么我该如何解决这个问题(确定在构建“我的”库之后,我对所有 ABI 都有 *.so 并且我正在使用 ${ANDROID_ABI} 将它们链接到主代码)?

我的 Android Studio 项目中有 2 个模块:库和应用程序。该库构建良好,但我无法将其链接到应用程序,因为 cmake 告诉我该库是一个不兼容的目标。更改 cmake 后,我摆脱了 ABI 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}")

【问题讨论】:

  • 库中没有“通用”之类的东西。使用 Android Studio 构建库的所有相关 ABI 变体(它将包括为您处理 ABI 和平台技巧的 CMake 工具链文件),并确保在编译使用此库的代码时链接正确的变体。

标签: android-studio cmake android-ndk abi


【解决方案1】:

我终于做到了!在我重写了 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()

【讨论】:

    【解决方案2】:

    您不需要手动添加该 CMake 块(它还远未完成)。遵循将 CMake 与 NDK 结合使用的文档,它将为您处理详细信息:https://developer.android.com/studio/projects/add-native-code

    【讨论】:

    • 好吧,没有那个块“我的”库甚至无法编译。我有一个类似的问题:stackoverflow.com/questions/44793617/…
    • 自从我开始使用 Androod Studio 就开始关注它。但无论如何我解决了我的问题。
    猜你喜欢
    • 2012-06-05
    • 2021-07-25
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-06
    • 1970-01-01
    • 2022-01-05
    相关资源
    最近更新 更多