January 11, 2024
Building a WPE and RDK Image for Raspberry Pi 4B Using Buildroot
The integration of diverse technologies like Web Platform for Embedded (WPE), Reference Design Kit (RDK), Buildroot, and Raspberry Pi 4B opens up exciting possibilities in the field of embedded systems and IoT. In this guide, we'll explore how these technologies synergize to create powerful, efficient, and highly customizable embedded devices.
WPE and RDK: WPE is a fully-featured browser engine specifically designed for embedded systems. It's lean, fast, and customizable, making it ideal for running web-based applications on devices with limited resources. RDK, on the other hand, is a software platform for set-top boxes, smart TVs, and other broadband devices, providing a common framework for powering customer-premises equipment. When combined, these technologies offer a robust foundation for developing advanced, web-enabled embedded devices.
Raspberry Pi 4B: Raspberry Pi 4B, known for its versatility and performance, is a popular choice for embedded projects. Its ample processing power, memory, and connectivity options make it an excellent platform for hosting WPE and RDK, offering developers a flexible and powerful environment for their embedded applications.
Buildroot: A key tool in this process is Buildroot, a simple, efficient, and flexible build system. Buildroot streamlines the process of creating a complete embedded Linux system. Unlike Yocto, another popular build system, Buildroot is known for its simplicity and speed, making it ideal for quickly setting up and prototyping embedded systems.
Building with Buildroot
Buildroot is a powerful tool for building embedded Linux systems. It's simpler and faster compared to Yocto, focusing on simplicity and ease of use. You can learn more about Buildroot through this comprehensive guide.
Setting Up a Virtual Machine
Our development environment will be based on Ubuntu 20.04 LTS, hosted on a MacOS X system using UTM, a versatile virtual machine manager for MacOS. The setup process is straightforward:
- Install UTM: Download UTM from here and install it on your MacOS X.
- Download Ubuntu 20.04 LTS: Acquire the UTM compatible image from the UTM Gallery and follow the instructions to set up your virtual machine.
Minimum Requirements for Ubuntu 20.04 LTS Virtual Machine
Ensure your virtual machine meets these minimum requirements for smooth operation:
- RAM: 12GB or more
- CPU Cores: At least 6, preferably on a powerful Mac M1
- Storage: 100GB minimum, 150GB recommended (considering the OS takes around 16GB)
Expanding the Ubuntu Partition
After allocating storage to your VM, follow these steps to expand the Ubuntu partition:
- Identify the partition using
df -H
. - Locate your disk using
sudo parted -l
. - Check available space with
sudo vgdisplay
. - Extend the logical volume using
sudo lvextend -L +20G <partition-name>
. - Resize the filesystem:
sudo resize2fs <partition-name>
.
Confirm the expansion by rerunning df -H
.
Cross-Compiling with Buildroot
With the hardware and software prerequisites in place, we're ready to start cross-compiling. This involves installing dependencies, cloning the Buildroot repository, configuring the build, and finally generating the OS image.
Installing Software Dependencies
Follow the instructions on RDK Central to install essential packages:
# essential packages installation
# super user mode is required
# major essential packages
sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib g++-multilib build-essential chrpath socat bison curl cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3 xterm
Cloning and Configuring Buildroot
Clone the Buildroot repository from the WebPlatformForEmbedded organization and checkout the appropriate branch for our build:
git clone https://github.com/WebPlatformForEmbedded/buildroot.git
cd buildroot
git checkout R4_4
Configure Buildroot for the Raspberry Pi 4B by editing the raspberrypi4_64_wpe_ml_defconfig
file in the /configs
directory. Add necessary configurations, then use make menuconfig
to access additional configuration options.
As part of configuring Buildroot, it's crucial to ensure that our build includes all necessary components. Through my experimentation, I found that the build process requires certain additional configurations to succeed. Let's modify the raspberrypi4_64_wpe_ml_defconfig
file to incorporate these configurations:
sudo nano ./configs/raspberrypi4_64_wpe_ml_defconfig
WPE ML (Media Layer): This configuration focused on optimizing WebKit for Embedded (WPE) for media playback. It might include specific settings for better handling of multimedia content, optimizations for video and audio codecs, and possibly some machine learning enhancements for media processing.
Within this configuration file, add the following lines:
BR2_PACKAGE_WPEWEBKIT2_38=y
BR2_PACKAGE_WPEFRAMEWORK_MESSAGING=y
These lines are pivotal for the build process. The BR2_PACKAGE_WPEWEBKIT2_38
directive instructs Buildroot to include the WPE Webkit source code, specifically from the GitHub branch tagged 2_38
. This version is selected for its stability and compatibility with our target system.
Similarly, BR2_PACKAGE_WPEFRAMEWORK_MESSAGING
refers to a necessary package from RDK Thunder, which, if omitted, results in an incomplete build. Including this package ensures that all required components of the RDK framework are present, facilitating a successful build process.
By integrating these configurations, we address potential gaps in the default setup and pave the way for a smooth and efficient build experience. If you are curious what does each configuration represents, refer to the apendinx for breakdown of each configuration option.
Fine-Tuning the Configuration with menuconfig
After incorporating the essential configurations, we need to delve deeper and adjust additional settings via the Buildroot configuration interface. This step is vital for tailoring the build to our specific requirements. Begin by executing the following command in the root folder of Buildroot:
make menuconfig
This command launches a user interface that allows for an interactive configuration experience. You'll be presented with a menu-driven interface as shown below:

In this interface, you'll navigate through various options and make selections that align with our project's requirements. The process is iterative, and it's crucial to carefully enable or disable specific configurations as per your needs. The following table, inspired by a discussion in the WPEWebKit GitHub repository, outlines the key configurations to adjust:
Operation in menuconfig | Location | Value |
---|---|---|
ENABLE | Target packages -> Filesystem and flash utilities | dosfstools |
ENABLE | Target packages -> Filesystem and flash utilities | mtools |
ENABLE | Filesystem images | ext2/3/4 root filesystem |
ENABLE | Filesystem images | ext2/3/4 root filesystem |
SET VALUE | Filesystem images | ext2/3/4 root filesystem -> ext2/3/4 variant ext4 |
DISABLE | Filesystem images | initial RAM filesystem linked into linux kernel |
ENABLE | Host utilities -> genimage | initial RAM filesystem linked into linux kernel |
Each configuration option serves a specific purpose:
- dosfstools and mtools: These utilities are essential for file system management, particularly for FAT file systems, which are commonly used in embedded systems.
- ext2/3/4 root filesystem: Enabling support for ext2, ext3, and ext4 file systems ensures compatibility and flexibility in managing the root filesystem of the embedded Linux.
- ext4 variant: Setting the ext2/3/4 root filesystem to use the ext4 variant offers a balance of performance and reliability, making it a preferred choice for many embedded applications.
- Initial RAM filesystem: Disabling the initial RAM filesystem linked into the Linux kernel can help optimize boot time and system resources, especially in resource-constrained environments.
By meticulously adjusting these settings, you ensure that the Buildroot environment is optimally configured for building a robust and efficient WPE and RDK image for the Raspberry Pi 4B.
Cross-Compiling the Image
Start the cross-compiling process with make
. This may take some time, as building a Buildroot image is resource-intensive.
Troubleshooting and Patching During Build
The build process can occasionally encounter issues, such as missing dependencies, configuration errors, or problems in the source code. Efficiently addressing these challenges involves a systematic approach that includes iterative troubleshooting, applying patches, or making direct modifications in the build folder. Here’s how to navigate these challenges:
- Identify and Resolve the Issue: First, pinpoint the problem and implement a solution.
- Clean the Previous Output: Use
rm -rf output
ormake clean
to clear any previous, potentially corrupted build outputs. - Rebuild the System: Run
make
to start the build process again.
This process is cyclical; if a new issue arises, repeat these steps until the build succeeds.
Strategies for Fixing Issues
Different types of build problems require different strategies:
Missing Dependencies: If an error indicates a missing file or library, the solution often involves installing the missing dependency. For example, the error message
fatal error: gmp.h: No such file or directory
suggests that thelibgmp-dev
package is missing and can be installed usingsudo apt-get install libgmp-dev
.Changing Configuration: Sometimes, the issue may stem from an incomplete or incorrect configuration. An example of this was our earlier modification to the
raspberrypi4_64_wpe_ml_defconfig
, where we addedBR2_PACKAGE_WPEWEBKIT2_38=y
andBR2_PACKAGE_WPEFRAMEWORK_MESSAGING=y
to address specific build requirements.Applying a Patch to the Source Code: When a specific package fails during the build, applying a patch can be effective. This involves identifying the problematic package, applying the necessary patch, and then rebuilding. Patches can be created using
git
and are well-documented in the Buildroot training materials. For instance, a known issue with a Python package missing_ctypes
can be resolved with a specific patch as detailed in this bug report.Direct Modifications in the Build Folder: In some cases, directly editing the code in the
/output/build
folder may be the quickest solution. This approach, however, is temporary as any changes will be lost if the build folder is cleaned.
Resolving Specific Build Issues
During the build, I encountered and resolved several issues. For instance:
Patches for WPE/WPEWEBKIT:
- Navigate to
/output/build/linux-custom/scripts/dtc/dtc-lexer.lex.c
. - Modify the line
YYLTYPE yylloc
toextern YYLTYPE yylloc
.
- Navigate to
Patches for WPE/WPEFRAMEWORK-rdk-services:
- Go to
/output/build/wpe/wpeframework-rdkservices*(version)/CMakeLists.txt
. - Comment out the following lines:
- Go to
...
#if(PLUGIN_MONITOR)
# add_subdirectory(Monitor)
#endif()
...
# if(PLUGIN_TRACECONTROL)
# add_subdirectory(PLUGIN_TRACECONTROL)
# endif()
...
- Fix for WPE/WPEFRAMEWORK:
- Add the
BR2_PACKAGE_WPEFRAMEWORK_MESSAGING=y
to configuration.
- Add the
These modifications addressed specific issues I encountered, facilitating a successful build process.
Applying Patches to Packages in Buildroot
This section is dedicated to elucidating the process of applying patches to a package within the Buildroot environment. The steps below outline this process using the example of patching the WPE/WPEFRAMEWORK-rdk-services package.
Identify the Package: First, pinpoint the package requiring a patch. For demonstration purposes, we're focusing on
packages/wpe/wpeframework-rdkservices
.Locate the Source Code: The source code for the package is typically specified in the package's
.mk
file. In our case, the relevant repository isThunderNanoServicesRDK
, accessible athttps://github.com/WebPlatformForEmbedded/ThunderNanoServicesRDK
.Check Out the Correct Commit: The specific commit to work from can also be found in the
.mk
file. For this example, it'sR4.4.1
.Modify the Code: Proceed to make the necessary changes to the code. In this example, we are commenting out specific lines in the
CMakeLists.txt
file:... #if(PLUGIN_MONITOR) # add_subdirectory(Monitor) #endif() ... # if(PLUGIN_TRACECONTROL) # add_subdirectory(PLUGIN_TRACECONTROL) # endif() ...
Commit the Changes: Use Git to commit your changes with the following command:
git add . & git commit -m "Patching Trace Control and Monitor" -n
Generate the Patch: Next, create a patch file using the command
git format-patch R4.4.1
. This will produce a patch file resembling the following:From 44d5a101483a705ac2d072ed73b318bf575f4639 Mon Sep 17 00:00:00 2001 ... Date: Fri, 12 Jan 2024 13:33:48 +0000 Subject: [PATCH] Patching trace control and monitor --- CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d72a453..c5a366b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,9 +59,9 @@ if(PLUGIN_MESSENGER) add_subdirectory(Messenger) endif() -if(PLUGIN_MONITOR) - add_subdirectory(Monitor) -endif() +# if(PLUGIN_MONITOR) +# add_subdirectory(Monitor) +# endif() if(PLUGIN_OPENCDMI) add_subdirectory(OpenCDMi) @@ -83,9 +83,9 @@ if(PLUGIN_SECURITYAGENT) add_subdirectory(SecurityAgent) endif() -if(PLUGIN_TRACECONTROL) - add_subdirectory(TraceControl) -endif() +# if(PLUGIN_TRACECONTROL) +# add_subdirectory(TraceControl) +# endif() if(PLUGIN_WEBKITBROWSER) add_subdirectory(WebKitBrowser) -- 2.42.1
Place the Patch in the Package Directory: Finally, move the newly created patch file to the
packages/wpe/wpeframework-rdkservices
directory, alongside the.mk
file. The patch will be applied automatically before the execution of the.mk
file.
Through these steps, we've successfully applied a custom patch to a specific package within Buildroot, showcasing the flexibility and control developers have over their build configurations and package customizations.
Output Image
Upon successful compilation, locate the sdcard.img
file in the /output
folder. This is the WPE RDK image for your Raspberry Pi.
Flashing the Image onto Raspberry Pi
Transfer the image from the Ubuntu VM to your host machine using SCP, then flash it onto an SD card using a tool like Balena Etcher. Insert the SD card into your Raspberry Pi 4B, power it up, and you should see the RDK Central home screen.
Troubleshooting Post-Installation Issues
If you encounter issues like incompatible start4.elf
files, updating the firmware on the Raspberry Pi's SD card with files from the official Raspberry Pi firmware repository may resolve them.
Navigating to ThunderUI
With your device operational, ThunderUI offers a streamlined interface for managing and controlling your RDK environment.

Opening a Browser URL via Metrologic UI
First, identify the IP address of the Raspberry Pi displayed in the top right corner. Ensure your computer is connected to the same network as the Raspberry Pi, and navigate to the IP address in your browser. For example, in this scenario, it would be http://192.168.2.119
.
Upon accessing this address, you'll be greeted with the following user interface:

Here, you can insert any desired URL and click "SET" to direct the Raspberry Pi to open that page in the WPE browser.
For instance, setting it to YouTube, you'll see it successfully launch on your device:

Opening Web Inspector
To delve deeper, the browser's web inspector can be accessed by selecting "Inspect" in the Metrologic UI. This feature allows for in-depth analysis and debugging of web content displayed on the Raspberry Pi.

Hardware Acceleration Demo
As a Demo we can try running a hardware acceleration to run some WebGL animations. We can try and open the Jellyfish demo
Device Logs
Access to the device via ssh. For WPEFramework, we must use the logging of RDK. This can be accomplished by running:
WPEFramework-1.0.0
This is just a binary that exists in our raspberry pi image. You can find more binaries by navigating to the binaries folder.
- Find the binaries location. This is usually indicated in the
$PATH
environment variable.
echo $PATH
... Output ...
/bin:/sbin:/usr/bin:/usr/sbin
Navigate to the binaries location from path. By looking at the code snippet above, it is in
/usr/bin
Observe the binaries

Enabling GStreamer Logs
You can tail the logs by enabling WPEFramework-1.0.0. However, it will not show all the logs. We can expand those. For instance to increase verbosity of gStreamer logs run the following:
export GST_DEBUG=3
Conclusion
In this guide, we have successfully navigated the complexities of building a WPE and RDK image for the Raspberry Pi 4B using Buildroot. From setting up a virtual machine to configuring and cross-compiling with Buildroot, each step was meticulously detailed to ensure a smooth process. The culmination of our efforts is the operational RDK environment on the Raspberry Pi, demonstrated through the use of ThunderUI and the Metrologic UI. This achievement not only showcases our technical prowess but also opens avenues for innovative applications in embedded systems. With these tools and knowledge, we are now well-equipped to explore and create in the exciting world of embedded technology.
Appendix - Buildroot Configurations Breakdown
The raspberrypi4_64_wpe_ml_defconfig
file in Buildroot is a configuration file that sets up a build environment tailored for the Raspberry Pi 4 with a focus on Web Platform for Embedded (WPE) and multimedia layer (ML). Let's break down what each of these configurations means:
- BR2_aarch64=y: Sets the target architecture to AArch64 (64-bit ARM architecture).
- BR2_cortex_a72=y: Optimizes the build for the Cortex-A72 CPU, which is used in the Raspberry Pi 4.
- BR2_ARM_FPU_VFPV4=y: Enables support for the ARM VFPv4 floating-point unit, which is part of the Cortex-A72.
- BR2_CCACHE=y: Enables ccache to speed up recompilation by caching previous compilations.
- BR2_OPTIMIZE_2=y: Sets optimization level to -O2 for a good balance between performance and compilation time.
- BR2_TOOLCHAIN_BUILDROOT_GLIBC=y: Uses the GNU C Library (glibc) in the Buildroot toolchain.
- BR2_TOOLCHAIN_BUILDROOT_CXX=y: Includes C++ support in the toolchain.
- BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y: Uses dynamic device node creation with eudev.
- BR2_TARGET_GENERIC_ROOT_PASSWD="root": Sets the default root password to "root".
- BR2_ROOTFS_POST_BUILD_SCRIPT and BR2_ROOTFS_POST_IMAGE_SCRIPT: Specifies custom scripts to be executed post-build and post-image creation.
- BR2_ROOTFS_POST_SCRIPT_ARGS: Additional arguments for the post-build/image scripts.
- BR2_LINUX_KERNEL=y: Includes the Linux kernel in the build.
- BR2_LINUX_KERNEL_CUSTOM_TARBALL=y: Uses a custom Linux kernel tarball.
- BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION: Location of the custom Linux kernel tarball.
- BR2_LINUX_KERNEL_DEFCONFIG="bcm2711": Uses the bcm2711 default kernel configuration, suitable for the Raspberry Pi 4.
- BR2_LINUX_KERNEL_DTS_SUPPORT=y: Enables Device Tree support in the kernel.
- BR2_LINUX_KERNEL_INTREE_DTS_NAME: Specifies the Device Tree Blob (DTB) for the Raspberry Pi 4.
- BR2_LINUX_KERNEL_DTB_OVERLAY_SUPPORT=y: Enables support for Device Tree overlays.
- BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y: Indicates that the kernel build requires OpenSSL on the host system.
- The BR2PACKAGE_GST1_PLUGINS* lines: Include various GStreamer 1.x plugins for multimedia handling.
- BR2_PACKAGE_BITSTREAM_VERA=y: Includes the Bitstream Vera font.
- BR2_PACKAGE_KMSCUBE=y: Includes kmscube, a sample app to demonstrate DRM/KMS capabilities.
- BR2_PACKAGE_MESA3D and related lines: Includes Mesa 3D graphics library and specific drivers.
- BR2_PACKAGE_RPI lines:** Include various Raspberry Pi-specific packages like firmware and Wi-Fi support.
- BR2_PACKAGE_CA_CERTIFICATES=y: Includes CA certificates.
- BR2_PACKAGE_WPEFRAMEWORK and related plugins: Include the WPE Framework and various plugins for functionality like compositor, Wi-Fi control, web server, etc.
- BR2_PACKAGE_WPEWEBKIT2_22=y: Includes version 2.22 of the WPE WebKit browser engine.
- BR2_PACKAGE_ORC=y: Includes the Orc library, used for compiling and optimizing code.
- BR2_PACKAGE_SHARED_MIME_INFO=y: Includes shared MIME database.
- BR2_PACKAGE_DROPBEAR=y: Includes the Dropbear SSH server and client.
- BR2_PACKAGE_RDKSPLASHSCREEN and related lines: Include the RDK splash screen.
- BR2_PACKAGE_HOST_DOSFSTOOLS, BR2_PACKAGE_HOST_GENIMAGE, BR2_PACKAGE_HOST_MTOOLS: Includes various host utilities for filesystem image generation.
Buildroot configurations specifically related to the WPE Framework and its components.
- BR2_PACKAGE_WPEFRAMEWORK=y: Includes the WPE Framework, a collection of libraries and tools for developing and running applications on embedded devices, especially focused on web-based applications.
- BR2_PACKAGE_WPEFRAMEWORK_CDMI_CLEARKEY=y: Includes support for the ClearKey Content Decryption Module (CDM) within WPE Framework. This is used for handling DRM (Digital Rights Management) for media content.
- BR2_PACKAGE_WPEFRAMEWORK_COMPOSITOR=y: Includes the compositor plugin for WPE Framework, which manages the graphical output, handling windowing and rendering of graphics.
- BR2_PACKAGE_WPEFRAMEWORK_DHCPSERVER=y: Adds a DHCP server capability to the WPE Framework, enabling it to assign IP addresses to devices in a network.
- BR2_PACKAGE_WPEFRAMEWORK_LOCATIONSYNC=y: Includes the LocationSync plugin, which provides location services and geolocation functionalities.
- BR2_PACKAGE_WPEFRAMEWORK_LOCATIONSYNC_URI: Sets the URI for the LocationSync service, in this case, using Metrological's JSON IP service.
- BR2_PACKAGE_WPEFRAMEWORK_MONITOR=y: Includes the Monitor plugin, which is used for monitoring the performance and resource usage of applications running within the WPE Framework.
- BR2_PACKAGE_WPEFRAMEWORK_REMOTECONTROL=y: Adds support for remote control functionalities, enabling control of the device through external inputs.
- BR2_PACKAGE_WPEFRAMEWORK_REMOTECONTROL_DEVINPUT=y: Enables device input handling for the remote control feature, allowing the use of various input devices.
- BR2_PACKAGE_WPEFRAMEWORK_TIMESYNC=y: Includes the TimeSync plugin, which ensures the device maintains accurate time, often critical for networked applications.
- BR2_PACKAGE_WPEFRAMEWORK_TRACECONTROL=y: Adds TraceControl, a tool for tracing and debugging applications within the WPE Framework.
- BR2_PACKAGE_WPEFRAMEWORK_WEBKITBROWSER=y: Includes the WebKitBrowser plugin, providing a web browser based on the WebKit engine within the WPE Framework.
- BR2_PACKAGE_WPEFRAMEWORK_WEBKITBROWSER_STARTURL: Sets the default start URL for the WebKitBrowser.
- BR2_PACKAGE_WPEFRAMEWORK_WEBKITBROWSER_MEMORYPRESSURE: Configures memory usage limits for various processes within the WebKitBrowser to optimize performance.
- BR2_PACKAGE_WPEFRAMEWORK_WEBKITBROWSER_DISKCACHE: Sets the size of the disk cache used by the WebKitBrowser.
- BR2_PACKAGE_WPEFRAMEWORK_WEBKITBROWSER_XHRCACHE=y: Enables caching for XMLHttpRequests in the WebKitBrowser, improving performance for web applications making frequent AJAX calls.
- BR2_PACKAGE_WPEFRAMEWORK_YOUTUBE=y: Includes support for a YouTube application or plugin within the WPE Framework.
- BR2_PACKAGE_WPEFRAMEWORK_UX=y: Adds User Experience (UX) improvements or features to the WPE Framework, potentially including UI elements, animations, and other user interface enhancements.
- BR2_PACKAGE_WPEFRAMEWORK_WEBKITBROWSER_THREADEDPAINTING: Configures the WebKitBrowser to use threaded painting, which can improve rendering performance by using multiple CPU cores.
- BR2_PACKAGE_WPEFRAMEWORK_WEBSERVER=y: Includes a web server component within the WPE Framework, enabling the device to host web content or services.
- BR2_PACKAGE_WPEFRAMEWORK_WIFICONTROL=y: Adds Wi-Fi control capabilities to the WPE Framework, allowing the management of Wi-Fi connections.