Linux aarch64交叉编译之 weston窗口管理程序

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

1 weston的来龙去脉

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

Wayland资料索引:

  • Wayland官网为:https://wayland.freedesktop.org/
  • Wayland官方文档学习手册: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经过计算,通知驱动层进行绘制。

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

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

Wayland协议诞生的缘由:

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

接下来谈谈Wayland本身,也就是what:

@1 Wayland是啥?

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

@2 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这种链接库的设置是无效的。

你可能感兴趣的:(Linux,系统,linux,服务器,嵌入式Linux,debian,运维)