从 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