移植 vcpkg 到鸿蒙 PC:vcpkg-tool 交叉编译与实践手记
终于可以在鸿蒙PC电脑上直接使用vcpkg啦。用到的三方库可以直接在鸿蒙PC上使用vcpkg命令安装。在鸿蒙PC上使用之前,需要先把vcpkg这个可执行命令行程序移植上去。本文记录使用 OHOS SDK + CMake + Ninja,在Ubuntu24.04的linux宿主机环境上 ,交叉编译 vcpkg-tool(生成可在鸿蒙 PC 上运行的
vcpkg可执行文件)的全过程,包括依赖约定、典型报错与处理方式,以及在设备侧运行时与 dlopen / 签名 / libcurl 相关的注意事项。
vcpkg在鸿蒙PC上使用效果截图:

移植成功的鸿蒙PC上的vcpkg项目地址:https://gitcode.com/qq8864/vcpkg-tool.git,
找到ohos-pc分支,里面有编译好的在鸿蒙PC上可运行的vcpkg可执行文件,将其拷贝到鸿蒙PC上即可运行。
如何真机验证和使用?
1.在鸿蒙PC上,clone以下仓库地址:
git clone https://gitcode.com/OpenHarmonyPCDeveloper/ohos_vcpkg.git
将构建生成的可在鸿蒙pc上运行的vcpkg可执行文件放进上面clone下来的ohos_vcpkg里。将依赖的鸿蒙PC平台上的so库(libcurl.so.4、libssl.so.3、 libcrypto.so.3、libz.so)也放进来。
2.运行:
cd ohos_vcpkg
LD_LIBRARY_PATH="$(pwd)" ./vcpkg --version
预期可见版本信息,例如:
vcpkg package management program version 2999-12-31-unknownhash
接下来介绍下vcpkg-tool 交叉编译的详细过程:
1. 环境与目标
| 项目 | 说明 |
|---|---|
| 目标三元组 / 架构 | aarch64-linux-ohos |
| SDK | OHOS SDK(示例路径见下) |
| CMake | ≥ 3.28,示例 4.1.2 |
| Ninja | 示例 1.12.1 |
| 生成系统 | Ninja |
| 典型宿主机 | Ubuntu 24.04(x86_64),交叉编译目标为 aarch64 OHOS |
| 真机验证环境 | 鸿蒙PC(arm64-v8a) |
宿主机 | Ubuntu 24.04(x86_64)环境下SDK安装及下载:
1.0 环境准备(Ubuntu 24.04_x86_64 宿主机环境)
sudo apt update
sudo apt install -y git curl cmake ninja-build gcc g++ make autoconf automake libtool yasm nasm
sudo apt install -y gettext autopoint
sudo apt install python3 python3-pip
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1
1.1下载配置ohos-sdk
sdk_download_url="https://cidownload.openharmony.cn/version/Daily_Version/OpenHarmony_6.1.0.27/20260111_020523/version-Daily_Version-OpenHarmony_6.1.0.27-20260111_020523-ohos-sdk-public.tar.gz"
curl -o ohos-sdk-public.tar.gz $sdk_download_url
mkdir ohos-sdk
tar -zxf ohos-sdk-public.tar.gz -C ohos-sdk
cd ~/ohos-sdk/linux
unzip native-linux-x64-6.1.0.27-Beta1.zip
unzip toolchains-linux-x64-6.1.0.27-Beta1.zip
这段代码的作用是从指定的 URL 下载 SDK 压缩包,然后创建一个名为 ohos-sdk 的目录,并将压缩包解压到该目录下。
SDK 目录示例(以 $OHOS_SDK_ROOT/linux/native/ 为前缀):
/root/ohos-sdk/linux/native/
├── build-tools/
├── llvm/ # clang、lld、ar 等
├── sysroot/ # 头文件与系统库
└── toolchain.cmake # 或 ohos.toolchain.cmake(依 SDK 版本而定)
设置环境变量:
export OHOS_SDK_ROOT=/root/ohos-sdk/linux
2. 前置依赖
在配置工程前,确认 SDK 自带的构建工具可用:
"$OHOS_SDK_ROOT/native/build-tools/cmake/bin/cmake" --version
"$OHOS_SDK_ROOT/native/build-tools/cmake/bin/ninja" --version
注意, 还需要:
- 已在 同一 OHOS triplet 下通过 vcpkg(或其它方式)准备好
curl、fmt、nlohmann-json等鸿蒙PC上的so库,外部依赖的安装前缀(下文 CMake 变量中的路径需要用到)。 - 若在大陆网络环境构建,
FetchContent/ GitHub 直连失败时需准备代理或离线包(见第 5 节)。
关于这部分内容,可以参考博文:使用 vcpkg 为鸿蒙(HarmonyOS / OHOS)下载与安装三方库实践指南
简单来说,就是需要先搞个在linux或windows上能用的vcpkg环境,用来安装鸿蒙pc上的三方库。
因为vcpkg可执行文件,依赖了curl和openssl等鸿蒙pc上的so库。
如下所示:
1.安装依赖fmt:
./vcpkg install fmt:arm64-ohos

2.安装libcurl和json库:
# 安装鸿蒙pc上的libcurl的so库
./vcpkg install libcurl:arm64-ohos
# 安装鸿蒙pc上的nlohmann-jsonso库
./vcpkg install nlohmann-json:arm64-ohos

3. 构建思路简述
- 使用 OHOS 的 CMake toolchain 指向 Clang 与 sysroot。
- 将
curl、nlohmann-json作为外部 CMake 包接入(DVCPKG_DEPENDENCY_EXTERNAL_*),避免使用 vcpkg-tool 内置抓取的头文件与宿主不匹配。 fmt建议走内置静态依赖:外部 fmt 主版本与 vcpkg-tool 源码(期望 fmt v11 /fmt::v11)不一致时会出现模板符号歧义(见第 6 节)。- 对
curl/curlbuild.h一类交叉编译宏冲突,通过 额外 include 路径 指向你用 OHOS 工具链编好的 curl 头文件。
4. 问题一:libcurl 头文件 / curlbuild.h 报错
4.1 典型报错摘录
In file included from include/vcpkg/base/curl.h:14:
build/_deps/libcurlheaders-src/include/curl/curlbuild.h:122:4:
error: "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
build/_deps/libcurlheaders-src/include/curl/curlrules.h:79:4:
error: "CURL_SIZEOF_LONG definition is missing!"

4.2 原因说明(简述)
vcpkg-tool 会 FetchContent 一套用于编译期的 curl 头文件树;该树里的 curlbuild.h 与当前交叉目标(OHOS / aarch64)的长整数、socklen_t 等尺寸假定不一致时,会触发 curlrules.h 的静态断言。
4.3 处理办法
改为使用已为 OHOS 编好的 curl 安装树中的头文件,并通过编译选项把该 include 目录放到搜索路径最前(示例路径请替换为你的包路径):
-DCMAKE_CXX_FLAGS="-I/root/ohos_vcpkg/packages/curl_arm64-ohos/include"
同时配合「外部 curl CMake 包」开关(见第 7 节完整 CMake 命令)。
5. 问题二:CMake 拉取 GitHub / FetchContent 失败
5.1 现象
配置阶段在下载 cmrc、libcurlheaders 等依赖 tarball 时超时或 TLS 失败。

5.2 方法一:代理(推荐)
export http_proxy=http://<代理主机>:<端口>
export https_proxy=http://<代理主机>:<端口>
# 重新执行 cmake 配置命令
5.3 方法二:离线放置源码包(「欺骗」下载步骤)
在可访问 GitHub 的机器上下载对应版本,例如:
https://github.com/vector-of-bool/cmrc/archive/refs/tags/2.0.1.tar.gz
上传到构建机后,放入 CMake FetchContent 期望的 populate 源码目录(路径需与你的 build/_deps/... 实际一致),例如:
mkdir -p /root/vcpkg-tool/build/_deps/cmakerc-subbuild/cmakerc-populate-prefix/src/
cp 2.0.1.tar.gz /root/vcpkg-tool/build/_deps/cmakerc-subbuild/cmakerc-populate-prefix/src/
mkdir -p /root/vcpkg-tool/build/_deps/libcurlheaders-subbuild/libcurlheaders-populate-prefix/src/
cp curl-7.29.0.tar.gz /root/vcpkg-tool/build/_deps/libcurlheaders-subbuild/libcurlheaders-populate-prefix/src/
保留 build 目录后再次运行 同一套 cmake 命令,若哈希与大小校验策略允许,常会跳过重新下载。
5.4 方法三:改镜像 URL
若允许修改 vcpkg-tool 仓库内的 CMakeLists.txt / cmake/ 中的 FetchContent URL,可替换为国内镜像或自建制品地址(注意版本与校验和一致性)。
6. 问题三:fmt 版本不一致导致编译歧义
6.1 典型报错特征
编译错误中出现 fmt::v11 与 fmt::v12(或其它主版本)并存、formatter ambiguous 等描述。
6.2 根因
vcpkg-tool 当前源码按 fmt v11 API 编写;若 DVCPKG_DEPENDENCY_EXTERNAL_FMT=ON 且提供的 fmt 过新(例如 v12),会出现命名空间与模板实例歧义。
这个报错的原因是 fmt 库的版本冲突导致的。
报错根本原因版本不匹配:vcpkg-tool 的源代码(尤其是 stringview.h 和 fmt.h)是基于 fmt v11 编写的(代码中期望找到 fmt::v11)。
符号冲突:你手动编译并提供的外部 fmt 库版本太新了(从错误日志看是 v12,即 fmt::v12::formatter)。歧义:当编译器遇到 fmt::formatter 时,它同时发现了 v11(代码声明)和 v12(你提供的库),导致 reference to ‘formatter’ is ambiguous(引用歧义)。
6.3 推荐做法
-DVCPKG_DEPENDENCY_EXTERNAL_FMT=OFF
让工程 内置获取并静态链接 与源码匹配的 fmt,避免与外部包版本打架。外部 curl / nlohmann-json 仍可保持 ON。关闭它,让它自己下载并编译链接使用内部的静态库。
7. 问题四:构建成功后在鸿蒙 PC 上运行找不到 libcurl
7.1 现象
可执行文件启动即退出,提示类似:
vcpkg was unable to find a libcurl.so.4, libcurl-gnutls.so.4, or libcurl-nss.so.4 to use on this system.
即便已将目录加入 LD_LIBRARY_PATH,仍可能失败。
7.2 原因概要
- vcpkg-tool 不在链接期硬链接 libcurl,而是在运行时用
dlopen("libcurl.so.4", ...)加载(参见源码src/vcpkg/base/curl.cpp)。 - 鸿蒙侧对加载进进程的 ELF 共享库往往有签名校验要求;未签名的
libcurl.so/ 其传递依赖可能在策略上无法被成功dlopen。 libcurl.so.4与 SONAME:部分构建产物 SONAME 为libcurl.so,但 dlopen 按文件名查找libcurl.so.4;部署时需保证 查找路径下存在期望文件名(必要时同时保留符号链接或拷贝)。
7.3 依赖链自检
readelf -d build/libcurl.so | grep -E "SONAME|NEEDED"
示例输出(示意):
0x0000000000000001 (NEEDED) Shared library: [libssl.so.3]
0x0000000000000001 (NEEDED) Shared library: [libcrypto.so.3]
0x0000000000000001 (NEEDED) Shared library: [libz.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so]
0x000000000000000e (SONAME) Library soname: [libcurl.so]
结论: libcurl、openssl、zlib 等在运行路径中不仅要「找得到」,在鸿蒙 PC 上通常还需要满足 签名 / 安全策略。
7.4 签名与运行示例
在鸿蒙环境使用 binary-sign-tool 对 .so 签名(路径与参数以你的 SDK / 系统文档为准):
cd build
binary-sign-tool sign -inFile libcurl.so -outFile libcurl.so -selfSign "1"
binary-sign-tool sign -inFile libcurl.so.4 -outFile libcurl.so.4 -selfSign "1"
binary-sign-tool sign -inFile libssl.so.3 -outFile libssl.so.3 -selfSign "1"
binary-sign-tool sign -inFile libcrypto.so.3 -outFile libcrypto.so.3 -selfSign "1"
binary-sign-tool sign -inFile libz.so -outFile libz.so -selfSign "1" || true
批量示例:
cd build
for lib in libcurl.so libcurl.so.4 libssl.so.3 libcrypto.so.3; do
binary-sign-tool sign -inFile "$lib" -outFile "$lib" -selfSign "1"
done
binary-sign-tool sign -inFile libz.so -outFile libz.so -selfSign "1" || true
运行:
cd build
LD_LIBRARY_PATH="$(pwd)" ./vcpkg --version
预期可见版本信息,例如:
vcpkg package management program version 2999-12-31-unknownhash
便捷脚本示例(run-vcpkg.sh):
#!/bin/sh
cd "$(dirname "$0")/build"
export LD_LIBRARY_PATH="$(pwd)"
exec ./vcpkg "$@"
7.5 已知限制说明
binary-sign-tool对部分较小或非典型 ELF 文件可能报FILE_NOT_FOUND等误报;业界反馈中libz.so偶发;一般 不影响文件完整性,核心libcurl/libssl/libcrypto签名成功即可优先验证主流程。- 对
vcpkg主程序本身 的签名若失败,多数场景下 不影响「只要能加载依赖.so」的运行路径验证。
8. 完整 CMake 配置示例(全新构建)
以下为一组「可用作起点」的命令;请将所有 /root/... 路径替换为你的 OHOS SDK、vcpkg 安装前缀与依赖包路径。
##进入vcpkg-tool目录
cd ~/vcpkg-tool/
# 执行脚本
cmake -S . -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF \
-DCMAKE_TOOLCHAIN_FILE="$OHOS_SDK_ROOT/native/build/cmake/ohos.toolchain.cmake" \
-DCMAKE_INSTALL_PREFIX=build/install \
-DVCPKG_DEPENDENCY_EXTERNAL_FMT=OFF \
-DVCPKG_DEPENDENCY_EXTERNAL_CURL=ON \
-DVCPKG_DEPENDENCY_EXTERNAL_NLOHMANN_JSON=ON \
-Dfmt_DIR="/root/ohos_vcpkg/packages/fmt_arm64-ohos/share/fmt" \
-Dcurl_DIR="/root/ohos_vcpkg/packages/curl_arm64-ohos/share/curl" \
-Dnlohmann_json_DIR="/root/ohos_vcpkg/packages/nlohmann-json_arm64-ohos/share/nlohmann_json" \
-DCMAKE_CXX_FLAGS="-I/root/ohos_vcpkg/packages/curl_arm64-ohos/include"
cmake --build build
增量重建:
ninja -C build
清理:
ninja -C build -t clean
# 或彻底删除 build/
rm -rf build
在鸿蒙PC上执行:
拷贝vcpkg可执行文件和依赖的库放到鸿蒙PC上,例如下面的build目录作为测试:
# 鸿蒙 PC 运行前:对依赖 .so 签名(见第 7 节)
cd build
for lib in libcurl.so libcurl.so.4 libssl.so.3 libcrypto.so.3; do
binary-sign-tool sign -inFile "$lib" -outFile "$lib" -selfSign "1"
done
LD_LIBRARY_PATH="$(pwd)" ./vcpkg --version
9. 常见问题 FAQ
Q1:clang++: warning: argument unused during compilation: '--gcc-toolchain=...'
多为 OHOS Clang 识别了 --gcc-toolchain 但在当前链接模型下未使用所致,一般 可忽略。如需静默可加:
-Wno-unused-command-line-argument
或在 toolchain 中精简该参数的传递(视 SDK 版本而定)。
Q2:明明存在 libcurl.so.4,仍提示找不到?
- 用
readelf -S等工具确认是否已有 鸿蒙 codesign /.ohos.codesign相关段(具体命令以你环境文档为准)。 - 确认
libssl.so.3、libcrypto.so.3、libz.so等同路径可得且策略允许加载。 LD_LIBRARY_PATH是否覆盖 实际放置.so的目录;文件名是否与dlopen期望一致。
Q3:在鸿蒙 PC 上没有图形界面,如何低成本验证?
可在 x86_64 Linux 上通过容器模拟鸿蒙 PC 运行环境;社区有不少基于 Docker 的搭建文章可参考,例如:
低成本搭建鸿蒙 PC 运行环境:基于 Docker 的 x86_64 服务器(CSDN)

真机上运行:
附录:产物自检命令
file ohos_vcpkg/vcpkg
# 示例:ELF 64-bit LSB executable, ARM aarch64, ...
readelf -d ohos_vcpkg/vcpkg | grep NEEDED
readelf -n ohos_vcpkg/vcpkg | grep "Build ID"
readelf -S ohos_vcpkg/libcurl.so.4 | grep -i codesign
readelf -d ohos_vcpkg/libcurl.so | grep -E "SONAME|NEEDED"
LD_LIBRARY_PATH=ohos_vcpkg ohos_vcpkg/vcpkg --version
结语
将 vcpkg-tool 交叉编译到 鸿蒙 PC(aarch64 OHOS),难点通常集中在三件事:交叉编译下 curl 头文件与宏的一致性、FetchContent 的网络与离线兜底、以及 运行时 libcurl 的 dlopen + 系统级签名策略。按本文顺序逐项对齐后,可在宿主机稳定产出 ELF,并在鸿蒙 PC(或容器模拟环境)中完成 vcpkg --version 级别的冒烟验证。
更多分享请访问:猫哥的博客
欢迎加入鸿蒙PC开发者社区,共同打造开发者工具生态: 鸿蒙PC开发者社区
更多推荐




所有评论(0)