从 3.6 更新到 Android Studio 4.0 后构建具有 NDK 支持的项目时出错

Posted

技术标签:

【中文标题】从 3.6 更新到 Android Studio 4.0 后构建具有 NDK 支持的项目时出错【英文标题】:Error when building project with NDK support after updating to Android Studio 4.0 from 3.6 【发布时间】:2020-09-17 03:33:31 【问题描述】:

android Studio 更新到 4.0 后,项目构建完成并出现错误

找到多个文件,其独立于操作系统的路径为“lib/armeabi-v7a/libdlib.so”。如果您使用 jniLibs 和 CMake IMPORTED 目标,请参阅https://developer.android.com/studio/preview/features#automatic_packaging_of_prebuilt_dependencies_used_by_cmake

链接指向带有Android Studio Preview 中的新功能的页面,即 4.1

编辑 实际上,您可以在 Google 缓存中找到链接的信息: Automatic packaging of prebuilt dependencies used by CMake 里面写的是:

Android Gradle 插件的早期版本要求您使用 jniLibs 显式打包 CMake 外部原生构建使用的任何预构建库。使用 Android Gradle Plugin 4.0,上述配置不再需要,会导致构建失败:

但对我来说不是这样

这里是build.gradle

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android 
compileSdkVersion 29
buildToolsVersion "29.0.2"


defaultConfig 
    minSdkVersion 21
    targetSdkVersion 29
    versionCode 1
    versionName "1.0"

    externalNativeBuild 
        cmake 
            cFlags "-O3"
            cppFlags "-std=c++11 -frtti -fexceptions -mfpu=neon"
            arguments "-DANDROID_PLATFORM=android-16",
                    "-DANDROID_TOOLCHAIN=clang",
                    "-DANDROID_STL=c++_shared",
                    "-DANDROID_ARM_NEON=TRUE",
                    "-DANDROID_CPP_FEATURES=rtti exceptions"
        
    


buildTypes 
    debug 
    stage 
        debuggable true
        minifyEnabled false
    

    release 
        minifyEnabled false
    


kotlinOptions 
    jvmTarget = "1.8"


externalNativeBuild 
    cmake 
        path "src/main/cpp/CMakeLists.txt"
        version "3.10.2"
    


packagingOptions 
    pickFirst "**/libc++_shared.so"
    pickFirst "**/libdlib.so"




dependencies 
   implementation fileTree(dir: 'libs', include: ['*.jar'])

   implementation 'androidx.annotation:annotation:1.1.0'
   implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

CMakeLists.txt

set(LIB_DIR $CMAKE_SOURCE_DIR/src/main/jniLibs)

#
cmake_minimum_required(VERSION 3.4.1)

add_library(dlib SHARED IMPORTED)

# sets the location of the prebuilt dlib .so
set_target_properties( dlib
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/../jniLibs/$ANDROID_ABI/libdlib.so )

# ------------------------------------------------------------------

add_library( # Sets the name of the library.
        face-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        face-lib.cpp)

target_include_directories(
        face-lib PRIVATE
        $CMAKE_SOURCE_DIR/include
)

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)


target_link_libraries( # Specifies the target library.
        face-lib

        dlib

        # Links the target library to the log library
        # included in the NDK.
        $log-lib)

【问题讨论】:

在这里打开了一个错误:issuetracker.google.com/issues/157901344 抱歉文档问题。出于某种原因,它已从 4.0 发行说明中删除。得到那个固定的atm。 在添加 packagingOptions 块之前,我可以重现该问题。这使问题消失了。这是您为解决问题而添加的内容吗? 不幸的是,谷歌缓存链接现在是 404。这个链接今天有效:developer.android.com/studio/releases/… 【参考方案1】:

好的,所以我找到了解决方案,我已将其添加到带有我的本机库的模块中:

 packagingOptions 
        pickFirst "**/libdlib.so"
    

我不喜欢它,因为它解决了后果,而不是根本原因。 如果有人有更好的解决方案,请在此处发布。

另一个有效的解决方案指向@GavinAndre answer 重点是,如果您使用的是 Cmake,请不要将您的 .so 存储在 jniLibs 文件夹中。

将它们移动到另一个文件夹,例如cmakeLibs。 例如:

set_target_properties( dlib
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/../cmakeLibs/$ANDROID_ABI/libdlib.so )

【讨论】:

我认为这是由于“add_library(dlib SHARED IMPORTED)”。但不知道如何正确解决这个问题。我有同样的问题。 这是因为您有IMPORTED 目标并且jniLibs 中有库。这两者都会导致它被打包,并且打包任务不够聪明,无法对它们进行重复数据删除。 pickFirst 显然对我有用!我还不明白是什么原因造成的 实际上在我的情况下我删除了jniLibs 文件夹(因为我是从我的电脑上的本地目录导入的)。此外,我还有另一个库(arcore)也提供了此类错误,因此在这里我需要添加pickFirst,正如您在答案的第一部分中提到的那样。所以,谢谢:) 我不得不放弃用十多个模块升级我的项目,其中每个模块都导入了一些.so库...【参考方案2】:

我遇到了同样的问题。

我的 gradle 文件就是这样写的:

    sourceSets 
        main 
            jniLibs.srcDirs 'src/main/cpp/libs'
        
    

实际上文件夹中有两个 .so 文件,因为链接 see https://developer.android.com/studio/preview/features#automatic_packaging_of_prebuilt_dependencies_used_by_cmake 似乎显示了信息Andrioid Stuido 将自动为您打包库

所以我只是在我的 gradle 文件中删除此内容,一切正常。

【讨论】:

这应该被标记为正确答案,因为 Gradle 插件是引入此更改的第一个答案是 hack 方式【参考方案3】:

根据https://developer.android.com/studio/projects/gradle-external-native-builds#jniLibs

If you are using Android Gradle Plugin 4.0, move any libraries that are used by IMPORTED CMake targets out of your jniLibs directory to avoid this error.

所以你只需要将$ANDROID_ABI/libdlib.so文件夹移动到另一个地方比如新建一个目录名cmakeLibs

例如:

set_target_properties( dlib
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/../cmakeLibs/$ANDROID_ABI/libdlib.so )

【讨论】:

【参考方案4】:

在我看来,作为文件夹名称的 jniLibs 错误地触发了错误。在文件系统的路径和 cmakelists.txt 中将文件夹的名称更改为其他名称(我使用了“库”)解决了这个问题。

cmakelists.txt 片段

# import library and set path
add_library(ixxs-plugin SHARED IMPORTED) # or STATIC instead of SHARED
set_target_properties(ixxs-plugin PROPERTIES
        IMPORTED_LOCATION "$CMAKE_SOURCE_DIR/../libraries/$CMAKE_ANDROID_ARCH_ABI/libixxs-plugin.so"
        )

不需要对 gradle 文件做任何事情,它会自动找到库并将它们放入 aar 文件中。您可以解压缩 aar 文件以进行检查。 (库位于 nameofaar/jni/arch_type/nameoflib.so)

【讨论】:

所以对于每个声明“libs”文件夹的“set_target_properties”,我们应该将“libs”更改为“libraries”? 我有jniLibs,我改用libraries,你可以改用iwannabeoriginalandnotuselibraries之类的其他东西。在 cmakelists 文件和文件系统上。祝你好运。【参考方案5】:

好的,所以我找到了解决方案,我已将其添加到带有我的本机库的模块中:

andrid
packagingOptions 
        pickFirst "**/lib/**"
    

【讨论】:

【参考方案6】:

根据https://developer.android.com/studio/releases/gradle-plugin#cmake-imported-targets,我在我的npm包@flyskywhy/react-native-gcanvas中fix More than one file was found with OS independent path 'lib/armeabi-v7a/libfreetype.so'当>=com.android.tools.build:gradle:4.0.0(意味着react-native>=0.64)在/androidbuild.gradle

【讨论】:

以上是关于从 3.6 更新到 Android Studio 4.0 后构建具有 NDK 支持的项目时出错的主要内容,如果未能解决你的问题,请参考以下文章

Progruard 和 R8 被弃用 - Android Studio 3.6

Android studio 3.6 无法打开模拟器

在 Android Studio 3.6 中使用 Import Sceneform Asset 导入 FBX 时出错

Android studio 3.6 ToolBar问题

Android studio 3.6 ToolBar问题

android studio 4.0 中的 AVD 管理器在哪里