在这里插入图片描述

网罗开发 (小红书、快手、视频号同名)

  大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。


本文说明如何在鸿蒙 PC(HarmonyOS / OpenHarmony,OHOS 工具链)上使用 vcpkg 构建 ZenLib(libzen),并在此基础上安装依赖它的 libmediainfo。重点记录 musl / OHOS 环境下 pthread_cancel 不可用 的典型报错与 port 补丁 做法,便于在团队内复现与升级版本,做为使用vcpkg 鸿蒙化三方库的迁移使用指导。

前言:背景与动机

鸿蒙 PC 侧原生应用或媒体类工具常需要成熟的 C/C++ 三方库。手动管理源码、补丁和交叉编译参数成本高,而 vcpkg 作为微软开源的 C/C++ 包管理器,通过 port(构建配方) 统一处理下载、打补丁、CMake 配置与安装,并与 scripts/buildsystems/vcpkg.cmake 深度集成,适合作为 OHOS 三方库的「单一入口」。

社区已有面向 OHOS 的 vcpkg 衍生仓库与文档,本文建立在以下资源之上:

库简介

ZenLib(vcpkg 包名:libzen

ZenLibMediaArea 维护的 C++ 跨平台基础库(字符串、线程、工具类等),广泛用于同一生态内的其它组件。在 vcpkg 中端口名为 libzen(当前文基于版本 0.4.41port-version 调整见后文)。

libmediainfo

libmediainfo 用于读取音视频及多媒体文件的 元数据(封装格式、编码、时长等),底层依赖 ZenLib 等组件。完成 libzen 在 OHOS 上的编译与安装后,libmediainfo 的依赖链在 vcpkg 侧通常已打通,安装命令简洁;文末给出简要步骤与参考仓库。

前置条件

环境变量与工具链

export OHOS_SDK_ROOT=/path/to/ohos-sdk/linux

确认 Clang 可用:

ls "$OHOS_SDK_ROOT/native/llvm/bin/clang++"

Triplet

下文以 arm64-ohos 为例(名称需与本仓 triplets 实际一致)。

第一部分:移植 libzen(ZenLib)

1.1 在 OHOS 上容易踩坑的原因

移植难点往往不在于依赖数量,而在于:

  • 工具链与 sysroot--target=…-ohos 对齐;
  • libc 行为差异:OHOS 侧常见 musl 取向;部分在 glibc 上习以为常的接口 不存在或未实现

其中 pthread_cancel 是最常见的卡点之一。

1.2 典型报错:pthread_cancel 未声明

编译 Source/ZenLib/Thread.cpp 时可能出现:

error: use of undeclared identifier 'pthread_cancel'

根因简述: pthread_cancel 并非 POSIX 必选接口,在 musl 等实现中通常不可用;OHOS 编译参数里也常见 -D__MUSL__。ZenLib 原先策略是 Android 不走 pthread_cancel,其它 Unix 走该路径;OHOS/musl 更接近应采用与 Android 同类策略,而不是传统 glibc Linux。

1.3 vcpkg 侧解决方案

补丁文件

仓库中提供:

  • ports/libzen/ohos-musl-no-pthread-cancel.patch

并在 ports/libzen/portfile.cmakevcpkg_from_github 里通过 PATCHES 自动应用。

思路:__ANDROID_API____OHOS____MUSL__ 任一成立时 不调用 pthread_cancel,并用 (void)ThreadPointer; 消除未使用变量告警。

提升 port-version

为避免二进制缓存或旧构建树认为 port「未变化」,在 ports/libzen/vcpkg.json 中已增加例如:

"port-version": 1

(具体数值以仓库为准。)

1.4 关键文件摘录

补丁核心 diff(示意):

diff --git a/Source/ZenLib/Thread.cpp b/Source/ZenLib/Thread.cpp
--- a/Source/ZenLib/Thread.cpp
+++ b/Source/ZenLib/Thread.cpp
@@ -519,11 +519,15 @@ Thread::returnvalue Thread::ForceTerminate()
 {
     //Terminating (not clean)
-    #if !defined(__ANDROID_API__)
+    // pthread_cancel is not available on some libc implementations (e.g. musl,
+    // OpenHarmony). Android already excludes it; extend the same policy.
+    #if !defined(__ANDROID_API__) && !defined(__OHOS__) && !defined(__MUSL__)
     pthread_cancel((pthread_t)ThreadPointer);
+    #else
+    (void)ThreadPointer;
     #endif
 
     //Configuring
     State=State_Terminated;

portfile.cmake(结构与补丁引用):

if(VCPKG_TARGET_IS_WINDOWS)
    vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
endif()

vcpkg_from_github(
    OUT_SOURCE_PATH SOURCE_PATH
    REPO MediaArea/ZenLib
    REF "v${VERSION}"
    SHA512 4232eb6e73e9b380f6fe2ce3cfeb9fe343936362a35ca8d088c783dc6277332df762d689efe023e3f1418c2e6d2629e0b82ac93df9cce3ae0ab346c2ed1911f1
    HEAD_REF master
    PATCHES
        ohos-musl-no-pthread-cancel.patch
)

vcpkg_find_acquire_program(PKGCONFIG)

vcpkg_cmake_configure(
    SOURCE_PATH "${SOURCE_PATH}/Project/CMake"
    OPTIONS
        "-DPKG_CONFIG_EXECUTABLE=${PKGCONFIG}"
        -DCMAKE_REQUIRE_FIND_PACKAGE_PkgConfig=1
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(PACKAGE_NAME zenlib)
vcpkg_fixup_pkgconfig()
if(NOT VCPKG_BUILD_TYPE AND VCPKG_TARGET_IS_WINDOWS)
    vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/libzen.pc" " -lzen" " -lzend")
endif()

file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include" "${CURRENT_PACKAGES_DIR}/debug/share")

vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/License.txt")

vcpkg.json 示例:

{
  "name": "libzen",
  "version": "0.4.41",
  "port-version": 1,
  "description": "ZenLib is a C++ utility library for easiest cross-platform development",
  "homepage": "https://github.com/MediaArea/ZenLib",
  "license": "Zlib",
  "dependencies": [
    {
      "name": "vcpkg-cmake",
      "host": true
    },
    {
      "name": "vcpkg-cmake-config",
      "host": true
    }
  ]
}

1.5 安装命令与产物位置

修改 port 后建议清理 libzen 构建树,避免补丁未重新应用:

rm -rf /path/to/vcpkg/buildtrees/libzen

vcpkg install libzen:arm64-ohos

安装成功后,典型产物路径:

  • installed/arm64-ohos/lib/(库文件,具体静态/动态由 triplet 决定)
  • installed/arm64-ohos/include/
  • installed/arm64-ohos/share/zenlib/(CMake 包配置,以实际生成为准)

编译成功效果(示意):

在这里插入图片描述

第二部分:移植 libmediainfo

libzen 已正确安装的前提下,libmediainfo 在依赖解析上通常不再卡在 ZenLib 层;按本仓库 port 状态执行安装即可,例如:

vcpkg install libmediainfo:arm64-ohos

(若 port 名称或 feature 与上游变动,以 ohos_vcpkg 仓库内 ports/libmediainfo 为准。)

安装成功效果(示意):

在这里插入图片描述

相关仓库参考:

排障清单

  1. 补丁是否生效: 删除 buildtrees/libzen 后重新 vcpkg install libzen:arm64-ohos
  2. 交叉编译参数: 编译命令中应出现 --target=…-ohos--sysroot=…/native/sysroot
  3. OHOS_SDK_ROOT 路径正确,避免出现多余 / 或缺失目录。
  4. 其它 libc 差异: 若仍有报错,按报错逐个比对是否为 glibc-only API,再考虑补丁或替换实现。

结语

libzen 移植到 HarmonyOS / OHOS,本质是 交叉编译 + libc 能力对齐pthread_cancel 看似「标准 pthread」,在 musl/OHOS 下却不成立;通过 vcpkg port 补丁 把平台差异收敛在包管理侧,业务 CMake 可保持简洁,并便于版本升级与团队复用。

附录:社区与交流

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐