Building Embedded Linux with Yocto and Buildroot

Scan and follow to learn embedded systems together, learn and grow together.
Doing Linux system development primarily revolves around the root file system, as uboot and kernel are generally provided by the manufacturer, and drivers for peripherals are also provided officially, so the actual development work is minimal.

The most challenging aspect of building the root file system is ensuring version compatibility and completeness. This is because the root file system involves many requirements, libraries, source files, etc., and there are version requirements, making it not easy.

The most troublesome libraries when constructing the root file system include the OpenGL library, Java library, Qt library, TSLib library, OpenVG library, Python library, SQLite, etc. Below, we will introduce several different construction methods, explaining the materials and tools, process, and output.

Yocto is a common tool for building root file systems, and it can also build uboot and kernel, but most people only need the root file system. Many SOC manufacturers, such as NXP, have joined the Yocto project to produce Yocto versions of SDKs. This is not necessarily a good thing, as SOC users prefer each chip to have a separate SDK provided for configuration and compilation.

The materials and tools required for Yocto construction need a computer with high memory, frequency, and hard disk, as well as an Ubuntu environment and repo, git environment, and a Yocto package provided by the SOC manufacturer.

The process involves downloading, configuring the build, and compiling. The entire compilation can take several hours and is also related to the computer's performance. The output includes a cross-compilation toolchain, binary uboot and kernel, and most importantly, the root file system that contains various required libraries.

Buildroot is also a common method for SDKs provided by SOC manufacturers, such as Rockchip and STM32MP. The configuration and compilation of Buildroot are relatively simple, and the process is not complicated; it resembles the configuration and compilation process of the kernel, and the compilation speed is relatively fast. After obtaining the SDK from the manufacturer, compiling it is not difficult.

Busybox is only used for building the root file system, but it only includes some basic components like shell, telnet, etc. The compilation process is similar to compiling the kernel, starting with 'make menuconfig', followed by configuration and final compilation.

When building the root file system, I believe it is better to have more than less. Many people think that flash resources are limited and not suitable for including so many libraries. However, since you have chosen to use Linux, do not approach it with the mindset of an MCU. If resources are genuinely constrained, you should use RTOS instead of considering Linux. Because if one or two libraries are missing, the application cannot run, and rebuilding the root file system is very painful.

Additionally, porting Android is not as difficult as many imagine. Generally, SOCs capable of running Android will have an official public SDK released. The difficulty of Android lies in deep customization and application development, while the porting itself is less challenging than Linux.

Comparison of Buildroot and Yocto

Comparison content:
(1) Embedded construction system
    The goal is to build a complete, customized embedded Linux system
    Including root filesystem, toolchain, kernel, bootloader
(2) Starting from source code
(3) Using cross-compilation toolchain
(4) Very active maintenance and development engineering
(5) Widely used in the industry
(6) Documentation and training courses available
(7) Free software

Buildroot's general principles:
(1) Focus on simplification
(2) Easy to use, easy to understand, easy to extend
(3) Handle special cases through extension scripts rather than modifying Buildroot itself
(4) Use existing technologies/languages: kconfig, make (worth investing time to learn)
(5) Defaults to small
(6) Purpose-agnostic
(7) Open community, no vendor or bureaucratic/company management

Yocto's general principles:
(1) Supports major CPU architectures
    OpenEmbedded: only qemu
    Yocto Project: adds support for a small number of machines
(2) Only provides core methods, uses layers to support more packages and machines
(3) Customer modifications should be in a separate layer
(4) Multi-purpose build system: flexibly handles more use cases
(5) Open community, but the project is overseen by the Yocto Project Advisory Board initiated by company sponsors
(6) OpenEmbedded is a community-driven independent project.

Buildroot output:
(1) Mainly root filesystem images
    Also includes: toolchain, kernel image, bootloader, etc.
(2) Supports multiple formats: ext2/3/4, ubifs, iso9600, etc.
(3) No binary packages, no package management system
    Some call it a firmware generator
    Updating through packages is not possible
    Updates require a complete system update, similar to Android
    Partial updates are considered harmful

Yocto output:
(1) Builds distributions, with the main output being a package feed
    Package management system is optional
    Loading and updating parts of the system is possible
(2) By installing some packages, it can also produce root filesystem images. Supports ext2/3/4, ubifs, iso9600, and also supports VM images: vmdk, vdi, qcow2
(3) Ultimately, image classes or tools, wic can be used to build disk images
(4) When generating images, SDKs can also be generated, allowing application developers to compile and test their applications (without integrating into the build). However, the SDK must match the image.

Buildroot configuration:
(1) Uses kconfig like the Linux kernel
(2) Simple {menu, x, n, g} configuration interface
(3) Entire configuration is saved in a file .config/defconfig
(4) Defines various aspects of the system: architecture, kernel version/kernel configuration, bootloader, user space packages, etc.
(5) make menuconfig, make
(6) Builds a common system for different machines: handled separately
    A tool can build defconfig from fragments
    Feasible, but not super simple
    Each machine builds completely independently

Yocto configuration:
(1) Configuration is divided into several parts:
    Distribution configuration (package configuration, toolchain and libc selection...)
    Machine Configuration (defines architecture, CPU features, BSP)
    Image recipe (target installs what packages)
    Local configuration (Distribution and default machine selection, how many threads to use during compilation, whether to delete build artifacts)
(2) It is necessary to collect the layers to be used and declare them.
(3) Allows building the same image for different machines or different distributions or images for the same machine.

Buildroot layers:
(1) No concept of layers
(2) All packages are maintained in the official repository
(3) Adding BR2_EXTERNAL
    Allows storage of package definitions, configurations, and other manual files
    A BR2_EXTERNAL
    Typically used for proprietary/customized packages and configurations
    Only adds packages, does not override packages in buildroot

Yocto layers:
(1) Layer mechanism allows modification and addition of new packages or images
(2) Clear separation between core build system, BSP, and custom modifications
(3) Third parties provide layers for their BSPs or a set of methods to handle specialized applications
(4) Layers need to be compatible and use the same OE branch base
(5) Beware of layer quality, checking is not systematic
(6) OpenEmbedded Metadata Index lists available layers, recipes, machines: http://layers.openembedded.org/layerindex/
(7) Additionally, there is a powerful override mechanism that can adjust recipe variables based on the machine or distribution

Buildroot/Yocto toolchain
Same functions:
(1) Build your own toolchain based on gcc, C libraries (glibc, uClibc, musl)
(2) Use external toolchains; for buildroot, this is easier as it has this feature built-in. For Yocto, it is only fully supported in additional vendor layers.

Buildroot new package
Involves three files: Config.in, xxx.mk, xxx.hash

Yocto new package
Involves one file: xxx.bb

Buildroot: complexity
(1) Designed for simple use
(2) For core, each suggested feature is analyzed for its usefulness/complexity ratio
(3) Core logic is entirely written in make, with less than 1000 lines of code containing 230 lines of comments: indeed easy to understand what, why, how; almost as simple as a shell script downloading, extracting, building, and installing software one after another.
(4) Documentation is ample, with many resources available
(5) An hour's talk is enough to describe all internal implementations (ELCE 2014)
(6) Typical feedback on IRC: very surprised by Yocto, it is so easy to use. This is the first thing that puzzled me.

Yocto Project: complexity
(1) Has a somewhat steep learning curve
(2) The core is bitbake, a separate project written in python (60,000 lines of code)
(3) A set of class definitions for common tasks
(4) Recipes use a bitbake specific language, mixing python and shell
(5) Logs and debugging help understand what each task does
(6) Detailed documentation, but many different configuration variables
(7) Not always easy to understand best practices (e.g., Poky cannot be used for production, distro/image modifications cannot be done in local.conf, delete tmp/)
(8) People still find some terms confusing (Yocto Project, Poky, OpenEmbedded, bitbake)

Buildroot packages:
(1) 1800+ packages
(2) Graphics: X.org, Wayland, Qt4/Qt5, Gtk2/Gtk3, EFL
(3) Multimedia: Gstreamer 0.10/1.x, ffmpeg, Kodi, OpenGL
(4) Languages: Python2/3, PHP, Lua, Perl, Erlang, Mono, Ruby, Node.js
(5) Networking: Apache, Samba, Dovecot, Exim, CUPS, lots of servers/tools
(6) Init systems: Busybox (default), initsysv, systemd
(7) No support for a toolchain on the target

Yocto Project packages:
(1) Thousands of recipes: for oe-core, meta-openembedded, meta-qt5 about 2200. More than 8400 known through Metadata Index
(2) Most are similar to buildroot
(3) More languages: Java, Go, Rust, Smalltalk
(4) There is still a functioning layer for Qt3
(5) meta-virtualization (Docker, KVM, LXC, Xen) and meta-openstack layers

Buildroot dependency method:
(1) Minimal dependencies, if a feature can be turned off, it is off by default
(2) Many automatic dependencies; for example, if you enable OpenSSL, it will automatically gain SSL support from other enabled packages that can provide SSL support
(3) Default to effortlessly obtaining a small root file system

Yocto Project dependency method:
(1) Package configuration at the distribution level
    Enabling OpenSSL will enable it for all packages, but can disable it for some packages; conversely, can enable some features for selected packages.
(2) Can be modified at the machine level, but should avoid doing so
(3) Each recipe can define its own default feature set, a robust default configuration.

Buildroot updates/security:
(1) Releases every three months, two months of development, one month of stability
(2) Releases include package version updates: security updates and major updates
(3) Core architecture may also potentially change
(4) No LTS version, requires handling on your own
(5) Providing a script to assess unresolved CVEs (Common Vulnerabilities & Exposures) in a given buildroot configuration

Yocto Project updates/security:
(1) Releases every six months, once in April, once in October
(2) Planning and roadmap can be found through wiki: https://wiki.yoctoproject.org/wiki/Yocto_Project_v2.1_Status
(3) Contains four milestones within three months between M1 and final release
(4) At least previous and current release versions have designated maintainers who obtain security and important fixes, but no recipe updates
(5) Old versions are maintained by the community

Buildroot detects configuration changes:
(1) Buildroot is not very intelligent
(2) When modifying configurations, it does not attempt to detect what needs to be rebuilt
(3) Once a package is built, buildroot will not rebuild it unless forced
(4) Major configuration changes require a full rebuild
(5) Minor configuration changes may not require a full rebuild
(6) One configuration, one build, cannot share configurations between builds

Yocto Project detects configuration changes:
(1) bitbake maintains a shared State Cache allowing incremental builds
(2) It detects input modifications for tasks by creating checksums of inputs
(3) The cache can be shared across all builds, making builds faster for similar machines
(4) The cache can be shared across hosts, such as a nightly server and a development machine, significantly speeding up full builds

Buildroot: architecture support:
(1) Supports many architectures
(2) ARM (64), MIPS, PowerPC (64), x86/x86-64
(3) Also supports many more specialized architectures: Xtensa, Blackfin, ARC, m68k, SPARC, Microblaze, NIOSII; ARM noMMU, especially ARMv7-M
(4) Architecture vendors provide assistance: MIPS from Imagination Technologies, PowerPC64 from IBM, ARC from Synopsys, Blackfin from Analog Devices

Yocto Project: architecture support:
(1) Core supports ARM, MIPS, PowerPC, X86, and their 64-bit series
(2) Separate layers: Microblaze, NIOSII
(3) Typically, chip manufacturers maintain their own BSP layers: meta-intel, meta-altera (ARM & NIOSII), meta-atmel, meta-fsl, meta-ti, meta-xilinx ...
(4) Community provides: meta-rockchip, meta-sunxi

Buildroot: minimal build:
The minimal build takes 15 minutes and 25 seconds, image size 2.2MB

Yocto project: minimal build:
The minimal build takes 50 minutes and 47 seconds, image size 4.9MB. If there is an existing sstate-cache, it takes 1 minute and 21 seconds.

License:
(1) Both can create a list of licenses used
(2) Both can detect license changes
(3) The Yocto project can exclude GPLv3

Choosing between Buildroot & Yocto:
Buildroot
(1) Very specialized CPU architectures
(2) Very small rootfs < 8M
(3) Does not place high demands on engineers
(4) Does not support various machines or similar systems
(5) Does not require package/partial system updates
(6) Small system

Yocto
(1) Not very specialized CPU architectures, not very small rootfs, requires experienced engineers.
(2) Not very specialized CPU architectures, not very small rootfs, requires experienced engineers. Supports several similar systems
(3) Not very specialized CPU architectures, not very small rootfs, requires experienced engineers. Requires package and partial system updates
(4) Not very specialized CPU architectures, not very small rootfs, requires experienced engineers. Very large system

Source: The article is from the internet, and the copyright belongs to the original author. If there is any infringement, please contact for deletion.

Follow 【Learn Embedded Together】 and reply 'Join Group' to enter the technical exchange group.

If you find the article good, please click 'Share', 'Like', or 'View'!

Leave a Comment