1mkroot - simple linux system builder
2
3Compiles a toybox-based root filesystem and kernel that can boot under qemu.
4
5Prebuilt binaries available from http://landley.net/bin/mkroot/latest
6launched via ./run-qemu.sh (which assumes you have QEMU installed, KVM
7works in a pinch), and then run "exit" to shut down the emulated system.
8
9This project is a successor to https://landley.net/aboriginal/about.html
10and shares most of the same goals, with a much simpler implementation.
11
12--- Quick Start
13
14To install the build prerequisites: download toybox source, linux kernel source,
15and one or more musl cross compiler toolchain(s) in the "ccc" directory:
16
17 $ cd toybox
18 $ git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
19 $ wget https://landley.net/bin/toolchains/latest/i686-linux-musl-cross.tar.xz
20 $ mkdir ccc
21 $ tar xvJCf ccc i686-linux-musl-cross.tar.xz
22
23Then invoke mkroot like:
24
25 $ mkroot/mkroot.sh CROSS=i686 LINUX=linux
26 $ root/i686/run-qemu.sh
27
28This project is a successor to https://landley.net/aboriginal/about.html
29and shares most of the same goals, with a much simpler implementation.
30
31--- Building without a cross compiler (warning: glibc sucks)
32
33Running ./mkroot.sh with no arguments and no $CROSS_COMPILE environment
34variable builds a statically linked root filesystem with the host's compiler.
35
36 $ mkroot/mkroot.sh
37
38You can then chroot into it like this:
39
40 $ sudo chroot output/host/root /init
41 $ ls -l
42 $ exit
43
44Unfortunately, glibc doesn't properly support static linking, so if your host
45Linux uses glibc the build will spit out a bunch of warnings indicating
46all sorts of glibc features won't work (DNS lookups always fail, ls -l can't
47read names out of /etc/password, etc). This is a known problem with glibc,
48because ex-maintainer Ulrich Drepper had a strong personal dislike of static
49linking and actively sabotaged it.
50
51If building on a non-glibc system, such as Alpine Linux, you're fine.
52Otherwise, you'll probably want to cross compile with a musl-libc toolchain
53to avoid glibc's very long list of static linking bugs. (The resulting root
54filesystem is also significantly smaller: a stripped statically linked
55"hello world" binary for x86-64 is 5420 bytes with musl-libc, and 682,696 bytes
56with glibc.)</p>
57
58--- Building with a cross compiler.
59
60The variable $CROSS_COMPILE indicates the toolchain prefix to apply to
61commands such as "cc" and "ld". Since prefixed cross compiler names tend
62to look like "armv5l-cc" this prefix tends to end with a dash.
63
64 $ mkroot/mkroot.sh CROSS_COMPILE=armv5l-
65
66If you haven't added the cross compiler to your $PATH, you can specify
67a path as part of the prefix:
68
69 $ mkroot/mkroot.sh CROSS_COMPILE=~/x86_64-linux-musl-cross/bin/x86_64-linux-musl-cross-
70
71Don't forget the trailing dash.
72
73Alternately, the variable $CROSS (as used in the Quick Start above) tells
74mkroot to look in the "ccc" directory for a cross compiler starting with
75a short name:
76
77 $ mkroot/mkroot.sh CROSS=s390x
78
79That would look (using wildcards) for ccc/s390x-*cross/bin/s390x*-cc and
80if found, work out the appropriate $CROSS_COMPILER prefix to use for the
81corresponding other tools. Use "CROSS=help" to see the list of cross compilers
82currently available in the ccc directory.
83
84You only need to set one of $CROSS or $CROSS_COMPILE, the other gets derived
85from the one you provided.
86
87The downloadable toolchains were built with toybox's scripts/mcm-buildall.sh
88running in a fresh checkout of https://github.com/richfelker/musl-cross-make
89and are available as prebuilt binaries from https://landley.net/bin/toolchains
90(The "native" compilers run _on_ the target system, as well as producing
91binaries for them. Those are packaged as squashfs filesystems, to be loopback
92mounted within qemu.)
93
94--- Adding a kernel
95
96On the mkroot command line add LINUX= pointing to a kernel source directory:
97
98 $ mkroot/mkroot.sh CROSS=sh4 LINUX=~/linux
99
100This will build a kernel for the appropriate target, package the filesystem
101as cpio.gz for use by initramfs, and create a run-qemu.sh script to invoke
102qemu. This results in the following files under root/$CROSS:
103
104 initramfs.cpio.gz - the "fs" dir packaged for initramfs, plus any $MODULES
105 linux-kernel - the compiled kernel
106 linux.dtb - The device tree binary (if this target requires one)
107 run-qemu.sh - the qemu invocation to run it all
108
109And also:
110
111 fs/ - the generated root filesystem (you can chroot here)
112 docs/ - Additional information not needed to run qemu.
113
114The run-qemu.sh script will connect together the appropriate -kernel, -initrd,
115and -dtb arguments to consume the provided files, as well as -m board and
116-append "kernel command line arguments". The KARGS environment variable is
117added to the kernel command line arguments, and any additional arguments
118provided to the script are passed through to qemu, so you can do:
119
120 $ KARGS="rdinit=/bin/sh" ./run-qemu.sh -hda blah.img
121
122Running the script should boot the kernel to a command prompt, with the
123serial console connected to stdin and stdout of the qemu process so you can
124just type into it and see the output. The generated kernel config should
125provide basic NAT network support (as if behind a router) and block device
126support.
127
128--- Environment variables
129
130Any "name=value" argument provided on the mkroot.sh command line will set
131an environment variable, and any string without an = indicates a package
132script to run before building toybox (explained below). This is why CROSS=
133CROSS_COMPILE= and LINUX= were all set on the command line above.
134
135For portability reasons, mkroot.sh clears all environment variables at the
136start of its run, with the following exceptions:
137
138LINUX - Linux kernel source directory.
139CROSS_COMPILE - Cross compiler prefix (sets $CROSS from prefix before first -)
140CROSS - Short target name (sets $CROSS_COMPILE from ccc)
141HOME - Absolute path to user's home directory.
142PATH - Executable path to find binaries.
143NOCLEAR - Don't clear environment variables. (Can't set on command line.)
144
145Other interesting variables to set on the command line include:
146
147NOAIRLOCK - don't do a hermetic build, just use the $PATH's tools.
148NOLOGPATH - don't use the command line recording wrapper
149NOLOG - don't record build output to root/build/log/$CROSS.[yn]
150NOTOYBOX - don't build toybox
151PENDING - extra commands to enable out of toys/pending
152KEXTRA - Additional kernel symbols to enable (in short CSV format)
153MODULES - Kernel modules to build (in short CSV format)
154
155--- Adding build modules
156
157You can run additional build scripts from the mkroot/packages directory by
158listing them on the command line:
159
160 $ mkroot/mkroot.sh dropbear overlay OVERLAY=~/blah
161
162Any "name=value" argument provided on the command line will set an environment
163variable in mkroot (explained above), and any string that without an =
164indicates a package script to run before building toybox.
165
166The provided build scripts mostly download source tarballs, cross compile them,
167and install them into the root filesystem. Additional package build instructions
168are available from the "Linux From Scratch" (http://linuxfromscratch.org/lfs)
169and "Beyond Linux From Scratch" (http://linuxfromscratch.org/blfs) projects.
170
171If you specify any packages, the "plumbing" package is automatically read first
172to provide the download, setupfor, and cleanup shell functions to fetch and
173manage source tarballs, and set the $DOWNLOAD variable (defaulting to store
174downloaded tarballs in "./root_download").
175
176The "overlay" script copies the $OVERLAY directory (default "./overlay")
177into the root filesystem, so you can add arbitrary additional files.
178
179The "dynamic" script attempts to copy dynamic libraries out of the
180toolchain, to allow a dynamically linked root filesystem. It's a work in
181progress. (A debian host toolchain can have multiple gigabytes of shared
182libraries.)
183
184The "tests" script copies the toybox test suite into the new filesystem,
185downloads some test files, and adds some test modules to the kernel build.
186
187--- Creating new build modules
188
189Build scripts run after creating the directory layout and writing
190the the init script and etc files (resolv.conf/passwd/group), but before
191building toybox.
192
193These scripts are sourced, not run, so environment variables you set remain
194in force. The following variables can affect the remaining mkroot.sh build:
195
196NOTOYBOX - if set, toybox will not be installed into the new root filesystem
197KEXTRA - additional kernel symbols to enable (in same CSV format as $KCONF)
198QEMU_MORE - Additional qemu command line arguments added to run-qemu.sh
199
200To append instead of replacing (in case they're already set), you can use
201QEMU_MORE="$QEMU_MORE --blah" and KEXTRA="${KEXTRA+$KEXTRA,}"BLAH,BLAH,BLAH
202
203If you check your own build scripts into mkroot/packages without touching
204any existing files, you should be able to "git pull --ff" to update your tree
205without conflicts. Alternately, you can add your script directory to the start
206of the $PATH and bash's "source" command will fall back to looking there next.
207