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.jolt
from 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.jolt
from 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.jolt
from 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.jolt
from 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.jolt
from 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