The build system is a set of Makefiles and patches that automates the process of building a cross-compilation toolchain and then using it to build the Linux kernel, the root filesystem and possibly other pieces of software (such as uboot) required to run OpenWrt on a specific device. A typical toolchain consists of:
Usually a toolchain generates code for the same instruction set architecture (ISA) that it runs on (x86_64 in the case of most PCs and servers). However with OpenWrt this is not true. Most routers have processors that use a different architecture than the one we are using to run the build system. If we were to use our build system's toolchain to build OpenWrt for our router, it would generate code that would not work on our router. Nothing from the host system can be used. Everything, including the C standard library, the Linux kernel and all userspace programs, must be compiled with this cross-compilation toolchain.
Let's look at an example. We are building OpenWrt on an x86_64 system for a router that uses a MIPS32 architecture, so we can't use the same toolchain we use to generate programs we run on our x86_64 system. We need to first build a toolchain for the MIPS32 system, and then build all of the things that it needs to run OpenWrt using that toolchain.
The process of creating a cross compiler can be tricky. It's not something that's regularly attempted and so the there's a certain amount of mystery and black magic associated with it. When you're dealing with embedded devices you'll often be provided with a binary copy of a compiler and basic libraries rather than instructions for creating your own - it's a time saving step but at the same time often means you'll be using a rather dated set of tools. It's also common to be provided with a patched copy of the Linux kernel from the board or chip vendor, but this is also dated and it can be difficult to spot exactly what has been changed to make the kernel run on the embedded platform.
While it is possible to manually create your toolchain, and then build OpenWrt with it, this is difficult and error-prone. The OpenWrt build system takes a different approach to building a firmware: it downloads, patches and compiles everything from scratch, including the cross compiler. Or to put it in simpler terms, OpenWrt's build system doesn't contain any executables or even sources. It is an automated system for downloading the sources, patching them to work with the given platform and compiling them correctly for the platform. What this means is that just by changing the template, you can change any step in the process. And of course the side benefit of this is that builds are automated, which saves time and guarantees the same result every time.
For example if a new kernel is released, a simple change to one of the Makefiles will download the latest kernel, patch it to run on the requested platform and produce a new firmware image. There's no work to be done trying to track down an unmodified copy of the existing kernel to see what changes had been made - the patches are already provided and the process ends up almost completely transparent. This doesn't just apply to the kernel, but to anything included with OpenWrt - it's this strategy that allows OpenWrt to stay on the bleeding edge with the latest compilers, kernels and applications.
There are four key directories in the build system:
tools/ needs to be written about.
toolchain/ refers to the compiler, the c library, and common tools which will be used to build the firmware image. The result of this is two new directories, toolchain_build_<arch> which is a temporary directory used for building the toolchain for a specific architecture, and staging_dir_<arch> where the resulting toolchain is installed. You won't need to do anything with the toolchain directory unless you intend to add a new version of one of the components above.
target/ refers to the embedded platform, this contains items which are specific to a specific embedded platform. Of particular interest here is the “target/linux” directory which is broken down by platform and contains the kernel config and patches to the kernel for a particular platform. There's also the “target/image” directory which describes how to package a firmware for a specific platform.
package/ is for exactly that – packages. In an OpenWrt firmware, almost everything is an ipk, a software package which can be added to the firmware to provide new features or removed to save space.
Both the target and package steps will use the directory “build_<arch>” as a temporary directory for compiling. Additionally, anything downloaded by the toolchain, target or package steps will be placed in the “dl” directory.
tools– automake, autoconf, sed, cmake
toolchain/binutils– as, ld, …
toolchain/gcc– gcc, g++, cpp, …
target/linux– kernel modules
package– core and feed packages
target/linux– kernel image
target/linux/image– firmware image file generation