如果部署程序的设备是 ARM 环境,通常程序编译要么交叉编译器,要么使用开发板进行编译。本文介绍一种利用 LXC 交叉架构创建一个用于编译程序的容器。

当使用交叉编译器时,如果程序依赖很多包,维护交叉编译环境就特别麻烦,需要自己维护特定的 rootfs 。当使用开发板编译时,代码编辑到编译不方便,而且 占用一块开发板。如果我们可以在开发主机上搭建一个与设备架构环境一致的系统,那么将大大提升开发的便捷性。比如设备上用的 aarch64 的 ubuntu focal(20.04), 我们可以在开发主机上使用 LXC 搭建一个 aarch64 的 ubuntu focal 系统容器,所有开发编译都可以在这个容器里进行,除了依赖板子设备硬件的程序,其他 程序都还可以在这个容器里调试运行。

LXC 的安装可以参考前一篇博文使用 LXC 创建用于构建 BSP 的容器机

下面介绍搭建交叉架构的容器,以 aarch64 ubuntu focal 为例:

创建容器

因为使用交叉架构,那么需要安装 qemu 的一个库,用来转义系统调用,然后创建容器:

1
2
3
4
# 交叉架构依赖 qemu-user-static
sudo apt install qemu-user-static
# 创建 arm64(aarch64)架构的容器
sudo lxc-create -n ubuntu-aarch64 -t download  --  --dist ubuntu --release focal --arch arm64

配置容器系统

默认安装的发行版本没有给出用户 ubuntu 密码,而且网络部分存在一些问题,都需要手动进行配置。

首先,可以通过 lxc-attach 命令进入系统

1
2
# 无密码进入系统
sudo lxc-attach -n ubuntu-aarch64

修改 ubuntu 用户密码:

1
2
# 修改 ubuntu 用户密码
passwd ubuntu

临时配置网络

1
2
# 临时使用 dhcp 配置网络,然后就可以安装新包了
dhclient eth0 -v

需要卸载模块中的 netplan,然后使用 ifupdown 来管理网络:

1
2
3
# 使用 ifupdown 代替 netplan
apt remove netplan.io libnetplan0
apt install ifupdown

为了开发方便,还需要安装 ssh server:

1
2
# 安装 ssh server
apt install openssh-server

然后可以编辑网络,创建 /etc/network/ 文件夹并写入配置到 /etc/network/interfaces 文件中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 编辑网络
mkdir /etc/network

cat << EOF | sudo tee /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

source /etc/network/interface.d/*
EOF

然后就可以退出 lxc-attach ,来验证容器是否正常化。

1
2
3
4
5
6
7
8
9
# 首先退出 Lxc-AttacH
# 停止容器
lxc-stop ubuntu-aarch64
# 启动容器
lxc-start ubuntu-aarch64
# 等待几秒,查看容器是否已有 ip
lxc-ls -f
# 通过 ip 进入系统
ssh ubuntu@10.0.3.x

备注

为了编译方便,还可以挂在主机上的代码工程文件夹到容器中,参考前一篇博文,这样就可以在主机上编辑代码,在容器中进行编译测试了。