HarmonyOS PC(鸿蒙PC)交叉编译 OpenCV 4.8(WSL+Lycium++)并集成 DevEco Studio
工具:WSL + Ubuntu24 + DevEco Studio
环境配置
安装工具
## 切换root用户
sudo -i
## 更新和安装包
apt update
apt install -y gcc g++ cmake make pkg-config autoconf automake git git-lfs ninja-build
sudo apt install -y unzip curl wget tree vim
## 退出root用户
exit
## 配置python虚拟环境来安装meson,以免污染原有python环境
apt install -y python3-venv python3-full
cd ~
python3 -m venv ohos_env
source ohos_env/bin/activate
pip install meson==1.5.1
## 查看meson版本
meson --version
下载 OHOS SDK 压缩包
## 创建目录并下载 SDK 压缩包
mkdir -p ~/ohpkg
cd ~/ohpkg
~/ohpkg$ wget https://repo.huaweicloud.com/openharmony/os/6.0-Release/ohos-sdk-windows_linux-public.tar.gz
## 解压 SDK
~/ohpkg$ tar -zxf ohos-sdk-windows_linux-public.tar.gz
## 解压 native 工具链
cd linux
unzip -q native-linux-x64-6.0.0.47-Beta1.zip
~/ohpkg/linux$ unzip -q toolchains-linux-x64-6.0.0.47-Beta1.zip
配置 OHOS_SDK 等环境变量
## SDK路径和hnpcli路径改为自己的,一般只要改用户名(如:imlsy)
echo 'export OHOS_SDK=/home/imlsy/ohpkg/linux' >> ~/.bashrc
echo 'export HNP_TOOL=/home/imlsy/ohpkg/linux/toolchains/hnpcli' >> ~/.bashrc
source ~/.bashrc
## 检查是不是自己刚刚设置的
## 期望得到
## /home/imlsy/ohpkg/linux
## /home/imlsy/ohpkg/linux/toolchains/hnpcli
echo $OHOS_SDK
echo $HNP_TOOL
克隆 lycium++
# 克隆 Lycium++ 工具仓库(用于编译 HarmonyOS 第三方库)
git clone https://gitcode.com/OpenHarmonyPCDeveloper/lycium_plusplus.git
# 进入 Lycium 工具的脚本目录
cd ~/lycium_plusplus/lycium/script
# 备份环境配置文件(以防修改出错)
cp envset.sh envset.sh.bak
# 检查 envset.sh 脚本语法是否正确(不执行,仅做语法检查)
bash -n ~/lycium_plusplus/lycium/script/envset.sh
# 进入 Lycium 主目录
cd ~/lycium_plusplus/lycium
# 激活 Python 虚拟环境(用于运行 Lycium 工具)
source ~/ohos_env/bin/activate
# 加载环境变量(设置交叉编译工具链路径等)
source script/envset.sh
# 验证交叉编译器的 C 预处理器是否配置正确
# 应该输出:/home/imlsy/ohpkg/linux/native/llvm/bin/aarch64-linux-ohos-clang -E
echo $CPP
# 进入 CUPS 第三方库的源码目录
cd ~/lycium_plusplus/thirdparty/cups
# 返回 Lycium 主目录
cd ~/lycium_plusplus/lycium
# 重新激活 Python 虚拟环境
source ~/ohos_env/bin/activate
# 重新加载环境变量
source script/envset.sh
如果后续编译构建失败,记得用 rm 清除旧的构建
交叉编译
拉取 OpenCV 代码
进入 thirdparty,创建 opencv 适配目录,用 Git 进行项目拉取
## 进入目录,创建适配文件夹
cd ~/lycium_plusplus/thirdparty
mkdir -p opencv
cd opencv
## 拉取代码
git clone -b 4.8.0 https://github.com/opencv/opencv.git opencv-4.8.0

创建并编辑 HPKBUILD 文件
HPKBUILD 鸿蒙三方库的“构建说明书”,可以把它理解成是为特定 CPU(如鸿蒙 PC 的 ARM 架构)准备的一份“定制化编译菜谱”,lycium 框架会读取这份“菜谱”,并按照其中的步骤自动完成从下载源码到生成 .so 文件的全过程。
创建和编辑 HPKBUILD 文件
因为这里是部分编译 OpenCV 的内容,所以如果需要编译全部或者自己想要的内容可以进行修改。
# 编辑 HPKBUILD
vim HPKBUILD
~/lycium_plusplus/thirdparty/opencv/HPKBUILD
#!/bin/bash
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License
pkgname=opencv
pkgver=4.8.0
pkgrel=0
pkgdesc="OpenCV (core + imgproc + imgcodecs only)"
url="https://github.com/opencv/opencv"
archs=("arm64-v8a")
license=("Apache License 2.0")
depends=()
makedepends=()
source="https://gitee.com/lycium_pkg_mirror/$pkgname/repository/archive/$pkgver.zip"
autounpack=false
downloadpackage=false
patchflag=true
builddir="opencv-${pkgver}"
packagename="${pkgver}.zip"
test_data_name=opencv_extra
test_data_version=4.8.1
test_data=$test_data_name-$test_data_version
testresdownloadflag=true
prepare() {
# 检查本地源码是否存在
if [ ! -d "$builddir" ]; then
echo "ERROR: Source directory $builddir not found!"
echo "Please copy OpenCV source to: $(pwd)/$builddir"
exit 1
fi
echo "Using local source: $(pwd)/$builddir"
if [ $patchflag == true ];then
cd $builddir
patch -p1 < `pwd`/../opencv_oh_test.patch > $publicbuildlog 2>&1 || true
patchflag=false
cd $OLDPWD
fi
mkdir -p $builddir/$ARCH-build
}
build() {
cd $builddir
${OHOS_SDK}/native/build-tools/cmake/bin/cmake "$@" \
-DBUILD_LIST=core,imgproc,imgcodecs \
-DBUILD_TESTS=OFF \
-DBUILD_PERF_TESTS=OFF \
-DCMAKE_C_FLAGS="-fvisibility=default" \
-DCMAKE_CXX_FLAGS="-fvisibility=default" \
-DENABLE_NEON=OFF \
-B$ARCH-build -S./ > $buildlog 2>&1
$MAKE -C $ARCH-build VERBOSE=1 >> $buildlog 2>&1
ret=$?
cd $OLDPWD
return $ret
}
package() {
cd $builddir
$MAKE -C $ARCH-build install >> $buildlog 2>&1
cd $OLDPWD
}
check() {
if [ $ARCH == "arm64-v8a" ]; then
cp ${OHOS_SDK}/native/llvm/lib/aarch64-linux-ohos/libc++_shared.so $LYCIUM_ROOT/usr/$pkgname/$ARCH/lib/ 2>/dev/null || true
fi
echo "OpenCV built successfully for $ARCH"
}
cleanbuild(){
rm -rf ${PWD}/$builddir/$ARCH-build
}
如果更喜欢可视化编辑,可以下载MobaXterm进行文件编辑。
确认环境变量
export OHOS_SDK=/home/imlsy/ohpkg/linux
export LYCIUM_ROOT=/home/imlsy/lycium_plusplus/lycium
编译
cd ~/lycium_plusplus/lycium
./build.sh opencv
成功标志


编译出来的文件在 “~/lycium_plusplus/lycium/usr/opencv/arm64-v8a/”。
传送编译好的文件到 Windows
将编译好的三方库复制/发送到 Windows 电脑(即本机)。
采用的方法可以是通过 \\wsl$ 访问文件直接复制这些文件到 Windows 目录下,或者用 psftp/scp 从 WSL 传输到 Windows。
进行复制粘贴的路径是 “\\wsl.localhost\Ubuntu_24.04\home\imlsy\lycium_plusplus\lycium\output\arm64-v8a”。
可以随便找一个 Windows 目录放进去。后续会将解压出来的文件放进项目里面进行使用。

这里是在 WSL 用 cp 进行复制粘贴
# 1. 创建目标目录(如果不存在)
mkdir -p /mnt/d/harmonyos_libplacebo/temp
# 2. 复制头文件(整个 opencv4 目录)
cp -r ~/lycium_plusplus/lycium/usr/opencv/arm64-v8a/include/opencv4 /mnt/d/harmonyos_libplacebo/temp/
# 3. 复制 .so 文件(复制实际文件,重命名为不带版本号)
cp ~/lycium_plusplus/lycium/usr/opencv/arm64-v8a/lib/libopencv_core.so.4.8.0 /mnt/d/harmonyos_libplacebo/temp/libopencv_core.so
cp ~/lycium_plusplus/lycium/usr/opencv/arm64-v8a/lib/libopencv_imgproc.so.4.8.0 /mnt/d/harmonyos_libplacebo/temp/libopencv_imgproc.so
cp ~/lycium_plusplus/lycium/usr/opencv/arm64-v8a/lib/libopencv_imgcodecs.so.4.8.0 /mnt/d/harmonyos_libplacebo/temp/libopencv_imgcodecs.so
# 4. 确认文件已复制
ls -la /mnt/d/harmonyos_libplacebo/temp/

DevEco Studio 集成调用
创建项目
创建一个 Native C++ 的空项目。

把我们将复制出来的 3 个文件放到 “MyOpenCVProject/entry/libs/arm64-v8a/” 目录下:
- libopencv_core.so
- libopencv_imgproc.so
- libopencv_imgcodecs.so
将 opencv4 文件夹放入 “MyOpenCVProject\entry\src\main\cpp\include” 目录下,如果没有include 文件夹,就手动创建一个。

编写四个文件
CMakeLists.txt
告诉编译系统如何编译 C++ 代码
cmake_minimum_required(VERSION 3.5.0)
project(car_companion)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
if(DEFINED PACKAGE_FIND_FILE)
include(${PACKAGE_FIND_FILE})
endif()
# ========== 声明 OpenCV 库(三个模块) ==========
set(LIBS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH})
# core
add_library(opencv_core SHARED IMPORTED)
set_target_properties(opencv_core PROPERTIES IMPORTED_LOCATION ${LIBS_DIR}/libopencv_core.so)
# imgproc
add_library(opencv_imgproc SHARED IMPORTED)
set_target_properties(opencv_imgproc PROPERTIES IMPORTED_LOCATION ${LIBS_DIR}/libopencv_imgproc.so)
# imgcodecs
add_library(opencv_imgcodecs SHARED IMPORTED)
set_target_properties(opencv_imgcodecs PROPERTIES IMPORTED_LOCATION ${LIBS_DIR}/libopencv_imgcodecs.so)
# ========== 头文件路径 ==========
# 直接包含 opencv4 目录,这样 #include <opencv2/xxx.hpp> 就能找到
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include
${NATIVERENDER_ROOT_PATH}/include/opencv4)
# ========== NAPI 模块 ==========
add_library(entry SHARED napi_init.cpp)
# ========== 链接 ==========
target_link_libraries(entry PUBLIC
libace_napi.z.so
opencv_core
opencv_imgproc
opencv_imgcodecs
)
napi_init.cpp
C++ 代码的入口文件,实现具体的业务逻辑。可以提供给鸿蒙端使用。
#include "napi/native_api.h"
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <string>
#include <vector>
// ========== 工具函数 ==========
static std::string MatInfo(const cv::Mat& mat) {
char buf[256];
snprintf(buf, sizeof(buf), "%dx%d, %d channels, %s",
mat.cols, mat.rows, mat.channels(),
mat.type() == CV_8UC3 ? "BGR" : "other");
return std::string(buf);
}
// ========== 1. 获取版本 ==========
static napi_value GetOpenCVVersion(napi_env env, napi_callback_info info) {
std::string version = cv::getVersionString();
napi_value result;
napi_create_string_utf8(env, version.c_str(), version.size(), &result);
return result;
}
// ========== 2. 生成测试图片 ==========
static napi_value GenerateTestImage(napi_env env, napi_callback_info info) {
cv::Mat image(480, 640, CV_8UC3);
for (int y = 0; y < image.rows; y++) {
for (int x = 0; x < image.cols; x++) {
image.at<cv::Vec3b>(y, x) = cv::Vec3b(
(x * 255 / image.cols),
(y * 255 / image.rows),
128
);
}
}
std::string infoStr = MatInfo(image); // ← 改名为 infoStr
std::string resultStr = "测试图片已生成: " + infoStr;
napi_value result;
napi_create_string_utf8(env, resultStr.c_str(), resultStr.size(), &result);
return result;
}
// ========== 3. 灰度化 ==========
static napi_value ConvertToGray(napi_env env, napi_callback_info info) {
cv::Mat src(480, 640, CV_8UC3);
for (int y = 0; y < src.rows; y++) {
for (int x = 0; x < src.cols; x++) {
src.at<cv::Vec3b>(y, x) = cv::Vec3b(
(x * 255 / src.cols),
(y * 255 / src.rows),
128
);
}
}
cv::Mat gray;
cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
std::string resultStr = "灰度化成功: " + MatInfo(gray);
napi_value result;
napi_create_string_utf8(env, resultStr.c_str(), resultStr.size(), &result);
return result;
}
// ========== 4. 高斯模糊 ==========
static napi_value ApplyGaussianBlur(napi_env env, napi_callback_info info) {
cv::Mat src(480, 640, CV_8UC3);
for (int y = 0; y < src.rows; y++) {
for (int x = 0; x < src.cols; x++) {
src.at<cv::Vec3b>(y, x) = cv::Vec3b(
(x * 255 / src.cols),
(y * 255 / src.rows),
128
);
}
}
cv::Mat blurred;
cv::GaussianBlur(src, blurred, cv::Size(15, 15), 0);
std::string resultStr = "高斯模糊完成: " + MatInfo(blurred);
napi_value result;
napi_create_string_utf8(env, resultStr.c_str(), resultStr.size(), &result);
return result;
}
// ========== 5. 边缘检测 ==========
static napi_value ApplyCanny(napi_env env, napi_callback_info info) {
cv::Mat src(480, 640, CV_8UC3, cv::Scalar(128, 128, 128));
cv::rectangle(src, cv::Rect(100, 100, 200, 200), cv::Scalar(255, 255, 255), -1);
cv::circle(src, cv::Point(400, 300), 80, cv::Scalar(0, 0, 255), -1);
cv::Mat gray;
cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
cv::Mat edges;
cv::Canny(gray, edges, 50, 150);
std::string resultStr = "Canny 边缘检测完成: " + MatInfo(edges);
napi_value result;
napi_create_string_utf8(env, resultStr.c_str(), resultStr.size(), &result);
return result;
}
// ========== NAPI 模块注册 ==========
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {
{"getOpenCVVersion", nullptr, GetOpenCVVersion, nullptr, nullptr, nullptr, napi_default, nullptr},
{"generateTestImage", nullptr, GenerateTestImage, nullptr, nullptr, nullptr, napi_default, nullptr},
{"convertToGray", nullptr, ConvertToGray, nullptr, nullptr, nullptr, napi_default, nullptr},
{"applyGaussianBlur", nullptr, ApplyGaussianBlur, nullptr, nullptr, nullptr, napi_default, nullptr},
{"applyCanny", nullptr, ApplyCanny, nullptr, nullptr, nullptr, napi_default, nullptr},
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = ((void*)0),
.reserved = { 0 },
};
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) {
napi_module_register(&demoModule);
}
Index.d.ts
告诉 ArkTS 这个原生模块有什么函数和类型,相当于 C++ 代码的"说明书"。他可以让 ArkTS 代码有智能提示,提供类型检查,防止调用错误的函数。
即他是 C++ 与 ArkTS 之间的接口定义,让 ArkTS 调用 C++ 的函数。
export const getOpenCVVersion: () => string;
export const generateTestImage: () => string;
export const convertToGray: () => string;
export const applyGaussianBlur: () => string;
export const applyCanny: () => string;
Index.ets
在鸿蒙项目使用我们刚刚编译出来的库。
import { hilog } from '@kit.PerformanceAnalysisKit';
import cv from 'libentry.so';
const DOMAIN = 0x0000;
const TAG = 'OpenCV';
@Entry
@Component
struct Index {
@State version: string = '';
@State result: string = '';
build() {
Scroll() {
Column() {
Text('OpenCV 鸿蒙适配验证')
.fontSize(22)
.fontWeight(FontWeight.Bold)
.margin({ top: 24, bottom: 24 })
// 按钮1:获取版本
Button('获取 OpenCV 版本')
.width('90%')
.height(48)
.fontSize(16)
.backgroundColor('#007DFF')
.borderRadius(12)
.onClick(() => {
this.version = cv.getOpenCVVersion();
hilog.info(DOMAIN, TAG, 'Version: ' + this.version);
})
if (this.version) {
Text('版本: ' + this.version)
.fontSize(14)
.fontColor('#333')
.margin({ top: 8 })
}
// 按钮2:生成测试图片
Button('生成测试图片(渐变图)')
.width('90%')
.height(48)
.fontSize(16)
.backgroundColor('#52C41A')
.borderRadius(12)
.margin({ top: 16 })
.onClick(() => {
this.result = cv.generateTestImage();
hilog.info(DOMAIN, TAG, this.result);
})
// 按钮3:灰度化
Button('灰度化处理')
.width('90%')
.height(48)
.fontSize(16)
.backgroundColor('#FA8C16')
.borderRadius(12)
.margin({ top: 12 })
.onClick(() => {
this.result = cv.convertToGray();
hilog.info(DOMAIN, TAG, this.result);
})
// 按钮4:高斯模糊
Button('高斯模糊')
.width('90%')
.height(48)
.fontSize(16)
.backgroundColor('#722ED1')
.borderRadius(12)
.margin({ top: 12 })
.onClick(() => {
this.result = cv.applyGaussianBlur();
hilog.info(DOMAIN, TAG, this.result);
})
// 按钮5:边缘检测
Button('Canny 边缘检测')
.width('90%')
.height(48)
.fontSize(16)
.backgroundColor('#EB2F96')
.borderRadius(12)
.margin({ top: 12 })
.onClick(() => {
this.result = cv.applyCanny();
hilog.info(DOMAIN, TAG, this.result);
})
if (this.result) {
Text(this.result)
.fontSize(14)
.fontColor('#555')
.margin({ top: 12 })
.padding(12)
.backgroundColor('#F5F5F5')
.borderRadius(8)
}
Blank().height(40)
}
.width('100%')
.alignItems(HorizontalAlign.Center)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
检查
因为可能会出现找不到库的情况,所以需要检查 .so 文件的 SONAME 名字是否能指向正确 .so 文件。
- 先找到 sdk 的 里面的 llvm-readelf ,一般在sdk里面能找到,比如:“ E:\app\devecostudio-windows-6.0.2.642\6.0.2.642\DevEco Studio\sdk\default\openharmony\native\llvm\bin ”
- (可选)配置他到环境变量里面,我这里没有配
- 查看,一般看 CMake.txt 里面 set 设置得 .so 的名字。例如下面的三个 libopencv_xx.so 。

## 第三步配置了环境变量
llvm-readelf -d xxx.so | Select-String SONAME
## 没有配置环境变量
& "E:\app\devecostudio-windows-6.0.2.642\6.0.2.642\DevEco Studio\sdk\default\openharmony\native\llvm\bin\llvm-readelf.exe" -d xxx.so | Select-String SONAME
先进入 arm64-x8v 目录下,进行查看,可以看到下面三个文件的 SONAME 的名字都没有出现在 arm64-x8v 里面,所以可以给这三个文件改个名字,或改他们的 SONAME 名字。

## 复制一份改名字
## 这里只是创建一个满足加载器查找规则的文件名。
ELF 内部 SONAME 并没有发生变化。
cp libopencv_core.so libopencv_core.so.408
cp libopencv_imgproc.so libopencv_imgproc.so.408
cp libopencv_imgcodecs.so libopencv_imgcodecs.so.408
- 查看 SONAME,看复制到 “MyOpenCVProject/entry/libs/arm64-v8a/” 的三个 .so 文件是否有 SONAME 名字一样的
理解
理解文件的调用逻辑
为什么我们需要交叉编译,本质是指令集的不同,所以我们需要转换指令集。
为什么指令集会不同呢?因为如果直接使用 Windows 本机编译器(MSVC、MinGW)编译,则默认生成 x86/x64 指令;而交叉编译工具链指定目标为 aarch64-linux-ohos,因此最终生成 ARM 可执行文件。不然 x86/x64 指令烧录进 鸿蒙PC(ARM) 端,会无法运行,因为 arm 架构无法跑 x86 指令集。
所以交叉编译一般出现在开发编译的CPU架构和真正运行程序的CPU不一致产生的。
ArkTS 层 (Index.ets)
↓ 调用
接口声明层 (Index.d.ts)
↓ 映射到
NAPI 注册层 (napi_init.cpp)
↓ 调用
C++ 实现层 (include文件夹里面)
↓ 使用
第三方库层 (.so,存放从 x86 编译成 arm 的 arm 二进制指令集)
↓ 运行在
ARM 硬件层 (鸿蒙 PC)
理解 ELF 文件 —— .so
ELF 规定了一个可执行程序应该如何组织。它里面有很多个 section ,比如代码机器指令(.text)、未初始化变量(.bss)等。
在编译 C/C++ 库的时候最重要的是链接。这里讲一下动态链接。
.dynamic:这个库依赖谁?主要是 SONAME 和 NEEDED。在程序运行时被使用。
比如 :
- libplacebo.so 里面的 .dynamic 有 NEEDED libc.so,就是运行 libplacebo.so 之前必须先加载 libc.so,否则函数找不到。
- libplacebo.so 里面的 .dynamic 有 SONAME libplacebo.so.371,就是动态链接器依靠这个区分不同名的 .so 文件或同名不同版本的 .so 文件。
编译阶段:ld 会根据文件名查找 .so 文件(严格同名的文件)进行链接,并在生成的主 ELF 的 .dynamic 中记录 NEEDED。
运行阶段:动态链接器根据主 ELF 的 .dynamic 中的 NEEDED 加载 .so 文件,然后读取该 .so 文件里面的 SONAME 来识别库的真实身份,并继续加载该 .so 的 NEEDED 依赖。
整个过程就是:
编译时,ld 根据文件名查找并记录依赖;
运行时,动态链接器根据 NEEDED 加载库,根据 SONAME 识别库身份,递归加载所有依赖。
例子:
编译阶段:
ld 编译 libentry.so 时,根据 CMakeLists.txt 中的 target_link_libraries 找到 libplacebo.so
在 libentry.so 的 .dynamic 中记录:NEEDED libplacebo.so
运行阶段:
1. 主程序启动,动态链接器开始工作
2. 读取主程序的 .dynamic,发现 NEEDED libentry.so
3. 找到并加载 libentry.so
4. 读取 libentry.so 的 .dynamic,发现 NEEDED libplacebo.so
5. 找到文件 libplacebo.so
6. 读取 libplacebo.so 的 .dynamic,发现 SONAME libplacebo.so.371
7. 将该库注册为 libplacebo.so.371
8. 继续读取 libplacebo.so 的 NEEDED,发现 NEEDED libc.so
9. 加载 libc.so
10. 所有依赖加载完成,解析符号,程序开始执行
为什么要注意这个呢,因为他会和我们后面更改文件名有关。不然他会找不到库。
运行
接入 鸿蒙PC 进行真机运行。
记得给 PC 开通 开发者模式 和 USB调试功能。
开发者模式是点击序列号7下,可以搜一下。USB调试功能是开启开发者模式后的一个在设置里面的选项。
结果展示:

可能遇到的错误
找不到库文件
原因:这个的本质在 理解 ELF 文件 —— .so 有讲到,也就是 检查 有讲过详细步骤。简而言之就是:找不到库是因为动态链接器根据 SONAME 查找库时,对应的库文件名不存在。所以我们要更改 SONAME 或更改库文件名字。
解决:这里是直接更改文件名。
如果改SONAME需要问AI找一个保险的方法,不然可能会出现机器码没改对导致 .so 文件发生错误,无法使用。更改前可以进行备份,也可以去linux系统重新复制一份过来。
可以两个方法都用一下,用之前进行备份即可。
总结
本文完成了 OpenCV 在 HarmonyOS PC 上的交叉编译,并成功集成到 DevEco Studio。过程中介绍了 Lycium++ 的使用方法、HPKBUILD 的编写方式、OpenCV 模块裁剪、NAPI 调用流程,以及 ELF、SONAME 和动态链接机制。掌握这些内容后,不仅可以移植 OpenCV,也可以采用相同的方法移植 FFmpeg、libplacebo、SDL2 等其他第三方 C/C++ 库。
更多推荐


所有评论(0)