In embedded Linux development, building a system from source and getting it to run on hardware is one of the most exciting moments. This article will guide you step by step through this process, targeting the Raspberry Pi as the hardware platform and using the Buildroot toolchain to create a highly customized Linux system image. This is not just a technical share, but a practical tutorial that allows you to truly experience the joy of embedded development. Whether you are using a physical Raspberry Pi or a virtual machine, you can follow this article to get the system up and running!
Preparation: Development Environment and Hardware
Before getting started, make sure you have the following ready:
- Development Host: You need a host running Linux, preferably Ubuntu, which is simple and user-friendly. If you don’t have a Linux environment, you can use a virtual machine instead, but ensure that the virtual machine is allocated enough resources (at least 15GB of disk space and a multi-core CPU). While virtual machines are convenient, the compilation speed may be slower, so be prepared for that.
- Hardware (Optional): If you choose to use a Raspberry Pi (such as Zero W or Zero), you will need an SD card and an FT2232 serial adapter to connect to the serial console. If you don’t want to buy hardware, the virtual machine can also complete the experiment, and I will provide guidance for both options in the article.
- Time: The entire process will take 2-4 hours, including compilation and debugging. Embedded development is a slow and meticulous process, so take your time to learn and play.
- Basic Linux Knowledge: Familiarity with basic shell operations, such as
<span>cd</span>and<span>ls</span>. You don’t need to be a Linux expert for embedded development, but knowing how to use the terminal is essential. - Disk Space: At least 15GB of free space. Although the final product of the entire system image is small, the intermediate process will occupy a considerable amount of space.
With these preparations, let’s get started!
Buildroot: A Powerful Assistant for Embedded Development
Buildroot is a toolchain specifically designed for embedded systems, powerful yet easy to use. It automates the entire process from downloading source code to generating system images, allowing us to focus on more interesting customization work. Compared to other complex build tools, Buildroot’s philosophy is small and beautiful, generating streamlined and efficient images.

Next, we will build a Linux system image for the Raspberry Pi using Buildroot through a few simple steps, and the entire process only requires six commands.

Six Steps to Build a System Image
1. Install Host Tools
First, you need to install some tools that Buildroot depends on, including Git, compilers, and some auxiliary tools. These tools are essential for starting the Buildroot compilation.
On Ubuntu, run the following command:
sudo apt install -y git build-essential wget cpio unzip rsync bc libncurses5-dev screen
This command will install Git (for downloading Buildroot source code), the compiler (for building the cross-compilation toolchain), and <span>screen</span> (for serial debugging). If you are using other Linux distributions, the command may vary slightly; for example, CentOS uses <span>yum</span> or <span>dnf</span>, but the core toolset remains consistent. If you encounter issues, it is recommended to refer to the dependency list on the Buildroot official website.
2. Download Buildroot Source Code
Buildroot provides several ways to obtain the source code, but the most convenient method is to clone it via Git:
git clone git://git.buildroot.net/buildroot
cd buildroot
This will download the Buildroot source repository to your local machine. After entering the <span>buildroot</span> directory, we need to switch to a specific version, here we use 2019.11.1 (the latest stable version as of January 2020):
git checkout 2019.11.1
Git may prompt you that you are in a detached HEAD state; don’t worry, this is normal, indicating that we are using a specific version tag rather than a branch.
3. Configure Buildroot
Buildroot provides preset configuration files (defconfig) for different hardware, and we need to select the appropriate configuration based on the target hardware. For the Raspberry Pi Zero W, run:
make raspberrypi0w_defconfig
If you are using a Raspberry Pi Zero or a virtual machine, use the following commands respectively:
- Raspberry Pi Zero:
<span>make raspberrypi0_defconfig</span> - Virtual Machine:
<span>make qemu_x86_64_defconfig</span>
These configuration files are located in the <span>configs/</span> directory and define the default settings for the target hardware, such as kernel version, filesystem type, etc. After running <span>make xxx_defconfig</span>, Buildroot will generate a <span>.config</span> file that records all configuration options. If you need to adjust the configuration later, you can use <span>make menuconfig</span> to open a graphical configuration interface, similar to the Linux kernel configuration method.
4. Compile the System Image
Everything is ready, just need to compile! Run the following command to start the build:
make
This step will download the source code, build the cross-compilation toolchain, compile the kernel and root filesystem, and finally generate the SD card image (or virtual machine image). The entire process may take 2-3 hours, depending on your computer’s performance. During compilation, you need to be online because Buildroot will download various software package sources from the internet.
How Buildroot Works
While the compilation is in progress, let’s discuss how Buildroot transforms a bunch of source code into a runnable system image. Understanding this process will help you better customize the system.
Overview of the Compilation Process
The core work of Buildroot can be divided into the following stages:
- Build Toolchain: This includes cross-compilers, linkers, etc., used to compile software for the target system.
- Download Source Code: Obtain the source code for the kernel, libraries, and applications from the internet.
- Compile and Install: According to the configuration, extract the source code, apply patches, compile, and install it into the target root filesystem directory (
<span>output/target/</span>). - Add Configuration Files: Copy device-specific configuration files into the root filesystem.
- Generate Image: Package the root filesystem into the final firmware image, such as an SD card image.
These steps may seem complex, but Buildroot automates the process through scripts, allowing us to focus on configuration and customization.
Key Directory Analysis
There are several core directories in the Buildroot source tree:
- **board/**: Contains specific support files and scripts for the target hardware.
- **configs/**: Stores preset configuration files, such as
<span>raspberrypi0w_defconfig</span>. - **package/**: Defines the compilation rules for all software packages; Buildroot 2019.11 includes 2289 software packages, ranging from Nginx to game engines.
- **output/host/**: Tools running on the host, such as cross-compilers.
- **output/target/**: Contents of the target system’s root filesystem.
- **output/images/**: The final generated image files, such as SD card images.
Packages and Configuration
The concept of packages in Buildroot is central; each package defines how to download, compile, and install a specific software (such as BusyBox or the Linux kernel). The configuration options for packages are written in Kconfig language in the <span>Config.in</span> file, controlling whether to compile the package and which features to enable.
Through <span>make menuconfig</span>, you can adjust these configurations, such as adding a web server or disabling unnecessary kernel modules. The configuration file is ultimately saved in <span>.config</span>, and the <span>make</span> command will calculate dependencies based on this file, automatically compiling all packages in the correct order.
Booting the System: Powering Up the Raspberry Pi
After compilation is complete, an SD card image (<span>sdcard.img</span>) will be generated in the <span>output/images/</span> directory, typically only a few dozen MB in size, making it very compact. Next, we will write this image to the SD card and boot the Raspberry Pi. If using a virtual machine, the steps will be simpler.
Writing the SD Card (Raspberry Pi)
-
Confirm the SD Card Device Name: Insert the SD card and use
<span>dmesg -w</span>to view the kernel log and find a device name like<span>/dev/mmcblk0</span>. Note that the device name may vary depending on the system, such as it could be<span>/dev/sdX</span>. Be sure to confirm this to avoid accidentally overwriting the host hard drive! -
Write the Image:
sudo dd if=output/images/sdcard.img of=/dev/mmcblkX bs=1M status=progress
sync
<span>dd</span> command will write the image to the SD card, and <span>sync</span> ensures that the data is completely written. Once completed, safely eject the SD card and insert it into the Raspberry Pi.
Connecting Serial (Raspberry Pi)
The Raspberry Pi’s serial communication requires an FT2232 adapter. The connection is as follows:
- Raspberry Pi GPIO’s TXD (transmit) connects to FT2232’s RXD (receive).
- Raspberry Pi GPIO’s RXD (receive) connects to FT2232’s TXD (transmit).
- Connect the GND (ground) of both.
After connecting, insert the FT2232 into the host and use <span>dmesg -w</span> to check the serial device name, which is usually <span>/dev/ttyUSB0</span> or <span>/dev/ttyUSB1</span>.
Start the serial terminal:
sudo screen -fn /dev/ttyUSBX 115200
This will open the serial console at a baud rate of 115200. To exit <span>screen</span>, press <span>Ctrl+a</span> and then type <span>\</span>.
Starting the Virtual Machine (Virtual Machine)
If using a virtual machine, run the following command to start the QEMU emulator:
output/host/bin/qemu-system-x86_64 -M pc -kernel output/images/bzImage -drive file=output/images/rootfs.ext2,if=virtio,format=raw -append "rootwait root=/dev/vda" -net nic,model=virtio -net user
The virtual machine starts quickly, usually showing the login prompt in a few seconds.
Logging into the System
Whether on the Raspberry Pi or the virtual machine, after booting, you will see output similar to the following in the serial terminal or virtual machine window:
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.19.66 ...
...
Welcome to Buildroot!
buildroot login:
Enter the username root (no password) to log in. Try <span>ls /usr/bin</span> to see what command-line tools are available in the system. If you successfully log in, congratulations! You have built and booted an embedded Linux system from source!
