OpenWrt is undoubtedly the most popular open-source embedded operating system on the market right now. What is it? Why use it? And one of the most frequently asked questions how can I start using it. I have tried my best to incorporate and address all issues that I had initially faced during its setup and during package development.
What is OpenWrt?
OpenWrt an open-source embedded operating system has become a popular firmware choice replacing proprietary firmware on networking devices, whether the home routers or devices on enterprise networks. Unlike typical networking devices that provide us with a single, static proprietary firmware, OpenWrt provides us with a fully writable and accessible filesystem and package management that allows users to extend the capabilities of their network devices’ firmware.
Why use OpenWrt?
This question closely relates to my belief in open-source projects. People generally use Openwrt because it’s opensource and unlike other stock firmware from vendors, it is more stable, reliable, efficient, and provides far more features and functionalities. Its performance, security, and extensibility are superior to others. Its openness also brings along a strong supportive community of developers and users. The main reason why one uses OpenWrt could be :
Being an open-source Linux software it is resistant to most common vulnerabilities and there are no hidden backdoors that are left by the vendors. Also as the code is reviewed by many developers all over the world before its release, it is likely to have fewer vulnerabilities.
While other vendors’ firmware for network devices ship with a fixed set of capabilities, OpenWrt right out of the box provides its user with a wide range of packages for support for varieties of functionalities. One can also develop their own package in order to increase the capability of the device.
As OpenWrt is based on a Linux system, the user has full control over all the functionalities of the device.
Thanks to its volunteer contributors it is provided for free through its GPL license.
👨💻 How to get started
For a developer, the OpenWrt framework provides a way to build an application without having to build a complete firmware around it. This eliminates the hassle involved in building the firmware itself therefore the developer can focus more on the application development. With this, it brings friendliness to all the developers who just want to extend the functionalities to the devices with their application.
This article is written with the focus on installing Openwrt and OpenwrtSDK on the VirtualBox. After the installation, we create a simple helloworld application. This guide is present in the OpenWrt documentation but here I present the steps followed to build and deploy the application.
Preparing the OpenWrt build system
Here we download the OpenWrt source code and create the build system from scratch. But one can also simply download the precompiled OpenWrt SDK for the target environment. We begin from scratch ie. download the source code and start compiling the SDK and image for the target platform.
Build system setup
Distribution-specific instructions can be found at https://openwrt.org/docs/guide-developer/build-system/install-buildsystem
Here is the instruction for Debian / Ubuntu-based distributions.
sudo apt update
sudo apt install build-essential ccache ecj fastjar file g++ gawk \
gettext git java-propose-classpath libelf-dev libncurses5-dev \
libncursesw5-dev libssl-dev python python2.7-dev python3 unzip \
wget python3-distutils python3-setuptools rsync subversion swig \
time xsltproc zlib1g-dev
Preparing, configuring and building
We perform these steps as we chose to clone the source code. If you chose to use the SDK, you can skip this section.
I have decided to clone it in my home directory.
It is also suggested to use the most-current “stable” git branch which you can find from their website. As of January 2021, the stable version is OpenWrt 19.07.5. You can also find out other stable versions at https://openwrt.org/about/history.
You can update and install your ‘feeds’ packages to avoid future problems by using:
./scripts/feeds update -a
./scripts/feeds install -a
After that, we configure the cross-compilation toolchain from the graphical configuration menu by:
From the menu, you can choose the suitable ‘Target System’, ‘Subtarget’ and ‘Target Profile’.
Here I intend to run this on my virtual machine on an x86 platform so I set it up accordingly. Make sure you select build OpenWrt SDK.
If you are building the firmware for other devices then you can do it accordingly. More information about the different vendor-specific devices and their profile can also be found on the OpenWrt website.
Make sure you select the necessary packages. I recommend selecting gdb and gdbserver as they can of use in debugging process later on during package development. Then you can save your configurations as .config. Then run
This could take a while to complete so feel free to give yourself a break and get a coffee ☕.
You can find your OpenWrtSDK in ~/openwrt/bin/targets/x86/64/ . I copy it to my ~/openwrt-dev/ directory in home and extract it there.
👋 Creating a “Hello World” program
Now we make a simple helloworld program in C.
Using an editor you can add the following code in the file helloworld.c :
After the source file is created. We ensure the application can be built and executed by out native compilation tools on our dev environment.
gcc -c -o helloworld.o helloworld.c -Wall
gcc -o helloworld helloworld.o
We execute it by issuing the following command.
Then you will be greeted by a text “Hello, world!” on your screen. If this does not happen make sure your source code is correct and check if you encountered any errors in the compilation and linking commands.
Now you have a simple executable application built using the native compilation tools available in the development environment.
📦 Creating a package
After successfully creating a helloworld program. We start to explore the ways to create a package for the OpenWrt.The OpenWrt build framework is heavily based on the idea of packages. They’re the system’s bread and butter. These packages can also reside in a remote repository. The separation of package feeds and the core source code indeed allows OpenWrt to maintain the separation of concern.
Here in this case we create a new package named “mypackages” repository in a local directory.
mkdir -p mypackages/examples/helloworld
Now we create a package manifest file. OpenWrt packages are described by a package manifest file. The manifest file is responsible for describing the package, what it does, and instructions about where to obtain the source code and how to build it, how to built it, and which files are required for an installable package. It may also contain additional configuration scripts for specifying the dependencies between packages.
Now we head towards making our application to a package.
Make sure you put down the text given above as the content for the package manifest.
Be sure to consider the space and tabs within the makefile. This could potentially bring errors later on. 🔔 So do remember this and make sure to maintain the indentations accordingly. ie shorter are space characters, longer ones should be replaced with a tab.
🔔 Also do not forget to change the SOURCE_DIR:=/home/digggy/openwrt-dev/helloworld in the Makefile with your source directory path.
We don’t discuss in detail the package manifest file itself. You can find more about that here.
To describe the cross-compilation tool and target-dependent compilation and linking flags, we use these pre-defined variables within the manifest file. It is a modified form a normal Makefile :)
Until now, a new local package feed was developed and a package manifest file was added to the application, defining the name, version, definition, and build instructions for creating an installable package from the helloworld source code that we wrote earlier.
Including package feed into OpenWrt build system
Openwrt build system uses specific file feeds.conf or you can see a feeds.conf.default within the openwrt-sdk. It indicates the package feeds that will be made available during the firmware configuration stage. It is necessary to include the new package feed into this file.
So you can create a feed.conf file within the openwrt-sdk directory or if feeds.conf.default is already there then you append the file with:
echo “src-link mypackages /home/digggy/openwrt-dev/mypackages” >> feeds.conf.default
Make sure to update the package index based in the information in this feed and make all packages available in the configuration menu. We can do this by
./scripts/feeds update mypackages
./scripts/feeds install -a -p mypackages
If the steps were successful then you should be seeing the response as follows:
A feed configuration file was developed, where we added our local package feed. From this feed, we then modified the package index and loaded all available packages in this feed, ready to be used in the firmware setup/configuration.
🏗️ Building the .package (.ipk)
We should be now able to integrate the package into our firmware. So we include our package in the target firmware configuration and then issue the necessary commands to build it.
Be sure to select your target system accordingly. And select the helloworld within the Example submenu to include the package into firmware configuration. Save the config and exit. Then you can build the package by the following command.
If all goes successfully, in the bin/packages/<arch>/mypackages section, we are presented with a brand new package called helloworld 1.0–1<arch>.ipk which you can install on your target OpenWrt device.
Voila 🙌 !! You are ready to use your custom package for OpenWrt system.