Welcome to SBXG’s documentation¶
SBXG is a build system generator specialized in building from sources low-level components that are the foundation of Linux-based embedded devices, such as the U-Boot bootloader, the Linux kernel and the Xen hypervisor.
It is designed to offer a high level of reproductibility and tracability. Given that the URLs pointing to the different components are always available, SBXG should always generate the same outputs for a given set of inputs. No surprise to be expected.
On top of being able to build just the low-level components, SBXG can generate standalone images, ready to be flashed on an SDcard or used as virtual machine disks. In this mode, SBXG expects the rootfs to be available, it does not generate one.
All components (but the cross-compilation toolchain) are built from source, with a configuration file enforced by version. This allows SBXG users to rely on the sources and their own (or pre-packaged) configurations, instead of a black box downloaded from untrusted sources.
SBXG provides default configurations for some boards, toolchains, kernels and u-boot, to demonstrate its capabilities, but one of its goal is to be able to use opaque (private) user configurations that can leave outside of SBXG (e.g. reside in a dedicated source control repository).
Status of the project
SBXG is in omega stage (beyond alpha)! The documentation is being redacted, and some key features are being developed.
The Philosophy of SBXG¶
To summarize the key-points of the introduction, SBXG is designed to offer a high level of reproductibility and tracability when it comes to building the low-level components (Kernel, Bootloader) of a system. Configuration should be trivial, easy to maintain and keep track of.
It only concentrates in building from source the low-level components, eventually putting them together in a final image. In the later case, it expects the rootfs to be provided: it does not care about the roots. Even for kernel modules. How you distribuate these components is up to you.
Positions towards other tools¶
SBXG is not a innovation. There (hopefully) exist many other tools able to build a kernel. However, we think that SBXG fills a certain void when trying to generate Linux-based embedded systems, for which other tools do not offer a (subjectively judged) acceptable answer.
Why not Buildroot?¶
Buildroot allows to build root file systems, a Linux kernel and the U-Boot bootloader. If you are interesed in creating a self-contained, minimalistic and finely tailored to your needs, buildroot is the way to go. Don’t bother with us! However, if your objective is to build only the low-level components, or a whole bunch of them, you should consider using SBXG. Furthermore compiling these components with an explicit configuration (i.e. without fragments) is not handy with buildroot: if you don’t modify buildroot itself, you are obliged to add some kind of layer on top of it to generate a meaningful buildroot configuration.
Why not a simple shell script?¶
If your goal is just to build a couple of low-level components, a hand-crafted shell script is surely enough, given you are familiar with their build systems.
However, if you need to build a lot of them, SBXG may come handy, as it knows how to do. Also, if you want to create a full sdcard image, things may become a bit more challenging. This is even more true when trying to put Xen in the loop. SBXG knows how to do it. It should make things easier for you.
How to install SBXG¶
SBXG can be divided in two classes of components:
- the core of SBXG itself, which is a python package; and
- the run-time dependencies of SBXG, that are third-parties tools the generated build system will rely on.
Installing the dependencies¶
Only GNU/Linux distributions are supported. You may want to use the command-line that suits your distribution the best.
Debian-based distributions (including Ubuntu)¶
sudo apt install git python3-pip make curl build-essential autoconf \
autotools-dev tar swig python-dev libconfuse-dev mtools
Installing the SBXG python package¶
There are no pip package
Currently, there is no pip package on Pypi. You are obliged to build from sources!
Currently, the only way to install SBXG is by downloading the sources and
installing from these sources. So, you must have git
and pip3
installed.
Then, run the following commands:
git clone https://github.com/sbxg/sbxg.git
pip3 install --user -r sbxg/requirements.txt
pip3 install --user sbxg
Understand the use of each dependency¶
You may have noticed that SBXG requires quite some dependencies. We will explain here in which context they are important.
- Python 3.6
- SBXG is written in python. This is a no-brainer, without python 3.6 or higher, you will not be able to run SBXG at all.
- Make
- SBXG bootstraps its build system, by generating a Makefile. Therefore,
make
(only GNU make is tested) is a strong requirement for SBXG. Nomake
, no possibiltiy to use SBXG’s generated files. - mkfs (ext3, vfat)
- To generate the final image, mkfs (ext3 and vfat) will be required.
- curl and tar
- To download compressed tarballs from the internet, and extract them. This is typically used to retrieve the toolchain and components to be built.
- swig
- It seems that U-Boot requires swig to be built.
- autotools
- SBXG will build from sources a package that uses the autotools. As such, the autotools programs needs to be installed (e.g. autoconf, automake, …). This package is genimage.
- kernel build essentials
- SBXG will compile the Linux Kernel and U-Boot. Hence, such a development environment shall be installed.
How to use SBXG¶
SBXG is distributed as a python package, with a pre-defined entry point. It means you can use SBXG via its python API or as a command-line tool. N
Command-Line Interface¶
Stability of the CLI
Currently, SBXG’s CLI is not stable. It means it can change at any time, without prior notice.
SBXG’s command-line works with different commands:
show
: to display information on SBXG’s files;gen
(orgenerate
): to generate a build system able to download and build various un-connected components that share the same toolchain.
Note that SBXG accepts the following arguments before the commands. They will be applied to any command that follows:
--color
: can be set toyes
,no
orauto
, to respectively enable, disable or auto-detect if SBXG’s output should contain colors.-I
(or--lib-dir
): specify a directory to populate SBXG’s components library. If no arguments are provided, SBXG’s built-in library will be used. To understand what the library is, please refer to Understanding the SBXG Library.
sbxg show¶
SBXG can display the contents of its library, which has been populated with the
-I
option. Take a look at Understanding the SBXG Library if you are unsure of what the
library is.
This command will display in a human-readable way on the standard output:
- what are the toolchains that are available;
- what are the linux, u-boot and xen sources available; and
- what are the linux, u-boot and xen configurations available.
Note that this command accepts the --mi
option (for Machine Interface) that
displays the same information but serialized in JSON. This may come handy if
used for scripting. Refer to Machine Interface for details.
sbxg gen¶
The gen
command can be invoked with the following parameters:
-L
(or--linux-source
): the name of a file describing how to retrieve the sources of a given version of the Linux kernel.-U
(or--uboot-source
): the name of a file describing how to retrieve the sources of a given version of the U-Boot bootloader.-X
(or--xen-source
): the name of a file describing how to retrieve the sources of a given version of the Xen hypervisor.-l
(or--linux-config
) the name of a Kconfig file describing the various configuration parameters of a given Linux profile.-u
(or--uboot-config
) the name of a Kconfig file describing the various configuration parameters of a given U-Boot profile.-x
(or--xen-config
) the name of a Kconfig file describing the various configuration parameters of a given Xen profile.
The following argument pairs must be used together:
-L
and-l
;-U
and-u
;-X
and-x
.
Note that you can use as many arguments as you want. You can build a dozens of Linux kernels in one go for example, as long as they are to be built with the same toolchain.
A cross-compilation toolchain can be specified with the -t
or
--toolchain
option. Note that if this option is not present, SBXG will
assume you are building natively.
Architecture for cross-compilation
If you want to perform cross-compilation with the default toolchains, your host (the system that builds) MUST be x86. We don’t provide toolchains that are not x86 binaries. You can however define your own toolchain.
It takes a mandatory positional argument that is the path to the directory in which SBXG will generate its build system.
Python API¶
Stability of the Python API
Currently, SBXG’s python API is not stable. It means it can change at any time, without prior notice.
Understanding the SBXG Library¶
SBXG heavily relies on its own library concept. It is a finite set of directories that conform to a well-specified file hierarchy. This file hierarchy is explained in the present document.
The following directory hierarchy exposes all the different directories
recognized as being part of an SBXG library. Here, we assume the library is
composed of a single directory, named sbxg/lib/
:
sbxg/lib/
├── toolchains/
├── configs/
├── sources/
├── bootscripts/
├── images/
└── boards/
The toolchains/
subdirectory¶
The toolchains/
directory contains YAML files, each one describing a
toolchain:
sbxg/lib/
└── toolchains
└── *.yml
A toolchain file may contain the following paramters:
Name | Description |
---|---|
url | URL where to download the toolchain from |
path | Extracted (tar -xf ) directory |
prefix | Cross-compilation prefix |
arch | Linux and U-Boot architecture code name |
xen_arch | Xen architecture code name |
host | Typically, the prefix without underscore |
When cross-compiling, all these parameters should be mandatory. Note however that native compilation currently relies on the trick that some of these parameters may be not set or set to an empty string.
The configs/
subdirectory¶
The configs/
directory contains three subdirectories. Each of them
contains Kconfig files that are used by Linux, U-Boot and Xen to configure
their build:
sbxg/lib/
└── configs
├── linux
│ └── *
├── uboot
│ └── *
└── xen
└── *
These files may or may not have an extension. By convention, their name should
self-describe their purpose. For example, a Linux 4.14 configuration file that
allows to compile minimal Xen guests (domus) may be named:
linux-4.14-xen-domu-minimal
.
The sources/
subdirectory¶
The sources/
directory contains four subdirectories. Each of them
contains YAML files that describe how the various components (Linux, U-Boot,
Xen and genimage) may be retrieved:
sbxg/lib/
└── sources
├── genimage
│ └── *.yml
├── linux
│ └── *.yml
├── uboot
│ └── *.yml
└── xen
└── *.yml
A source file must contain the following paramters:
Name | Description |
---|---|
url | URL where to download the component from |
path | Extracted (tar -xf ) directory |
The bootscripts/
subdirectory¶
The bootscripts/
directory contains Jinja2 template files that must
program the U-Boot bootloader at boot-time. These files are associated with a
templating context that is described in Templating Context. To learn
more about bootscripts, please refer to U-Boot’s website.
sbxg/lib/
└── bootscripts
└── *
These files may or may not have an extension. By convention, their name should
self-describe their purpose, and the extension is always .j2
(but this is
not mandatory). For example a boot script allowing U-Boot to boot a sunxi board
may be named: boot-sunxi-default.j2
.
The images/
subdirectory¶
The images/
directory contains Jinja2 template files that describe how
a disk image must be generated by genimage. These files are associated with a
templating context that is described in Templating Context.
sbxg/lib/
└── images
└── *
These files may or may not have an extension. By convention, their name should
self-describe their purpose, and the extension is always .j2
(but this is
not mandatory). For example a genimage configuration describing a simple SDcard
partitioning may be named: sdcard-simple.j2
.
The boards/
subdirectory¶
The boards/
directory contains YAML files, each one describing a board:
sbxg/lib
└── boards
└── *.yml
A board describes what low-level components should be compiled, and what binaries from these components should be used to generate a final disk image. This file may contain the following top-level entries:
Name | Description |
---|---|
toolchain | Name of the toolchain to be used. |
genimage | Name of the genimage source to be used |
linux | Name of the Linux kernel source to be used |
linux_config | Name of the Linux Kconfig to be used |
linux_image | Filename of the Linux executable (e.g. zImage ) |
linux_dtb | Filename of the Linux DTB to be used |
uboot | Name of the U-Boot source to be used |
uboot_config | Name of the U-Boot Kconfig to be used |
uboot_image | Filename of the U-Boot executable |
boot_script | Name of the bootscript to be templated |
disk_image | Name of the genimage configuration to be templated |
root | In the Kernel bootargs, path to the rootfs block device |
rootfs | URL to the rootfs (.ext3 ) to be used in the image |
linux_bootargs | Additional Linux bootargs to be specified |
Templating Context¶
As explained in Understanding the SBXG Library, some files are to be templated by SBXG. Namely: the boot scripts and images configurations. The underlying templating engine is Jinja2. Templating engines uses what is called a templating context: it is the dataset used to output a meaningful result.
Since users are expected to create your own library to tweak SBXG to fit their needs, having a clear documentation of this templating context is mandatory. It can be seen as a stable interface between SBXG and its users.
Currently, no promise is made of a stable interface
As we are still in early development, this may change.
Notion of canonical names
Later in this document, we will mention canonical names. These are litteral strings derived from the names of files that are parts of the SBXG library. Canonical names are expected to be used by programming languages, such as GNU make. Which implies that it shall be get rid of unexpected characters (dots, dashes, spaces, …). In the canonical form, all the unwanted characters are replaced with underscores.
Top-level entries¶
The templating context will always contain the following top-level entries.
Note that they may be set to None
if not available, but it is guaranteed
that these keys will exist.
Name | Type | Description |
---|---|---|
top_build_dir | string |
Where components will be built |
toolchain | Toolchain |
Description of the toolchain |
downloads | list<Download> |
List of items to be downloaded |
linuxes | list<Item> |
List of the Linux kernels to be built |
uboots | list<Item> |
List of the bootloaders to be built |
xens | list<Item> |
List of the Xen hypervisors to be built |
genimage | Genimage |
Description of the genimage tool |
board | Board |
Description of the board |
The types mentioned in this table will be detailed in the next sections.
Toolchain data structure¶
The Toolchain
type is composed of following entries that were written in
the YAML file that describes the toolchain. See The toolchains/ subdirectory for
details.
Download data structure¶
It should be no surprise that the build system generated by SBXG will attempt
to download the sources of the components to be built. What falls in the
scope of a Download
object is compressed tar archives containing sources.
This includes Linux, U-Boot, Xen and genimage. A download receives a name,
that uniquely identifies it amongs others. It also allows components to be
built to depend on a download, by referring to its name.
Name | Description |
---|---|
name | Canonical name of the download |
url | URL where to fetch the component |
archive | Filename of the component to be downloaded |
Item data structure¶
An Item
describes either a Linux kernel, a U-Boot bootloader or a Xen
hypervisor. All entries in an Item
are of type string
. It is composed
of the entries written in the YAML file that describes these components. See
The sources/ subdirectory for details. In addition to these fields, the following
entries are guaranteed to exist:
Name | Description |
---|---|
config | Full path to the associated Kconfig file |
name | Canonical name of the component |
download | Name of the associated download information |
Genimage data structure¶
The Genimage
type is composed of the entries written in the YAML file that
describes genimage. See The sources/ subdirectory for details.
Board data structure¶
The Board
type is a subset of the elements described in The boards/ subdirectory,
which is defined by the following entries:
- linux_dtb;
- linux_image;
- uboot_image;
- boot_script;
- disk_image;
- root;
- bootargs.
It comes with the following extraneous string entries:
Name | Description |
---|---|
rootfs_url | The URL where the rootfs resides |
rootfs_path | Filename of the rootfs after download |
Machine Interface¶
Some commands or python API that SBXG provides expose a machine interface, which means formatted data that a script can easily takes as input.
Contents of the library¶
As explained in How to use SBXG, the sbxg show
command accepts the
--mi
argument, that returns a JSON-formatted string containing the contents
of the library. This paragraph details the format of these data.
The top-level dictionary contains a set of keys that are all lists of two kinds
of objects, that we name here Item
and TypedItem
. A list of objects of
type T
will be noted list<T>
.
Top-Level Keys | Type | Description |
---|---|---|
sources | list<TypedItem> |
List of the sources |
toolchains | list<Item> |
List of the toolchains |
configurations | list<TypedItem> |
List of the Kconfig files |
boards | list<Item> |
List of the available boards |
bootscripts | list<Item> |
List of the boot scripts |
images | list<Item> |
List of the images descriptions |
We now describe the Item
and TypedItem
objects:
Item Keys |
Type | Description |
---|---|---|
name | string |
Name of the item (e.g. value to be used) |
path | string |
Absolute path to the associated file |
TypedItem Keys |
Type | Description |
---|---|---|
name | string |
Name of the item (e.g. value to be used) |
path | string |
Absolute path to the associated file |
type | string |
Type of the item (e.g. linux, xen, u-boot) |
How about the rootfs?¶
As explained in the introduction, SBXG does not care about the Root Filesystem (rootfs). The rootfs is completely out of the scope of SBXG, because it is a completely different class of problem that requires specialized tools, and a awful lot lot of community work. Luckily, we already have tremendous work made openly available:
- Buildroot, to generate finely-tailored rootfs, mostly for embedded systems;
- Debootstrap, to retrieve pre-compiled Debian rootfs;
- DFT, a tool to heavily customize Debian rootfs.
- Gentoo stages, to generate or retrieve distribution-levels rootfs.
- And many, many more available choices…
Tutorial: using the built-in library¶
SBXG provides a built-in library, that can be extended by the users. This allows SBXG to provide users an out-of-the-box experience.
First, to observe the contents of the built-in library, just run:
sbxg show
and something like this will appear:
List of toolchains:
- local
- armv7-eabihf
List of sources:
- linux: linux-4.14.35
- linux: linux-4.12.0
- uboot: uboot-2017.07
- xen: xen-4.8.3
- genimage: genimage-v11
List of configurations:
- linux: linux-4.12-sunxi
- linux: linux-4.14-sunxi-xen-dom0
- linux: linux-4.14-xen-domu
- uboot: uboot-2017.07-minimal
- xen: xen-4.8-sunxi
List of bootscripts:
- boot-sunxi-default.j2
- boot-sunxi-xen.j2
List of images:
- sdcard-simple.j2
- guest-simple.j2
List of boards:
- cubietruck-standalone
Now, imagine that you want to build a Linux kernel for a sunxi <https://linux-sunxi.org/Main_Page> board from your x86 PC. You can see that SBXG provides a configuration for a 4.12 Linux kernel. Granted, this is quite old, but let’s say you have an old version of SBXG ;)
So you are interested in the following elements:
- the toolchain (
armv7-eabihf
); - the linux source (
linux-4.12.0
); and - the linux configuration (
linux-4.12-sunxi
).
Just tell that to SBXG:
sbxg gen -L linux-4.12.0 -l linux-4.12-sunxi -t armv7-eabihf build
SBXG will work a bit, and if everything went right, it should end with exit
code 0. In the build/
directory, you now have a generated standalone
Makefile
. You can build everything by running make
in this directory.
You can even pass to make
the number of jobs to be used for building. It
will be used to build the different components:
make -C build -j 3
Upon successful completion of this command, you will see the following directories:
build/
├── armv7-eabihf--glibc--stable-2018.02-2/
├── build_linux_4_12_sunxi/
├── downloads/
├── linux-4.12/
├── Makefile
└── stamps/
Let’s go through them one by one:
armv7-eabihf--glibc--stable-2018.02-2/
: this is where the toolchain was extracted.linux-4.12/
: this is where the sources of the kernel were extracted.downloads/
: you will find here compressed archives that were downloaded.stamps/
: this contains files generated by the Makefile that allows make to only download the archives when needed. Each file contains the URL from which the component was downloaded.build_linux_4_12_sunxi/
: this is where the linux kernel was built. Note that SBXG performs builds out-of-tree when possible.
Now that your kernel has been built, and now that you known where it was
built, you can freely dispose of them. For instance, the zImage
resides
in build/build_linux_4_12_sunxi/arch/arm/boot/
.
Developping in SBXG¶
Setting-up the development environment¶
SBXG is a python module, that requires python3.6 or higher. To make things simple, we advise you develop in a virtualenv.
You shall begin by installing python3.6 or higher on your platform. Recent
distributions should have it already installed. From now on, I assume that
the program python3
is in your PATH
, and that running:
python3 --version
yields something like:
$ python3 --version
Python 3.6.8
I will also assume that the associated program pip3
(pip for python3) is installed and in your
PATH
. Which means that running:
pip3 --version
yields something like:
$ pip3 --version
pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)
We now can install the virtualenv package, if it does not already exist:
pip3 install --user virtualenv
Now, for every new clone of SBXG sources, you must create the virtualenv in the top source directory:
virtualenv --python=python3 .venv
This will have for effect to create the directory .venv/
(which is already
described in the .gitignore
file) and will contain your python environment
when developping in SBXG.
Then, activate your virtualenv. If you have a POSIX-compatible shell, run:
. .venv/bin/activate
This will modify your current environment, so you can use the virtualenv.
From now on, the python
and pip
programs will be the ones of your
virtualenv! Not the ones of your system.
Don’t forget to activate your virtualenv!
For every new interactive session (i.e. when you open a new terminal to develop in SBXG), you MUST activate your virtualenv. Otherwise, you will not use it, and weird things may occur!
If you just created your virtualenv, you must install the appropriate python dependencies:
pip install -r requirements.txt
And you are good to go!
Coding Practises¶
Coding Style¶
Hate it or love it, but SBXG shall conform to PEP8. Docstrings shall conform to PEP257. There is currently no strict enforcement of these rules.
Linting¶
We use pylint to lint SBXG. It is not run automatically, because there’s nothing worse than seeing that your build fails because of an extraneous whitespace, or a rightful TODO you added. Use the linter to help you code, don’t bow to it.
To lint, just run the following from the top source directory:
pylint
Tests¶
We use pytest to run SBXG’s tests. It is a bit unusual to test, because it has a lot of interactions with the filesystem, which makes it not obvious to unit test it.
Also, since the goal of SBXG is to generate a build system, one of the possiblities to check that the build system was correctly generated is to run it, and see what happens. That’s the simple and obvious method. Problem is that we build sevaral Linux kernels… which take a lot of time to be downloaded and built. So, testing the correctness of the generated file is not that trivial after all. Currently, we run the generated Makefile for a single case that should cover most of the usecases, but it is not systematically executed.
To run the tests, just run the following from the top source directory:
pytest
Documentation¶
Documentation is obviously very important. It’s not always clear what to write, and how it should be written, but we try to figure out as we grow. Documentation, which is often looked down upon by developers tries to be a first-class citizen in SBXG. It demands work and dedication, but you’ll get used to it. We use Sphinx to manage the documentation.
To build the documentation, run the following from the top source directory:
make -C doc html
Contributions¶
This is currently a mess.
TODO.