Freetz Build Process⚓︎
Foreword and Motivation⚓︎
The how-tos contain important information about what make targets such
as menuconfig, toolchain, precompiled, recover, and others do
when building Freetz firmware. Nevertheless, the forum regularly sees
many questions about the build process, usually when the process does not
complete and the user does not know why. The reason is usually that the
user is unfamiliar with
GNU make
because, firstly, they are not a C/C++ programmer and/or, secondly, the
Linux command line itself is already a sealed book to them. At least the
first point also applies to me, so I read up superficially in order to
understand the Freetz Makefile better, or at all. I document the
result of my work here.
The problems of those seeking help in the forum do not end with the build
sometimes getting stuck. Since many questions sound "stupid" from the
experts' point of view and are repeated often, not everyone is skilled at
using the forum search or Google and some are simply lazy, the questions
become annoying to some professionals. The answers are then correspondingly
short, which in turn leads to follow-up questions and more clutter in the
forum. When the person seeking help has then fixed the cause of the
problem, by installing a Linux package, selecting or deselecting the right
option in make menuconfig, or installing a patch, they often still
cannot get the build running again because dependencies are not maintained
perfectly and they would first need to call xy-clean and/or
xy-precompiled, but nobody told them because it is also hard to predict.
The dream of a perfect Makefile that, after every file change, does
exactly the minimum necessary to build the current target is theoretically
achievable, but not realized here. It must be said, however, that the
Freetz make process is already relatively good, just not foolproof. That
was probably not the goal either, because a "fool" should not want to
build firmware for their DSL router. On the other hand, it is good for
our community if the learning curve for new members is made a little more
pleasant. It makes no sense for everyone to reinvent the wheel and work
everything out for themselves just because others had to do so earlier.
Basics⚓︎
This documentation is based on Freetz 1.1.4. Since newer Freetz
versions now exist, differences are noted in a few places.
What Does make Do?⚓︎
That would really exceed the scope here, so just a few links. Reading up
is worthwhile; education is never wasted:
- Wikipedia article about Make
- An introduction to
Makefiles
(German, short and concise, easy to understand) - Recursive Make Considered
Harmful
(very exciting for advanced users and philosophers, PDF download) - Wikipedia article about
Autoconf
(not used by Freetz itself, but by various packages)
What Does Freetz Consist Of?⚓︎
The modified firmware is assembled from several components:
- Original firmware, consisting of Linux kernel and filesystem. It
forms the basis and framework for the mod. Many beginners mistakenly
assume that the original firmware is discarded and completely replaced
by something self-built. That is not the case. Many important parts
are taken over as they are and extended with new functions, or
individual parts are specifically replaced. Important components of the
original firmware are:- Kernel (formerly 2.4, currently 2.6). For Daniel's mod, a 2.4
kernel could be reused; for Freetz, it must be replaced by a
self-built 2.6 kernel. If original firmware with a 2.6 kernel is
used as the basis, that kernel can be reused or optionally
replaced as well. - Filesystem with standard UNIX tools and AVM-specific tools,
such as the web interface. It is taken over almost unchanged with
one important exception; see the next point. - Busybox: collection of the most important command-line tools,
optimized for embedded systems and contained in a single
executable file. The individual tools are implemented through
symbolic links to
Busybox
under seemingly independent names.
- Kernel (formerly 2.4, currently 2.6). For Daniel's mod, a 2.4
After unpacking the corresponding archive, for example
freetz-1.1.4.tar.bz2, Freetz itself looks like the following list,
sorted alphabetically, not by importance. The subdirectories build,
packages, and source are created only during the first make run.
- Root directory: contains several configuration files, more on that
later, as well as changelog, firmwares, and readme. There are also
various subdirectories:- addon: static and theoretically dynamic packages, already
compiled, are unpacked here if they should be included in the
firmware filesystem and go beyond the standard mod's delivery
scope. - build: the original firmware image is unpacked into
build/original. The three individual components are then in the
subdirectories kernel (Linux kernel), filesystem (root
filesystem), and firmware (tools contained at the top level of
the firmware image and required for its installation). As already
mentioned, these components are woven together with generated
components such as kernel, Busybox, packages, and others, and
stored in the parallel directory structure build/modified. From
there they are then taken to finally pack the firmware image with
tar. - busybox: storage location of the newly built Busybox for the
mod. Starting with Freetz 1.2 it is found under
packages/target-mips(el)_uClbic-$(uClibc-Version)/busybox. - dl: downloads of source and binary packages for toolchain
and mod. With a few exceptions, package web interfaces are
contained directly in the mod; other files are downloaded from the
internet during the build using wget. - favicon: currently contains two small sets of favicons that
can be selected viamake menuconfigto give the Freetz web
interface nice small browser icons, displayed in the address bar
and bookmarks. - howtos: a few short German and English guides for building
the mod or custom extensions. - kernel: storage location of the newly built Linux kernel and
its modules for the mod. - make: for each package, this contains the include files and
configuration data for the largeMakefilein the root directory,
as well as startup scripts, CGI files, and other files belonging
to the package. The configuration data also contains the version
numbers of packages downloaded into dl. - packages: built packages are stored here. In one
subdirectory per package, as undermake, the corresponding
binary and configuration data are located and woven into the
filesystem, visible underbuild/modified; compare the previous
point. Starting with Freetz 1.2, an additional directory level is
added underpackages/, separating by big or little endian and
uClibc version. - patches: patches that are applied to the sources after
unpacking, depending on which hardware and/or configuration
setting is used. - root: image of the future firmware root filesystem. Web
pages, startup scripts, configuration data, and so on are located
here. During firmware building, they are woven together with the
original data and additional generated files such as kernel and
Busybox into a complete image.- Freetz 1.2: the directory was moved to
make/mod/files/root
for unification.
- Freetz 1.2: the directory was moved to
- source: all source texts for toolchain, AVM GPL package,
tools, packages, Busybox, and kernel are unpacked here so the
corresponding build processes can run over them afterwards.- Freetz 1.2: to achieve better separation and avoid unnecessary
make dircleans, the sources are split as follows:- host-tools: tools for the host are built here, such
as busybox, mksquashfs, fakeroot, and so on. - kernel: kernel sources.
- target-mips(el)_uClibc-$(uClibc-Version): selected
packages are unpacked and built here. - toolchain-mips(el)_gcc-\((GCC-Version)_uClibc-\)(uClibc-Version):
toolchain sources and build. Depending on menuconfig
selection, contains binutils, ccache, gcc, gdb, uClibc,
and libtool.
- host-tools: tools for the host are built here, such
- Freetz 1.2: to achieve better separation and avoid unnecessary
- toolchain: after unpacking the mod, the Makefile includes
for building the toolchains are located here. A toolchain in
general is a collection of tools required to build software, such
as compilers and linkers. In our case, there are two separate
toolchains: one for building the kernel (gcc-3.4.6) and one for
the remaining targets (gcc-4.2.1-uClibc-0.9.28/0.9.29). The
toolchains are then built into corresponding subdirectories.
Building the toolchains is optional because precompiled versions
are available for download. Depending on host speed, building the
toolchain can take 20 to 60 minutes.- Freetz 1.2: the GCC versions were updated to current versions
at the time, gcc-4.4.6, gcc-4.5.3, and gcc-4.6.0.
- Freetz 1.2: the GCC versions were updated to current versions
- tools: additional tools and their
Makefileincludes are
located here, required for building firmware images or for
make recover. The tools are used, for example, to unpack the
original firmwares, SquashFS filesystem, and to repack the later
mod images after all components have been woven in. An older tar
version (15.1), which creates firmware archives compatible with
the unpackers contained in the original firmwares, is included
among other helpers.- Freetz 1.2: the tar package is no longer built as a tool.
Depending on the task, host tar or busybox tar is used.
- Freetz 1.2: the tar package is no longer built as a tool.
- addon: static and theoretically dynamic packages, already
Build Process Flow⚓︎
It should be generally known that the three most important make targets,
to be called in this order, are:
make menuconfig- interactively assemble packages, select
additional libraries, save configuration.make- build tools, build toolchains unless an external compiler was
selected, then build libraries, Linux kernel, and packages, and
finally build firmware.
In addition, there is a considerable number of other make targets, some
of which are not directly visible in the Makefile but are generated by
automated substitution processes. This has the advantage that, for
example, each package has the same sub-targets, so a make call can
always directly affect individual packages, for example clean up or build
again. If make precompiled, for example, got stuck in package mc
because a Linux package required for building was missing in the
distribution and first had to be installed with the package manager, a
new call to the global precompiled target may still not complete because
there are inconsistencies in the package build. A sequence such as
make <package>-clean, make <package>-precompiled, for example
mc-clean and mc-precompiled, usually helps. Package names can be seen
from the names of the subdirectories in the make directory.
Include Chain⚓︎
In general, there are two ways to use make for hierarchically structured
builds. The traditional one uses a Makefile in the main directory and
another Makefile in each subdirectory. That this is not a good idea is
convincingly explained in
Recursive Make Considered
Harmful
. The good news is that Freetz uses the second method: include files in
the subdirectories. That means the Makefile dynamically loads the
includes required for the current target and thus creates a single large
virtual Makefile, which is then processed. This is nice, but it means
that in the Makefile we see things being called and processed whose
origin is not quite so easy to determine unless the directory structure is
examined in detail. I try to make this a little more transparent here.
- First, the
Makefileincludes the configuration file.configin the
main directory. It contains the options set inmake menuconfigfor
assembling the firmware image. This already makes clear why
make menuconfigshould always be called first. Incidentally, the
file does not exist immediately after unpacking the mod archive. There
is an exception to the include: if only targets from the group
menuconfig, config, oldconfig, defconfig, tools are to be built, no
include happens here because those targets do not need it. - A little later,
tools/make/Makefile.inandtools/make/*.mkare
included, causing the individual tool targets, such as
find-squashfs, lzma, squashfs, tichksum, makedevs, fakeroot, to be
added to the variable TOOLS. Afterwards, a list of sub-targets is
generated for each tool target:: builds the tool. -source : unpacks the source files so the tool can be
built afterwards.-clean : calls the tool's ownMakefilein the tool
subdirectory withmake clean. The clean target usually deletes
all generated files and directories so a clean rebuild is possible.-dirclean : deletes the entire tool subdirectory. This
is useful when unpacking a newer version and wanting to remove the
old one completely first.-distclean : deletes the distribution directory inside
the tool subdirectory, where the built files lie ready for
installation.
- Now
.config.cmdis processed. This recursively reads configuration
switches of various packages that are later available to the build. - Now things really get going: including
make/pkgs/Makefile.in,
make/pkgs/*/Makefile.in,make/toolchain/Makefile.in, and the
corresponding *.mk files adds even more information to the
virtualMakefile. Afterwards, analogously to the tools above, the
following targets are available, divided into the groups TARGETS,
PACKAGES, LIBS, TOOLCHAIN:-precompiled : builds a target that does not belong
to a package, the library target group, or the toolchain. Examples
include the Linux kernel, the CGI mod (Freetz web interface),
Busybox, the CGI tool Haserl (currently not a package), iptables,
and the AVM GPL sources.- Freetz 1.2: only the kernel and Busybox count as targets.
-source : unpacks the source files so the target can
be built afterwards.-clean : calls the target's ownMakefilein the
target subdirectory withmake clean. The clean target usually
deletes all generated files and directories so a clean rebuild is
possible.-dirclean : deletes the entire target subdirectory;
useful when unpacking a newer version and removing the old one
completely first.-precompiled : builds a package.-source : unpacks the source files so the package
can be built afterwards.-clean : calls the package's ownMakefilein the
package subdirectory withmake clean. The clean target usually
deletes all generated files and directories so a clean rebuild is
possible.-dirclean : deletes the entire package
subdirectory; useful when unpacking a newer version and removing
the old one completely first.-list : adds the package either to the list of
static or dynamic packages.-precompiled : builds a library, for example ncurses,
libgcrypt, or OpenSSL.-source : unpacks the source files so the library can be
built afterwards.-clean : calls the library's ownMakefilein the
library subdirectory withmake clean. The clean target usually
deletes all generated files and directories so a clean rebuild is
possible.-dirclean : deletes the entire library subdirectory;
useful when unpacking a newer version and removing the old one
completely first.: builds the toolchains, kernel and target
toolchain.-source : unpacks the source files so the
toolchain can be built afterwards.-clean : calls the toolchain's ownMakefilein
the toolchain subdirectory withmake clean. The clean target
usually deletes all generated files and directories so a clean
rebuild is possible.-dirclean : deletes the entire toolchain
subdirectory; useful when unpacking a newer version and removing
the old one completely first.-distclean : deletes the distribution directory in
the toolchain subdirectory.
- In the previous step, two more targets were added, making it possible
to customize two central parts of the firmware even more
individually:- kernel-menuconfig: the Linux kernel also has a nice
configuration interface where many things can be set. Personally,
I do not recommend changing anything here unless you really know
what you are doing. It becomes very difficult to find help in the
forum if your kernel is configured differently from everyone
else's. - busybox-menuconfig: Busybox can also be extended with
features in various places at the cost of size. Owners of 8 MB
boxes, such as the 7170, usually still have enough space to add a
feature or two here. I recommend not omitting anything included by
default, so comparability in forum discussions remains. It is no
use disabling the Gunzip feature in Tar and then asking in the
forum why a Gzip archive could not be unpacked. On the other
hand, enabling Bunzip2 additionally is not very disturbing,
because it is only an add-on without side effects, as far as human
judgment can tell.
- kernel-menuconfig: the Linux kernel also has a nice
Other Make Targets⚓︎
Further targets are contained directly in the top-level Makefile, so
they are not included from elsewhere.
- Some of them are helper targets, rarely called manually because
they are mainly intended for use by higher-level targets. Examples are
config, oldconfig, defconfig. - There is also the utility target recover, with which a broken
box can be revived; details would exceed the scope of this article. - There are also aggregate targets such as sources, precompiled,
libs, packages-precompiled, which call a whole group of similarly
named or purpose-related sub-targets. - If you only want to assemble firmware and all necessary preliminary
work for it, such as building toolchains andmake precompiled, has
already been done, you can use the target firmware. It builds
the tools if needed, not to be confused with toolchains, and then gets
to work. At the end you have a firmware image in theimages
directory named *.image. This target is called implicitly when you
simply callmake, thus building the default target. Incidentally, the
scriptfwmodin the root directory does all the work of firmware
building. It is certainly interesting to look at this script in detail
if you want to know what happens there.
So, I hope this article helps one or another modder. Discussions,
feedback, and corrections are welcome as always and can be added in the
related
Forums-Thread
.
Alexander Kriegisch
(kriegaex)\
Revised by Oliver Metz