跟着AI分析mediapipe(facemesh编译)
一. Android FaceMesh 编译与运行故障排除
本文档记录了在 macOS 上编译和运行 FaceMesh Android 项目过程中遇到的问题及解决方案。
bazel构建可以使用命令:
bazel build -c opt --config=android_arm64 //mediapipe/examples/android/solutions/facemesh/src/main:facemesh
bazel构建完成后安装apk可以使用:
adb install -r bazel-bin/mediapipe/examples/android/solutions/facemesh/src/main/facemesh.apk
1. 环境配置 (SDK/NDK)
问题:
Bazel 无法定位 Android SDK 和 NDK。
交互与错误日志:
运行构建命令:bazel build -c opt --config=android_arm64 //mediapipe/examples/android/solutions/facemesh/src/main:facemesh
系统返回错误:
ERROR: .../BUILD:19:15: While resolving toolchains for target //mediapipe/examples/android/solutions/facemesh/src/main:facemesh (cf63efd): No matching toolchains found for types @@bazel_tools//tools/android:sdk_toolchain_type.
To debug, rerun with --toolchain_resolution_debug='@@bazel_tools//tools/android:sdk_toolchain_type'
If platforms or toolchains are a new concept for you, we'd encourage reading https://bazel.build/concepts/platforms-intro.
ERROR: Analysis of target '//mediapipe/examples/android/solutions/facemesh/src/main:facemesh' failed; build aborted
原因分析:
Bazel 需要在 WORKSPACE 文件中明确指定 Android SDK 和 NDK 的路径才能找到对应的构建工具链。
解决方案:
更新项目根目录下的 WORKSPACE 文件,指向你本地的 Android SDK 和 NDK 路径。
# WORKSPACE
android_sdk_repository(
name = "androidsdk",
path = "/Users/your_user/Library/Android/sdk", # 请根据实际情况调整路径
)
android_ndk_repository(
name = "androidndk",
path = "/Users/your_user/Library/Android/sdk/ndk/<version>", # 请根据实际情况调整版本
api_level = 21,
)
bind(
name = "android/crosstool",
actual = "@androidndk//:toolchain",
)
2. zlib 编译错误 (macOS)
问题:
在 macOS 上编译时,zlib 因 fdopen 宏重定义而编译失败。
错误日志:
external/zlib/zutil.h:147:33: note: expanded from macro 'fdopen'
# define fdopen(fd,mode) NULL /* No fdopen() */
...
error: expected identifier or '('
解决方案:
修改 third_party/zlib.BUILD 文件,在编译器选项中添加 -Dfdopen=fdopen。
# third_party/zlib.BUILD
copts = select({
"//conditions:default": [
"-Wno-dangling-else",
"-Wno-format",
"-Wno-implicit-function-declaration",
"-Wno-incompatible-pointer-types",
"-Wno-incompatible-pointer-types-discards-qualifiers",
"-Wno-parentheses",
"-DIOAPI_NO_64",
"-Dfdopen=fdopen", # 添加这一行
],
}),
3. 运行时崩溃:缺少 libc++_shared.so
问题:
启动"MediaPipe FaceMesh"应用后,点击"START CAMERA"时立即崩溃,报错 UnsatisfiedLinkError。
错误日志:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found: needed by ... libopencv_java4.so
解决方案:
OpenCV 库依赖 libc++_shared.so,但该库未被打包进 APK。
补充说明:OpenCV 的下载与配置
OpenCV 是在运行bazel build命令时,由 Bazel 根据项目根目录WORKSPACE文件中的定义自动下载和配置的。
- 定义:
WORKSPACE文件中使用http_archive规则定义了名为android_opencv的外部仓库,指向 OpenCV Android SDK 的下载链接(例如 v4.12.0 zip 包)。- 配置:Bazel 下载并解压后,使用
third_party/opencv_android.BUILD文件来描述其构建规则。- 引用:
third_party/BUILD文件中的opencv目标会根据构建平台(如android_arm64)选择对应的 OpenCV 库。这里的崩溃问题是因为 OpenCV 的预编译库依赖于
libc++_shared.so,而 Bazel 默认没有将其包含在 APK 中。
-
复制库文件:
从你的 NDK 目录(例如sysroot/usr/lib/<arch>/libc++_shared.so)复制libc++_shared.so到mediapipe/third_party/目录。 -
更新
third_party/BUILD:
将libc++_shared的定义从cc_binary改为cc_import。# third_party/BUILD cc_import( name = "libc++_shared", shared_library = "libc++_shared.so", ) cc_library( name = "libc++_shared_lib", deps = [":libc++_shared"], alwayslink = 1, ) -
添加应用依赖:
在 Android 二进制目标的deps中添加//third_party:libc++_shared_lib。# mediapipe/examples/android/solutions/facemesh/src/main/BUILD android_binary( name = "facemesh", deps = [ # ... 其他依赖 ... "//third_party:libc++_shared_lib", ], )
二. # Android Solutions Gradle 构建故障排除
gradle工程直接使用了预编译的solutions,只是展示了上层调用接口
本文档记录了在 mediapipe/examples/android/solutions 目录下使用 Gradle 构建项目时遇到的问题、解决步骤以及最终的成功构建流程。
1. 初始构建尝试与 Gradle 版本冲突
操作:
尝试使用现有的 gradlew 脚本进行构建:
./gradlew assembleDebug
问题 1:
Gradle 版本不兼容。项目配置使用了较旧的 Gradle 插件,但 gradle-wrapper.properties 指向了 Gradle 8.14.3,导致构建失败。
错误日志:
Task failed with an exception.
...
Cannot use @TaskAction annotation on method IncrementalTask.taskAction$gradle_core() ...
这是典型的 Gradle 版本与 Android Gradle Plugin (AGP) 版本不匹配导致的错误。
尝试修复 (失败):
尝试将 Gradle Wrapper 降级到 6.7.1 以匹配旧版 AGP (4.2.0)。
虽然解决了版本不匹配,但在 Java 17 环境下运行旧版 Gradle 导致了严重的类加载错误 (Could not create service of type ScriptPluginFactory),因为旧版 Gradle 不支持 Java 17。
2. 升级 Gradle 与 Android Gradle Plugin (AGP)
决策:
为了适配当前的开发环境 (Java 17) 和构建工具,决定全面升级项目的构建配置。
操作步骤:
-
恢复 Gradle Wrapper: 将
gradle-wrapper.properties恢复为使用 Gradle 8.14.3。distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip -
升级 AGP: 修改根目录 [
build.gradle](file:///Volumes/exssd/mediapipe/mediapipe/examples/android/solutions/build.gradle),将 Android Gradle Plugin 从4.2.0升级到8.2.0。dependencies { classpath "com.android.tools.build:gradle:8.2.0" // ... } -
升级 Compile SDK: 修改所有子模块 (
facemesh,facedetection,hands) 的build.gradle,将compileSdkVersion从30升级到34,以满足 AGP 8.x 的要求。
3. 适配 AGP 8.0+ 的 Namespace 变更
问题 2:
再次构建时报错,提示 AndroidManifest.xml 中的 package 属性不再被支持用于设置命名空间。
错误日志:
Execution failed for task ':facedetection:processDebugMainManifest'.
> Incorrect package="com.google.mediapipe.examples.facedetection" found in source AndroidManifest.xml
Setting the namespace via the package attribute in the source AndroidManifest.xml is no longer supported.
解决方案:
将包名配置从 AndroidManifest.xml 迁移到 build.gradle 的 namespace 属性中。
-
修改 build.gradle:
在每个模块的android块中添加namespace:facemesh/build.gradle:namespace 'com.google.mediapipe.examples.facemesh'facedetection/build.gradle:namespace 'com.google.mediapipe.examples.facedetection'hands/build.gradle:namespace 'com.google.mediapipe.examples.hands'
-
修改 AndroidManifest.xml:
移除<manifest>标签中的package属性。<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <!-- package 属性已移除 --> ... </manifest>
4. 构建目录冲突问题 (BUILD file vs build directory)
问题 3:
在解决上述配置问题后,构建过程中出现无法创建目录的错误。
错误日志:
FAILURE: Build failed with an exception.
* What went wrong:
java.lang.IllegalArgumentException: Could not create problems-report directory '/.../build/reports/problems'
原理:
这是一个在 macOS 和 Windows 等不区分大小写的文件系统上常见的冲突问题。
- 冲突源:Bazel 构建系统在
solutions目录下放置了一个名为BUILD的文件(用于定义 Bazel 构建规则)。 - Gradle 行为:Gradle 默认的输出目录名为
build/。 - 系统行为:在不区分大小写的文件系统上,系统认为文件
BUILD和目录build是同一个名称。当 Gradle 试图创建build目录时,发现已存在一个同名文件(即 Bazel 的BUILD文件),导致目录创建失败。
解决方案:
如果不再使用 Bazel 编译该目录下的 Android 项目,可以直接删除或重命名 BUILD 文件。
# 删除 Bazel 的 BUILD 文件以允许 Gradle 创建 build 目录
rm BUILD
# 然后执行清理和构建
./gradlew clean assembleDebug
注意:如果不希望删除
BUILD文件,也可以在build.gradle中修改项目的构建输出目录(buildDir),例如将其改为gradle_build。
5. 最终构建成功
操作:
执行清理并构建命令:
./gradlew clean && ./gradlew assembleDebug
结果:
构建成功 (BUILD SUCCESSFUL)。
产物位置:
- Face Mesh:
facemesh/build/outputs/apk/debug/facemesh-debug.apk - Face Detection:
facedetection/build/outputs/apk/debug/facedetection-debug.apk - Hands:
hands/build/outputs/apk/debug/hands-debug.apk
5. 总结
为了在现代环境 (Java 17, Gradle 8+) 中编译该项目,必须进行以下现代化改造:
- Gradle: 8.14.3
- AGP: 8.2.0
- Compile SDK: 34
- Namespace: 迁移至
build.gradle配置
更多推荐



所有评论(0)