User Tools

Site Tools


docs:guide-developer:build-system:start

The Build System

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:

  • a compiler, such as gcc
  • binary utilities such as an assembler and a linker; for example binutils
  • a C standard library, such as glibc, musl, uClibc or dietlibc

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.

Build System Directory Structure

There are four key directories in the build system:

  • tools
  • toolchain
  • target
  • package

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.

Build system – Features

  • Makes it easy to port software
  • Uses kconfig (Linux Kernel menuconfig) for configuration of features
  • Provides integrated cross-compiler toolchain (gcc, ld, …)
  • Provides abstraction for autotools (automake, autoconf), cmake, scons
  • Handles standard download, patch, configure, compile and packaging workflow
  • Provides a number of common fixups for badly behaving packages

Build system – Make Targets

  • Offers a number of high level make targets for standard package workflows
  • Targets always in the format “component/name/action”, e.g. “toolchain/gdb/compile” or “package/mtd/install”
  • Prepare a package source tree: package/foo/prepare
  • Compile a package: package/foo/compile
  • Clean a package: package/foo/clean

Build system – Build sequence

  1. tools – automake, autoconf, sed, cmake
  2. toolchain/binutils – as, ld, …
  3. toolchain/gcc – gcc, g++, cpp, …
  4. target/linux – kernel modules
  5. package – core and feed packages
  6. target/linux – kernel image
  7. target/linux/image – firmware image file generation

Patch management

  • Many packages will not work as-is and need patches to work on the target or to even compile
  • the build system integrates quilt for easy patch management
  • Turn package patches into quilt series: make package/foo/prepare QUILT=1
  • Update patches from modified series: make package/foo/update
  • Automatically rebase patches after an update: make package/foo/refresh

Packaging considerations

  • Main objective is small memory and size footprint
  • Features that make no sense on embedded systems are disabled through configure or patched out
  • Packages must be compilable regardless of the host system, they should be self contained
  • Shipped “configure” scripts are often faulty or unusable in a cross-compile setting, autoreconf or patching is often needed
  • Build variants and kconfig includes allow for configurable compile-time settings
  • There is no standard way for porting software, in many cases it “just works” but often the package build process needs tweaks

Documentation

History

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
docs/guide-developer/build-system/start.txt · Last modified: 2020/03/04 18:09 by adamkpickering