To make the Redox build process more consistent across platforms, we are using Rootless Podman for major parts of the build. Podman is invoked automatically and transparently within the Makefiles.
The TL;DR version is here.
You can find out more about Podman here.
By default, Podman Build is disabled. The variable
mk/config.mk defaults to zero, so that Podman will not be invoked. If you find that it is enabled but you want it disabled, set
mk/config.mk, and ensure it is not set in your environment,
Podman is a virtual machine manager that creates containers to execute a virtual machine image. In our case, we are creating an Ubuntu image, with a Rust installation and all the packages needed to build the system.
The build process is performed in your normal working directory, e.g.
~/tryredox/redox. Compilation of the Redox components is performed in the container, but the final Redox image (
build/$ARCH/$CONFIG/livedisk.iso) is constructed using FUSE running directly on your host machine.
PODMAN_BUILD to 1 in
mk/config.mk, on the
make command line (e.g.
make PODMAN_BUILD=1 all) or in the environment (e.g.
export PODMAN_BUILD=1; make all) will cause Podman to be invoked when building.
First, a base image called
redox_base will be constructed, with all the necessary packages for the build. A "home" directory will also be created in
build/podman. This is the home directory of your container alter ego,
poduser. It will contain the
rustup install, and the
.bashrc. This takes some time, but is only done when necessary. The tag file build/container.tag is also created at this time to prevent unnecessary image builds.
make commands are executed in containers built from the base image. The files are constructed in your working directory tree, just as they would for a non-Podman build. In fact, if all necessary packages are installed on your host system, you can switch Podman on and off relatively seamlessly, although there is no benefit to doing so.
The build process is using Podman's
keep-id feature, which allows your regular User ID to be mapped to
poduser in the container. The first time a container is built, it takes some time to set up this mapping. After the first container is built, new containers can be built almost instantly.
Envionment and Command Line Variables, other than ARCH, CONFIG_NAME and FILESYSTEM_CONFIG, are not passed to the part of
makethat is done in Podman. You must set any other config variables in
mk/config.mkand not on the command line or in your environment.
If you are building your own software to include in Redox, and you need to install additional packages using
apt-getfor the build, follow Adding Packages to the Build.
If you have already read the Building Redox instructions, but you wish to use Podman Build, follow these steps.
- Make sure you have the
curlcommand. E.g. for Pop!_OS/Ubuntu/Debian:
which curl || sudo apt-get install curl
- Make a directory, get a copy of
podman_bootstrap.shand run it. This will clone the repository and install Podman.
mkdir -p ~/tryredox cd ~/tryredox curl -sf https://gitlab.redox-os.org/redox-os/redox/raw/master/podman_bootstrap.sh -o podman_bootstrap.sh time bash -e podman_bootstrap.sh
- Change to the
gedit mk/config.mk &
... PODMAN_BUILD?=1 ...
- Build the system. This will take some time.
time make all
If you already have the source tree, you can use these steps.
- Change to your working directory and get the updates to the build files.
cd ~/tryredox/redox git fetch upstream master git rebase upstream/master
- Install Podman. Many distros require additional packages. Check the Minimum Installation instructions to see what is needed for your distro. Or, run the following in your working directory:
PODMAN_BUILDto 1 and run
make. The first container setup can take 15 minutes or more, but it is comparable in speed to native build after that.
export PODMAN_BUILD=1 make all
PODMAN_BUILD is properly set for future builds, edit
mk/config.mk and change its value.
gedit mk/config.mk &
... PODMAN_BUILD?=1 ...
Most of the packages required for the build are installed in the container as part of the build process. However, some packages need to be installed on the host computer. You may also need to install an emulator such as QEMU. This is done for you in
podman_bootstrap.sh, but you can do a minimum install by following the instructions below.
sudo apt-get install podman
sudo apt-get install podman curl git make libfuse-dev
sudo pacman -S --needed git podman fuse
sudo dnf install podman
The building of the image is controlled by the tag file
build/container.tag. If you run
make all with
PODMAN_BUILD=1, the file
build/container.tag will be created after the image is built. This file tells
make that it can skip updating the image after the first time.
Many targets in the Makefiles
build/container.tag as a dependency. If the tag file is missing, building any of those targets may trigger an image to be created, which can take some time.
When you move to a new working directory, if you want to save a few minutes, and you are confident that your image is correct and your
poduser home directory
build/podman/poduser is valid, you can do
This will create the file
build/container.tag without rebuilding the image. However, it will fail if the image does not exist. If it fails, just do a normal
make, it will create the container when needed.
To remove the base image, any lingering containers,
poduser's home directory, including the Rust install, and
To check that everything has been removed,
podman ps -a podman images
will show any remaining images or containers. If you need to do further cleanup,
podman system reset
will remove all images and containers. You still may need to remove
build/container.tag if you did not do
In some rare instances,
poduser's home directory can have bad file permissions, and you may need to do
sudo chown -R `id -un`:`id -gn` build/podman
`id -un` is your User ID and
`id -gn` is your effective Group ID. Be sure to
make container_clean after that.
make cleandoes not run
make container_cleanand will not remove the container image.
- If you already did
make container_clean, doing
make cleancould trigger an image build and a Rust install in the container. It invokes
cargo cleanon various components, which it must run in a container, since the build is designed to not require Cargo on your host machine. If you have Cargo installed on the host and in your PATH, you can use
make PODMAN_BUILD=0 cleanto clean without building a container.
If you are developing your own components and wish to do one-time debugging to determine what package you are missing in the Podman Build environment, the following instructions can help. Note that your changes will not be persistent. After debugging, you must Add your Packages to the Build. With
PODMAN_BUILD=1, run the command:
This will start a
bash shell in the Podman container environment, as a normal user without
sudo privilege. Within that environment, you can build the Redox components with:
or, if you need to change
./build.sh -a ARCH -c CONFIG_NAME repo
If you need
root privileges, while you are still running the above
bash shell, go to a separate Terminal or Console window on the host and type:
This will list all running containers. There should be only one, but if there is more than one, consider only the newest. In the last column of the display, the container will have a randomly generated name
boring_dickens. Replace the word
CONTAINER with that name and type:
podman exec --user=0 -it CONTAINER bash
You will then be running bash with
root privilege in the container, and you can use
apt-get or whatever tools you need, and it will affect the environment of the user-level
container_shell above. Do not precede the commands with
sudo as you are already
root. And remember that you are in an Ubuntu instance.
Note: Your changes will not persist once both shells have been exited.
exit on both shells once you have determined how to solve your problem.
The default Containerfile,
podman/redox-base-containerfile, imports all required packages for a normal Redox build.
However, you cannot easily add packages after the base image is created. You must add them to your own Containerfile.
podman/redox-base-containerfile and add to the list of packages in the initial
cp podman/redox-base-containerfile podman/my-containerfile gedit podman/my-containerfile &
... xxd \ rsync \ MY_PACKAGE \ ...
Make sure you include the continuation character
\ at the end of each line except after the last package.
mk/config.mk, and change the variable
CONTAINERFILE to point to your Containerfile, e.g.
If your Containerfile is newer than
build/container.tag, a new image will be created. You can force the image to be rebuilt with
If you feel the need to have more than one image, you can change the variable
mk/podman.mk to give the image a different name.
PODMAN_BUILD: If set to 1 in
mk/config.mk, or in the environment, or on the
makecommand line, much of the build process takes place in Podman.
CONTAINERFILE: The name of the containerfile used to build the image. This file includes the
apt-getcommand that installs all the necessary packages into the image. If you need to add packages to the build, edit your own containerfile and change this variable to point to it.
make build/container.tag: If no container image has been built, build one. It's not necessary to do this, it will be done when needed.
make container_touch: If a container image already exists and
poduser's home directory is valid, but there is no tag file, create the tag file so a new image is not built.
make container_clean: Remove the container image,
poduser's home directory and the tag file.
make container_shell: Start an interactive Podman
bashshell in the same environment used by
make; for debugging the
apt-getcommands used during image build.
make env: Start an interactive
bashshell with the
prefixtools in your PATH. Automatically determines if this should be a Podman shell or a host shell, depending on the value of
./build.sh -a ARCH -c CONFIG repo: Used while in a Podman shell to build all the Redox component packages.
make allwill not complete successfully, since part of the build process must take place on the host.
podman exec --user=0 -it CONTAINER bash: Use this command in combination with
make envto get
rootaccess to the Podman build environment, so you can temporarily add packages to the environment.
CONTAINERis the name of the active container as shown by
podman ps. For temporary, debugging purposes only.
podman system reset: Use this command when
make container_cleanis not sufficient to solve problems caused by errors in the container image. It will remove all images, use with caution. If you are using Podman for any other purpose, those images will be deleted as well.
If you are interested in how we are able to use your working directory for builds in Podman, the following configuration details may be interesting.
We are using Rootless Podman's
--userns keep-id feature. Because Podman is being run Rootless, the container's
root user is actually mapped to your User ID on the host. Without the
keep-id option, a regular user in the container maps to a phantom user outside the container. With the
keep-id option, a user in the container that has the same User ID as your host User ID, will have the same permissions as you.
During the creation of the base image, Podman invokes Buildah to build the image. Buildah does not allow User IDs to be shared between the host and the container in the same way that Podman does. So the base image is created without
keep-id, then the first container created from the image, having
keep-id enabled, triggers a remapping. Once that remapping is done, it is reused for each subsequent container.
The working directory is made available in the container by mounting it as a volume. The Podman option
takes the directory that
make was started in as the host working directory, and mounts it at the location
$CONTAINER_WORKDIR, normally set to
:Z at the end of the name indicates that the mounted directory should not be shared between simultaneous container instances. It is optional on some Linux distros, and not optional on others.
For our invocation of Podman, we set the PATH environment variable as an option to
podman run. This is to avoid the need for our
make command to run
.bashrc, which would add extra complexity. The
FILESYSTEM_CONFIG variables are passed in the environment to allow you to override the values in
mk/config.mk, e.g. by setting them on your
make command line or by using
We also set
PODMAN_BUILD=0 in the environment, to ensure that the instance of
make running in the container knows not to invoke Podman. This overrides the value set in
In the Containerfile, we use as few
RUN commands as possible, as Podman commits the image after each command. And we avoid using
ENTRYPOINT to allow us to specify the
podman run command as a list of arguments, rather than just a string to be processed by the entrypoint shell.
Containers in our build process are run with
--rm to ensure the container is discarded after each use. This prevents a proliferation of used containers. However, when you use
make container_clean, you may notice multiple items being deleted. These are the partial images created as each
RUN command is executed while building.
Container images and container data is normally stored in the directory
$HOME/.local/share/containers/storage. The command
podman system reset
removes that directory in its entirety. However, the contents of any volume are left alone.