[BusyBox] Building Linux from Scratch 5.0 with busybox: how I did it.
rob at landley.net
Thu May 6 02:34:16 UTC 2004
Okay, I just finished building Linux From Scratch 5.0 all the way through with
busybox replacing most of the FSF packages. The resulting system SEEMS to
My scripts are attached. Here's what I did.
The documentation I started with is the file "LFS-BOOK-5.0-HTML.tar.bz2",
available from www.linuxfromscratch.org. Using that and a lot of work, I
created the three script files: "mktools-busybox.sh", "build.sh", and
About Linux From Scratch:
LFS produces a working Linux distro entirely from source code. Exactly how it
goes about this has evolved a bit over the years, version 5.0 of the
instructions uses a two stage process. The first stage ("chapter 5") builds
a toolchain where everything has its paths bent to live in a subdirectory
under "/tools". The second stage ("chapter 6") chroots into an environment
that contains nothing but the /tools directory created by Chapter 5, and then
creates the final system, deleting "/tools" at the end. The point of this
two stage process is to isolate the finished system from the parent system,
and to make sure nothing leaks from the parent system that isn't specified by
the build process and built from source.
What did I do:
I replaced most of the packages the Linux From Scratch system's "chapter 5"
with busybox, and then used that intermediate system to build the final
system (which also replaced everything it could with busybox). Thus busybox
was used as part of a development environment, to compile packages and build
a working linux system.
The Chapter 5 toolchain consists of binutils, gcc, the 2.4 kernel headers,
glibc, busybox, make, and ncurses. This is the "tools" directory created by
the mktools-busybox.sh script. (Note: this script needs to run as root
because it creates a symlink /tools at the root level pointing to the tools
directory it's building. This is necessary because the paths of all the
packages it's creating expect libraries and headers and the dynamic linker
and such to live under /tools, and to compile/link/run these suckers on the
parent system you need the symlink.)
The actual process of disentangling these tools from the host system is a bit
involved, and means that binutils gets built three times and and gcc gets
built twice. I commented the relevant section of the build script fairly
extensively if you'd like to know what's going on. All this complexity is
for cleansing purposes.
Note the sed production on line 171 of mktools-busybox.sh. This finds all the
references to the dynamic linker, for all architectures, and prepends it with
"/tools". (This could easily be adapted to adjust the thing to use uclibc
instead, but I haven't done that yet.) Both uclibc's buildroot and Linux
From Scratch use a patch file for this. One advantage of writing a sed
implementation is you learn how use the sucker... :) I turned as many
patches as possible into sed scripts, which should be more robust against
In theory, I shouldn't have needed any other packages to make Chapter 5 work.
Just binutils, gcc, kernel headers, glibc, busybox, make and ncurses. And in
fact, chapter 5 builds just fine with just those packages. But it doesn't
work to build the finished LFS system in chapter 6. :)
In reality, I needed a couple more things because busybox is incomplete and
buggy. (I'm working on it.) I had to build the following packages during
chapter 5 to compensate, but busybox can be upgraded to remove all these
I had to grab "sort" from coreutils because the busybox sort doesn't support
keys. (I'm doing a rewrite to make it SuS3 compliant, bug me about that next
I had to build gawk, because busybox awk needs major work. Possibly on the
order of magnitude of the sed rewrite; I won't know until I sit down and try
it some more. Right now it Just Doesn't Work (tm), and breaks deep in
./configure scripts that are a pain to debug.
I had to build bash. The busybox shell situation needs major work as well.
(The fact we have _three_ of them is a hint how big of an undertaking
unraveling this will be. I want to find, combine, or write _one_ shell that
can replace ash, lash, and hush. Yes, I know how big a pain this is going to
be, that's why I built bash for now.)
I had to build diffutils, because busybox doesn't have "diff -u". At all.
Bit of an oversight, if you ask me...
I had to build gzip, because of the bugs in busybox's gzip and gunzip that I
mentioned earlier. (When used on more than one file, the second and later
files are corrupt due to global variables that don't get re-initialized.
This is one of the big problems with "ash" too, by the way. I looked at it a
bit, and started doing the same kind of complete rewrite of gzip and gunzip
that I did of bzip and bunzip. This will take a while.)
I had to build Larry Wall's patch because busybox patch doesn't support -i.
Shouldn't be too hard to fix. Busybox patch also doesn't support any fuzz
factor, which is something Glenn and I have discussed. To-do item...
I also had to build miniperl from the perl package, because glibc needs perl
to build. (Actually, it seems to build ok but then inisits on testing the
new glibc using a perl script, and refuses to install if it fails. Once I
replace glibc with uclibc, this requirement should go away.)
And THAT is what the "mktools-busybox.sh" script does.
This "chapter 5" toolchain was then used to build a complete working Linux
system (Chapter 6) in a chroot environment. The build.sh and make-chroot.sh
scripts actually do this. The build.sh script sets up the chroot environment
(creates a build directory with the tools.tar.gz and sources.tar.gz extracted
into it, copies in the make-chroot.sh script, and chroots to execute it with
the path adjusted so that it starts with /tools/bin). The make-chroot.sh
script runs in the chroot environment to actually compile the new system
using the tools built in chapter 5.
The resulting system goes through the following steps:
Make lots of directories, and a few symlinks.
Create /etc/passwd and and /etc/group.
makedev script to populate /dev directory (to be replaced with udev).
install kernel headers
build glibc, tweak gcc spec file to point to it.
build coreutils, but only install src/sort and src/comm. (Sort is used by a
number of things, and the version in busybox is incomplete. comm is needed
to build perl, and busybox hasn't got one at all.)
build gawk (because busybox awk is horked).
build less (busybox ain't got one, just "more" which is no substitute.)
build groff (needed for man pages, I think).
delete busybox's gzip, gunzip, and uncompress (which need to be built for tar
to support z, but the need to be replaced with the real gzip's versions or
building kbd breaks.)
write misc config files (/etc/inittab, /etc/services...)
The result is a system you can chroot into and play with. Build a kernel and
run grub and you should be able to boot into it.
The following packages are built to test the development environment, but are
To reproduce all this, you'll need a source tarball (sources.tar.gz). I'd
file attach it, but it's 126 megabytes. You can either email me to put it up
for download somewhere, or you can assemble it yourself from the following
In the "sources" directory:
autoconf-2.57.tar.bz2, automake-1.7.6.tar.bz2, bash-2.05b-2.patch,
bash-2.05b.tar.bz2, binutils-2.14.tar.bz2, bison-1.875-attribute.patch,
bison-1.875.tar.bz2, busybox-config.bz2, busybox-cvs.tar.bz2,
diffutils-2.8.1.tar.bz2, e2fsprogs-1.34.tar.bz2, flex-2.5.4a.tar.bz2,
gawk-3.1.3-libexecdir.patch, gawk-3.1.3.tar.bz2, gcc-core-3.3.1.tar.bz2,
gcc-g++-3.3.1.tar.bz2, glibc-2.3.2-sscanf-1.patch, glibc-2.3.2.tar.bz2,
grub-0.93-gcc33-1.patch, grub-0.93.tar.bz2, gzip-1.3.5.tar.bz2,
less-381.tar.bz2, libtool-1.5.tar.bz2, linux-2.4.22.tar.bz2, m4-1.4.tar.bz2,
make-3.80.tar.bz2, MAKEDEV-1.7.bz2, man-1.5m2.tar.bz2,
man-pages-1.60.tar.bz2, ncurses-5.3-etip-2.patch, ncurses-5.3.tar.bz2,
openssl-0.9.7d.tar.gz, patch-2.5.4.tar.bz2, perl-5.8.0.tar.bz2,
In the "sources/unused" directory:
bzip2-1.0.2.tar.bz2, coreutils-5.0-hostname-2.patch, coreutils-5.0.tar.bz2,
file-4.04.tar.bz2, findutils-4.1.20.tar.bz2, grep-2.5.1.tar.bz2,
inetutils-1.4.2.tar.bz2, kbd-1.08-more-programs.patch, kbd-1.08.tar.bz2,
net-tools-1.60.tar.bz2, procinfo-18.tar.bz2, procps-3.1.11.tar.bz2,
psmisc-21.3.tar.bz2, sed-4.0.7.tar.bz2, shadow-4.0.3-newgrp-fix.patch,
shadow-4.0.3.tar.bz2, sysklogd-1.4.1.tar.bz2, sysvinit-2.85.tar.bz2,
tar-1.13.25.tar.bz2, util-linux-2.12.tar.bz2, vim-6.2.tar.bz2
All the patch files are available from the Linux From Scratch website as part
of their LFS 5.0 source. None of them are busybox specific, they all fix
various minor bugs in the original packages. The LFS-BOOK file explains what
they all do; I actually discarded a number of the LFS patches and turned a
lot of the rest into minor sed scripts.
The "unused" subdirectory contains the packages that busybox successfully
replaced, and are thus only built as a test of the development environment,
and not actually installed.
The fourth script (buildall.sh) does chapter 5 and chapter 6 in sequence,
building a finished system straight from a tarball. Yes, it has to run as
root. If you want to play with fakeroot or something, be my guest.
My to-do list:
Fix all the busybox deficiencies to get rid of coreutils, gawk, bash,
diffutils, gzip, patch, and less. This means implementing/fixing: sort,
comm, awk, sh, diff, gzip, gunzip, patch, less. And while we're add it,
implement the write half of "ar" too... And I have a note that "split" is
missing, but chapter 6 seems ok without it...?
Update all packages to the latest versions.
Use 2.6 kernel, building libc against the 2.6 kernel headers from:
Run the various "make test" productions on the packages I'm not actually
using. (Apparently, this means installing tcl, which is icky.)
Replace glibc with uclibc. (This means I can throw perl to the end as an
Implement various missing bits of bzip package (bzip2, bzcat, bzless, etc) in
Add dropbear, python...
Make a desktop out of it with x11, xfce...
Investigate more closely what the ./configure steps from each package look
like in a GNU environment and a busybox environment. Is ./configure
disabling anything because it detects (or thinks it detects) missing
functionality? I already got busybox sed to lie for --version to make
binutils happy. Stupid FSF software...
Go through Single Unix Spec V3 and compare it to busybox.
The binaries produced in /tools are way too big. I think there might have
been two copies of glibc in the path or something. That means stuff gets
linked in statically, but it still needs the shared library. Strange, I
know. Try it; symlink /lib to /usr/lib and dump the conents of /lib into
/usr/lib. Now build software with a standard gcc and check the resulting
binary sizes. Icky, isn't it?
P.S. Oh yeah, busybox "find" is horked too. Run "make mrproper" on the linux
kernel source and the following kind of thing makes busybox spit out a usage
message instead of finding:
find . \( -size 0 -o -name .depend \) -type f -print | xargs rm -f
Our find doesn't do parentheses, it seems. Another to-do item...
-------------- next part --------------
A non-text attachment was scrubbed...
Size: 10805 bytes
Desc: not available
Url : http://lists.busybox.net/pipermail/busybox/attachments/20040505/cbc52ccc/attachment.bin
More information about the busybox