Building Linux
Jolt includes task base classes that can be used to build the Linux kernel and filesystem images. The tasks are designed to be easily extended and customizable to fit your specific needs.
Toolchain
In order to build a kernel, a toolchain must be available. The toolchain is a collection of tools and libraries required to build the kernel. The toolchain can be installed manually or provisioned by a task.
The example below shows how to provision a toolchain using a DebianHostSdk task. This tasks assumes that the host system is running a Debian-based Linux distribution and that the required packages have been installed. It exports environment variables that are used by the kernel build task to locate the toolchain.
examples/linux/sdk.joltfrom jolt.plugins import linux class Sdk(linux.DebianHostSdk): """ SDK for Debian-based hosts Verifies that the required build tools are available on the host and exports environment variables such as PATH, CC, and CROSS_COMPILE to consumer tasks. """ name = "debian/sdk"
Kernel
To build the kernel, define a new task that inherits the
jolt.plugins.linux.Kernel base class available in the
jolt.plugins.linux module. Target architecture, defconfig and
make targets are specified as parameters from the command line. Multiple
targets can be built at once.
In the example below, a kernel build task is defined where the kernel source is cloned from the official repository on demand.
examples/linux/kernel.joltfrom jolt.plugins import git, linux class Kernel(linux.Kernel): """ Builds the Linux kernel. This task clones the Linux kernel repository from GitHub and builds the kernel for the parameter specified architecture and defconfig. """ requires = [ # Clone the Linux kernel repository from GitHub "git:url=https://github.com/torvalds/linux.git", # Rely on host Debian to provide the required build tools "debian/sdk:arch={arch}", ] # Use the required git repository as the source directory srcdir = "{git[linux]}"
This command builds a zImage kernel image and device tree blobs for the ARM architecture using the vexpress defconfig. The build output will be published into the task artifact.
$ jolt build kernel:arch=arm,defconfig=vexpress,targets=zimage+dtbs
Accepted parameter values can be displayed with:
$ jolt inspect kernel
Filesystem
Filesystem images can be built using the jolt.plugins.linux.Initramfs
and jolt.plugins.linux.Squashfs base classes available in the linux
plugin module. The classes use Podman to build images. It’s a daemonless container
engine for developing, managing, and running OCI containers. It uses the same
command line interface as Docker and can be used as a drop-in replacement.
The filesystem image content is defined in a Dockerfile or directly in the task class.
When building images for a different architecture than the host, the host system
must have the binfmt-support and qemu-static-user packages installed to
allow execution of foreign binaries. The packages are available in most Linux
distributions.
Initramfs
The next example task builds an initramfs image. The image is based on the BusyBox userland and includes a minimal set of tools and libraries required to boot the system.
examples/linux/initramfs.joltfrom jolt import influence from jolt.plugins import linux @influence.files("initramfs") class Initramfs(linux.Initramfs): """ Build an initramfs image. The image is based on the BusyBox userland and includes a minimal set of tools and libraries required to boot the system. """ dockerfile = """ FROM docker.io/busybox:latest RUN mkdir -p /proc ADD initramfs/ / """$ jolt build initramfs:arch=arm
The resulting artifact contains a cpio archive (initramfs) of the built container image.
SquashFS
It is also possible to build a SquashFS image. This image is baised on the Debian stable-slim image and includes a minimal set of tools and libraries required to boot the system. Instead of using systemd, the image uses finit-sysv as the init system.
examples/linux/squashfs.joltfrom jolt import influence from jolt.plugins import linux @influence.files("squashfs") class Squashfs(linux.Squashfs): """ Build a SquashFS image. The image is based on the Debian stable-slim image and includes a minimal set of tools and libraries required to boot the system. Instead of using systemd, the image uses finit-sysv as the init system. """ dockerfile = """ FROM docker.io/debian:stable-slim as base ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get install -y --no-install-recommends finit-sysv finit-plugins ADD squashfs/ / """ size = "64M" """ Pad image to a valid SD card image size. """$ jolt build squashfs:arch=arm
Virtual Machine
To try out the kernel, initramfs and SquashFS tasks, a VM task can be created. The VM task uses QEMU to boot the kernel and initramfs image and to mount the SquashFS image.
examples/linux/vm.joltfrom jolt.plugins import linux class VMIrfs(linux.Qemu): """ Run the Linux kernel and initramfs in a vexpress virtual machine. """ name = "vm/initramfs" arch = "arm" # dtb = "arm/vexpress-v2p-ca9.dtb" kernel = "kernel:arch={arch},defconfig=multi_v7,targets=dtbs+zimage" initrd = "initramfs:arch={arch}" machine = "virt" arguments = [ "-append", "console=ttyAMA0 quiet", "-nographic", ] class VMSquashfs(linux.Qemu): """ Run the Linux kernel and squashfs in a vexpress virtual machine. """ name = "vm/squashfs" arch = "arm" dtb = "arm/vexpress-v2p-ca9.dtb" kernel = "kernel:arch={arch},defconfig=vexpress,targets=dtbs+zimage" rootfs = "squashfs:arch={arch}" machine = "vexpress-a9" arguments = [ "-append", "console=ttyAMA0 root=/dev/mmcblk0 ro quiet", "-drive", "if=sd,driver=file,file={deps[rootfs].paths.squashfs}", "-nographic", ]
To run the VM using initramfs:
$ jolt build vm/initramfs
With the SquashFS image:
$ jolt build vm/squashfs