Building a GNU/Linux system from sources
Rolf Veen (Updated 4 Dec 2003)


The objective of this document is to describe the steps needed to build a GNU/Linux system from its sources, introducing at the same time some innovations:

The build process is based on two scripts and some OGDL descriptors. OGDL is a simple data language very appropiate for configuration files (see The two scripts are:

The method described here is oriented towards developers. Many aspects are not covered and it is purely experimental. For a pedagogic approach to building a GNU/Linux system see Linux From Scratch.

The basic steps


In this context, we call profile to a set of descriptors, scripts and patches needed to build a particular GNU/Linux system. The profile does not include the sources of the packages itself.

Each profile needs, as starting point, a Linux installation with development tools included, one that is able to compile the packages that make up the chroot environment. The exact prerequisites depend on the system we are going to build and is out of the scope of this document.

Additionally we need a directory filled with the original sources and patches, by default $SRC/in. In order to know what source packages are needed, each master build script has an option 'info' that lists them.


/src/inInput directory, where sources are to be found
/src/rootThe base environment (chroot)
/src/workWhere packages are unpacked and build
/src/profileThe profile.
/src/packagesPackage descriptors

Step 0. Prepare the host system

First unpack hlinuxutils somewhere and then do:

make check
make install

hlinuxutils provides the needed tools and also one example profile, based on LFS and BLFS (see again Linux From Scratch).

The build script

The build script first checks if all the needed source files are available in /src/in. If that is ok, it then executes the pre target found in the descriptor. Then it builds the packages in the order they appear in the descriptor, and finally executes the post target. While building packages, a summary file is generated that records starting and ending times and disk usage of each package.

Here is a fragment a build descriptor:

title 'Basic packages'
description \
  The packages in this set substitute the transition packages
  used to initially creating the chroot.

version 1.0

  pre \
    echo 'Setting environment'
    set +h
    export LC_ALL=POSIX
    export PATH=/bin:/tools/bin
    umask 022
  target build

  linux     ( version 2.4.23; target headers2; noclean )
  linux     ( version 2.4.23; target install; nounpack )

Here is a frament of a summary file:

    starttime 1068646332 s
    diskfree_before 464217 kB
    endtime 1068646595 s
    diskfree_after 399975 kB

Step 1. Build a controlled (chroot) environment

cd /src/profile
./build chroot

This will create a small Linux distribution suitable for chroot'ing to, and that has all its commands statically build or linked against the new glibc in order to serve as a neutral base on which to build packages. This environment provides isolation from the host system.

Step 2. Building the base system

cd /src/profile
./build base

Step 3. Building an additional package set

./build server

Building the kernel

src profile=default -p linux-2.4.22

This command builds a kernel using the 'default' configuration and places it in /pkg/linux/. The different pre-made configuration files should be located in /src/packages/linux/conf. The kernel is build with the 'make oldconfig' option.

Build a bootable or installable environment

./build cd

This command takes as input the chroot'ed environment with the packages built, and makes a layout suitable for a bootable CD. It also produces the final ISO image.

As an alternative, one can build a distribution that is bootable right from the same disk, without interfering with the original installation. This is ideal for testing purposes. The command to build it is different than the one that produces a CD ISO image:


If the distribution is build in the default location then a complete Linux hierarchy is available in /pkg-src/BOOT, and can be booted into by specifying an alternative init at the boot prompt:

boot: linux init="/pkg-src/BOOT/bin/init2"

Appendix A. Schemas

build descriptor

title- *
description- *
  * !sh
defaults target *
  * ( version *; target- *; ** )


    unit !enum ( s, kB )
  * !map
    starttime !int !unit
    endtime   !int !unit
    diskfree_before !int !unit
    diskfree_after !int !unit