HarmonyOS Next构建工具 lycium 原理介绍

HarmonyOS Next构建工具 lycium 原理介绍

在这里插入图片描述

背景介绍

HarmonyOS Next中很多系统API是以C++接口提供,如果要使用C++接口,必须要使用NAPI在ArkTS与C++间交互,这种场景在使用DevEco-Studio中集成的交叉编译工具,以及cmake构建工具就完全够用了。但是针对一些三方库迁移的场景,比如ffmpeg、openssl等,如果自己配置编译环境和脚本比较麻烦,进行交叉编译的过程中较关注的问题是:不同编译构建方式如何进行交叉编译、不同的编译构建平台如何配置交叉编译的环境、不同的交叉编译架构如何配置以及交叉编译后的产物如何进行测试验证。当前开源的C/C++三方库编译方式多样化,以下为主流的几种交叉编译方式:

  • cmake 编译构建。
  • configure 编译构建方式。
  • make 编译构建。
    官方提供了交叉编译构建工具lycium,帮助我们快速构建三方库。

lycium工具介绍

lycium是一款协助开发者通过shell语言实现C/C++三方库快速交叉编译,并在OpenHarmony 系统上快速验证的编译框架工具。开发者只需要设置对应C/C++三方库的编译方式以及编译参数,通过lycium就能快速的构建出能在OpenHarmony 系统运行的二进制文件。

lycium的构建原则是移植过程,不可以改源码(即不patchc/cpp文件,不patch构建脚本)。如移植必须patch,patch必须评审,给出充分理由。(不接受业务patch)

lycium构建工具地址:https://gitee.com/openharmony-sig/tpc_c_cplusplus

使用示例

  1. 编译环境准备:lycium框架支持多种构建方式的三方库,为了保障三方库能正常编译,我们需要保证编译环境中包含以下几个基本编译命令: gcc, cmake, make, pkg-config, autoconf, autoreconf, automake, 如若缺少相关命令,可通过官网下载对应版本的工具包,也可以在编译机上通过命令安装,如若Ubuntu系统上缺少cmake可以通过以下命令安装:sudo apt install cmake
  2. 修改三方库的编译方式以及编译参数,lycium框架提供了HPKBUILD文件供开发者对相应的C/C++三方库的编译配置。具体方法:
    • 在thirdparty目录下新建需要共建的三方库名字pkgname。
    • 将HPKBUILD模板文件拷贝到新建三方库目录下。
    • 根据三方库实际情况修改HPKBUILD模板,文件修改可参考minizip共建。
  3. 快速编译三方库:配置完三方库的编译方式参数后,在lycium目录执行./build.sh pkgname,进行自动编译三方库,并打包安装到当前目录的 usr/pkgname/
    ARCH 目录./build.sh # 默认编译 thirdparty 目录下的多有库,也可以:./build.sh aaa bbb ccc ... # 编译 thirdparty 目录下指定的 aaa bbb ccc ...库 当 aaa 库存在依赖时,必须保证入参中包含依赖,否则 aaa 库不会编译

lycium框架是通过linux shell脚本语言编写的,接下来我们分析构建工具的shell代码,理解构建流程,有助于帮助我们定位编译时遇到的失败问题。

构建脚本原理介绍

lycium框架主要由以下几个部分组成:

  1. HPKBUILD 构建配置
  2. 顶层构建脚本 build.sh
  3. 交叉编译工具链
  4. 测试验证环境
构建流程
1. 构建配置准备

开发者需要在 thirdparty 目录下为待编译的三方库创建目录,并编写 HPKBUILD 构建配置文件。HPKBUILD 文件定义了:

  • 源码获取方式
  • 编译参数配置
  • 依赖关系声明
  • 安装规则

HPKBUILD构建配置文件示例:

# Contributor: Jeff Han <hanjinfei@foxmail.com>
# Maintainer: Jeff Han <hanjinfei@foxmail.com>
pkgname=FFmpeg
pkgver=n6.0
pkgrel=0
pkgdesc="FFmpeg is a collection of libraries and tools to process multimedia content such as audio, video, subtitles and related metadata."
url="https://github.com/FFmpeg/FFmpeg/"
archs=("armeabi-v7a" "arm64-v8a")
license=("GPL2" "GPL3" "LGPL3" "MIT" "X11" "BSD-styl")
depends=("rtmpdump" "openssl_1_0_2u")
makedepends=()
source="https://github.com/FFmpeg/$pkgname/archive/refs/tags/$pkgver.tar.gz"autounpack=false
downloadpackage=true
buildtools="configure"builddir=$pkgname-${pkgver}
packagename=$builddir.tar.gz
source envset.sh
buildhost=true
arch=
ldflags=prepare() {if [ "$LYCIUM_BUILD_OS" == "Linux" ]thenhostosname=linuxelif [ "$LYCIUM_BUILD_OS" == "Darwi" ]thenhostosname=darwinelseecho "System cannot recognize, exiting"return -1fiif [ $buildhost == true ]thentar -zxf $packagenamecd $builddir./configure --enable-static --enable-shared --disable-doc --disable-htmlpages \--target-os=$hostosname --disable-optimizations --prefix=`pwd`/hostbuild > $publicbuildlog 2>&1$MAKE >> $publicbuildlog 2>&1$MAKE install >> $publicbuildlog 2>&1export LD_LIBRARY_PATH=`pwd`/hostbuild/lib:$LD_LIBRARY_PATHsed -i.bak 's/include $(SRC_PATH)\/tests\/fate\/source.mak/#include $(SRC_PATH)\/tests\/fate\/source.mak/g' tests/Makefile$MAKE check >> $publicbuildlog 2>&1ret=$?buildhost=falsecd $OLDPWDfimkdir $pkgname-$ARCH-buildtar -zxf $packagename -C $pkgname-$ARCH-buildcd  $pkgname-$ARCH-build/$builddirpatch -p1 < ../../FFmpeg_oh_test.patchcd $OLDPWDif [ $ARCH == "armeabi-v7a" ]thensetarm32ENVarch=armldflags="-L${OHOS_SDK}/native/sysroot/usr/lib/arm-linux-ohos"elif [ $ARCH == "arm64-v8a" ]thensetarm64ENVarch=aarch64ldflags="-L${OHOS_SDK}/native/sysroot/usr/lib/aarch64-linux-ohos"elseecho "${ARCH} not support"return -1fireturn $ret
}build() {cd $pkgname-$ARCH-build/$builddirPKG_CONFIG_LIBDIR="${pkgconfigpath}" ./configure "$@" --enable-neon --enable-asm --enable-network \--disable-vulkan --enable-cross-compile --enable-librtmp --disable-x86asm --enable-openssl --enable-protocols \--enable-static --enable-shared --disable-doc --disable-htmlpages --target-os=linux --arch=$arch \--cc=${CC} --ld=${CC} --strip=${STRIP} --host-cc="${CC}" --host-ld="${CC}" --host-os=linux \--host-ldflags=${ldflags} --sysroot=${OHOS_SDK}/native/sysroot > $buildlog 2>&1$MAKE >> $buildlog 2>&1ret=$?cd $OLDPWDreturn $ret
}package() {cd $pkgname-$ARCH-build/$builddir$MAKE install >> $buildlog 2>&1cd $OLDPWD
}checktestfiles() {cd $pkgname-$ARCH-build/$builddir/tests/reftmpdir=("fate" "acodec" "lavf" "lavf-fate" "pixfmt" "seek" "vsynth")for dir in ${tmpdir[*]}dofor file in `ls $dir`doif [ ! -f $dir/$file ]; thencontinuefistr=`cat $dir/$file | grep "\*tests"`if [ ! -z "$str" ]thensed -i.bak 's/\*tests/tests/g' $dir/$filefidonedonecd $OLDPWD
}copyhostbin() {file=$1if [[ -f tests/$file ]] && [[ ! -f tests/$file.${ARCH} ]]thenmv tests/$file tests/$file.${ARCH}cp ../../$builddir/tests/$file tests/$filefi
}check() {cd $pkgname-$ARCH-build/$builddir# disable running cmdsed -i.bak 's/	$(Q)$(SRC_PATH)\/tests\/fate-run.sh/#	$(Q)$(SRC_PATH)\/tests\/fate-run.sh/g' tests/Makefile# disable check git sourcessed -i.bak 's/include $(SRC_PATH)\/tests\/fate\/source.mak/#include $(SRC_PATH)\/tests\/fate\/source.mak/g' tests/Makefile# disable check ffprobe,this use xmllint command, which ohos is not supportsed -i.bak 's/include $(SRC_PATH)\/tests\/fate\/ffprobe.mak/#include $(SRC_PATH)\/tests\/fate\/ffprobe.mak/g' tests/Makefile# change x86 cmd for generate test targetmv ffmpeg ffmpeg.${ARCH}cp ../../$builddir/ffmpeg ./retrytimes=0ret=0while truedo$MAKE check >> $buildlog 2>&1if [ $? -eq 0 ]thenbreak;ficopyhostbin base64copyhostbin audiomatchcopyhostbin audiogencopyhostbin videogencopyhostbin tiny_psnrcopyhostbin tiny_ssimcopyhostbin rotozoomlet retrytimes=$retrytimes+1if [ $retrytimes -gt 4 ]thenret=1breakfidonemv ffmpeg.${ARCH} ffmpegfor file in `ls tests/*.${ARCH}`dotmpfile=${file%.*}mv $file $tmpfiledone# reduction running cmd for real testsed -i.bak 's/#	$(Q)$(SRC_PATH)\/tests\/fate-run.sh/	$(Q)$(SRC_PATH)\/tests\/fate-run.sh/g' tests/Makefilecd $OLDPWDchecktestfilesecho "The test must be on an OpenHarmony device!"# skip running test on host# real test CMD# make checkreturn $ret
}recoverpkgbuildenv() {unset archunset ldflagsif [ $ARCH == "armeabi-v7a" ]thenunsetarm32ENVelif [ $ARCH == "arm64-v8a" ]thenunsetarm64ENVelseecho "${ARCH} not support"return -1fi
}# 清理环境
cleanbuild() {rm -rf ${PWD}/${builddir} ${PWD}/$pkgname-arm64-v8a-build ${PWD}/$pkgname-armeabi-v7a-build #${PWD}/$packagename
}
2. 构建过程

主入口 build.sh 脚本执行以下步骤:

  1. 解析命令行参数,确定要编译的目标库
  2. 检查编译环境(编译工具链等)
  3. 读取目标库的 HPKBUILD 配置
  4. 按照依赖关系顺序编译各个库
  5. 对每个库执行:
    • 获取源码
    • 配置编译参数
    • 执行编译
    • 安装到指定目录

检查编译环境代码:

# 检测操作系统类型
unames=`uname -s`
osname=${unames:0:5}# 设置根目录
LYCIUM_ROOT=$(cd $(dirname ${BASH_SOURCE[0]}); pwd)# 检查 OHOS_SDK 环境
if [ -z ${OHOS_SDK} ]
thenecho "OHOS_SDK 未设置..."exit 1
fi

依赖管理检测:

# 依赖库暂存文件
depend_tmp_file="/tmp/$USER-lycium_deps-$build_time"
export LYCIUM_DEPEND_PKGNAMES=$depend_tmp_file# 已完成库列表
donelist=()
donelibs=()

核心函数 buildhpk() 实现了构建流程控制:

  1. 任务分轮次执行
  2. 处理依赖关系
  3. 错误处理机制
    主要变量:
  • nextroundlist: 下一轮待构建项目
  • notdonelist: 未完成项目列表
  • buildfalselist: 构建失败项目列表

关键函数说明如下:
checkbuildenv()
检查必要的构建工具是否安装:

  • gcc, cmake, make 等基础工具

  • autoconf, automake 等自动化工具

  • git, curl 等辅助工具 prepareshell()
    为每个构建目录准备必要的脚本:

  • build_hpk.sh: 项目构建脚本

  • envset.sh: 环境设置脚本 makelibsdir()
    管理构建目录:

  • 检查目录有效性

  • 过滤已构建项目

  • 添加到构建队列

3. 交叉编译支持

框架通过以下方式实现交叉编译:

  1. 使用 OpenHarmony NDK 提供的交叉编译工具链
  2. 在 HPKBUILD 中配置交叉编译相关参数
  3. 支持 arm32/arm64/x86 等多架构编译
4. 产物输出

编译产物按照如下结构组织:

usr/└── ${pkgname}/└── ${ARCH}/├── lib/      # 库文件├── include/  # 头文件└── bin/      # 可执行文件
build_hpk.sh构建脚本说明

核心构建函数说明:

1. prepare()

准备构建环境:

  • 宿主机构建(buildhost=true时)
  • 解压源码包
  • 应用补丁
  • 设置交叉编译环境
2. build()

执行构建过程:

  • 配置构建参数
  • 执行configure配置
  • 执行make编译
  • 返回构建结果
3. package()

安装打包:

  • 执行make install
  • 生成最终安装包
4. check()

测试验证:

  • 修改测试配置
  • 准备测试环境
  • 执行测试用例
  • 处理测试结果
5. 环境管理函数
  • recoverpkgbuildenv()
    • 清理编译环境变量
    • 恢复原始环境
  • cleanbuild()
    • 清理构建目录
    • 删除临时文件

总结

本文介绍了HarmonyOS Next跨平台构建脚本功能、使用、以及原理,介绍了构建脚本相关的shell代码等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/893553.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最长递增——蓝桥杯

1.题目描述 在数列 a1​,a2​,⋯,an​ 中&#xff0c;如果ai​<ai1​<ai2​<⋯<aj​&#xff0c;则称 ai​ 至 aj​ 为一段递增序列&#xff0c;长度为 j−i1。 定一个数列&#xff0c;请问数列中最长的递增序列有多长。 输入描述 输入的第一行包含一个整数 n。…

【远程视频必备】Briefing:安全视频群聊让远程办公无忧

文章目录 前言1.关于briefing2.本地部署briefing3.使用briefing4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定briefing公网地址 前言 对于有远程办公或者身处异地与家人好友视频聊天需求的人来说&#xff0c;在享受高效沟通的同时&#xff0c;也或多或少会有对信息泄…

华为发展历程:战略转型与分析

纵观30多年的发展历程&#xff0c;在创始人任正非及创业团队奋力牵引下&#xff0c;全体员工共同奋斗&#xff0c;华为实现了从“一无所有”到“三分天下”、从“积极跟随者”到“行业领先者”的跨越式发展。 华为在业务战略上经历了数次变革&#xff0c;分别是从农村到城市&a…

热更新杂乱记

热更新主要有一个文件的MD5值的比对过程&#xff0c;期间遇到2个问题&#xff0c;解决起来花费了一点时间 1. png 和 plist 生成zip的时候再生成MD5值会发生变动。 这个问题解决起来有2种方案&#xff1a; &#xff08;1&#xff09;.第一个方案是将 png和plist的文件时间改…

Elementor Pro 3.27 汉化版 2100套模板 安装教程 wordpress主题中文编辑器插件免费下载

插件下载地址 https://a5.org.cn/a5ziyuan/732506.html 转载请注明出处! Elementor Pro 是流行的 Elementor 的付费扩展 WordPress 页面构建器插件. 它为免费的 Elementor 插件添加了许多附加功能和增强功能&#xff0c;使其成为创建美丽的更强大的工具 WordPress 网站。 如果…

【Unity】使用Canvas Group改变UI的透明度

目录 一、前言二、Canvas Group三、结合DOTween达到画面淡进的效果 一、前言 在平时开发中&#xff0c;可以通过控制材质、Color改变UI透明度&#xff0c;除此之外还可以CanvasGroup组件来控制透明度。 二、Canvas Group 官方文档链接&#x1f449;&#x1f449; 点击进入 …

计算机工程:解锁未来科技之门!

计算机工程与应用是一个充满无限可能性的领域。随着科技的迅猛发展&#xff0c;计算机技术已经深深渗透到我们生活的方方面面&#xff0c;从医疗、金融到教育&#xff0c;无一不在彰显着计算机工程的巨大魅力和潜力。 在医疗行业&#xff0c;计算机技术的应用尤为突出。比如&a…

AT8870单通道直流电机驱动芯片

AT8870单通道直流电机驱动芯片 典型应用原理图 描述 AT8870是一款刷式直流电机驱动器&#xff0c;适用于打印机、电器、工业设备以及其他小型机器。两个逻辑输入控制H桥驱动器&#xff0c;该驱动器由四个N-MOS组成&#xff0c;能够以高达3.6A的峰值电流双向控制电机。利用电流…

什么是报文的大端和小端,有没有什么记忆口诀?

在计算机科学中&#xff0c;**大端&#xff08;Big-Endian&#xff09;和小端&#xff08;Little-Endian&#xff09;**是两种不同的字节序&#xff08;即多字节数据在内存中的存储顺序&#xff09;。理解这两种字节序对于网络通信、文件格式解析以及跨平台编程等非常重要。 1…

Vue2.0+ElementUI实现查询条件展开和收起功能组件

一、需求 el-form如果查询条件过多&#xff0c;影响页面的展示效果。查询条件表单是我们系统中非常常见的功能&#xff0c;我们需要把它封装成一个通用的组件&#xff0c;方便在系统开发中提升开发效率。除了在实现基本查询条件的功能上&#xff0c;还需要实现多条件的折叠和展…

Flutter 使用 flutter_inappwebview 加载 App 本地 HTML 文件

在 Flutter 开发中&#xff0c;加载本地 HTML 文件是一个常见的需求&#xff0c;尤其是在需要展示离线内容或自定义页面时。flutter_inappwebview 是一个功能强大的插件&#xff0c;支持加载本地文件和网络资源。本文将详细介绍如何使用 flutter_inappwebview 加载 App 本地 HT…

Scrapy之一个item包含多级页面的处理方案

目标 在实际开发过程中&#xff0c;我们所需要的数据往往需要通过多个页面的数据汇总得到&#xff0c;通过列表获取到的数据只有简单的介绍。站在Scrapy框架的角度来看&#xff0c;实际上就是考虑如何处理一个item包含多级页面数据的问题。本文将以获取叶子猪网站的手游排行榜及…

LINQ 和 LINQ 扩展方法(2)

1.表联接&#xff08;连接&#xff09; Join() 相当于 join on equals 默认是inner join内联系 JoinGroup()是左外联 数据关联&#xff1a;Join 是在数据库查询中常用的操作&#xff0c;用于基于某个共同的键关联两个表。在内存中处理集合时&#xff0c;LINQ的 Join 方法提…

MySQL8【学习笔记】

第一章前提须知 1.1 需要学什么 Dbeaver 的基本使用SQL 语句&#xff1a;最重要的就是查询&#xff08;在实战的时候&#xff0c;你会发现我们做的绝大部分工作就是 “查询”&#xff09;MySQL 存储过程&#xff08;利用数据库底层提供的语言&#xff0c;去进行业务逻辑的封装…

聊一聊 CSS 样式的导入方式

一、CSS 的导入方式有哪些 1、内联样式&#xff0c;在HTML 元素上使用 style 属性&#xff0c;设置当前标签元素的样式 <p style"color: red;">Hello world!</p>2、嵌入样式表&#xff0c;直接在head标签内使用style标签定义元素样式 <head><st…

【JVM】垃圾收集器详解

你将学到 1. Serial 收集器 2. ParNew 收集器 3. Parallel Scavenge 收集器 4. Serial Old 收集器 5. Parallel Old 收集器 6. CMS 收集器 7. G1 收集器 在 Java 中&#xff0c;垃圾回收&#xff08;GC&#xff09;是自动管理内存的一个重要机制。HotSpot JVM 提供了多种…

前端Vue框架——npm ci与npm install的区别以及package-lock.json文件与package.json的区别

目录 一、npm ci与npm install的区别 &#xff08;一&#xff09;npm ci 的作用 &#xff08;二&#xff09;与 npm install 的区别 二、package-lock.json文件与package.json的区别 1️⃣ package.json 2️⃣ package-lock.json 3️⃣ 区别对比 4️⃣ 使用建议 5️⃣…

项目上线后,是否会进行复盘?

是的&#xff0c;定期复盘在软件测试项目里极为关键&#xff0c;我会按以下步骤开展复盘工作&#xff1a; 复盘周期确定 短期项目&#xff1a;针对周期较短&#xff08;如 1 - 2 个月&#xff09;的项目&#xff0c;会在项目结束后的一周内进行复盘&#xff0c;确保大家对项目…

SOME/IP服务接口

本系列文章将分享我在学习 SOME/IP 过程中积累的一些感悟&#xff0c;并结合 SOME/IP 的理论知识进行讲解。主要内容是对相关知识的梳理&#xff0c;并结合实际代码展示 SOME/IP 的使用&#xff0c;旨在自我复习并与大家交流。文中引用了一些例图&#xff0c;但由于未能找到原作…

编写0号中断的处理程序

实验内容、程序清单及运行结果 编写0号中断的处理程序&#xff08;课本实验12&#xff09; 解&#xff1a; assume cs:code code segment start: mov ax,cs mov ds,ax mov si,offset do mov ax,0 mov es,ax mov di,200h mov cx,offset doend-offset do ;安装中断例…