Contents
Build Machine
Development Tools
Ipkg Manager
Directory Structure
bin Directory and Tools
etc/ipk Directory
makefiles Directory
Packages
Downloading
Building Packages
Creating the Filesystem
Building the Kernel
Building Glibc
Building Busybox
Installing Packages
Building Image
Creating CDROM
Making Bootable
Build Machine
The machine used to build is a Packard Bell desktop, with an Intel Quad CPU Q6600 @ 2.40GHz (19200 BogoMIPS total), with 1Gb RAM.
Each of the compile steps below, was performed in sequence, and has an indication of how long it took on my machine. Once you have performed one of the steps, you should gain an understanding of how each step takes (releatively).
Development Tools
A number of development tools are needed to build a software release - with Mandriva, all of these tools can be installed through the admin menu.
- GCC 4.3.2 or later
- GNU Make
- GNU Bison
- GNU binutils 2.9.1.0.23 or later
- Other standard GNU/Unix tools
- LZO 1.02 (devel) or later
- Ruby
From the installation files, you will see that I am always trying to keep the install size down, that's why I selected busybox. This is also why I've selected to use the itsy package manager which is a cut down version of the Debian package manager. It creates ipk files, and the tools can be downloaded from here:
- ipkg-tools
- ipkg-build
Directory Structure
I've created a directory hierarchy on my Linux machine, which will contain files as follows:
- bin - contains scripts and programs I used to develop the build
- build - working directory where all of the compilation is performed
- etc - directory, where I include all of my configuration files for the build
- ipk - directory where all of the ipk install files are stored
- makefiles - I use make to control all of the building, and the makefiles live here
- sources - holds the downloaded source code
- image - where a build image is created
- iso - where the iso cdrom images are stored
In the bin directory, I have several scripts, the first being 'setpath', which is used to set up the build environment, and is sourced by typing a dot, space and setpath, i.e.: . setpath
setpath file contents:
#Now, I manage all of my source bundles with ipk control files, which are stored in etc/ipk (see below). There are two scripts that extract information from these files: getversion and download.
# Root work area
#
ROOT="/home/blin"
export ROOT
PATH="$ROOT/bin:$PATH"
export PATH
#
# Source Tarball directory
#
SRC="$ROOT/source"
export SRC
#
# SVN Archive directory
# Used for locally developed applications
#
SVN="$ROOT/svn"
export SVN
#
# Build directory
# Used to compile programs
#
BUILD="$ROOT/build"
export BUILD
#
# Installation directory
# Used to install programs (full development tree)
#
INSTALL="$ROOT/install"
export INSTALL
#
# IPK directory
# Used to create distribution packages from installation
#
IPK="$ROOT/ipk"
export IPK
#
# Image directory
# Used to create distribution image from packages
#
IMAGE="$ROOT/image"
export IMAGE
#
# Aliases
#
alias cdp="cd $ROOT"
alias cdb="cd $BUILD"
getversion looks into the appropriate ipk control file, and extracts the version number of the requested application:
getversion file contents:
#!/bin/shdownload is used to download the requested file from its source, and store the resulting tar / bzip file in the sources directory.
if [ "$ROOT" == "" ]
then
echo "\$ROOT not set, did you source setpath?"
exit
fi
cd $ROOT/build
if [ "$1" == "" ]
then
echo "getversion application"
echo ""
echo "e.g. getversion glibc"
echo ""
exit
fi
if [ -f $ROOT/etc/ipk/$1 ]
then
VERS="`cat $ROOT/etc/ipk/$1 | grep Version | cut -d' ' -f2-`"
echo "$VERS"
else
echo "0.0.0.0.0.0.0"
fi
download file contents:
#!/bin/shIn order to unpack the downloaded bundles for compilation, I use an unpack script called, unpack!
DATE="`date +%y%m%d`"
if [ "$ROOT" == "" ]; then
echo "ROOT environment variable is not set."
echo "has setpath been sourced?"
exit
fi
if [ "`which wget`" == "" ]; then
echo "wget is required, please install."
exit
fi
cd "$ROOT/sources"
#
# Download via wget
#
if [ "$1"=="" ]; then
SOURCES="cat /etc/ipk/* | grep Source: | grep wget, | cut -d ',' -f2-`"
else
SOURCES="cat /etc/ipk/$1 | grep Source: | grep wget, | cut -d ',' -f2-`"
fi
for SOURCE in $SOURCES
do
FILE=`basename $SOURCE`
NAME="`echo $FILE | cut -d- -f1`"
if [ -f $FILE ]
then
echo "$NAME has already been downloaded, skipping."
else
echo "Downloading $NAME from $SOURCE."
mv -f "$NAME-*" old > /dev/null 2>&1
wget -nv "$SOURCE"
fi
done
#
# Download via git
#
if [ "$1"=="" ]; then
SOURCES="`cat ../etc/ipk/* | grep Source: | grep git, | cut -d',' -f2-`"
else
SOURCES="`cat ../etc/ipk/$1 | grep Source: | grep git, | cut -d',' -f2-`"
fi
for SOURCE in $SOURCES
do
NAME=`basename $SOURCE`
FILE="$NAME-$DATE.tar.bz2"
if [ -f $NAME-*.tar.bz2 ]
then
echo "$NAME has already been downloaded, skipping. (Manually remove $FILE to force download)"
else
echo "Downloading $NAME from $SOURCE."
cd ../tmp
rm -rf ../tmp/*
git clone $SOURCE > /dev/null
mv $NAME $NAME-$DATE
rm -rf $NAME-$DATE/.git
tar cf ../sources/$NAME-$DATE.tar $NAME-$DATE
rm -rf $NAME-$DATE
cd ../sources
bzip2 $NAME-$DATE.tar
fi
done
unpack file contents:
#!/bin/shetc/ipk Directory
if [ "$ROOT" == "" ]
then
echo "\$ROOT not set, did you source setpath?"
exit
fi
if [ "$ARCH" == "" ]
then
echo "\$ARCH not set, did you remember to set and export it?"
exit
fi
HOSTP="`cat $ROOT/etc/ipk/$1 | grep Depends | cut -d' ' -f2`"
if [ "$HOSTP" == "host-development-environment" ]
then
export ARCH="host"
fi
mkdir -p $ROOT/build/$ARCH
cd $ROOT/build/$ARCH
if [ "$1" == "" ]
then
echo "unpack application"
echo ""
echo "e.g. unpack glibc"
echo ""
exit
fi
if [ -f $ROOT/sources/$1-* ]
then
FILE="`ls $ROOT/sources/$1-* | head -1`"
EXT="`echo $FILE | awk -F . '{print $NF}'`"
DONE="0"
if [ "$EXT" == "tar" ]
then
echo "Unpacking $FILE"
tar xf $FILE
touch $1-*
DONE="1"
fi
if [ "$EXT" == "gz" ]
then
echo "Unpacking compressed $FILE"
tar xzf $FILE
touch $1-*
DONE="1"
fi
if [ "$EXT" == "bz2" ]
then
echo "Unpacking bz2 compressed $FILE"
bunzip2 -dc $FILE | tar xf -
touch $1-*
DONE="1"
fi
if [ "$DONE" == "0" ]
then
echo "Unknown file extension, or file not found for $0"
fi
else
echo "package $1 not found in $ROOT/sources"
echo "ensure that the ipk control file exists in $ROOT/etc/ipk"
echo "then run download"
exit
fi
The etc/ipk directory contains the control files for all of the applications to be downloaded and used in the image. The ipkg manager understands the concept of dependencies, and requires that specific packages are installed in order to use other packages. Each package has a control file, which contains this and more information. Control files are in the following format:
Package: packagenamePackages are downloaded and stored in files containing their package name and version number, e.g. packagename-version.number.tar.bz2. The word ARCHITECTURE is automatically replaced during compilation with the processor architecture of the release, e.g. i586. When they are built, they end up in an ipk file with a name such as busybox-1.16.0-i586.ipk.
Section: admin / base / comm / editors / extras / graphics / libs / misc / net / text / web / x11
Priority: required / optional / standard / important / extra
Version: version.number
Architecture: ARCHITECTURE / all
Maintainer: www.vizier.co.uk
Source: wget,url / git,url
Depends: dependencies,separated,by,commas
Description: Textual Description of the package
The source field is used by the download script to fetch the appropriate sourcecode and place it in the sources directory.
Depends is a list of the packages that must be installed for this package to work. The root package is named filesystem, onto which the linux kernel is installed. The main library glibc needs the kernel, and most applications need glibc. The hierarchy of dependencies is shown in the Packages section below.
There are also 4 scripts which may be used during installation / removal of a package - these are:
preinst [runs prior to install]
postinst [runs after files are installed]
prerm [runs prior to removal]
postrm [runs after files are removed]
These scripts may also exist in the etc/ipk directory, and be named packagename-preinst, packagename-postinst etc.makefiles Directory
Building packages is performed using makefiles. In order to place all of the customisation in a single place, it is all done in the apporpriate make file.
... add words on makefiles here ..
Packages
The packages are all identified in the etc/ipk directory, and have the following dependency hierarchy:
filesystemRather than show the contents of all of the packages here, they can be downloaded as part of the install tree from here.
linux
glibc
busybox
ipkg
brltty
Downloading
With the configuration files created, downloading is as simple as typing 'download', which runs the script from the bin directory.
Building Packages
Downloaded packages all need to be configured and compiled for the target architecture.
Creating the Filesystem
The target machine filesystem needs some basic directory structure, and some system device 'files' creating. This can all be done inside an ipk install script.
.. list the ipk install script here as it is interesting ..
Once the ipk install script has been created, it should be saved as a source tarball (remember that this one is created and cannot be downloaded, so be careful about removing everything in the sources directory).
.. create the filesystem tarball ..
.. create the filesystem ipk file ..
Building the Kernel
Building the linux kernel is probably one of the longest individual tasks that you will need to do - for me, the compilation took 25 minutes.
Building Glibc
Building Busybox
Installing Packages
Building Image
Creating CDROM
Making Bootable
Unpacking, Configuring and Building the Kernel (25 minutes )
For my first build, I've decided to build the kernel with its default configuration. I've downloaded the kernel source, and unpacked into source/linux-2.6.28.10 and compiled it:
# unpack* Note - need to install the kernel and header files in images, so that glibc can use them when it is being compiled.
cd sources
tar xzf ../0-tarballs/linux-2.6.28.10.tar.gz
# configure kernel
cd source/linux-*
make mrproper
make menuconfig
cp .config* ../kernel-config
# compile
make
make bzImage
make modules
rm -rf ../../images/kernel
mkdir ../../images/kernel ../../images/kernel/boot
make INSTALL_MOD_PATH=../../images/kernel INSTALL_PATH=../../images/kernel/boot modules_
install install
This installation created .... in ....
Unpacking and Building GLibC (15 minutes)
GLibC is configured and built in the images directory:
# unpackThis installation creates libc.a and libc.so in images/glibc, along with the header files.
cd sources
tar xzf ../tarballs/glibc-2.10.tar.gz
# build
mkdir ../root ../root/etc
cd ../images/glibc
../../source/glibc*/configure --prefix=`pwd`/../root CFLAGS="-march=i586 -O2"
make
echo > ../root/etc/ld.so.conf
make install
* Note need to install glibc and header files in images so that applications can use them when compiling.
Unpacking and Building the Bootloader
# cd bld/grub-1.96Unpacking and Building Busybox
# DST=`pwd`/../../dst
# ./configure --prefix=$DST CFLAGS="-march=i586 -O2"
# make
# make install
I've downloaded and unpacked busybox-1.13.2 into the bld/busybox-1.13.2 directory.
# unpackBusybox need libm.so.6, libc.so.6, linux-gate.so.1, ld-linux.do.2 - the above script need modifying to link against freshly compiled libraries.
cd source
tar xvf ../tarballs/busybox*.tar.bz2
cd busybox*
make defconfig
make
This installation creates 'busybox' in the source/busybox* directory.
Building and Installing Grub
cd source/grub-1.95
./configure --prefix=`pwd`/../../root
make
make install
Building an Image
# Directories here need to be sorted outThe Automated Makefile
cd distribution
rm -rf iso-boot
mkdir iso-boot
(cd kernel ; tar cf - . ) | ( cd iso-boot ; tar xf - )
(cd iso-boot/boot ; ln -s vm* vmlinuz)
genisoimage -o iso/boot.iso \
-b source/syslinux*/core/isolinux.bin -c source/syslinux*/core/boot.cat \
-no-emul-boot -boot-load-size 4 -boot-info-table \
images/iso-boot
Booting VirtualBox
Modifying the Image
Distributing the Image
Notes
Builds should be done with the correct architecture in mind, for example:
CFLAGS="-march=i586 -O2"The C Flag -march indicates that the architecture is for the Intel 586. This is particularly important when compiling low level code, such as parts of GLibC and Kernel Drivers, which use architecture-dependent assembler.
You can change the architecture, but you need to do it consistently.
No comments:
Post a Comment