对于weston的交叉编译。该文章的目标是编译一套aarch64 Linux Debian嵌入式版本上可以运行的版本库以及相关程序,接下来就开始趟坑。老套路,先把linux桌面版搞好,然后 移植到嵌入式Linux Debian 板子上。

1 weston的来龙去脉

在介绍weston之前,我们不得不来说说wayland。因为weston本质上就是wayland的一种实现。而说到wayland,又不得不提一下X11,那么接下来我们从X11->wayland->weston这条路线系统地理解下weston。

Wayland资料索引:

我们基于黄金圈法则,搞懂why,也就是为啥要搞出一个wayland来?那我们首先就要了解历史,先来看看X11。

1.1 X11,一个古老的图形系统

这里X表示的是协议,是1984年起始于 MIT(麻省理工学院)。11表示的是协议的版本号(实际版本是11 release 7.6),是在 1987年9月提出的。该方案是由 X 基金会所领导。

在wayland出来之前,Linux系统一直使用X11图形系统,这是一个古老的系统,到目前为止有近40年的历史,设计之初是因为个人PC性能低,所以构建了这样架构:

  • 所有渲染相关的计算都放在X Server端(本地的X显示程序,提供显示服务,它扮演了服务器的角色),而X Client端是既可以运行在本地端,也可以运行在网络端,代表客户端角色。 
  • X Server和XClient通信的手段就是X Protocol。所有的客户端接收到鼠标,键盘等等事件,都要通知Server,Server经过计算,通知驱动层进行绘制。

那么为什么要这样设计呢?因为它的设计背景和繁琐性主要受到当时计算机和网络技术的限制以及需求的影响。主要有:

  • 分布式计算环境: X11 最初是在分布式计算环境下开发的,这意味着图形界面的显示和应用程序的运行可以在不同的计算机上进行。这个设计考虑到了早期计算机性能的限制,通过将图形渲染任务分布到不同的机器上,可以减轻单个机器的负担,同时也为将来的网络连接提供了基础。
  • 网络带宽和延迟: 早期的网络带宽和延迟都相对较低。因此,X11的设计注重了通过网络传输图形数据,而不是在本地机器上直接渲染。这种设计决策导致了一些复杂的协议和延迟,因为所有的图形命令都需要在网络上传输并在远程服务器上执行。
  • 硬件限制: 早期计算机的图形硬件相对较弱,无法轻松处理复杂的图形渲染。因此,X11的设计允许服务器(图形渲染的主机)和客户端(应用程序运行的主机)之间共享图形处理负担,以实现更好的性能。
  • 多平台兼容性: X11旨在支持多种不同的图形硬件和操作系统,这也导致了一些设计上的复杂性,以确保在各种平台上都能够运行。

然而,随着计算机技术的进步,这些早期的限制逐渐消失。现代的硬件更加强大,网络连接更稳定且带宽更大,使得分布式图形渲染变得不再那么必要。这也促使了 Wayland 等现代图形协议的出现,这些协议更注重性能、响应性和安全性,避免了 X11 中一些复杂的设计,以适应现代计算环境。

1.2 wayland诞生缘由和原理,性能大幅度提升带来的变革

@1 Wayland的定位:替换Linux上的X11系统。

@2 wayland 对比X11优势如下:

  • 性能: Wayland 采用了更现代的设计,减少了图形渲染的中间步骤,从而提高了性能。X11 的架构在处理图形时会引入一些额外的延迟,而 Wayland 的设计可以更好地适应现代硬件和图形技术。
  • 更好的响应性: Wayland 的设计使得应用程序能够更直接地与图形硬件通信,从而实现更快的输入响应时间。这使得在 Wayland 下,窗口管理、鼠标和键盘输入等更加流畅和敏感。
  • 安全性: X11 设计的早期,缺乏对安全性的深入考虑,使得恶意应用程序可能会截取或篡改其他应用程序的显示内容。Wayland 引入了更严格的安全模型,限制了应用程序之间的直接访问,从而提高了系统的整体安全性。
  • 简化的架构: X11 的架构相对复杂,而 Wayland 的设计更加简单。Wayland 的核心思想是将图形显示的任务分解为一个个小模块,每个模块负责特定的功能,从而使整个系统更加模块化和易于维护。
  • 无需扩展和插件: X11 的扩展和插件机制可能会导致兼容性问题,而 Wayland 旨在通过默认支持现代图形特性来避免这些问题,从而减少了应用程序开发人员需要考虑的复杂性。
  • 多屏幕和高分辨率支持: Wayland 更好地支持多屏幕布局和高分辨率显示,减少了在这些方面出现问题的可能性。
  • 更好的窗口管理: Wayland 的设计使得窗口管理更加精细和灵活,窗口的渲染和处理在系统层面得到更好的控制,有助于实现更好的用户体验。

注意:尽管 Wayland 有很多优势,但在推广过程中可能会遇到一些挑战,例如与现有的 X11 应用程序的兼容性问题,以及某些特定硬件和驱动程序的支持情况。不过,许多 Linux 发行版和桌面环境已经在逐步过渡到 Wayland,并逐步解决这些问题。尤其是22.04,已经开始默认选择wayland而不是x11图形系统。

@3 Wayland协议诞生的缘由:

  • X11的框架在当时计算机性能较弱的环境下几乎是唯一可行的方式,但随着计算机性能的提升,“客户端”也有很强大的渲染能力。
  • 原本在X11图形系统中 X Server中做的事很多已被移到kernel或者单独的库中,因此X Server就显得比较累赘了。

@4 接下来谈谈Wayland本身,Wayland到底是个啥?

Wayland是一种表示显示系统server端与client端之间的通信协议。与X11相比只是原理不同而已。

@5 Wayland原理是啥?

Wayland的大概原理是:所有渲染都发生在client端,client端根据自己的业务逻辑构建相应的图形界面,计算需要渲染render的区域,然后在内存中开辟一段空间(可以是共享内存,也可以是显存,取决于实际硬件,注意,这里不是buffer的拷贝,而是把buffer的fd直接进行传递,效率高),将绘制好的图像放入buffer中,通知Wayland的Server(Compositor,表图像合成器),Compositor会监听所有client的请求,把所有Client绘制好的图片合成后发送到渲染器渲染并显示。

这种设计相比X11大幅度减少了Client和Server的频繁交互和数据传递,所以效率大幅度提高。

1.3 关键解读:Weston是啥?

Weston是Wayland compositor的参考实现(就像OpenGL是一种标准,而mesa是OpenGL的一种实现一样)。其官网为http://wayland.freedesktop.org/

最后附上weston的Github下载地址:GitHub - wayland-project/weston

2 Linux 本地编译 & 交叉编译

2.1 Linux(ubuntu20.04)上 weston的编译

weston是使用meson进行编译的,根据README.md的提示,编译关键步骤如下:

$meson build
$ninja -C build
$ninja -C build install

这里关于安装位置,可以通过--prefix=具体路径来设置。

2.2 aarch64交叉编译与移植

2.2.1 交叉编译

因为是用aarch64交叉编译,需要提前配置环境,安装如下软件:

sudo apt install binutils-aarch64-linux-gnu-dbg binutils-aarch64-linux-gnu cpp-aarch64-linux-gnu \
g++-10-aarch64-linux-gnu g++-9-aarch64-linux-gnu g++-aarch64-linux-gnu g++ \
gcc-10-aarch64-linux-gnu-base gcc-9-aarch64-linux-gnu-base gcc-aarch64-linux-gnu \
pkg-config-aarch64-linux-gnu qemu-efi-aarch64 gcc arch-test

构建一个sysroot路径需要用到的aarch64虚拟机,方式如下:

#创建一个虚拟fs文件系统
$sudo qemu-debootstrap --arch arm64 bullseye /mnt/data/arm64 http://deb.debian.org/debian/
#进入到文件系统
$sudo chroot /mnt/data/arm64/
#退出文件系统
$exit

在weston目录下构建一个arm64文件,内容如下:

[binaries]
c = 'aarch64-linux-gnu-gcc'
cpp = 'aarch64-linux-gnu-cpp'
ar = 'aarch64-linux-gnu-gcc-ar'
strip = 'aarch64-linux-gnu-strip'
pkgconfig = 'aarch64-linux-gnu-pkg-config'
ld = 'aarch64-linux-gnu-ld'
pcap-config = ''
cmake = 'cmake'

[properties]
skip_sanity_check = true
sys_root = '/mnt/data/arm64'
# Generate binaries that are portable across all Armv8 machines
platform = 'generic'
pkg_config_libdir ='/mnt/data/arm64/usr/lib/aarch64-linux-gnu/pkgconfig:/mnt/data/arm64//usr/share/pkgconfig'

[built-in options]
c_args = ['--sysroot', '/mnt/data/arm64']
c_link_args = ['-Wl,-rpath', '/mnt/data/arm64/usr/lib/aarch64-linux-gnu/', '-Wl,--as-needed']

[host_machine]
system = 'linux'
cpu_family = 'aarch64'
cpu = 'armv8-a'
endian = 'little'

之后在weston目录下执行:

$meson build --cross-file arm64.txt 
$ninja -C build
$ninja -C build install

注意:这个时候编译有可能出现各种缺库的问题,我们需要执行

$sudo chroot /mnt/data/arm64/
$apt search [缺的库 关键字检索]
$apt-file search [缺少的头文件之类的关键字检索]
$apt install [相关的库]

也就是进入到sysroot对应的虚拟机/mnt/data/arm64中安装缺失的库。

2.2.2 解决移植中的库链接问题

通过前面的操作,编译成功后可以将weston其移动到debian开发板上(注意:开发版的库 需要和 虚拟机运行时缺少的库作同步)。但是这时候发现会有很多链接的错误,找不到库,我们这样调整

调整compositor中内容,主要是将环境变量WESTON_MODULE_MAP置空,进而在链接库的时候走默认路径,weston代码修改如下:

diff --git a/weston/libweston/compositor.c b/weston/libweston/compositor.c
index a594d67..bd942da 100644
--- a/weston/libweston/compositor.c
+++ b/weston/libweston/compositor.c
@@ -7985,7 +7985,7 @@ weston_version(int *major, int *minor, int *micro)
 WL_EXPORT size_t
 weston_module_path_from_env(const char *name, char *path, size_t path_len)
 {
-       const char *mapping = getenv("WESTON_MODULE_MAP");
+       const char *mapping ="";// getenv("WESTON_MODULE_MAP");
        const char *end;
        const int name_len = strlen(name);

接下来修改weston配置文件meson_options.txt,修改内容如下:

diff --git a/weston/meson_options.txt b/weston/meson_options.txt
index 32daa01..cb9c179 100644
--- a/weston/meson_options.txt
+++ b/weston/meson_options.txt
@@ -85,6 +85,20 @@ option(
        description: 'Xwayland: path to installed Xwayland binary'
 )
 
+option(
+        'x-moduledir-path',
+        type: 'string',
+        value: 'default',
+        description: 'x define for different moduledir path'
+)
+
+option(
+        'x-libwestonmoduledir-path',
+        type: 'string',
+        value: 'default',
+        description: 'x define for different libweston moduledir path'
+)
+
 option(
        'systemd',
        type: 'boolean',

接下来修改weston的配置文件meson.build,将MODULEDIR 和LIBWESTON_MODULEDIR的默认加载路径重新设置,如下所示:

diff --git a/weston/meson.build b/weston/meson.build
index 63943f3..6ecf32c 100644
--- a/weston/meson.build
+++ b/weston/meson.build
@@ -116,8 +116,11 @@ config_h.set_quoted('PACKAGE_BUGREPORT', 'https://gitlab.freedesktop.org/wayland
 config_h.set_quoted('BINDIR', dir_bin)
 config_h.set_quoted('DATADIR', dir_data)
 config_h.set_quoted('LIBEXECDIR', dir_libexec)
-config_h.set_quoted('MODULEDIR', dir_module_weston)
-config_h.set_quoted('LIBWESTON_MODULEDIR', dir_module_libweston)
+
+#config_h.set_quoted('MODULEDIR',dir_module_weston)
+#config_h.set_quoted('LIBWESTON_MODULEDIR',dir_module_libweston)
+config_h.set_quoted('MODULEDIR', get_option('x-moduledir-path'))
+config_h.set_quoted('LIBWESTON_MODULEDIR', get_option('x-libwestonmoduledir-path'))
 
 config_h.set10('TEST_GL_RENDERER', get_option('test-gl-renderer'))

修改好代码后,这次我们重新编译,执行meson时候多了两个宏的设置,详细如下:

$meson build --prefix=[交叉编译输出路径] \
-Dx-moduledir-path=[开发板 库路径] \
-Dx-libwestonmoduledir-path=[开发板 库路径] \
--cross-file arm64.txt 
$ninja -C build
$ninja -C build install

之后编译出来的库和相关bin文件就可以在开发板上运行啦~。

特殊说明:之前在解决该问题时优先考虑的是设置LD_LIBRARY_PATH变量,但是发现并不管用,这是为什么呢?因为weston人家自己搞了一套设置加载库路径的东东,那为啥要这么搞呢?如果看了代码我们会知道,weston是使用dlopen这种方式直接打开库的,并不是简单的加载,因此 LD_LIBRARY_PATH这种链接库的设置是无效的。

Logo

更多推荐