有听过《如意玲珑--新时代Linux桌面应用分发和治理方案》[1]的朋友应该知道,“通过隔离技术彻底解决系统与应用、应用与应用之间因升级引起的兼容性冲突问题”是如意玲珑方案众多核心特性之一。基于上述特性以及《如意玲珑技术架构介绍》[2],我们可以知道如意玲珑方案主要通过沙箱、容器方案来对应用与系统进行隔离,这就意味着应用容器中的大部分目录仅具备只读权限, 无法当作日常系统环境来使用。
近期,如意玲珑与 OpenTenBase 开源社区开展了“跨界”合作,在如意玲珑容器中试验性地进行了 OpenTenBase 开源项目的源代码编译,且成功运行了。在此基础上,我手握 OpenTenBase 源码,又开始了一轮如意玲珑构建环境的可移植性探索,发现在如意玲珑容器里编译的项目居然可以直接拿出来用,打破了如意玲珑无法实现完整系统环境的功能现状。接下来就和大家好好聊聊如何实现这项操作。
如意玲珑容器操作展示
为了补偿部分朋友无法见证如意玲珑与 OpenTenBase 开源社区“跨界”分享的现场演示,我这里简单将操作过程向各位展示一遍。
前期准备
1. 本次分享基于 deepin 23 发行版,因此在进行以下任一步骤前均需要准备一个可以构建玲珑应用的 deepin 23 系统环境。
2. 由于在构建过程中我们需要联网获取如意玲珑容器的运行库以及可能需要的第三方库,因此我们需要保障全操作过程中网络连接顺畅。
3. 按照以下模板简单编写一版玲珑构建工程配置文件 linglong.yaml,来生成一个符合要求的容器。
主要有以下需要关注的点:
- 由于本次操作是直接进入容器进行操作,因此 build 部分的构建规则可不详细写;
- 由于本次涉及编译操作,为了能够极大程度包含所需的运行库, 我们加入 runtime 段,具体编写规范参考《构建配置文件简介》[3] 和《玲珑应用构建工程基础知识》[4]。
# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: LGPL-3.0-or-laterversion: "3"
package:
id: org.opentenbase.pgxc
name: "OpenTenBase"
version: 2.6.0.3
kind: app
description: |
pgxc binary built from OpenTenBasebase: org.deepin.foundation/23.0.0
runtime: org.deepin.Runtime/23.0.1command:
- /opt/apps/org.opentenbase.pgxc/files/bin/pgxc_ctlsource:
- kind: local
name: "OpenTenBase"build: |
##Extract res
mkdir -p ${PREFIX}/bin/ ${PREFIX}/share/
4. 在完成 linglong.yaml 编辑并将相关源代码解压到当前目录下后,我们就可以开始编译了。
项目编译演示
插播一个知识点:在如意玲珑容器中,与构建工程配置文件 linglong.yaml 同级的构建目录将被映射为 /project 目录。做好前期准备,我们就可以开始编译了:1. 为了方便操作,我们在构建目录下同时开启两个shell窗口,分别用于如意玲珑容器操作和普通操作。2. 进入如意玲珑容器:
szbt@szbt-linyaps23:/media/szbt/Data/ll-build/openTenbase$ ll-builder build --
exec bash
路径发生类似以下变化时,即意味着我们已经进入如意玲珑容器中了:
szbt@szbt-linyaps23:/project$
3. 通过普通操作窗口解压 openTenbase 源码到构建目录中,在这里我将其单独解压到一个子目录中。
szbt@szbt-linyaps23:/media/szbt/Data/ll-build/openTenbase$ tar -xvf
OpenTenBase-v2.6.0-src.tar.zst -C src/
4. 源码解压后,我们在编译任意源代码前应该正确选择编译系统/工具。我们可以先阅读 《OpenTenBase源码编译安装》[5]来准备编译材料。
5. 由于如意玲珑容器中不存在 apt 联网安装依赖包的说法,因此我们先跳过依赖安装步骤。不过需要注意的是,如意玲珑容器中当前明确具备的库/编译器有:gcc12.3、zlib、 openssl3,其他暂未表明的库有可能不存在于容器中而需要我们手动编译。
综上, 我们有可能会缺失文档中提示的 libreadline-dev libossp-uuid-dev。
6. 我们通过如意玲珑容器操作窗口进入源码目录,为了尽量避免对源目录的干扰,我这里新建一个 build 目录用于编译。进入 build 目录后我们输入《OpenTenBase源码编译安装》[5]中的 configure 指令来配置构建工程。根据《玲珑应用构建工程基础知识》[4],我们将 --prefix 赋予 $PREFIX 的值,最终我在本地执行了以下操作:
../configure --prefix=$PREFIX --enable-user-switch
--with-openssl\ --with-ossp-uuid CFLAGS=-g\
LDFLAGS=-L$PREFIX/lib/ CFLAGS=-I$PREFIX/include\
--with-libs=$PREFIX/lib/ --with-includes=$PREFIX/include\
CPPFLAGS=-L$PREFIX/include
7. 上述操作之后,出现了一个错误导致无法完成配置。我们看到是 libreadline 库无法找到,考虑到【玲珑应用构建工程基础知识】[4] 中提到的目录特性,我单独检查了对应的 include 目录,均无法找到与此库相关的资源。
configure: error: readline library not found
If you have readline already installed, see config.log for details on the failure. It is possible the compiler isn't looking in the proper directory.
Use --without-readline to disable readline support.szbt@szbt-linyaps23:/project$ ls /usr/include/ |grep readlineszbt@
szbt-linyaps23:/project$ ls /runtime/include/ |grep readlineszbt@
szbt-linyaps23:/project$
结合此报错,基本可以判断为该库缺失。根据提示,我们可以使用 --without-readline 参数来禁用此库以跳过错误。
8. 禁用后我们重新 configure,出现了 uuid 相关库丢失的情况。由于不能完全确认库缺失情况,我执行了 ./configure --help 来查看当前工程支持哪些参数,很快我就找到了和 uuid 的相关参数,并更新成以下的参数:
../configure --prefix=$PREFIX --enable-user-switch --with-openssl\
--with-uuid=e2fs CFLAGS=-g\
LDFLAGS=-L$PREFIX/lib/ CFLAGS=-I$PREFIX/include\
--with-libs=$PREFIX/lib/ --with-includes=$PREFIX/include\
CPPFLAGS=-L$PREFIX/include --without-readline
9. 重新执行后, 成功完成工程配置了,这一步直接执行 make 操作即可。10. 在该过程中, 依次出现了 bison、 flex 程序缺失的错误,我们返回普通操作窗口将对应的源码下载到当前构建目录中,进入如意玲珑容器操作窗口重新编译。
11. 重新编译 OpenTenBase 项目和 readline ,相关报错不存在了。重新编译后,第一次 make 可以成功完成了。
12. 随之我们立即根据文档开始第二次 make ,但出现了相对路径无法寻找的问题。
make: *** 没有规则可制作目标“../src/Makefile.global”。停止。
13. 仔细一看,这是因为我在编译上一级源码时使用了独立的编译目录,破坏了原有的 Makefile 设定。因此我又重新生成如意玲珑容器,更换了编译目录为 configure 同级目录,按 `1==>11` 顺序完全编译一次即可。
14. 但是这次 make 中出现了 readline 头文件丢失的情况,这意味着即便我们上一步禁用了此库,想要完成所有二进制程序编译还是无法离开此库。
我们参考 1==>10 的步骤重新编译 readline 及其依赖运行库 libncurses 后,也成功完成二次编译了。
./configure --prefix=$PREFIX --enable-user-switch --with-openssl\
--with-uuid=e2fs CFLAGS=-g\
LDFLAGS=-L$PREFIX/lib/ CFLAGS=-I$PREFIX/include\
--with-libs=$PREFIX/lib/ --with-includes=$PREFIX/include\
CPPFLAGS=-L$PREFIX/include --with-readline
编译结果测试
在完成 make install 后,由于 --prefix 被修改为了 $PREFIX,该变量也在容器默认 PATH 中,因此我查看是否可以正常运行此二进制:
szbt@szbt-linyaps23:/project/src/OpenTenBase-v2.6.0/contrib$ pgxc_ctl --help
/bin/bash
pgxc_ctl [option ...] [command]
option:
-c or --configuration conf_file: Specify configruration file.
-v or --verbose: Specify verbose output.
-V or --version: Print version and exit.
-l or --logdir log_directory: specifies what directory to write logs.
-L or --logfile log_file: Specifies log file.
--home home_direcotry: Specifies pgxc_ctl work director.
-i or --infile input_file: Specifies inptut file.
-o or --outfile output_file: Specifies output file.
-h or --help: Prints this message and exits.
For more deatils, refer to pgxc_ctl reference manual included inpostgres-xc reference manual.
至此,足以证明 OpenTenBase 项目可以在如意玲珑应用容器中成功编译并运行!
二进制程序封装&二次分发
随着 OpenTenBase 项目在如意玲珑应用容器中成功编译并运行,我心里又萌生了一个想法:有没有方案可以将如意玲珑容器中编译的二进制文件导出,并打包成 deb 等传统包格式提供给暂不支持玲珑环境的发行版体验呢?
很快,我发现如意玲珑容器中是包含了 tar 程序的,结合 /project 路径可以映射为宿主机的构建目录,我将 $PREFIX 目录封装为归档文件:
szbt@szbt-linyaps23:/project$ tar -jcvf OpenTenBase-v2.6.0-x86_64-binary.tar.bz2 $PREFIX/
OpenTenBase-v2.6.0-x86_64-binary.tar.bz2
返回普通操作窗口,发现我们通过宿主机也可以对此归档文件进行读写操作。
随后,我将归档文件内的二进制文件封装为了deb安装包,将路径 $PREFIX 修改为传统的 /usr。
三、其他基线相近的发行版安装使用由如意玲珑容器构建的二进制程序
在得到 deb 安装包后,我在不同主流发行版上尝试体验,来确认通过如意玲珑容器构建的二进制程序是否也存在通用性。
deepin 23
openKylin 2.0
Ubuntu 2404
四、 总结
通过本文,我们可以知道,除了通过如意玲珑容器封装的应用支持在不同发行版上使用(需要支持玲珑环境)之外,通过如意玲珑容器编译的二进制程序也支持在满足运行库要求的不同发行版上使用(暂不支持玲珑环境)。朋友们还等什么呢?赶紧操练起来吧!
最后,十分感谢来自如意玲珑社区 Maintainer Ziggy的投稿,也欢迎大家踊跃投稿,分享你的新发现和新玩法。
参考:
[1] 如意玲珑--新时代Linux桌面应用分发和治理方案:https://linglong.space/
[2] 如意玲珑技术架构介绍:https://linglong.space/about
[3] 构建配置文件简介:https://linglong.dev/guide/ll-builder/manifests.html
[4] 玲珑应用构建工程基础知识:https://github.com/OpenAtom-Linyaps/linyaps-meetup-open-doc/blob/main/docs/Tianjin-20241116/others/building-basic-notes.md
[5]OpenTenBase源码编译安装:https://docs.opentenbase.org/guide/01-quickstart/#opentenbase