12. Ubuntu 根文件系统构建

借助LubanCat-SDK我们可以方便的一键构建Ubuntu镜像,但是Ubuntu根文件系统的构建过程是相对独立的,不依赖SDK的其他部分。

我们可以使用Ubuntu官方的Ubuntu-base根文件系统来构建适配我们板卡的根文件系统。

我们的Ubuntu构建仓库由很多构建脚本组成,可以最大化的减少人工操作, 使构建的根文件系统具有一致性,同时我们的构建脚本支持Ubuntu18.04/20.04/22.04三个版本的构建。

目前Ubuntu20.04为我们主要支持的版本,本文档也是以Ubuntu20.04为例进行讲解的, 不过三个版本的构建方法基本相同,详细构建命令请查看对应分支的readme文件。

注解

由于不同版本的Ubuntu镜像构建环境不同,除非有定制文件系统的需求,不建议客户自行构建Ubuntu根文件系统, 建议直接使用我们构建好的根文件系统镜像。具体使用方法和下载地址,请查看LubanCat-SDK构建章节.

注解

如果确有自行构建根文件系统的需求,为了解决不同版本的Ubuntu镜像构建环境依赖问题,请参考 Docker构建根文件系统 章节

12.1. Ubuntu系统支持情况

12.1.1. LubanCat-RK356x

主要支持ubuntu 20.04 “Focal”,有限支持:ubuntu 18.04 “Bionic”、ubuntu 22.04 “Jammy”

  • lite无桌面版本

  • xfce4桌面版本

  • xfce4-full桌面版本

12.1.2. LubanCat-RK3588

主要支持ubuntu 20.04 “Focal”,有限支持:ubuntu 22.04 “Jammy”

  • lite无桌面版本

  • gnome桌面版本(默认桌面)

  • xfce桌面版本(无技术支持)

12.2. 什么是Ubuntu Base

Ubuntu 针对不同的 CPU 架构提供相应的 Ubuntu base 根文件系统,目前提供的架构有amd64、arm64、armhf、i386、s390x、ppc64.

Ubuntu Base 是用于为特定需求创建自定义映像的最小rootfs,是Ubuntu可以运行的最小环境。

Ubuntu Base 的下载地址是 http://cdimage.ubuntu.com/ubuntu-base/releases

../../_images/ubuntu01.png

12.3. 拉取Ubuntu构建仓库

如果要在SDK构建Ubuntu根文件系统镜像,我们需要在LubanCat-SDK根目录下执行此操作。

提示

由于完整的Ubuntu根文件系统构建仓库体积很大,我们需要构建哪个版本的镜像就拉取哪一个分支, 如下,我们需要构建Ubuntu20.04的根文件系统,就是用–branch=选项来选择; 如果不想查看git仓库提交历史的话,我们还可以添加–depth=1来拉取指定分支的最新一次提交, 这样可以有效减少拉取的仓库的体积。

1
git clone --branch=ubuntu20.04 --depth=1 https://github.com/LubanCat/ubuntu.git
../../_images/ubuntu02.png

图中我使用了公司内部Git服务器,我们会同步镜像到github和gitee。

拉取完成后进入ubuntu目录下,有以下文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
ls -hgG

-rwxrwxr-x  1  765 9月  29  2022 ch-mount.sh
-rwxrwxr-x  1 7.6K 4月  18 10:18 mk-base-ubuntu.sh
-rwxrwxr-x  1  841 4月  12 14:16 mk-image.sh
-rwxrwxr-x  1  11K 4月  18 10:18 mk-ubuntu-rootfs.sh
drwxrwxr-x  5   39 3月  31 16:41 overlay
drwxrwxr-x  5   49 9月  29  2022 overlay-debug
drwxrwxr-x  3   17 9月  29  2022 overlay-firmware
drwxrwxr-x  3   19 3月  31 16:41 packages
-rwxrwxr-x  1 1.8K 9月  29  2022 post-build.sh
-rw-rw-r--  1 1.1K 4月  18 11:10 readme.md
-rw-rw-r--  1  962 9月  29  2022 sources.list
drwxrwxr-x  3   58 9月  29  2022 ubuntu-build-service
  • mk-base-ubuntu.sh:在Ubuntu Base上安装软件包,以构建基础的ubuntu根文件系统。

  • mk-ubuntu-rootfs.sh:在基础的lite版本根文件系统上添加Rockchip overlay层。

  • mk-image.sh:将根文件系统打包成img镜像文件

  • sources.list:软件源地址

  • overlay:Rockchip overlay层,主要是rootfs中的配置文件

  • overlay-debug:Rockchip overlay层,主要是debug脚本和工具

  • overlay-firmware:Rockchip overlay层,主要是wifi/bt/npu的固件

  • packages:硬件加速包

  • ubuntu-build-service:用于搭建构建环境的依赖文件

目前构建脚本支持五种版本的镜像构建

  • lite:无桌面,终端版

  • xfce:使用xfce套件的桌面版

  • xfce-full:使用xfce套件+更多推荐软件包的桌面版

  • gnome:使用gnome套件的桌面版

  • gnome-full:使用gnome套件+更多推荐软件包的桌面版

注意

由于gnome桌面将会耗费更多资源,不建议在RK356x处理器的板卡上使用gnome镜像

12.4. Ubuntu根文件系统构建流程

Ubuntu根文件系统的构建主要分为四个步骤

第一步:从Ubuntu官网下载对应版本的最小rootfs,即下载Ubuntu Base

第二步:在最小rootfs的基础上安装常用的软件包和工具,并根据是否为桌面版来决定是否添加桌面显示套件。这个过程完成后得到基础根文件系统

第三步:在第二步的基础上,我们进一步添加基于RK处理器进行功能增强的软件包如GPU驱动和硬件firmware等。

第四步:将构建完成的根文件系统打包成img格式,方便烧录和下一步处理。

一、二步使用mk-base-ubuntu.sh脚本来实现;

第三步使用mk-ubuntu-rootfs.sh来实现;

第四步通过mk-image.sh来实现,在第三步脚本的末尾自动调用。

12.5. 搭建构建环境

在ubuntu目录下执行以下命令

1
2
3
sudo apt-get install binfmt-support qemu-user-static
sudo dpkg -i ubuntu-build-service/packages/*
sudo apt-get install -f
../../_images/ubuntu03.png

上面的命令执行过程中可能有警告或报错,这是正常现象,我们直接忽略报错即可。

12.6. 构建base镜像

我们以ubuntu-base镜像为基础,构建我们自己的base镜像。

这里我们自己的base镜像是指以ubuntu-base镜像为基础,安装了我们指定软件包, 并进行一些基础设置,如用户名、密码、用户组、时区等配置的根文件系统。

理论上这个根文件系统已经能在我们的板卡上运行了,不过还没有添加针对板卡的配置, 如网络,显示等,只能运行核心的服务。

下面我们来看一下具体的构建过程:

12.6.1. 构建基础根文件系统

我们在ubuntu目录下运行下面的命令

1
./mk-base-ubuntu.sh

选择要构建的Ubuntu版本,这里我们选择xfce版本,输入2并按下Enter按键,根据提示输入用户密码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
---------------------------------------------------------
please enter TARGET version number:
请输入要构建的根文件系统版本:
[0] Exit Menu
[1] gnome
[2] xfce
[3] lite
[4] gnome-full
[5] xfce-full
---------------------------------------------------------
2

等待命令结束以后我们看一下ubuntu目录下的文件变化:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
drwxr-xr-x 19 4.0K 4月  19 16:13 binary
-rwxrwxr-x  1  765 9月  29  2022 ch-mount.sh
-rwxrwxr-x  1 7.6K 4月  18 10:18 mk-base-ubuntu.sh
-rwxrwxr-x  1  841 4月  12 14:16 mk-image.sh
-rwxrwxr-x  1  11K 4月  18 10:18 mk-ubuntu-rootfs.sh
drwxrwxr-x  5   39 3月  31 16:41 overlay
drwxrwxr-x  5   49 9月  29  2022 overlay-debug
drwxrwxr-x  3   17 9月  29  2022 overlay-firmware
drwxrwxr-x  3   19 3月  31 16:41 packages
-rwxrwxr-x  1 1.8K 9月  29  2022 post-build.sh
-rw-rw-r--  1 1.1K 4月  18 11:10 readme.md
drwxrwxr-x  2    6 4月  19 16:13 rootfs
-rw-rw-r--  1  962 9月  29  2022 sources.list
-rw-rw-r--  1  26M 8月  30  2022 ubuntu-base-20.04.5-base-arm64.tar.gz
-rw-r--r--  1 756M 4月  13 16:42 ubuntu-base-xfce-arm64-20230413.tar.gz
drwxrwxr-x  3   58 9月  29  2022 ubuntu-build-service

我们看到,新增了三个文件

  • binary:存放解压后的根文件系统,构建过程在这个文件夹中进行

  • ubuntu-base-20.04.5-base-arm64.tar.gz:在cdimage.ubuntu.com下载的ubuntu-base根文件系统压缩包

  • ubuntu-base-xfce-arm64-20230413.tar.gz:我们通过上述脚本构建好的基础版根文件系统后的压缩包

上面的命令是使用 ./mk-base-ubuntu.sh 脚本来构建根文件系统。 他具体的工作流程如下:

  • 下载指定版本的ubuntu-base根文件系统压缩包并解压

  • 向解压后的根文件系统添加软件源、DNS服务

  • 根据ARM架构添加模拟器

  • 使用chroot来修改根文件系统
    • 升级并安装系统软件包

    • 创建用户和密码,并设置权限

    • 设定主机名、时区、服务项设置等

    • 清理软件安装缓存

  • 将设置好的根文件系统打包成压缩包便于保存管理

经过以上步骤,一个基础版本的根文件系统就制作好了

12.7. 构建完整的Ubuntu根文件系统镜像

完整版的Ubuntu根文件系统镜像主要是添加了Rockchip overlay层, 里面主要是一些配置文件和固件,用于添加或覆盖根文件系统中原有的配置文件, 以达到我们想要的定制效果。

12.7.1. 根文件系统构建

我们在ubuntu目录下,根据想要构建的根文件系统版本

1
2
#构建完整的根文件系统
./mk-base-ubuntu.sh

先选择要构建的CPU型号,我们选择rk3566/rk3568,输入1然后按回车键, 接着选择要构建的Ubuntu版本,这里我们选择xfce版本,输入2并按下Enter按键,根据提示输入用户密码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
jiawen@dev120:~/RK356X_LINUX_SDK/ubuntu$ ./mk-ubuntu-rootfs.sh
---------------------------------------------------------
please enter soc number:
请输入要构建CPU的序号:
[0] Exit Menu
[1] rk3566/rk3568
[2] rk3588/rk3588s
---------------------------------------------------------
1
set SOC=rk356x......
---------------------------------------------------------
please enter TARGET version number:
请输入要构建的根文件系统版本:
[0] Exit Menu
[1] gnome
[2] xfce
[3] lite
[4] gnome-full
[5] xfce-full
---------------------------------------------------------
2

上述命令中的脚本在最后调用了./mk-image.sh脚本,会自动将binary文件夹中的文件打包成img镜像:

等打包过程结束以后我们看一下ubuntu目录下的文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
drwxr-xr-x 19 4.0K 4月  19 16:13 binary
-rwxrwxr-x  1  765 9月  29  2022 ch-mount.sh
-rwxrwxr-x  1 7.6K 4月  18 10:18 mk-base-ubuntu.sh
-rwxrwxr-x  1  841 4月  12 14:16 mk-image.sh
-rwxrwxr-x  1  11K 4月  18 10:18 mk-ubuntu-rootfs.sh
drwxrwxr-x  5   39 3月  31 16:41 overlay
drwxrwxr-x  5   49 9月  29  2022 overlay-debug
drwxrwxr-x  3   17 9月  29  2022 overlay-firmware
drwxrwxr-x  3   19 3月  31 16:41 packages
-rwxrwxr-x  1 1.8K 9月  29  2022 post-build.sh
-rw-rw-r--  1 1.1K 4月  18 11:10 readme.md
drwxrwxr-x  2    6 4月  19 16:13 rootfs
-rw-rw-r--  1  962 9月  29  2022 sources.list
-rw-rw-r--  1  26M 8月  30  2022 ubuntu-base-20.04.5-base-arm64.tar.gz
-rw-r--r--  1 756M 4月  13 16:42 ubuntu-base-xfce-arm64-20230413.tar.gz
drwxrwxr-x  3   58 9月  29  2022 ubuntu-build-service
-rw-rw-r--  1 3.5G 4月  19 15:55 ubuntu-xfce-rootfs.img

我们看到,新增了三个文件

  • ubuntu-xfce-rootfs.img:打包好的完整根文件系统镜像

  • rootfs:mk-image.sh脚本打包的临时目录

mk-ubuntu-rootfs.sh脚本的构建流程如下:

  • 清空binary目录,并将对应的base根文件系统压缩包解压

  • 根据参数将packages/overlay/overlay-firmware/overlay-debug目录中的文件复制到解压后的根文件系统中

  • 根据ARM架构添加模拟器

  • 使用chroot来修改根文件系统
    • 升级并安装系统软件包

    • 安装本地packages目录内的硬件加速包

    • 根据上面的SOC参数安装对应的GPU驱动

    • 清理软件安装缓存

  • 调用mk-image.sh脚本打包img镜像

12.8. 定制Ubuntu根文件系统

由于镜像体积的限制,我们提供的定制Ubuntu镜像预装了一部分常用软件, 但是在用户开发时可能还需要预装更多的软件,以及对根文件系统做进一步的定制。 以下部分将对根文件系统的修改做具体说明。

12.8.1. 添加预装软件包

对于预装软件的添加,我们建议根据不同的版本放在mk-ubuntu-rootfs.sh脚本中, 这样在我们做修改以后,只要重复添加Rockchip overlay层和打包img镜像的过程即可, 可以节约大量的开发时间。

比如我们想要预装git和vim到根文件系统中, 则可以在mk-lite/desktop-rootfs.sh添加以下内容

1
2
3
4
5
6
export APT_INSTALL="apt-get install -fy --allow-downgrades"
#添加的位置在 export APT_INSTALL 下一行

#添加的内容是
echo -e "\033[47;36m ---------- LubanCat -------- \033[0m"
\${APT_INSTALL} git vim

12.8.2. 添加外设firmware

如果我们使用无线网卡这样的外设,就需要向根文件系统中添加网卡的firmware, 这时直接将对应的firmware存放在overlay-firmware/目录下,按根文件系统中的路径保存。

12.8.3. 添加服务项及配置文件

我们希望对有些服务项的配置进行自定义,就可以在overlay/目录下添加对应的配置文件。 制作根文件系统的过程中,在添加Rockchip overlay层的时候,就会添加或替换根文件系统中原有的配置文件, 以实现对配置文件自定义的效果。

这里我们以网络配置工具netplan的配置为例,netplan的配置文件在根文件系统的/etc/netplan/目录下, 这里对应的是overlay/etc/netplan/目录。

我们在overlay/etc/netplan/中新建一个名为01-network-manager-all.yaml的文件,在文件中添加以下内容:

1
2
3
4
5
6
7
network:
    renderer: NetworkManager
    ethernets:
        eth0:
            dhcp4: true
        eth1:
            dhcp4: true

上面文件的内容是使用netplan配置网络管理器为NetworkManager, 设置eth0和eth1都开启dhcp。

在添加配置文件以后,我们重新构建镜像,再烧录到板卡启动,就可以达到我们想要的网络配置效果。

注意

如果添加的是shell脚本,需要在创建文件后修改文件权限为775,否则在根文件系统中可能无法执行。

12.8.4. 重新打包根文件系统镜像

在对根文件系统的构建脚本做出修改之后,我们要重新打包ubuntu-xfce/lite-rootfs.img镜像。

  • 如果我们没有修改 mk-base-ubuntu.sh 脚本中的内容,则不需要重复构建base镜像部分。如果修改了则需要重新构建基础根文件系统

1
./ mk-base-ubuntu.sh
  • 如果修改了mk-ubuntu-rootfs.sh、overlay、overlay-debug、overlay-firmware、packages的内容,则需要执行以下命令

1
./mk-ubuntu-rootfs.sh

12.9. 使用LubanCat-SDK一键构建

在完成 拉取Ubuntu构建仓库搭建构建环境 这两个步骤以后, 我们也可以直接使用一键构建命令,就可以构建我们提供的定制根文件系统镜像了, 还可以借助SDK的镜像打包功能,将U-boot、内核等部分也一并打包成一个完整的系统镜像。

12.9.1. SDK配置文件说明

LubanCat板卡的SDK配置文件存放在device/rockchip/rk356x/目录内,以BoardConfig-LubanCat-CPU型号-系统类型-系统版本.mk来命名

我们来看Ubuntu根文件系统的配置文件,BoardConfig-LubanCat-RK3568-ubuntu-xfce.mk为例, 主要说明与Ubuntu根文件相关的设置。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# SOC
export RK_SOC=rk356x

# build.sh save 打包时名称
export RK_PKG_NAME=lubancat-${RK_UBOOT_DEFCONFIG}

# 定义默认rootfs为ubuntu
export RK_ROOTFS_SYSTEM=ubuntu

# 默认Ubuntu 版本
export RK_UBUNTU_VERSION=20.04

# 定义默认rootfs是否为桌面版  xfce :桌面版       lite :控制台版 xfce-full :桌面版+推荐软件包
export RK_ROOTFS_TARGET=xfce

# 定义默认rootfs是否添加DEBUG工具  debug:添加   none:不添加
export RK_ROOTFS_DEBUG=debug
  • RK_SOC:定义SOC类型

  • RK_PKG_NAME:定义镜像发布打包时的名称

  • RK_ROOTFS_SYSTEM:定义根文件系统类型

  • RK_UBUNTU_VERSION:定义Ubuntu发行版,一般无需修改,发布打包时使用

  • RK_ROOTFS_TARGET:定义根文件系统版本

  • RK_ROOTFS_DEBUG: 是否添加rockchip overlay_debug

12.9.2. build.sh中的自动构建脚本

Ubuntu根文件系统的一键构建功能,主要由build.sh脚本中的以下函数实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function build_ubuntu(){
    ARCH=${RK_UBUNTU_ARCH:-${RK_ARCH}}
    case $ARCH in
        arm|armhf) ARCH=armhf ;;
        *) ARCH=arm64 ;;
    esac

    echo "=========Start building ubuntu for $ARCH========="
    echo "==RK_ROOTFS_DEBUG:$RK_ROOTFS_DEBUG RK_ROOTFS_TARGET:$RK_ROOTFS_TARGET=="
    cd ubuntu


    if [ ! -e ubuntu-$RK_ROOTFS_TARGET-rootfs.img ]; then
        echo "[ No ubuntu-$RK_ROOTFS_TARGET-rootfs.img, Run Make Ubuntu Scripts ]"
        if [ ! -e ubuntu-base-$RK_ROOTFS_TARGET-$ARCH-*.tar.gz ]; then
            ARCH=arm64 TARGET=$RK_ROOTFS_TARGET ./mk-base-ubuntu.sh
        fi

        VERSION=$RK_ROOTFS_DEBUG TARGET=$RK_ROOTFS_TARGET ARCH=$ARCH SOC=$RK_SOC ./mk-ubuntu-rootfs.sh
    else
        echo "[    Already Exists IMG,  Skip Make Ubuntu Scripts    ]"
        echo "[ Delate Ubuntu-$RK_ROOTFS_TARGET-rootfs.img To Rebuild Ubuntu IMG ]"
    fi

    finish_build
}

其工作流程如下

  • 使用echo命令打印相关配置信息。

  • 判断ubuntu-$RK_ROOTFS_TARGET-rootfs.img是否存在( $RK_ROOTFS_TARGET 为配置文件中定义的是否为桌面版),存在则跳过构建过程,不存在则运行构建命令。根文件系统构建时间很长,不希望频繁构建根文件系统或使用已经构建好的根文件系统镜像。

  • 判断构建base镜像是否存在,不存在则构建base镜像,若存在则跳过base镜像构建过程。除了首次构建外,我们一般不会去修改base镜像。

  • 以base镜像为基础,添加rockchip overlay。

  • 打包镜像。

12.9.3. 编译前的准备工作

在编译开始前,首先要确保SDK的配置文件与要编译的rootfs一致, 如果当前配置文件与要编译的rootfs不一致,需要先切换配置文件。

1
2
3
4
5
# 选择SDK配置文件-直接指定
./build.sh BoardConfig-xxx-debian-版本.mk

# 选择SDK配置文件-按序号选择
./build.sh lunch

在设置正确的配置文件后,我们就可以进行下一步的构建工作了

12.9.4. 单独构建rootfs并打包

我们使用以下命令构建Ubuntu根文件系统,

1
2
# 构建Ubuntu
./build.sh ubuntu

编译生成的rootfs镜像为ubuntu/ubuntu-$RK_ROOTFS_TARGET-rootfs.img,同时被软链接到rockdev/rootfs.ext4。

注意

只有不存在ubuntu/ubuntu-$RK_ROOTFS_TARGET-rootfs.img时,才会重新构建Ubuntu根文件系统。如果修改了Ubuntu根文件系统的配置文件或构建脚本,要先将buntu/ubuntu-$RK_ROOTFS_TARGET-rootfs.img手动删除后再重新构建。

构建完成后就可以将独立的分区表、boot.img、uboot.img等分区镜像打包成一个完整的镜像了。

在执行以下操作前,请确保已经事先完成了U-Boot编译、Kernel编译以及刚刚完成的单独构建rootfs的过程。

确保无误后,执行以下命令

1
2
3
4
5
# 固件打包
./mkfirmware.sh

# 生成update.img
./build.sh updateimg

打包完成后,生成的镜像为rockdev/update.img,我们可以使用烧录工具将update.img烧录到板卡eMMC中或SD卡中。

12.9.5. 一键构建完整镜像

在设置正确的配置文件后,执行以下命令就可以一键完成U-Boot、Kernel、rootfs的编译,并生成update.img镜像

1
2
# 一键编译
./build.sh

打包完成后,生成的镜像为rockdev/update.img,我们可以使用烧录工具将update.img烧录到板卡eMMC中或SD卡中。