| mkroot - simple linux system builder |
| |
| Compiles a toybox-based root filesystem and kernel that can boot under qemu. |
| |
| Prebuilt binaries available from http://landley.net/bin/mkroot/latest |
| launched via ./run-qemu.sh (which assumes you have QEMU installed, KVM |
| works in a pinch), and then run "exit" to shut down the emulated system. |
| |
| This project is a successor to https://landley.net/aboriginal/about.html |
| and shares most of the same goals, with a much simpler implementation. |
| |
| --- Quick Start |
| |
| To install the build prerequisites: download toybox source, linux kernel source, |
| and one or more musl cross compiler toolchain(s) in the "ccc" directory: |
| |
| $ cd toybox |
| $ git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux |
| $ wget https://landley.net/bin/toolchains/latest/i686-linux-musl-cross.tar.xz |
| $ mkdir ccc |
| $ tar xvJCf ccc i686-linux-musl-cross.tar.xz |
| |
| Then invoke mkroot like: |
| |
| $ mkroot/mkroot.sh CROSS=i686 LINUX=linux |
| $ root/i686/run-qemu.sh |
| |
| This project is a successor to https://landley.net/aboriginal/about.html |
| and shares most of the same goals, with a much simpler implementation. |
| |
| --- Building without a cross compiler (warning: glibc sucks) |
| |
| Running ./mkroot.sh with no arguments and no $CROSS_COMPILE environment |
| variable builds a statically linked root filesystem with the host's compiler. |
| |
| $ mkroot/mkroot.sh |
| |
| You can then chroot into it like this: |
| |
| $ sudo chroot output/host/root /init |
| $ ls -l |
| $ exit |
| |
| Unfortunately, glibc doesn't properly support static linking, so if your host |
| Linux uses glibc the build will spit out a bunch of warnings indicating |
| all sorts of glibc features won't work (DNS lookups always fail, ls -l can't |
| read names out of /etc/password, etc). This is a known problem with glibc, |
| because ex-maintainer Ulrich Drepper had a strong personal dislike of static |
| linking and actively sabotaged it. |
| |
| If building on a non-glibc system, such as Alpine Linux, you're fine. |
| Otherwise, you'll probably want to cross compile with a musl-libc toolchain |
| to avoid glibc's very long list of static linking bugs. (The resulting root |
| filesystem is also significantly smaller: a stripped statically linked |
| "hello world" binary for x86-64 is 5420 bytes with musl-libc, and 682,696 bytes |
| with glibc.)</p> |
| |
| --- Building with a cross compiler. |
| |
| The variable $CROSS_COMPILE indicates the toolchain prefix to apply to |
| commands such as "cc" and "ld". Since prefixed cross compiler names tend |
| to look like "armv5l-cc" this prefix tends to end with a dash. |
| |
| $ mkroot/mkroot.sh CROSS_COMPILE=armv5l- |
| |
| If you haven't added the cross compiler to your $PATH, you can specify |
| a path as part of the prefix: |
| |
| $ mkroot/mkroot.sh CROSS_COMPILE=~/x86_64-linux-musl-cross/bin/x86_64-linux-musl-cross- |
| |
| Don't forget the trailing dash. |
| |
| Alternately, the variable $CROSS (as used in the Quick Start above) tells |
| mkroot to look in the "ccc" directory for a cross compiler starting with |
| a short name: |
| |
| $ mkroot/mkroot.sh CROSS=s390x |
| |
| That would look (using wildcards) for ccc/s390x-*cross/bin/s390x*-cc and |
| if found, work out the appropriate $CROSS_COMPILER prefix to use for the |
| corresponding other tools. Use "CROSS=help" to see the list of cross compilers |
| currently available in the ccc directory. |
| |
| You only need to set one of $CROSS or $CROSS_COMPILE, the other gets derived |
| from the one you provided. |
| |
| The downloadable toolchains were built with toybox's scripts/mcm-buildall.sh |
| running in a fresh checkout of https://github.com/richfelker/musl-cross-make |
| and are available as prebuilt binaries from https://landley.net/bin/toolchains |
| (The "native" compilers run _on_ the target system, as well as producing |
| binaries for them. Those are packaged as squashfs filesystems, to be loopback |
| mounted within qemu.) |
| |
| --- Adding a kernel |
| |
| On the mkroot command line add LINUX= pointing to a kernel source directory: |
| |
| $ mkroot/mkroot.sh CROSS=sh4 LINUX=~/linux |
| |
| This will build a kernel for the appropriate target, package the filesystem |
| as cpio.gz for use by initramfs, and create a run-qemu.sh script to invoke |
| qemu. This results in the following files under root/$CROSS: |
| |
| initramfs.cpio.gz - the "fs" dir packaged for initramfs, plus any $MODULES |
| linux-kernel - the compiled kernel |
| linux.dtb - The device tree binary (if this target requires one) |
| run-qemu.sh - the qemu invocation to run it all |
| |
| And also: |
| |
| fs/ - the generated root filesystem (you can chroot here) |
| docs/ - Additional information not needed to run qemu. |
| |
| The run-qemu.sh script will connect together the appropriate -kernel, -initrd, |
| and -dtb arguments to consume the provided files, as well as -m board and |
| -append "kernel command line arguments". The KARGS environment variable is |
| added to the kernel command line arguments, and any additional arguments |
| provided to the script are passed through to qemu, so you can do: |
| |
| $ KARGS="rdinit=/bin/sh" ./run-qemu.sh -hda blah.img |
| |
| Running the script should boot the kernel to a command prompt, with the |
| serial console connected to stdin and stdout of the qemu process so you can |
| just type into it and see the output. The generated kernel config should |
| provide basic NAT network support (as if behind a router) and block device |
| support. |
| |
| --- Environment variables |
| |
| Any "name=value" argument provided on the mkroot.sh command line will set |
| an environment variable, and any string without an = indicates a package |
| script to run before building toybox (explained below). This is why CROSS= |
| CROSS_COMPILE= and LINUX= were all set on the command line above. |
| |
| For portability reasons, mkroot.sh clears all environment variables at the |
| start of its run, with the following exceptions: |
| |
| LINUX - Linux kernel source directory. |
| CROSS_COMPILE - Cross compiler prefix (sets $CROSS from prefix before first -) |
| CROSS - Short target name (sets $CROSS_COMPILE from ccc) |
| HOME - Absolute path to user's home directory. |
| PATH - Executable path to find binaries. |
| NOCLEAR - Don't clear environment variables. (Can't set on command line.) |
| |
| Other interesting variables to set on the command line include: |
| |
| NOAIRLOCK - don't do a hermetic build, just use the $PATH's tools. |
| NOLOGPATH - don't use the command line recording wrapper |
| NOLOG - don't record build output to root/build/log/$CROSS.[yn] |
| NOTOYBOX - don't build toybox |
| PENDING - extra commands to enable out of toys/pending |
| KEXTRA - Additional kernel symbols to enable (in short CSV format) |
| MODULES - Kernel modules to build (in short CSV format) |
| |
| --- Adding build modules |
| |
| You can run additional build scripts from the mkroot/packages directory by |
| listing them on the command line: |
| |
| $ mkroot/mkroot.sh dropbear overlay OVERLAY=~/blah |
| |
| Any "name=value" argument provided on the command line will set an environment |
| variable in mkroot (explained above), and any string that without an = |
| indicates a package script to run before building toybox. |
| |
| The provided build scripts mostly download source tarballs, cross compile them, |
| and install them into the root filesystem. Additional package build instructions |
| are available from the "Linux From Scratch" (http://linuxfromscratch.org/lfs) |
| and "Beyond Linux From Scratch" (http://linuxfromscratch.org/blfs) projects. |
| |
| If you specify any packages, the "plumbing" package is automatically read first |
| to provide the download, setupfor, and cleanup shell functions to fetch and |
| manage source tarballs, and set the $DOWNLOAD variable (defaulting to store |
| downloaded tarballs in "./root_download"). |
| |
| The "overlay" script copies the $OVERLAY directory (default "./overlay") |
| into the root filesystem, so you can add arbitrary additional files. |
| |
| The "dynamic" script attempts to copy dynamic libraries out of the |
| toolchain, to allow a dynamically linked root filesystem. It's a work in |
| progress. (A debian host toolchain can have multiple gigabytes of shared |
| libraries.) |
| |
| The "tests" script copies the toybox test suite into the new filesystem, |
| downloads some test files, and adds some test modules to the kernel build. |
| |
| --- Creating new build modules |
| |
| Build scripts run after creating the directory layout and writing |
| the the init script and etc files (resolv.conf/passwd/group), but before |
| building toybox. |
| |
| These scripts are sourced, not run, so environment variables you set remain |
| in force. The following variables can affect the remaining mkroot.sh build: |
| |
| NOTOYBOX - if set, toybox will not be installed into the new root filesystem |
| KEXTRA - additional kernel symbols to enable (in same CSV format as $KCONF) |
| QEMU_MORE - Additional qemu command line arguments added to run-qemu.sh |
| |
| To append instead of replacing (in case they're already set), you can use |
| QEMU_MORE="$QEMU_MORE --blah" and KEXTRA="${KEXTRA+$KEXTRA,}"BLAH,BLAH,BLAH |
| |
| If you check your own build scripts into mkroot/packages without touching |
| any existing files, you should be able to "git pull --ff" to update your tree |
| without conflicts. Alternately, you can add your script directory to the start |
| of the $PATH and bash's "source" command will fall back to looking there next. |