[鸿蒙三方库适配实战] 多媒体信息工具 MediaInfo CLI 的 OpenHarmony 平台迁移实践
[鸿蒙三方库适配实战] 多媒体信息工具 MediaInfo CLI 的 OpenHarmony 平台迁移实践
摘要:本文详细介绍了如何将多媒体信息分析工具 MediaInfo CLI 适配到 鸿蒙PC 平台。文章将系统性地讲解如何利用 lycium_plusplus 构建框架,处理 C/C++ 项目在鸿蒙环境下的交叉编译流程,展示如何处理 musl libc 兼容性问题、CMake 构建配置优化以及 HNP 包生成的完整实践。
本文是软件鸿蒙化迁移实践系列文章之一,专注于 C/C++ 原生库的鸿蒙 PC 适配,为开发者提供完整的迁移指南。
AtomGit仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_mediainfo
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
项目信息说明
| 项目 | 说明 |
|---|---|
| 名称 | MediaInfo CLI |
| 开源协议 | BSD-2-Clause |
| 源码版本 | 25.03 |
| 目标平台 | 鸿蒙 PC |
| 依赖项 | CMake, ZenLib, MediaInfoLib, zlib |
| 操作系统平台 | WSL Ubuntu 24.04 |
一、背景介绍
1.0 功能与效果
MediaInfo CLI 在本实践中的预期能力如下:
功能:提供跨平台的视频和音频文件技术信息分析功能,支持多种媒体格式(MP4、MKV、AVI、MP3、FLAC 等),输出详细的技术参数(编码格式、分辨率、比特率、帧率、采样率等)。
效果:在鸿蒙 PC 上提供与标准 Linux 环境相近的 MediaInfo CLI 使用体验,便于在鸿蒙应用开发中实现媒体文件分析、元数据提取、媒体库管理等场景的多媒体处理功能。
1.1 什么是 鸿蒙PC HNP 生态
HNP(Harmony Native Package)是 鸿蒙PC 的原生包格式,lycium 是增强型构建框架,支持自动下载源码、交叉编译(arm64-v8a、armeabi-v7a)、一键生成 HNP 包以及开源声明聚合。C/C++ 原生库的适配是鸿蒙系统生态建设中的重要一环。
1.2 为什么适配 C/C++ 原生库会有难度
常见挑战包括:
- 构建系统差异:C/C++ 项目通常使用 CMake、Autotools 等构建系统,需要配置交叉编译工具链(aarch64-linux-ohos-clang/clang++)。
- musl libc 兼容性:鸿蒙PC使用 musl libc,不支持某些 glibc 特有的函数(如 pthread_cancel),需要修改源码或注释掉不兼容的调用。
- 依赖管理复杂:项目可能依赖多个第三方库(如 MediaInfo 依赖 ZenLib、MediaInfoLib、zlib),需要正确配置依赖路径和编译选项。
- 产物体积优化:默认的 make install 会安装所有文件(头文件、库文件、文档等),需要优化只保留可执行文件以减小产物体积。
- Windows 元数据干扰:从 Windows 环境复制的源码可能包含 :Zone.Identifier 等区域标识文件,需要在打包前清理。
- 构建缓存问题:lycium 使用 hpk_build.csv 跟踪构建状态,需要正确清理缓存才能重新构建。
1.3 MediaInfo 简介
MediaInfo 是一款由 MediaArea 开发的方便统一显示视频和音频文件最相关技术和标签数据的工具。其主要特点包括:
- 多格式支持:支持视频(MP4、MKV、AVI、MOV、WMV 等)和音频(MP3、FLAC、AAC、OGG 等)格式。
- 详细技术分析:提供编码格式、分辨率、比特率、帧率、采样率、声道数等技术参数。
- 多种输出格式:支持文本、HTML、XML、JSON、CSV 等输出格式。
- 跨平台特性:原生支持 Windows、macOS、Linux,本次适配扩展到 鸿蒙PC 平台。
- 开源地址:
- MediaInfo源码GitHub地址: https://github.com/MediaArea/MediaInfo
- MediaInfo适配后AtomGit地址: https://atomgit.com/OpenHarmonyPCDeveloper/ohos_mediainfo
二、环境准备
2.0 系统要求
- 开发环境:Ubuntu 24.04(推荐 WSL 2)
- 核心工具:CMake(v3.16+)、GCC/G++、Git、Python3
- 构建框架:lycium_plusplus
- 鸿蒙 SDK:OpenHarmony SDK(提供交叉编译工具链 aarch64-linux-ohos-clang/clang++)
- 目标架构:arm64-v8a(AArch64)
2.0.1 扩展阅读与参考教程
下方汇总展示了多位老师在鸿蒙 OpenHarmony 适配方面的高质量教程。若在前提准备(环境、工具链、框架)部分还有不清楚的地方,可参考这些文章进一步学习。 以下资源不分先后顺序,均具有参考价值。
| 资源类型 | 描述 | 链接 |
|---|---|---|
| 三方库交叉编译环境(Ubuntu) | 在 Ubuntu 中搭建鸿蒙PC 三方库交叉编译构建开发环境 | 👉 点击查看 |
| 三方库交叉编译环境(macOS) | 在 macOS 中搭建鸿蒙PC 三方库交叉编译开发环境 | 👉 点击查看 |
| 基础环境搭建 | Windows 10 上安装和使用 WSL 2、安装 Ubuntu 24 详细指南 | 👉 点击查看 |
| Mac 移植指南 | 鸿蒙PC命令行适配指南(Mac 版) | 👉 点击查看 |
| Win 移植指南 | 鸿蒙PC 生态三方软件移植:开发环境搭建及三方库移植指南 | 👉 点击查看 |
| 全流程适配指南 | OpenHarmony Linux 命令行工具适配实战:基于 Cursor × WSL 的 tree 2.2.1 交叉编译与 HNP 打包全流程指南 | 👉 点击查看 |
| 官方构建文档 | 新脚手架:社区维护的鸿蒙PC 生态命令行工具构建框架 lycium_plusplus(原 build 仓库为旧方式,请以本仓库为准) | 👉 点击查看 |
2.1 lycium_plusplus 框架
lycium_plusplus 是本次适配工作的核心工具,主要用于统一管理各类第三方库的构建流程,通过规范编译、依赖与打包逻辑,实现三方库在目标平台上高效、稳定地编译与集成,是整个适配环节中保障构建一致性与可维护性的关键支撑。
# 克隆 lycium_plusplus 项目
git clone https://gitcode.com/OpenHarmonyPCDeveloper/lycium_plusplus.git
cd lycium_plusplus
2.2 CMake 与交叉编译环境
由于 MediaInfo 是 C/C++ 项目,需要 CMake 和 鸿蒙 SDK 提供的交叉编译工具链。
# 安装 CMake
sudo apt-get install -y cmake
# 验证安装
cmake --version
# 配置 鸿蒙 SDK 环境变量
export OHOS_SDK=/home/weishuo/ohos-sdk/linux
三、实战:以 MediaInfo 为例的适配步骤
本章节将为新人开发者提供完整的、可复现的适配步骤。我们将从零开始,逐步完成 MediaInfo CLI 的鸿蒙适配工作。每个步骤都包含详细的说明、命令示例和注意事项。
我们主要需要创建HPKBUILD、hnp.json、README.OpenSource、HPKCHECK四个核心文件
HPKBUILD:三方库编译构建脚本,下载、补丁、交叉编译、打包全流程管控
hnp.json:鸿蒙 HNP 安装包元信息,系统识别安装、路径依赖配置
README.OpenSource:开源版权溯源、协议声明,合规审计必备文档
HPKCHECK:编译产物真机校验脚本,检测库可用性、兼容性与运行异常
鸿蒙 Lycium++ 三方库 标准完整流程
Tip:AI 全面渗透的技术时代,开发不再等同于亲手写码。核心在于掌握全流程的适配逻辑与框架,用精准的 Prompt 与 AI 工具协同调试,高效达成目标
比如:学习鸿蒙适配框架lycium_plusplus,参考已经适配完成的三方库命令,适配三方库命令MediaInfo,lycium_plusplus/thirdparty/ 创建库目录,编写HPKBUILD、hnp.json、README.OpenSource、HPKCHECK,编译产物需要生成在output/目录下
- 创建目录
在 lycium_plusplus/thirdparty/ 下新建库名目录
- 放入 4 个必备文件 + 补丁(按需)
- HPKBUILD:定义信息 + 下载 / 编译 / 安装 / 打包
- hnp.json:HNP 包元数据,系统识别配置
- README.OpenSource:开源合规、版权协议声明
- HPKCHECK:真机运行校验、兼容性测试
- 适配补丁文件(*.patch)
- 一键构建
执行:./build.sh 库名
- 框架全自动执行
下载源码 → 打补丁 → 交叉编译 → 安装 → 生成 HNP → 真机校验
- 获取产物
- usr/:二进制库、头文件
- output/:鸿蒙 HNP 安装包
3.1 创建项目目录结构
步骤说明:
在 lycium_plusplus 框架中,每个三方库都需要在 thirdparty/ 目录下拥有独立的目录。这个目录将存放该库的所有构建配置文件(HPKBUILD、hnp.json、README.OpenSource、HPKCHECK 等)。
详细操作流程:
# 1. 进入 lycium_plusplus 项目根目录
cd /home/weishuo/lycium_plusplus
# 2. 进入 thirdparty 目录
cd thirdparty
# 3. 创建 mediainfo 目录
mkdir -p mediainfo
# 4. 进入新创建的目录
cd mediainfo
# 5. 验证目录创建成功
pwd
# 输出:/home/weishuo/lycium_plusplus/thirdparty/mediainfo
# 6. 查看目录结构
ls -la
目录结构说明:
lycium_plusplus/
├── thirdparty/
│ ├── mediainfo/ ← 我们刚创建的目录
│ │ ├── HPKBUILD ← 将要创建的构建脚本
│ │ ├── hnp.json ← 将要创建的包元数据
│ │ ├── README.OpenSource ← 将要创建的开源声明
│ │ └── HPKCHECK ← 将要创建的检查脚本
│ ├── fuse3/ ← 其他三方库示例
│ ├── glib/ ← 其他三方库示例
│ └── ...
├── lycium/
│ ├── build.sh ← lycium 构建入口脚本
│ └── usr/ ← 构建产物输出目录
└── Projects/
└── MediaInfo/ ← MediaInfo 源码目录(需提前准备)
注意事项:
- 目录名称必须与 pkgname 变量保持一致(本例中为 mediainfo)
- 确保 Projects/MediaInfo/ 目录中已经有 MediaInfo 的源码
- 如果源码还未准备,需要先下载或克隆源码到 Projects/MediaInfo/ 目录
3.2 创建 HPKBUILD 文件
步骤说明:
HPKBUILD 是 lycium 框架的核心构建脚本,它定义了三方库的元信息配置及下载、编译、打包等全流程构建逻辑。可以理解为一个“构建配方”,告诉 lycium 框架如何编译和打包这个库。
HPKBUILD 的核心作用:
- 元信息定义:库名、版本、描述、许可证、目标架构等
- 依赖管理:声明编译时和运行时依赖
- 构建流程:prepare() → build() → package() → archive()
- 环境配置:交叉编译工具链、CMake 参数、安装路径等
详细操作流程:
前提准备,需要提前准备源码放在Projects目录下 MediaInfo源码GitHub地址: https://github.com/MediaArea/MediaInfo
# 1. 确保当前在 mediainfo 目录
cd /home/weishuo/lycium_plusplus/thirdparty/mediainfo
# 2. 创建 HPKBUILD 文件
# 方法 1:使用 vim 编辑器
vim HPKBUILD
# 方法 2:使用 nano 编辑器(对新人更友好)
nano HPKBUILD
# 方法 3:使用 Windows 编辑器创建后复制到 WSL(需要注意 CRLF 问题)
# 在 Windows 上创建 HPKBUILD 文件,然后复制到 WSL
# 注意:必须使用 LF 换行符,不能使用 CRLF
HPKBUILD 文件内容详解:
#!/bin/bash
# 编译构建脚本:MediaInfo CLI 工具 (适配鸿蒙系统)
# 贡献者/维护者信息
# Contributor: Your Name <youremail@domain.com>
# Maintainer: Your Name <youremail@domain.com>
# 基础包配置
# 包名
pkgname=mediainfo
# 包版本
pkgver=25.03
# 包发布版本号
pkgrel=0
# 包描述:音视频文件技术信息和标签数据查看工具(命令行版)
pkgdesc="A convenient unified display of the most relevant technical and tag data for video and audio files (CLI version)"
# 项目源码地址
url="https://github.com/MediaArea/MediaInfo"
# 支持的架构:32位ARM / 64位ARM
archs=("armeabi-v7a" "arm64-v8a")
# 开源协议
license=("BSD-2-Clause")
# 运行依赖(无)
depends=()
# 编译依赖:需要cmake
makedepends=("cmake")
# 源码配置
# 使用本地源码,不自动解压
autounpack=false
# 不自动下载源码包
downloadpackage=false
# 编译工具
buildtools="cmake"
# 本地源码路径(从环境变量 LYCIUM_ROOT 指向项目目录)
srcpath="${LYCIUM_ROOT}/../Projects/MediaInfo"
# 编译目录名称 = 包名+版本
builddir=${pkgname}-${pkgver}
# 准备阶段:复制源码、打补丁
prepare() {
# 判断本地源码目录是否存在
if [ -d "$srcpath" ]; then
# 创建编译目录
mkdir -p "$builddir"
# 复制本地所有源码到编译目录
cp -rf "$srcpath"/* "$builddir/"
# 删除备份文件 .bak
find "$builddir" -name "*.bak" -type f -delete 2>/dev/null || true
# 删除 Windows 系统遗留的区域标识符文件
find "$builddir" -name "*:Zone.Identifier" -type f -delete 2>/dev/null || true
# 如果存在musl兼容补丁,则自动打补丁
if [ -f "../mediainfo-zenlib-musl.patch" ]; then
cd "$builddir"
patch -p1 < "../mediainfo-zenlib-musl.patch"
cd "$OLDPWD"
fi
else
# 源码不存在则报错退出
echo "ERROR: Source not found at $srcpath"
exit 1
fi
}
# 编译阶段:cmake + make
build() {
# 进入编译目录
cd "$builddir"
# cmake 配置
cmake "$@" \
-B"$ARCH-build" \ # 按架构区分构建目录
-S./Project/CMake/CLI/ \ # CLI 版源码路径
-D CMAKE_BUILD_TYPE=Release \ # 编译 Release 版本
-D CMAKE_INSTALL_PREFIX="/usr" \ # 安装路径前缀
-D BUILD_ZENLIB=ON \ # 编译依赖库 ZenLib
-D BUILD_MEDIAINFOLIB=ON \ # 编译核心库 MediaInfoLib
-D BUILD_ZLIB=ON \ # 编译 zlib
-D ZLIB_BUILD_SHARED=OFF \ # zlib 编译为静态库
-D ZLIB_BUILD_TESTING=OFF \ # 不编译 zlib 测试程序
-D MediaInfoLib_BUILD_STATIC=ON # MediaInfoLib 编译为静态库
# 多线程编译(4线程)
make -j4 -C "$ARCH-build"
# 记录 make 执行结果
ret=$?
# 返回原目录
cd "$OLDPWD"
# 返回编译结果状态码
return $ret
}
# 安装阶段:将编译产物安装到指定目录
package() {
cd "$builddir"
# 安装到目标架构目录(用于后续打包)
make -C "$ARCH-build" install DESTDIR="${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}"
cd "$OLDPWD"
}
# 测试阶段:提示需在真机/设备上运行
check() {
echo "The test must be on an OpenHarmony device!"
}
# 归档打包阶段:生成 .tar.gz + .hnp 鸿蒙安装包
archive() {
# 指定 hnp 工具路径(鸿蒙 SDK 工具链)
export HNP_TOOL="${HNP_TOOL:-${OHOS_SDK}/toolchains/hnpcli}"
# 创建输出目录
mkdir -p "${LYCIUM_ROOT}/output/${ARCH}"
# 进入安装目录并打包成 tar.gz
pushd "${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}" > /dev/null 2>&1
tar -zcf "${LYCIUM_ROOT}/output/${ARCH}/${pkgname}_${pkgver}.tar.gz" .
echo "Archive completed: ${LYCIUM_ROOT}/output/${ARCH}/${pkgname}_${pkgver}.tar.gz"
popd > /dev/null 2>&1
# 如果 hnpcli 工具存在,则生成鸿蒙 .hnp 包
if [ -f "${HNP_TOOL}" ]; then
cp "${LYCIUM_ROOT}/../thirdparty/${pkgname}/hnp.json" "${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}/"
${HNP_TOOL} pack -i "${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}" -o "${LYCIUM_ROOT}/output/${ARCH}/"
echo "Archive completed: ${LYCIUM_ROOT}/output/${ARCH}/${pkgname}.hnp"
else
# 缺少工具则跳过 hnp 打包
echo "Warning: hnpcli not found at ${HNP_TOOL}, skipping HNP generation"
fi
}
# 清理构建目录
cleanbuild() {
rm -rf "${PWD}/$builddir"
}
构建流程说明:
HPKBUILD 执行流程:
1. prepare() ← 准备阶段:复制源码、清理文件
↓
2. build() ← 构建阶段:CMake 配置、编译
↓
3. package() ← 打包阶段:安装产物到指定目录
↓
4. archive() ← 归档阶段:生成 tar.gz 和 hnp 包
↓
5. cleanbuild() ← 清理阶段:清除构建产物(可选)

3.3 创建 hnp.json(包元数据)
步骤说明:
hnp.json 文件用于描述 HNP 包的元信息,类似于 Node.js 的 package.json 或 Python 的 setup.py。它告诉鸿蒙系统这个包是什么、包含哪些文件、如何安装等信息。
hnp.json 的作用:
- 包信息描述:名称、版本、描述、许可证
- 架构信息:目标架构(arm64-v8a、armeabi-v7a)
- 安装规则:哪些文件安装到哪些目录
- 依赖声明:运行时依赖的其他 HNP 包
详细操作流程:
# 1. 确保当前在 mediainfo 目录
cd /home/weishuo/lycium_plusplus/thirdparty/mediainfo
# 2. 创建 hnp.json 文件
vim hnp.json
# 或
nano hnp.json
# 3. 验证 JSON 格式是否正确
python3 -m json.tool hnp.json > /dev/null && echo "JSON 格式正确" || echo "JSON 格式错误"
hnp.json 文件内容详解:
{
"type": "hnp-config",
"name": "mediainfo",
"version": "25.03",
"description": "A convenient unified display of the most relevant technical and tag data for video and audio files (CLI version)",
"license": "BSD-2-Clause",
"arch": "arm64-v8a",
"install": {
"bin": ["usr/bin/mediainfo"]
}
}

3.4 创建 README.OpenSource(开源声明)
步骤说明:
README.OpenSource 是为了满足开源合规性要求而创建的文件。它声明了 MediaInfo 及其所有依赖库的许可证信息、上游地址和版本信息。这是鸿蒙生态开源合规的必要文件。
为什么需要 README.OpenSource:
- 开源合规:声明所有使用的开源组件及其许可证
- 许可证追踪:记录每个组件的许可证文件和上游地址
- 版本管理:明确每个依赖库的版本号
- 法律风险规避:避免侵犯开源许可证条款
详细操作流程:
# 1. 确保当前在 mediainfo 目录
cd /home/weishuo/lycium_plusplus/thirdparty/mediainfo
# 2. 创建 README.OpenSource 文件
vim README.OpenSource
# 或
nano README.OpenSource
# 3. 验证 JSON 格式是否正确
python3 -m json.tool README.OpenSource > /dev/null && echo "JSON 格式正确" || echo "JSON 格式错误"
README.OpenSource 文件内容详解:
[
{
"Name": "MediaInfo",
"License": "BSD-2-Clause",
"License File": "https://github.com/MediaArea/MediaInfo/blob/master/LICENSE",
"Version Number": "25.03",
"Owner": "your-email@example.com",
"Upstream URL": "https://github.com/MediaArea/MediaInfo/releases/download/v25.03/MediaInfo_CLI_25.03_GNU_FromSource.tar.xz",
"Description": "MediaInfo is a convenient unified display of the most relevant technical and tag data for video and audio files."
},
{
"Name": "ZenLib",
"License": "zlib/libpng",
"License File": "https://github.com/MediaArea/ZenLib/blob/master/License.txt",
"Version Number": "0.4.41",
"Owner": "your-email@example.com",
"Upstream URL": "https://github.com/MediaArea/ZenLib/archive/refs/tags/v0.4.41.tar.gz",
"Description": "ZenLib is a C++ library for cross-platform development, used by MediaInfo."
},
{
"Name": "MediaInfoLib",
"License": "BSD-2-Clause",
"License File": "https://github.com/MediaArea/MediaInfoLib/blob/master/LICENSE",
"Version Number": "25.03",
"Owner": "your-email@example.com",
"Upstream URL": "https://github.com/MediaArea/MediaInfoLib/releases/download/v25.03/MediaInfoLib_25.03_GNU_FromSource.tar.xz",
"Description": "MediaInfoLib is the library for MediaInfo, providing media file analysis capabilities."
},
{
"Name": "zlib",
"License": "Zlib",
"License File": "https://github.com/madler/zlib/blob/master/LICENSE",
"Version Number": "1.3.1",
"Owner": "your-email@example.com",
"Upstream URL": "https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.gz",
"Description": "zlib is a software library used for data compression."
}
]

3.5 创建 HPKCHECK 检查脚本
步骤说明:
HPKCHECK 是 lycium 框架的构建检查脚本,用于在编译前验证环境是否满足构建要求,以及在编译后验证产物是否正确。它相当于一个“自动化测试脚本”,确保构建质量。
HPKCHECK 的作用:
- 环境验证:检查编译环境是否满足要求
- 产物验证:验证生成的可执行文件是否存在且可执行
- 功能测试:运行基本的功能测试(如 --version、–help)
- 日志记录:记录测试结果到日志文件
详细操作流程:
# 1. 确保当前在 mediainfo 目录
cd /home/weishuo/lycium_plusplus/thirdparty/mediainfo
# 2. 创建 HPKCHECK 文件
vim HPKCHECK
# 或
nano HPKCHECK
# 3. 添加可执行权限
chmod +x HPKCHECK
# 4. 验证脚本语法
bash -n HPKCHECK && echo "脚本语法正确" || echo "脚本语法错误"
HPKCHECK 文件内容详解:
#!/bin/bash
# HPKCHECK for MediaInfo CLI
HPK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${HPK_DIR}" || exit 1
source ./HPKBUILD > /dev/null 2>&1
logfile="${HPK_DIR}/${pkgname}_${ARCH}_test.log"
checkprepare() {
return 0
}
openharmonycheck() {
res=0
inst_bin="${LYCIUM_ROOT}/usr/${pkgname}/${ARCH}/bin"
if [ -x "${inst_bin}/mediainfo" ]; then
cd "$inst_bin" || return 1
else
echo "no mediainfo binary in ${inst_bin}" >&2
return 1
fi
{
echo "start test times: $(date)"
echo "=== MediaInfo CLI version check ==="
if [ -x ./mediainfo ]; then
./mediainfo --version
res=$(( res | $? ))
else
echo "missing ./mediainfo"
res=1
fi
echo "=== MediaInfo CLI help check ==="
if [ -x ./mediainfo ]; then
./mediainfo --help | head -20
res=$(( res | $? ))
else
echo "missing ./mediainfo"
res=1
fi
echo "end test times: $(date)"
} >> "${logfile}" 2>&1
if [ $res -ne 0 ] && [ -n "${LYCIUM_FAULT_PATH}" ]; then
mkdir -p "${LYCIUM_FAULT_PATH}/${pkgname}"
fi
cd "${OLDPWD}"
return $res
}

3.6 创建 mediainfo-zenlib-musl.patch(musl 兼容性补丁)
步骤说明:
mediainfo-zenlib-musl.patch 是修复 musl libc 兼容性的关键补丁文件。MediaInfo 依赖的 ZenLib 库使用了 pthread_cancel 函数,但 OpenHarmony 使用的 musl libc 不支持该函数,会导致编译失败。
为什么需要这个补丁:
- pthread_cancel 缺失:ZenLib 的 Thread.cpp 中调用了 pthread_cancel 来取消线程
- musl libc 限制:musl libc(OpenHarmony 使用的 C 库)出于简化设计,不提供 pthread_cancel 实现
- 编译阻断:不修复会导致链接错误 undefined reference to ‘pthread_cancel’
- 功能安全:MediaInfo CLI 实际上不需要线程取消功能,注释掉不影响正常使用
--- a/ZenLib/Source/ZenLib/Thread.cpp
+++ b/ZenLib/Source/ZenLib/Thread.cpp
@@ -520,7 +520,7 @@
{
#ifdef __unix__
- pthread_cancel((pthread_t)ThreadPointer);
+ // pthread_cancel not supported in musl libc (OpenHarmony)
#endif
#ifdef _WIN32
#ifdef UNICODE
补丁修改说明:
- 修改位置:ZenLib/Source/ZenLib/Thread.cpp 第 520 行附近
- 修改内容:将 pthread_cancel 函数调用替换为注释
- 影响范围:仅影响线程取消功能,MediaInfo CLI 不依赖此功能
HPKBUILD 中的使用方式:
补丁在 prepare() 函数中自动应用(见 3.2 节 HPKBUILD 的 prepare() 函数):
# 应用 musl 兼容性 patch(修复 pthread_cancel 不可用问题)
if [ -f "../mediainfo-zenlib-musl.patch" ]; then
echo "Applying musl compatibility patch..."
cd "$builddir"
patch -p1 < "../mediainfo-zenlib-musl.patch"
if [ $? -eq 0 ]; then
echo " Patch applied successfully"
else
echo " Patch may have already been applied or failed"
fi
cd "$OLDPWD"
fi
注意事项:
- patch 文件放在 thirdparty/mediainfo/ 目录,与 HPKBUILD 同级
- 使用 patch -p1 参数,因为 patch 文件中的路径以 a/ 和 b/ 开头
- 如果 patch 已经应用过,patch 命令会提示失败,脚本中会忽略此错误
- 这是标准做法,比直接在 HPKBUILD 中用 sed 或 python 修改源码更规范

四、编译流程与完整示例
4.1 环境准备
配置用于前置环境检查与变量设置,通过指定 鸿蒙SDK 路径、验证 CMake 环境,为 lycium_plusplus 构建三方库提供基础运行环境
# 1. 确保鸿蒙 SDK 已安装
export OHOS_SDK=/home/weishuo/ohos-sdk/linux
# 2. 确保 CMake 已安装
cmake --version
4.2 创建项目结构并执行编译
通过目录操作、脚本创建、清理缓存、执行构建指令,完成 lycium_plusplus 中 MediaInfo 三方库的从零构建全流程
cd lycium_plusplus/thirdparty
mkdir -p mediainfo
cd mediainfo
# 创建 HPKBUILD 文件(内容见第三章)
vim HPKBUILD
cd ../../lycium
# 清理历史构建记录(可选,但推荐)
grep -v 'mediainfo' usr/hpk_build.csv > usr/hpk_build.csv.tmp
mv usr/hpk_build.csv.tmp usr/hpk_build.csv
rm -rf ../thirdparty/mediainfo/mediainfo-25.03
rm -rf output/*/mediainfo*
# 开始构建
./build.sh mediainfo
4.3 构建成功输出示例

4.4 验证产物
构建成功后,编译产物会统一输出至 output 目录,包含标准 tar 压缩包 与鸿蒙专用 hnp 格式包

五、鸿蒙PC 上验证结果(测试)



解压并进入目录,并且查看二进制文件并添加执行权限,执行签名操作
# 解压到鸿蒙 PC 桌面(路径示例)
tar -zxf arm64-v8a.tar.gz
# 进入对应目录
cd arm64-v8a/bin
# 查看文件
ls -l
# 在鸿蒙 PC 上若策略要求,可对二进制签名(示例)
binary-sign-tool sign -inFile mediainfo -outFile mediainfo -selfSign "1"
# 按需添加执行权限
chmod +x mediainfo
# 执行测试
./mediainfo --version
MediaInfo help 命令测试
./mediainfo --help

MediaInfo 媒体文件分析测试
./mediainfo test.mp4


六、常见问题与解决方案(FAQ)
Q1:构建时报错 $‘\r’: command not found?
A:这是 Windows 换行符(CRLF)导致的问题。在 WSL + Windows 共享目录环境下,使用 create_file 工具创建的文件会自动带有 CRLF 换行符。解决方案是使用 Python 脚本在 Linux 环境中重新创建文件。
# 使用 Python 二进制模式转换(推荐)
python3 << 'EOF'
import os
files = [
"/path/to/HPKBUILD",
"/path/to/HPKCHECK"
]
for filepath in files:
with open(filepath, "rb") as f:
content = f.read()
content = content.replace(b"\r\n", b"\n").replace(b"\r", b"\n")
with open(filepath, "wb") as f:
f.write(content)
print(f"Fixed: {filepath}")
print("All files fixed!")
EOF
Q2:执行 ./build.sh mediainfo 后,日志显示 ALL JOBS DONE!!! 但 output 目录为空?
A:这通常是因为 hpk_build.csv 中已有该包的构建记录,导致构建被跳过。需要手动清理构建记录和缓存。
cd lycium_plusplus/lycium
grep -v 'mediainfo' usr/hpk_build.csv > usr/hpk_build.csv.tmp
mv usr/hpk_build.csv.tmp usr/hpk_build.csv
rm -rf ../thirdparty/mediainfo/mediainfo-25.03
rm -rf output/*/mediainfo*
./build.sh mediainfo
Q3:编译时报错 use of undeclared identifier ‘pthread_cancel’?
A:原因是 鸿蒙 使用 musl libc,不支持 pthread_cancel 函数。HPKBUILD 中已包含自动修复逻辑,会在 CMake 配置后检测并注释掉该函数调用。
--- a/ZenLib/Source/ZenLib/Thread.cpp
+++ b/ZenLib/Source/ZenLib/Thread.cpp
@@ -520,7 +520,7 @@
{
#ifdef __unix__
- pthread_cancel((pthread_t)ThreadPointer);
+ // pthread_cancel not supported in musl libc (OpenHarmony)
#endif
#ifdef _WIN32
#ifdef UNICODE
Q4:如何在鸿蒙 PC 上使用 MediaInfo CLI?
A:安装 HNP 包后,可以直接运行 mediainfo 命令。
# 查看版本
mediainfo --version
# 查看帮助
mediainfo --help
# 分析媒体文件
mediainfo video.mp4
# 输出 JSON 格式
mediainfo --Output=JSON audio.mp3
# 完整技术参数
mediainfo --Full movie.mkv
# 批量分析
mediainfo *.mp4 *.mkv
Q5:构建产物中包含 Windows 区域标识文件(:Zone.Identifier)?
A:原因是源码从 Windows 环境复制时带来了这些元数据文件。解决方案是在 prepare() 和 package() 阶段都添加清理命令。
# 在 prepare() 中清理
find "$builddir" -name "*:Zone.Identifier" -type f -delete
# 在 package() 中清理
find "${destdir}" -name "*:Zone.Identifier" -type f -delete
Q6:CMake 配置时报错找不到 ZenLib 或 MediaInfoLib?
A:MediaInfo 使用 CMake 的 FetchContent 机制自动下载依赖。确保网络连接正常(GitHub 可访问),已初始化子模块。
# 手动初始化子模块
cd ~/lycium_plusplus/Projects/MediaInfo
git submodule update --init --recursive
Q7:如何验证生成的可执行文件是否正确?
A:使用 file 命令检查 ELF 文件格式。
file ~/lycium_plusplus/lycium/usr/mediainfo/arm64-v8a/usr/bin/mediainfo
# 正确输出:
# ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV),
# dynamically linked, interpreter /lib/ld-musl-aarch64.so.1,
# with debug_info, not stripped
**Q8:**如何系统排查构建错误?
A:按以下步骤排查:
# 1. 查看完整日志
./build.sh mediainfo 2>&1 | tee build.log
# 2. 确认失败阶段:prepare / build / package / archive
# 3. 检查 prepare()
ls -la thirdparty/mediainfo/mediainfo-25.03/
# 4. 检查 build()
cat thirdparty/mediainfo/mediainfo-25.03/build.log
# 5. 检查 package() - 确认 destdir 路径和可执行文件是否存在
# 6. 检查 archive() - 确认打包路径是否正确
Q9:为什么选择本地源码而非 Git 下载?
A:本地源码模式更适合快速迭代开发,避免每次构建都重新下载。MediaInfo 包含多个子模块(ZenLib、MediaInfoLib、zlib),本地源码可以确保版本一致性。对于已经验证过的稳定版本,可以改为从 GitHub 下载。
# 改为从 GitHub 下载(修改 HPKBUILD)
source="https://github.com/MediaArea/MediaInfo/releases/download/v${pkgver}/MediaInfo_CLI_${pkgver}_GNU_FromSource.tar.xz"
autounpack=true
downloadpackage=true
# 需要提取准备源码放在Projects
# 本地源码路径(从环境变量 LYCIUM_ROOT 指向项目目录)
srcpath="${LYCIUM_ROOT}/../Projects/MediaInfo"
autounpack=false
downloadpackage=false
七、技术总结
本次将 MediaInfo CLI 适配至 鸿蒙PC 平台,完整验证了 C/C++ 原生项目在鸿蒙环境下的交叉编译、构建打包与体积优化流程,形成了可复用的适配范式。通过规范 HPKBUILD 配置、兼容 musl libc、清理 Windows 元数据、精简打包产物等关键处理,实现了工具正常编译运行与轻量化部署,相关思路可广泛迁移至各类开源 C/C++ 库的鸿蒙移植工作。
- 建立了 CMake 类项目标准化的 HPKBUILD 适配模板,明确交叉编译与依赖管理要点
- 解决 musl libc 兼容性、Windows 换行与元数据、CMake 目录规范等常见适配问题
- 通过产物裁剪实现包体积显著优化,提升在鸿蒙设备上的部署效率
- 适配方案具备通用性,可直接用于 FFmpeg、7-Zip、curl 等同类工具移植
- 为后续多架构扩展、动态链接优化、自动化适配工具开发奠定基础
八、结语
本次实践成功将 MediaInfo CLI 移植至 鸿蒙PC 平台,充分体现了 lycium_plusplus 框架对 C/C++ 项目交叉编译的支撑能力。通过合理运用 HPKBUILD 构建流程、适配 musl libc 环境、规范 CMake 编译配置、优化产物体积及自动管理依赖等关键措施,有效解决了适配中的兼容性与构建问题,为同类开源 C/C++ 项目迁移至鸿蒙生态提供了可复用的思路与实践参考,也助力开源鸿蒙原生工具生态的完善与发展。
提示:本文基于 MediaInfo CLI 25.03 版本进行适配。不同版本的依赖和构建脚本可能有所差异,建议在适配前先熟悉目标项目的 CMakeLists.txt 和构建配置文件。
更多推荐



所有评论(0)