There are a few articles from this blog that are old, but still known an read – even outside the small area of people speaking German. Thus this article written in English. My intention is to show how to cross compile uClibc and a BusyBox that is statically linked with this uClibc. The resulting BusyBox can be used to build some minimal Linux system. Around three or four Megabytes if you keep it really small. Nearly five years ago I wrote a tutorial on this topic (in German) on which I still receive feedback quite often. Since this tutorial is very outdated (module loading, initrd vs. initramfs, multiple initramfs), I plan to update it. This tutorial will show a quick alternative to get a working cross compiled BusyBox.
The content of this blog entry is partially based on the “semi official tutorial” how to cross compile BusyBox and partially on my experience with Linux from Scratch, especially Chapter 5 – Constructing a temporary system. At the time of this being written, I tried to make sure that very few patches are necessary – this will not always be the way, maybe GCC 4.7 will need more patches or BusyBox 1.19 does. uClibc 0.9.32 does not yet build cleanly on x86, thus I stay with uClibc 0.9.31.1 for this time:
Needed files
Sources and patches:
- GNU Binutils 2.21
- GCC 4.6.0 plus gcc-4.6.0-cross_compile-1.patch
- Linux sources 2.6.39.2
- uClibc 0.9.31.1
- BusyBox 1.18.5
- Gmp 5.0.2
- Mpfr 3.0.1
- Mpc 0.9
Configuration files:
1. Setting up the environment
Very few modifications to the environment are necessary. We just need three variables:
export TGTARCH=i486
export INSTDIR=/usr/local/crosstools
export PATH=${INSTDIR}/bin:${PATH}
$TGTARCH is the targeted architecture, it should be either i486, i586, i686 or x86_64. Of course it is possible to build for several ARM or MIPS targets if you need a statically linked BusyBox for a rooted Android device or a DSL router. There is one drawback however: My configs for uClibc and BusyBox are very x86 specific. For the first build I recommend using the same target architecture as the machine you are building:
export TGTARCH=` uname -m `
$INSTDIR is the location of the resulting toolchain. When building for different target architectures, you might also include the name of the target arch into the path. This makes deinstallation easier – you just have to delete a branch in the file system. For example:
export TGTARCH=i486
export INSTDIR=/usr/local/uclibc-crosstools-${TGTARCH}
export PATH=${INSTDIR}/bin:${PATH}
2. Building binutils
Unpack the binutils and create a directory binutils-build on the same level of the file system, then configure binutils:
tar xvjf binutils-2.21.tar.bz2
mkdir binutils-build
cd binutils-build
../binutils-2.21/configure \
--target=${TGTARCH}-linux-uclibc \
--prefix=${INSTDIR} --disable-nls \
--disable-werror
Now build and install binutils:
make && make install
3. Building GCC
As far as I tested, GCC needs a small patch to result in a properly working cross compiler. Besides this, GMP, MPFR and MPC must be present:
tar xvjf gcc-4.6.0.tar.bz2
tar xvjf mpfr-3.0.1.tar.bz2
tar xvjf gmp-5.0.2.tar.bz2
tar xvzf mpc-0.9.tar.gz
mv mpfr-3.0.1 gcc-4.6.0/mpfr
mv gmp-5.0.2 gcc-4.6.0/gmp
mv mpc-0.9 gcc-4.6.0/mpc
mkdir gcc-build
cd gcc-4.6.0
cat ../gcc-4.6.0-cross_compile-1.patch | patch -p1
cd ../gcc-build
Now configure, build and install GCC:
../gcc-4.6.0/configure \
--target=${TGTARCH}-linux-uclibc \
--prefix=${INSTDIR} \
--disable-nls --disable-shared --disable-multilib \
--disable-libmudflap --disable-libssp --disable-libgomp \
--disable-libquadmath --disable-target-libiberty \
--disable-target-zlib --disable-decimal-float \
--disable-threads --enable-languages=c \
--without-ppl --without-cloog
make && make install
4. Installing kernel headers
The kernel headers used should ressemble the version you intend to run the BusyBox on. Unpack and install them – the sanitizing step is taken from Linux from Scratch:
tar xvjf linux-2.6.39.2.tar.bz2
cd linux-2.6.39.2
make INSTALL_HDR_PATH=dest headers_install
find dest/include \( -name .install -o -name ..install.cmd \) -delete
mkdir -p ${INSTDIR}/${TGTARCH}-linux-uclibc/include
cp -rv dest/include/* ${INSTDIR}/${TGTARCH}-linux-uclibc/include
In the next steps ${INSTDIR}/${TGTARCH}-linux-uclibc will become more populated with headers, libraries and other development files for our build target.
5. Installing uClibc
Unpack uClibc and copy the config into the resulting directory. Since uClibc uses the same configuration scheme as the Linux kernel, some parameters in the config have to be changed with sed, and a run of make oldconfig is needed if you do not run my exact version of uClibc:
unxz -c uClibc-0.9.31.1.tar.xz | tar xvf -
cp uClibc-0.9.31.1.config uClibc-0.9.31.1/.config
cd uClibc-0.9.31.1
# This fixes the path of the linux headers
sed -i 's%/usr/local/crosstools/i486-linux-uclibc/include%'${INSTDIR}/${TGTARCH}-linux-uclibc/include'%g' .config
# This fixes the path to GCC and binutils:
sed -i 's%/usr/local/crosstools/bin/i486-linux-uclibc-%'${INSTDIR}/bin/${TGTARCH}-linux-uclibc-'%g' .config
make oldconfig
When building for x86_64 instead of i486-i686, replace the target as well:
sed -i 's%TARGET_i386=y%#TARGET_i386 is not set%g' .config
sed -i 's%# TARGET_x86_64 is not set%TARGET_x86_64=y%g' .config
make oldconfig
Now build and install uClibc:
make
make install PREFIX=${INSTDIR}/${TGTARCH}-linux-uclibc/
Everything is in place now. In the next step we are building the statically linked BusyBox:
6. Building BusyBox
Our BusyBox will be statically linked. Since BusyBox also uses the configuration scheme from the Linux kernel, configuration is done by copying the .config file:
tar xvjf busybox-1.18.5.tar.bz2
cp busybox-1.18.5.config busybox-1.18.5/.config
cd busybox-1.18.5
make oldconfig CROSS_COMPILE=${TGTARCH}-linux-uclibc-
Build BusyBox and install it to the subdirectory _install:
make CROSS_COMPILE=${TGTARCH}-linux-uclibc-
make install CROSS_COMPILE=${TGTARCH}-linux-uclibc-
If your build system is x86_64, any i486 to i686 or x86_64 can be directly run. There will be no hassle with libraries since our binary is statically linked:
# Should result in: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped
file _install/bin/busybox
# Should print the BusyBox applets contained
./_install/bin/busybox
That’s it. Have fun with your BusyBox. In a short time I will tell you how to configure and build a minimal Linux system that just consists of a kernel, BusyBox and Dropbear for SSH logins – that is just enough Linux to do imaging and restoring tasks.
Comments
3 responses to “Cross compiling uClibc and busybox”
I had to apply the patch under http://git.uclibc.org/uClibc/commit/?id=8245f3b4638fdff2011c2657af1bb211def704bc to uclibc(-0.9.32!)for a successful build under fedora_14_x86_64 with gcc 4.5.1.
Nevertheless one of the best and most helpful instructions for building a statically linked busybox (which is, apart from embedded systems, useful on possible rooted/untrustworthy boxes too).
.. oh, I might mention this for anyone else having problems.. my tool chain for an x86 was built with GCC 4.2.4 and Binutils 2.18..
>> Cross-Compiled Linux From Scratch – Version 1.1.0-x86
Chapter 5. Constructing Cross-Compile Tools <<
I used uClibc-0.9.30.1 for this example. I realize these sources are a little older but when trying to learn the "ropes" when compiling packages it seems to have less problems..
getting ready to "add" the busybox application now..
Cheers,
Bob
If уou wіsh fоr to get а gоod deal frοm thіѕ
artісle then you have tο apply such methodѕ
tο your wοn ωebѕite.
Look at my ωebpage; sa dating