Complex embedded and cyber-physical systems are getting more and more sophisticated, and perform increasingly complex tasks. In order to shorten their time to market, embedded Linux distributions are used as the base environment for newly developed products. While there is a big convenience in having the system set up quickly, it comes at the cost of the increased overall complexity of the solution. This means additional work for platform maintenance is required. Another level of complexity is added by the need to develop and maintain multiple product configurations that could cover systems of different scale, software and hardware architecture.
The Yocto Project addresses those issues by using layered architecture for providing support for various hardware architectures, boards, and software components. This approach not only allows to reuse existing software components but also makes them interchangeable, thus providing the building block for embedded systems developers and integrators.
Imagine a case where an embedded system manufacturer wants to build a custom product. In the traditional approach, engineers would have to prepare the bootloader, the Linux kernel and the root file system customized to match the requirements of each platform they intend to support. Moreover, application logic also needs to be integrated.
In the ideal world, the manufacturer would like to prepare one generic component that provides a solution to all specific problems. Such a component should be then reusable and reconfigurable across all base platforms of the manufacturer’s choice.
Here is where the Yocto Project brings value. With Yocto it is possible to provide an application to the integration team in a form of recipe contained in a product-specific layer. Such a layer can be added to any Yocto-based build system, usually without any additional work required to build embedded Linux system images for the target hardware platforms. This not only reduces the work required to bring up the system for the first time but also enables to switch the base platform pain-free while staying focused on the solution.
Having recipes prepared with care and the system architected as a set of independent and feature-related layers keeps the system clean and lets developers reuse software components. It is also possible to modify recipes that are provided by other layers without polluting them by using bitbake append file. The ability to use bitbake append files is a smart mechanism for modifying bitbake recipes provided by a 3rd party and keeping those modifications in a separate repository. That makes the management and maintenance of code, build configurations and build steps easy and efficient.
There is an obvious consequence of such a statement: the recipes have to be prepared with care and the system has to be architected as a set of independent and feature-related layers. It is also possible to modify recipes that are provided by other layers without polluting them by using bitbake append file.
OpenEmbedded, which is a well-known build framework for embedded Linux distributions, providing thousands of packages and Yocto base layers provide a foundation for a system being developed to be customized by other layers added on a top.
As its name already suggests, the Board Support Package (BSP) layer provides the support for a particular board or a set of boards. It is a place where configurations and customizations of the Linux kernel and bootloader should be located and any other software components that are required by the platform features. It should also contain any machine-specific tuning options necessary for the compiler.
The Distribution layer allows producing customized Linux distribution – a set of software packages that provide applications and libraries and the Linux kernel. It can be used to adjust more precisely all the low-level details like compile-time options, base files, package selection or branding. In many cases, the reference Poky distribution is enough, so this layer is optional customization.
The Application layer is a layer or a set of layers intended to provide application-specific features, most notably the application itself but also libraries, frameworks and other extra features that the developer needed to build the final solution. All those components come in generic form for portability.
An alternative to the Yocto Project is Buildroot. Both projects are able to generate fully functional embedded Linux distribution. What is the difference between them? Buildroot has a strong focus on simplicity, reuses existing, well-known technologies such as config and make. Yocto, on the other hand, requires knowledge about bitbake and performs builds in a sophisticated framework based on python and bash.
There is also a significant difference in output. The main artefact of Buildroot is a root filesystem, but also a toolchain, a kernel and a bootloader. On the other hand, the primary output of Yocto is a package feed that is then a foundation for the final root filesystem image. That means Buildroot is a better choice for single-configuration, monolithic systems with fixed package set, while with Yocto-based image one can work on package-level during development or even after the deployment. Similarly, extensible SDK (eSDK) provided by Yocto can be customized or updated. With such a development environment, developers are able to work on the application for the target system in a convenient way, without the need to rebuild the system image.
Now, not only development is easier, but also build times differ. Buildroot has no caching mechanism for reliable incremental builds in contrast to Yocto, which caches build results, so only modified packages are rebuilt. The difference is significant especially for complex systems in favour of Yocto build system. Moreover, cache files produced by one build can be shared via network and reused by multiple developers.
Configuration approach also differs between those two solutions. Buildroot stores configuration in a single file which defines system: bootloader, kernel, packages and CPU architecture. In Yocto configuration is divided into recipes and append files are provided by separate layers. The top-level configuration is controlled from a single configuration file that uses the aforementioned recipes as a building blocks.
The possibility of keeping specific configurations separate, e.g.: for distribution, machine architecture, BSP and root filesystem image allows to reuse it, e.g. build the same image for a various number of platforms. In Buildroot each platform requires separate monolithic configuration. That means a great part of it will be duplicated.
While the developers may find the Yocto Project to have a bit steeper learning curve, its well-defined project structure contributes to time savings, optimizing work, as well as most importantly it lends itself very well to the improved scalability. Both vertical – towards an increased complexity of embedded solutions, as well as horizontal – towards building approaches and platforms that support complex product families in a uniform manner. From the developer’s point of view, because Yocto allows to organize the code and the configuration in separate layers which can be stored in separate repositories, both the development as well as maintenance of projects becomes very structured and possible to organize very well. All those features make Yocto-based work environment effective, convenient, as well as well-suited to support very well all kinds of long-term developments. This reduces time to market and required effort especially in case of products with multiple configurations and base platforms.