Primer
Makrocosm provides Makefile rules to build a Linux kernel, build a bootloader, export container images from Docker, and convert between file formats. Utilities are provided to help combine these components into a disk image in custom rules. This framework is especially useful for building customized Linux operating systems as firmware for embedded devices.
Using Makrocosm involves writing a Makefile with rules that target your
desired build artifacts, creating the required dependency files, and
make
-ing the targets.
Makefile rules
Makrocosm uses Make as a build system, ensuring no final or intermediate artifacts are re-built unless any of their dependencies have changed.
The Makefile rules pages in the Reference section documents pattern rules provided by Makrocosm that perform a function without having to write any recipe script. These rules are described by the following properties:
- Target: The name of the build artifact that the rule will create.
These are usually patterns where the
${var}
part represents an arbitrary relative path that must match your project structure. - Required dependencies: Names of source files that you must create for
make
to build the target with the rule. These may also be patterns that must be consistent with the target filename. - Optional dependencies: Names of source files that you may create and manually add as a prerequisite of the target.
- Built dependencies: Names of build artifacts that you must ensure are able to be created by other rules. Rules with targets that are dependencies of other rules are chained and built as required. These may also be patterns that must be consistent with the target filename.
Makrocosm's Makefile rules are indexed in the following table:
Target | Dependencies | Reference documentation |
---|---|---|
build/${path} |
${path}.container.cfg ${path}/Dockerfile |
Build container image |
build/${path}.tar |
${path}.container.cfg ${path}/Dockerfile |
Export container image to tar |
build/${file}.sqfs |
${file}.sqfs.cfg build/${file}.tar |
Convert tar to Squashfs image |
build/${file}.ext4 |
${file}.ext4.cfg build/${file}.tar |
Convert tar to ext4 image |
build/${file}.fat |
${file}.fat.cfg build/${file}.tar |
Convert tar to FAT image |
build/${file}.cpio |
${file}.cpio.cfg build/${file}.tar |
Convert tar to cpio archive |
build/${path}/linux/install |
${path}/linux.cfg build/${path}/linux.src build/${path}/linux/.config |
Build Linux kernel and modules |
build/${path}/linux/.config |
${path}/linux.cfg build/${path}/linux.src *.kconfig |
Linux Kconfig build configuration |
build/${path}/u-boot/install |
${path}/u-boot.cfg build/${path}/u-boot.src build/${path}/u-boot/.config |
Build u-boot |
build/${path}/u-boot/.config |
${path}/u-boot.cfg build/${path}/u-boot.src *.kconfig |
u-boot Kconfig build configuration |
build/${path}.exec |
${path}.sh build/${path}.src |
Execute shell script |
build/${path}.src |
${path}.git.cfg *.patch |
Clone Git repository |
build/${path}.src |
${path}.download.cfg *.patch |
Download file |
build/${file}.qcow2 |
build/${file}.raw |
Convert raw disk image to QCOW2 |
build/${file}.xz |
build/${file} |
Compress file with xz |
build/${file}.gz |
build/${file} |
Compress file with gzip |
build/${file}.md5 |
build/${file} |
Calculate MD5 checksum |
build/${file}.sha256 |
build/${file} |
Calculate SHA256 checksum |
build/${file}.sha512 |
build/${file} |
Calculate SHA512 checksum |
build/${file}.bmap |
build/${file} |
Generate bmap metadata |
build/${file}.pad |
${file}.pad.cfg build/${file} |
Pad file to size |
Note that the targets all have the build/
prefix, which creates
the target files in the build
directory of the project root.
There is a clear distinction between source and build artifacts.
Also note that Make selects rules from candidates using dependencies it can
build in addition to the the dependencies already present -- rules are chained
together, creating intermediate targets to satisfy dependencies.
For example, if you target build/rootfs.sqfs
and have the file
rootfs.container.cfg
, then Make will build the intermediate target
build/rootfs.tar
from the Export container image to tar
rule before building the final target with the Convert tar to Squashfs image
rule.
To print a trace of the commands that are run, set the VERBOSE
environment
variable when invoking Make, e.g. make VERBOSE=1 ...
.
Configuration files
A number of Makrocosm Makefile rules expect a .cfg
-suffixed configuration
file to be present as a required dependency.
Configuration files must define options in new line separated key/value pairs,
e.g. KEY=VALUE
.
Conventional single and double shell quoting rules apply as these files
are evaluated as shell scripts
The options that are required to be set in the configuration files are described on the relevant Makefile rule's Reference page.
Disk images
Due to the variation in provisioning memory devices and constructing partition layouts for different hardware platforms and requirements, Makrocosm does not provide Makefile rules to automatically prepare disk images. It does, however, provide the makrocosm-disk utility that can be used in your own rules to construct disk images with GPT or MBR partiton tables, commonly used with block device storage media like hard drives and SD cards.
Workspace
To simplify setup of dependencies on the host system, the dependencies are installed in a Ubuntu 24.04 container image (default, see available workspaces).
Each shell command in Makefile recipes is run in a container using the makrocosm-workspace command, which passes through necessary host system resources such as the caller's UID/GID, the project root directory, and the Docker Unix domain socket.
Run make shell
to start an interactive shell in the workspace. This lets
you experiment in the environment that the Makefile rules' recipes are
executed in.
The workspace container image is built using a Build container image rule and will be automatically rebuilt when the Dockerfile or any files in its build context change.
Custom workspace
A custom container image can be used instead of the default Makrocosm workspace, allowing any additional packages to be made available in the build.
The custom container image is built using the Container images Makefile rule that builds the image into the container image store, and is rebuilt automatically when the container source changes.
In your Makefile, set the WORKSPACE
variable to the stem of the
*.container.cfg
target that to the container source.
For example, for a container image defined by
custom/workspace-ubuntu-24.04.container.cfg
and built with
custom/workspace-ubuntu-24.04/Dockerfile
:
WORKSPACE := custom/workspace-ubuntu-24.04
include makrocosm/rules.mk