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



将 Android Studio 更新到 4.0 后,项目构建完成并显示错误

发现多个文件与操作系统无关的路径为"lib/armeabi-v7a/libdlib.so"。如果您使用的是 jniLibs 和 CMake 导入的目标,请参阅 https://developer.android.com/studio/preview/features#automatic_packaging_of_prebuilt_dependencies_used_by_cmake

该链接指向具有Android Studio Preview中的新功能的页面,该页面为4.1

编辑实际上,您可以在Google缓存中找到链接的信息: 自动打包 CMake 使用的预生成依赖项 那里所说的是:

以前版本的 Android Gradle 插件要求您使用 jniLibs 显式打包 CMake 外部原生构建使用的任何预构建库。在 Android Gradle 插件 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})

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

packagingOptions {
pickFirst "**/libdlib.so"
}

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

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

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

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

我遇到了同样的问题。

我的 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 文件中删除此内容,一切正常。

根据 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 )

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

andrid{
packagingOptions {
pickFirst "**/lib/**"
}
}

在我这边,似乎 jniLibs 作为文件夹的名称错误地触发了错误。 在文件系统和cmakelist的路径中将文件夹的名称更改为其他名称(我使用了"库".txt解决了问题。

cmakelists.txt fragment

# 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 文件进行检查。(libs are in {nameofaar}/jni/{arch_type}/{nameoflib}.so(

根据https://developer.android.com/studio/releases/gradle-plugin#cmake-imported-targets,当>=com.android.tools.build:gradle:4.0.0(表示反应原生>=0.64/androidbuild.gradle(时,我在npm包@flyskywhy/react-native-gcanvas中修复了More than one file was found with OS independent path 'lib/armeabi-v7a/libfreetype.so'

如果你有两个模块(如SDKWrapperSDK(,SDKWrapper构建取决于SDK,你不能在gradle中实现SDK

例如。

asks.whenTaskAdded { task ->
if (task.name == 'externalNativeBuildRelease') {
task.dependsOn ":SDK:externalNativeBuildRelease"
} else if (task.name == 'externalNativeBuildDebug') {
task.dependsOn ":SDK:externalNativeBuildDebug"
}}

删除实现

implementation Project(path:'SDK') 

最新更新