Mercurial > hg > aboriginal
changeset 476:d4b89b94e027
I've been in the middle of rewriting these for a month. Need to do more documentation...
author | Rob Landley <rob@landley.net> |
---|---|
date | Wed, 12 Nov 2008 14:57:05 -0600 |
parents | 3116a52c8cb0 |
children | 40ef2d448e64 |
files | www/about.html www/design.html |
diffstat | 2 files changed, 287 insertions(+), 53 deletions(-) [+] |
line wrap: on
line diff
--- a/www/about.html Wed Nov 12 14:56:26 2008 -0600 +++ b/www/about.html Wed Nov 12 14:57:05 2008 -0600 @@ -2,11 +2,22 @@ <h2>What is Firmware Linux?</h2> -<p>Firmware Linux (FWL) is an embedded Linux build system implemented as a -series of shell scripts. The full build produces a complete -<a href=downloads/image>bootable linux system</a> (based on uClibc and -BusyBox/toybox) for various hardware platforms (including arm, mips, ppc, x86, -and x86-64).</p> +<p>Firmware Linux (FWL) is an embedded Linux build system designed to +eliminate the need for cross compiling, replacing it with native +compiling under emulation instead.</p> + +<p>FWL consists of a series of shell scripts which create a complete +<a href=downloads/image>bootable linux system</a> for a given target hardware +platform. This provides a minimal native Linux build environment for the +target, loosely based on <a href=http://linuxfromscratch.org>Linux From +Scratch</a> (stripped down to an embedded variant built from busybox, uClibc, +gcc, binutils, make, bash, and the Linux kernel). Running this native build +environment under an emulator such as QEMU (or on real target hardware if +applicable) allows fully native builds for arbitrary target platforms to +be performed on cheap and powerful commodity PC hardware.</p> + +<p>The currently supported target hardware platforms include arm, mips, powerpc, +x86, and x86-64, with partial support for sh4, mips, and sparc.</p> <p>Firmware Linux is loosely based on <a href=http://linuxfromscratch.org>Linux From Scratch</a>, stripped down and rebased on busybox and uClibc.</p> @@ -19,42 +30,44 @@ platform, eliminating the need for cross compiling in favor of <a href="#native_compiling">native compiling under emulation</a>.</p> -<h2>License</h2> - -<p>Firmware Linux is licensed under GPL version 2. This means that the build -scripts are licensed under GPL version 2, and each of the component packages -of the default "mini-native" root filesystem may be redistributed under the -terms of GPLv2 (and in the case of uClibc, LGPLv2).</p> - -<p>Adding your own packages to the resulting system is generally "mere -aggregation" (see the last paragraph of section 2), and thus not my -problem. This license statement is not intended to apply to your packages -as long as they are not derived works of existing GPLv2 code.</p> - <h2>Using the prebuilt binaries</h2> -<h3>qemu-image-*.tar.bz2</h3> +<h3>system-image-*.tar.bz2</h3> -<p>Each qemu-image tarball contains an ext2 root filesystem image, a kernel +<p>Each system-image tarball contains an ext2 root filesystem image, a kernel configured to run under qemu, and shell scripts to run the system (in various -modes) under the emulator <a href=http://qemu.org>qemu</a>.</p> +modes) under the emulator <a href=http://bellard.org/qemu/>qemu</a>.</p> <p>To test boot an FWL target system under qemu 0.9.1, download the appropriate <a href=downloads/image>prebuilt binary tarball</a> for the target you're -interested in, extract it, cd into it, and execute the "./run-emulator.sh" -script in that directory.</p> +interested in, extract it, cd into it, and execute one of the following +shell scripts:</p> + +<ul> +<li><p><b>./run-emulator.sh</b> - This boots the target Linux system under the +appropriate emulator, with /dev/console hooked to the emulator's stdin and +stdout. (I.E. the shell prompt the script gives you after the boot messages is +running in the emulator.) Type "cat /proc/cpuinfo" to confirm you're running +in the emulator, then play around and have fun.</p></li> -<p>This boots the target Linux system under the emulator, with /dev/console -hooked to the emulator's stdin and stdout. (I.E. the shell prompt the script -gives you after the boot messages is running in the emulator.) Type "cat -/proc/cpuinfo" to confirm you're running in the emulator, then play around and -have fun.</p> +<li><p><b>./run-with-home.sh</b> - Wrapper for run-emulator.sh which adds +a second virtual hard drive mounted on /home. (If the file "hdb.img" +doesn't exist on the host, this script automatically creates a 2 gigabyte +sparse file and formats it ext3.)</p></li> + +<li><p><b>./run-with-distcc.sh</b> - Wrapper for run-with-home.sh which +sets up the appropriate magic so the emulator will automatically call out to +the cross compiler on the host system via distcc. This can significantly speed +up build times under the emulator, while still avoiding most of the complexity +of cross compiling. (<a href="#distcc_trick">More info</a>)</p> +</ul> <p>The FWL boot script for qemu (/tools/bin/qemu-setup.sh) populates /dev from sysfs, sets up an emulated (masquerading) network (so you can wget source packages or talk to <a href="#distcc_trick">distcc</a>), and creates a few symlinks needed to test build normal software packages (such as making -/lib point to /tools/lib).</p> +/lib point to /tools/lib). It also mounts /dev/hdb (or /dev/sdb) on /home +if a second emulated drive is present.</p> <p>For most platforms, exiting the command shell will exit the emulator. (Some, such as powerpc, don't support this yet. For those you have to kill @@ -394,4 +407,17 @@ (ext2, initramfs, jffs2).</li> </ol> +<h2>License</h2> + +<p>Firmware Linux is licensed under GPL version 2. This means that the build +scripts are licensed under GPL version 2, and each of the component packages +of the default "mini-native" root filesystem may be redistributed under the +terms of GPLv2 (and in the case of uClibc, LGPLv2).</p> + +<p>Adding your own packages to the resulting system is generally "mere +aggregation" (see the last paragraph of section 2), and thus not my +problem. This license statement is not intended to apply to your packages +as long as they are not derived works of existing GPLv2 code.</p> + + <!--#include file="footer.html" -->
--- a/www/design.html Wed Nov 12 14:56:26 2008 -0600 +++ b/www/design.html Wed Nov 12 14:57:05 2008 -0600 @@ -2,46 +2,233 @@ <h1>The Firmware Linux build process</h1> -<p>Firmware Linux is an embedded Linux distribution builder, which creates a -bootable single file Linux system based on uClibc and BusyBox/toybox. It's -basically a shell script that builds a complete Linux system from source code.</p> +<h1>Overview</h1> + +<h2>User Interface</h2> + +<p>The script "./<b>build.sh</b>" calls the other scripts in the correct +sequence to perform a full build for one or more architectures. Its argument +is the architecture to build, and running it without arguments lists the +available architectures. (Configuration information for each architecture is +in the sources/targets directory.)</p> + +<p>Each stage can also be run (or re-run) individually. The individual stages +are described in the next section.</p> + +<p> + +<p>The script "<b>sources/forkbomb.sh</b>" builds all architectures at once. +Its command line arguments specify whether to build them in series (--nofork) or in +parallel (--fork). The output of each architecture's build is saved in a log +file named "out-$ARCH.txt". A quick scan of each log for success or failure +is available with "./forkbomb.sh --stat". Run it with no arguments to see +all available options.</p> + +<p>Setting the following environment variables to non-blank values can modify +the behavior of the build:</p> + +<ul> +<li><p><b>FWL_NO_TOOLCHAIN</b> - This tells mini-native.sh not to include a +compiler toolchain (binutils, gcc, bash, make, and distcc), but instead just +build a small uClibc/busybox system.</p> + +<p>Setting FWL_NO_TOOLCHAIN="headers" will leave the libc and kernel header +files in the appropriate include directory, for use by a compiler such as +pcc, llvm/clang, or tinycc. (Building and installing additional tools +such as "make" remains your problem.)</p> +</li> + +<li><p><b>FWL_TOPDIR</b> - Path to the top level directory within the +native filesystem. If this is blank, configure sets this to a default value +of "/tools", to act as a Linux From Scratch style chroot environment. For +a more traditional filesystem layout, set this to "/" or to "/usr".</p></li> + +<li><p><b>FWL_RECORD_COMMANDS</b> - Records all command lines used to build each +package.</p> + +<p>Tells host-tools.sh to build a logging wrapper (sources/toys/wrappy.c) and +populate a directory (build/wrapper) with symlinks to that wrapper for each +command name in $PATH. This allows later build stages to write log files in +the build directory (named "cmdlines.${STAGE_NAME}.${PACKAGE_NAME}") recording +each command run. (When build/wrapper exists, include.sh sets the wrapper +control variables $WRAPPY_LOGDIR, $WRAPPY_LOGPATH, and $WRAPPY_REALPATH, +then adjusts $PATH to point to the wrapper directory, which makes the wrapper +append to the appropriate log file before calling the actual command.)</p> + +<p>Afterwards, the script "sources/toys/report_recorded_commands.sh" can +generate a big report on which commands were used to build each package for +each architecture. To get a single list of the command names used by +everything, do:</p> + +<blockquote> +<p>echo $(find build -name "cmdlines.*" | xargs awk '{print $1}' | sort -u)</p> +</blockquote> + +<p>(Note: this will miss things which which call executables at absolute values +instead of checking $PATH, but the only interesting ones so far are the +#!/bin/bash type lines at the start of shell scripts.)</p> +</li> + +<li><p><b>FWL_BUILD_STATIC</b> - Tells cross-compiler.sh to statically link all +binaries in the cross compiler toolchain it creates.</p> + +<p>The prebuilt binary versions in the download directory are statically linked +against uClibc, by building a mini-native environment and re-running the build +under that with BUILD_STATIC=1.</p></li> + +<li><p><b>FWL_PREFERRED_MIRROR</b> - Tells download.sh to try to download +packages from this URL first, before falling back to the normal mirror list. +For example, "FWL_PREFERRED_MIRROR=http://landley.net/code/firmware/mirror".</p></li> + +<li><p><b>FWL_USE_TOYBOX</b> - Tells the host-tools.sh and mini-native.sh to +install the <a href=http://landley.net/code/toybox>toybox</a> implementation +of commands (where available) instead of the busybox versions.</p></li> +</ul> + +<h1>Implementation</h1> -<p>FWL builds a cross-compiler and then uses it to build a minimal system -containing a native compiler, BusyBox and uClibc. Then it runs this minimal -system under an emulator (QEMU) to natively build the final system. Finally it -packages the resulting system (kernel, initramfs, and root filesystem) into -a single file that can boot and run (on x86 by using a modified version of LILO).</p> +<p>The top level wrappers (<b>build.sh</b> or <b>forkbomb.sh</b>) call the +other stages in sequence. The other stages are <b>download.sh</b>, +<b>host-tools.sh</b>, <b>cross-compiler.sh</b>, <b>mini-native.sh</b>, and +<b>package-mini-native.sh</b>. Each script sources the common file +<b>include.sh</b>.</p> + +<p>In theory, the stages are othogonal. If you have an existing cross +compiler, you can add it to the $PATH and skip cross-compiler.sh. Or you +can use _just_ cross-compiler.sh to create a cross compiler, and then go build +something else with it. The host-tools.sh stage can often be skipped +entirely.</p> + +<h2>Stage 0: Setup</h2> + +<p>Before building anything we're going to keep, we need to do some setup +work.</p> + +<ul> +<li><p><b>include.sh</b> - header file defining common environment variables +and functions, and performing other miscelanous setup.</li> + +<p>This script is not run directly, instead it's included from all the other +scripts.</p> + +<p>For building packages, this file defines the functions:</p> +<ul> +<li><p><b>setupfor</b> - extracts a source package (named in the first +argument) into a temporary directory, and changes the current directory +to there.</p> + +<p>Source code is cached, meaning each package's source tarball is only +actually extracted once (into build/sources) and the temporary copies +are directories full of hard links to the cached source.</p> +</li> + +<li><p><b>cleanup</b> - delete temporary copy of source code after build.</p> +</li> +</ul> + +<li><p><b>download.sh</b> - Download source code packages from the web.</p> + +<p>This file is a series of calls to the <b>download</b> function (defined in +include.sh). If an existing copy of the tarball matching the sha1sum $SHA1 +doesn't currently exist in the sources/packages directory, it uses wget to +fetch it from $URL (or a series of fallback mirrors).</p> -<p>Firmware Linux builds in stages:</p> +<p>A blank value for $SHA1 will accept any file as correct, ignoring its +contents.</p> + +<p>After downloading all tarballs, the function <b>cleanup_oldfiles</b> deletes +any old files (meaning any files in sources/packages with a timestamp +before the call to download.sh, such as previous versions left over +after a package upgrade).</p> + +<p>Running this stage with the argument "--extract-all" will extract all +the tarballs, to preopulate the cache used by setupfor. (This is primarily +used to avoid race conditions in forkbomb.sh --fork.)</p> + +<li><p><b>host-tools.sh</b> - Set up a known environment on the host</p> + +<p>This script populates the <b>build/host</b> directory with +host versions of the busybox and toybox command line tools (the same ones +that the target's eventual root filesystem will contain), plus symlinks to the +host's compiler toolchain.</p> + +<p>This allows the calling scripts to trim the $PATH to point to just this +one directory, which serves several purposes:</p> + +<ul> + +<li><p><b>Isolation</b> - This prevents the ./configure stages of the source +packages from finding and including unexpected dependencies on random things +installed on the host.</p></li> + +<li><p><b>Portability</b> - Using a known set of command line utilities +insulates the build from variations in the host's Linux distribtion (such as +Ubuntu's /bin/echo lacking suport for the -e option).</p></li> + +<li><p><b>Testing</b> - It ensures the resulting system can rebuild itself +under itself, since the initial build was done with the same tools we +install into the target's root filesystem. The initial build acts as a smoke +test of most of the packages used to create the resulting system, and +restricting $PATH ensures that no necessary commands are missing. (Variation +can still show up between x86/arm/powerpc versions, of course.)</p></li> + +<li><p><b>Enumeration</b> - The RECORD_COMMANDS functionality (see +environment variables, above) starts here and continues into the later build +scripts.</p></li> +</ul> + +<p>This stage is optional. You don't need to run this stage if you don't +want to. If the build/host directory doesn't exist (or doesn't contain +a "busybox" executable), the build will use the host's original $PATH.</p> +</ul> <h2>Stage 1: Build a cross-compiler.</h2> -<p>The first stage builds a cross-compiler, -which runs on the host system and produces binaries that run on the target -system. (See my <a href=/writing/docs/cross-compiling.html>Introduction to -cross compiling</a> if you're unfamiliar with this.)</p> +<ul> +<li><p><b>cross-compiler.sh</b> - build a cross compiler for a target.</p></li> -<p>We have to cross-compile even if the host and target system are both -x86, because the host probably use different C libraries. If the host has +<p>This script builds a cross-compiler, which runs on the host system and +produces binaries that run on the target system. (See my +<a href=http://landley.net/writing/docs/cross-compiling.html>Introduction to +cross compiling</a> if you're unfamiliar with cross compiling.)</p> + +<p>The build requires a cross-compiler even if the host and target system are +both x86, because the host usually uses different C libraries. If the host has glibc and the target uses uClibc, then the (dynamically linked) target binaries -we produce won't run on the host. This is what distinguishes cross-compiling -from native compiling: different processors are just one reason the binaries -might not run. Of course, as long as we've got the cross-compiling support -anyway, we might as well support building for x86_64, arm, mips, or ppc -targets...</p> +we produce won't run on the host. (Target binaries that won't run on the +host are what distinguishes cross-compiling from native compiling. Different +processors are just one reason for it.)</p> + +<p>Building a cross-compiler toolchain requires four packages: binutils, +gcc, uClibc, and the linux kernel (for header files).</p> + +</ul> -<p>Building a cross-compiler toolchain requires four packages. The bulk of -it is binutils, gcc, and uClibc, but building those requires header files from -the Linux kernel which describe the target system.</p> +<h2>Stage 2: Cross compile a bootable target system.</h2> -<h2>Stage 2: Use the cross-compiler to build a native build environment -for the target.</h2> +<ul> +<li><p><b>mini-native.sh</b> - Build a minimal native development environment +for the target system.</p> + +<p>This script uses the cross compiler from the previous step to build a kernel +and root filesystem for the target, including a native compiler toolchain. +The resulting system should boot and run on the target, or under an +appropriate emulator.</p> <p>Because cross-compiling is persnickety and difficult, we do as little of it as possible. Instead we use the cross-compiler to generate the smallest possible native build environment for the target, and then run the rest of the build in that environment, under an emulator.</p> +<p>This script should perform all the cross compiling anyone ever +needs to do. It uses the cross-compiler to generate the simplest possible +native build environment for the target which is capable of rebuilding itself +under itself.</p> + +<p>Anything else that needs to be built for the target can then be built natively, +by running this kernel and root filesystem under an emulator and building +new packages there, bootstrapping up to a full system if necessary.</p> + <p>The emulator we use is QEMU. The minimal build environment powerful enough to boot and compile a complete Linux system requires seven packages: the Linux kernel, binutils, gcc, uClibc, BusyBox, make, and bash. It's packaged @@ -49,6 +236,9 @@ /tools directory approach, staying out of the way so the minimal build environment doesn't get mixed into the final system.</p> +</li> +</ul> + <h2>Stage 3: Run the target's native build environment under an emulator to build the final system.</h2> @@ -440,4 +630,22 @@ either /var/root or /home/root, change the passwd entry to do this), and life is good.</p> + +<!-- +<p>Firmware Linux is an embedded Linux distribution builder, which creates a +bootable single file Linux system based on uClibc and BusyBox/toybox. It's +basically a shell script that builds a complete Linux system from source code +for an arbitrary target hardware platform.</p> + +<p>The FWL script starts by building a cross-compiler for the appropriate +target. Then it cross-compiles a small Linux system for the target, which +is capable of acting as a native development environment when run on the +appropriate hardware (or under an emulator such as QEMU). Finally the +build script creates an ext2 root filesystem image, and packages it with +a kernel configured to boot under QEMU and shell scripts to invoke qemu +appropriately.</p> +--> + + + <!--#include file="footer.html" -->