User Tools

Site Tools


doc:howto:obtain.firmware.sdk

Using the SDK

The SDK is a relocatable, precompiled OpenWrt toolchain suitable to cross compile single userspace packages for a specific target without compiling the whole system from scratch.

Reasons for using the SDK are:

  • Compile custom software for a specific release while ensuring binary and feature compatibility
  • Compile newer versions of certain packages
  • Recompile existing packages with custom patches or different features

Obtain SDK

You can either download an already compiled SDK, or compile it yourself by using the "make menuconfig" command.

Download

You should find bz2-archives ready for download in the corresponding download directory:

Create one

configuration Choose you Target System and then

[x] Build the OpenWrt SDK

After the compilation, you will find in <build root>/bin/<arch>/

Usage

By default the SDK ships with no package definitions. Makefiles for packages to compile must be checked out from the OpenWrt repository and placed into the package/ directory first.

Obtain Definitions

Use the svn export command to obtain package definitions. OpenWrt's Trunk package feed is located at svn:svn.openwrt.org/openwrt/packages, the Trac browser can be used to find the appropriate subdirectory. The example below checks out the nano editor from the repository: | $ svn export svn:svn.openwrt.org/openwrt/packages/utils/nano package/nano A package/nano A package/nano/Makefile Exported revision 20365. |

Many packages require additional dependencies which can be found in the package Makefile:

$ grep DEPENDS package/nano/Makefile DEPENDS:=+libncurses

If there are additional dependencies, those need to be fetched and compiled as well.

Compile Packages

After the Makefile is in place, the usual buildroot commands apply:

  • make package/example/download - download the soures of example
  • make package/example/prepare - extract the sources, apply patches and download if necessary
  • make package/example/compile - compile example, prepare and download if necessary
  • make package/example/clean - clean the sourcecode
  • make package/index - build a repository index to make the output directory usable as local opkg source

Some packages are built on host:

$ make package/example/host/{clean,compile} V=99

The common command to recompile a package example and enable verbose output is:

$ make package/example/{clean,compile} V=99

After the compilation is finished, the generated .ipk files are placed in the bin directory.

The output of make might contain WARNING: your configuration is out of sync. Please run make menuconfig, oldconfig or defconfig!. That warning is misleading and wrong in the SDK case. Since everything is precompiled you cannot run oldconfig (see Why is the SDK configuration out of sync?).

Example: existing package

The example below rebuilds nano.

$ svn export svn://svn.openwrt.org/openwrt/packages/utils/nano package/nano
A    package/nano
A    package/nano/Makefile
Exported revision 20365.
$ grep DEPENDS package/nano/Makefile 
  DEPENDS:=+libncurses
$ svn export svn://svn.openwrt.org/openwrt/trunk/package/libs/ncurses package/ncurses
A    package/ncurses
A    package/ncurses/patches
A    package/ncurses/patches/100-ncurses-5.6-20080112-urxvt.patch
A    package/ncurses/patches/900-terminfo.patch
A    package/ncurses/patches/101-ncurses-5.6-20080628-kbs.patch
A    package/ncurses/patches/500-cross.patch
A    package/ncurses/Makefile
Exported revision 20365.
$ make package/ncurses/compile
Collecting package info: done
 make[1] package/ncurses/compile
 make[2] -C package/ncurses compile
$ make package/nano/compile
 make[1] package/nano/compile
 make[2] -C package/ncurses compile
 make[2] -C package/nano compile
$ make package/index
 make[1] package/index
$ ls bin/packages/mipsel/
libncurses_5.7-2_mipsel.ipk  nano_2.2.3-1_mipsel.ipk  Packages	Packages.gz

Build your own packages

Problems

Compiler not found, due to ccache problem. https://dev.openwrt.org/ticket/13949

from Oldwiki

Outdated Information!
This article contains information that is outdated or no longer valid. You can edit this page to update it.

oldwiki: About the OpenWrt SDK

This howto is for people who would like to port/package applications to OpenWrt with the OpenWrt Software Development Kit (SDK).

When using the SDK you don't require a full buildroot. The SDK is a stripped down version of it, which includes the toolchain and all the required library and header files to cross-compile applications for OpenWrt.

Requirements

  • a recent GNU/Linux distribution
  • GNU Make (at least 3.80 with the Debian patch)
  • wget
  • patch

These packages suffice for the "Hello world" program described below

Using the OpenWrt SDK

TIP: Before you begin porting your own package to OpenWrt, check if it has not been already done by someone else. To check that browse the subversion repository of the development version in your web browser and see if the package is already there. Don't do the work twice.

Let's start with porting and packaging the well known "Hello world" program as an example.

You can download an existing example here: https://forum.openwrt.org/viewtopic.php?pid=198460. Another useful resource is http://fleshandmachines.wordpress.com/2011/08/22/openwrt-cc-programing/.

Obtaining and installing the SDK

The SDK can be downloaded from http://downloads.openwrt.org/whiterussian/newest/.

Download it into your home directory (don't use the root account) and untar the tarball. After that change into the new directory.

cd ~
wget http://downloads.openwrt.org/whiterussian/newest/OpenWrt-SDK-Linux-i686-1.tar.bz2
bzcat OpenWrt-SDK-Linux-i686-1.tar.bz2 | tar -xvf -
cd ~/OpenWrt-SDK-Linux-i686-1

Creating the directories

Create the following directories:

cd ~/OpenWrt-SDK-Linux-i686-1
mkdir -p package/helloworld/ipkg
mkdir -p package/helloworld/patches

Directories and their contents:

#!CSV
Directory; Description
ipkg; Control file which contains information about your package
patches; Patch files for example 100-foo.patch

TIP: To compile more than one package in a special order do:

cd ~/OpenWrt-SDK-Linux-i686-1
mkdir -p package/100-packagename/ipkg
mkdir -p package/100-packagename/patches
mkdir -p package/200-packagename/ipkg
mkdir -p package/200-packagename/patches

Creating the required files

TIP: If you intend to 'copy & paste' the text from this Wiki to create files on your system, then use the Unix command

unexpand
to translate the leading spaces into tabs.

unexpand --first-only - >package/helloworld/Config.in

After pasting it into a text editor, press

ENTER
and then
CTRL-D
keys to save the file.

You can also create your own files in the

package/helloworld
directory (for example config files). That files you can access in your
package/helloworld/Makefile
with
./filename
and copy it to your
$(PKG_INSTALL_DIR)
directory.

package/helloworld/Config.in

config BR2_PACKAGE_HELLO
        prompt "hello............................. The classic greeting, and a good example"
        tristate
        default m if CONFIG_DEVEL
        help
              The GNU hello program produces a familiar, friendly greeting.  It
              allows non-programmers to use a classic computer science tool which
              would otherwise be unavailable to them.
               *
              Seriously, though: this is an example of how to do a Debian package.
              It is the Debian version of the GNU Project's `hello world' program
              (which is itself an example for the GNU Project).
              http://www.wheretofindpackage.tld

You need to create a Config.in file. It identifies the package name. In the above example BR2_PACKAGE_HELLO identifes that this is a 'BR2'(??) formatted 'PACKAGE' whose name is 'HELLO'. The final executable is 'hello'.

package/helloworld/Makefile

The Makefile determines the way the software package is shipped. Basically we can divide the software into 2 main categories :

  • C (or ANSI-C) programs
  • shipped with configure script
  • shipped with Makefile script (with references to gcc or $(CC) )
  • sources files only
  • C++ programs
  • potentially uClibc++ linkables
  • not uClibc++ linkables

TIP: Use the

md5sum
command to create the
PKG_MD5SUM
from the original tarball. Use
@SF/hello
(choose a and expanded random SourceForge mirror) for the
PKG_SOURCE_URL
when your program has a download location on SourceForge.

If PKG_SOURCE_URL and PKG_SOURCE are correctly identified, then the file will be downloaded into the ~/OpenWrt-SDK-Linux-i686-1/dl/ directory. It will be expanded into the ~/OpenWrt-SDK-Linux-i686-1/build_mipsel/ directory for compilation and processing.

Sample Makefile for C/C++ programs shipped with configure script

include $(TOPDIR)/rules.mk
PKG_NAME:=hello
PKG_VERSION:=2.1.1
PKG_RELEASE:=1
PKG_MD5SUM:=70c9ccf9fac07f762c24f2df2290784d
PKG_SOURCE_URL:=ftp://ftp.cs.tu-berlin.de/pub/gnu/hello \
        http://mirrors.sunsite.dk/gnu/hello \
        http://ftp.gnu.org/gnu/hello
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_CAT:=zcat
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
include $(TOPDIR)/package/rules.mk
$(eval $(call PKG_template,HELLO,$(PKG_NAME),$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH)))
$(PKG_BUILD_DIR)/.configured: $(PKG_BUILD_DIR)/.prepared
        (cd $(PKG_BUILD_DIR); \
                $(TARGET_CONFIGURE_OPTS) \
                CFLAGS="$(TARGET_CFLAGS)" \
                CPPFLAGS="-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include" \
                LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
                 */configure \
                        --target=$(GNU_TARGET_NAME) \
                        --host=$(GNU_TARGET_NAME) \
                        --build=$(GNU_HOST_NAME) \
                        --prefix=/usr \
                        --without-libiconv-prefix \
                        --without-libintl-prefix \
                        --disable-nls \
        );
        ## Add software specific configurable options above
        ## See : ./configure --help
        touch $@
$(PKG_BUILD_DIR)/.built:
        rm -rf $(PKG_INSTALL_DIR)
        mkdir -p $(PKG_INSTALL_DIR)/usr/bin
        $(MAKE) -C $(PKG_BUILD_DIR)/src \
                $(TARGET_CONFIGURE_OPTS) \
                prefix="$(PKG_INSTALL_DIR)/usr"
        $(CP) $(PKG_BUILD_DIR)/src/hello $(PKG_INSTALL_DIR)/usr/bin
        touch $@
$(IPKG_HELLO):
        install -d -m0755 $(IDIR_HELLO)/usr/bin
        $(CP) $(PKG_INSTALL_DIR)/usr/bin/hello $(IDIR_HELLO)/usr/bin
        $(RSTRIP) $(IDIR_HELLO)
        $(IPKG_BUILD) $(IDIR_HELLO) $(PACKAGE_DIR)
mostlyclean:
        make -C $(PKG_BUILD_DIR) clean
        rm $(PKG_BUILD_DIR)/.built

Sample Makefile for C/C++ software shipped with a Makefile containing references to gcc or $(CC)

If you Makefile contains harcoded "gcc" commands, then you will have to patch the makefile and replace gcc with $(CC) in order to define at "make time" the cross-compiler to use.

/!\ Note this Makefile is provided as an example only; it will not compile

include $(TOPDIR)/rules.mk
PKG_NAME:=hello
PKG_VERSION:=2.1.1
PKG_RELEASE:=1
PKG_MD5SUM:=70c9ccf9fac07f762c24f2df2290784d
PKG_SOURCE_URL:=ftp://ftp.cs.tu-berlin.de/pub/gnu/hello \
        http://mirrors.sunsite.dk/gnu/hello \
        http://ftp.gnu.org/gnu/hello
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_CAT:=zcat
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
include $(TOPDIR)/package/rules.mk
$(eval $(call PKG_template,HELLO,$(PKG_NAME),$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH)))
$(PKG_BUILD_DIR)/.configured: $(PKG_BUILD_DIR)/.prepared
        #Since there is no configure script, we can directly go to the building step
        touch $@
$(PKG_BUILD_DIR)/.built:
        rm -rf $(PKG_INSTALL_DIR)
        mkdir -p $(PKG_INSTALL_DIR)/usr/bin
        #Note here that we pass cross-compiler as default compiler to use
        $(MAKE) -C $(PKG_BUILD_DIR)/src \
                CC=$(TARGET_CC) \
                $(TARGET_CONFIGURE_OPTS) \
                prefix="$(PKG_INSTALL_DIR)/usr"
        $(CP) $(PKG_BUILD_DIR)/src/hello $(PKG_INSTALL_DIR)/usr/bin
        touch $@
$(IPKG_HELLO):
        install -d -m0755 $(IDIR_HELLO)/usr/bin
        $(CP) $(PKG_INSTALL_DIR)/usr/bin/hello $(IDIR_HELLO)/usr/bin
        $(RSTRIP) $(IDIR_HELLO)
        $(IPKG_BUILD) $(IDIR_HELLO) $(PACKAGE_DIR)
mostlyclean:
        make -C $(PKG_BUILD_DIR) clean
        rm $(PKG_BUILD_DIR)/.built

Sample Makefile for C/C++ programs without makefiles (usually one or two source files)

/!\ Note this Makefile is provided as an example only; it will not compile

include $(TOPDIR)/rules.mk
PKG_NAME:=hello
PKG_VERSION:=2.1.1
PKG_RELEASE:=1
PKG_MD5SUM:=70c9ccf9fac07f762c24f2df2290784d
PKG_SOURCE_URL:=ftp://ftp.cs.tu-berlin.de/pub/gnu/hello \
        http://mirrors.sunsite.dk/gnu/hello \
        http://ftp.gnu.org/gnu/hello
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_CAT:=zcat
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
include $(TOPDIR)/package/rules.mk
$(eval $(call PKG_template,HELLO,$(PKG_NAME),$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH)))
$(PKG_BUILD_DIR)/.configured: $(PKG_BUILD_DIR)/.prepared
        #Since there is no configure script, we can directly go to the building step
        touch $@
$(PKG_BUILD_DIR)/.built:
        rm -rf $(PKG_INSTALL_DIR)
        mkdir -p $(PKG_INSTALL_DIR)/usr/bin
        $(TARGET_CC) $(PKG_BUILD_DIR)/src/$(PKG_NAME).c -o $(PKG_BUILD_DIR)/$(PKG_NAME) ## -lyourlib #Note we directly call the cross-compiler and define its output
        $(CP) $(PKG_BUILD_DIR)/src/hello $(PKG_INSTALL_DIR)/usr/bin
        touch $@
$(IPKG_HELLO):
        install -d -m0755 $(IDIR_HELLO)/usr/bin
        $(CP) $(PKG_INSTALL_DIR)/usr/bin/hello $(IDIR_HELLO)/usr/bin
        $(RSTRIP) $(IDIR_HELLO)
        $(IPKG_BUILD) $(IDIR_HELLO) $(PACKAGE_DIR)
mostlyclean:
        make -C $(PKG_BUILD_DIR) clean
        rm $(PKG_BUILD_DIR)/.built

Sample Makefile for C++ shipped with configure script, and uClibc++ linkables

/!\ Note this Makefile is provided as an example only; it will not compile

include $(TOPDIR)/rules.mk
PKG_NAME:=hello
PKG_VERSION:=2.1.1
PKG_RELEASE:=1
PKG_MD5SUM:=70c9ccf9fac07f762c24f2df2290784d
PKG_SOURCE_URL:=ftp://ftp.cs.tu-berlin.de/pub/gnu/hello \
        http://mirrors.sunsite.dk/gnu/hello \
        http://ftp.gnu.org/gnu/hello
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_CAT:=zcat
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
include $(TOPDIR)/package/rules.mk
$(eval $(call PKG_template,HELLO,$(PKG_NAME),$(PKG_VERSION)-$(PKG_RELEASE),$(ARCH)))
$(PKG_BUILD_DIR)/.configured: $(PKG_BUILD_DIR)/.prepared
        (cd $(PKG_BUILD_DIR); \
                $(TARGET_CONFIGURE_OPTS) \
                CFLAGS="$(TARGET_CFLAGS)" \
                CPPFLAGS="-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include" \
                LDFLAGS="-L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \
                 */configure \
                        CXXFLAGS="$(TARGET_CFLAGS) -fno-builtin -fno-rtti -nostdinc++" \
                        CPPFLAGS="-I$(STAGING_DIR)/usr/include -I$(STAGING_DIR)/include" \
                        LDFLAGS="-nodefaultlibs -L$(STAGING_DIR)/usr/lib -L$(STAGING_DIR)/lib" \ #do not use default libraries since we want uClibc++ linking
                        LIBS="-luClibc++ -lc -lm -lgcc" \ # You may need to add other libraries : lpcap, lssl ... #
                        --target=$(GNU_TARGET_NAME) \
                        --host=$(GNU_TARGET_NAME) \
                        --build=$(GNU_HOST_NAME) \
                        --prefix=/usr \
                        --without-libiconv-prefix \
                        --without-libintl-prefix \
                        --disable-nls \
        );
        ## Add software specific configurable options above
        ## See : ./configure --help
        touch $@
$(PKG_BUILD_DIR)/.built:
        rm -rf $(PKG_INSTALL_DIR)
        mkdir -p $(PKG_INSTALL_DIR)/usr/bin
        $(MAKE) -C $(PKG_BUILD_DIR)/src \
                $(TARGET_CONFIGURE_OPTS) \
                prefix="$(PKG_INSTALL_DIR)/usr"
        $(CC) $(PKG_BUILD_DIR)/src/hello $(PKG_INSTALL_DIR)/usr/bin
        touch $@
$(IPKG_HELLO):
        install -d -m0755 $(IDIR_HELLO)/usr/bin
        $(CP) $(PKG_INSTALL_DIR)/usr/bin/hello $(IDIR_HELLO)/usr/bin
        $(RSTRIP) $(IDIR_HELLO)
        $(IPKG_BUILD) $(IDIR_HELLO) $(PACKAGE_DIR)
mostlyclean:
        make -C $(PKG_BUILD_DIR) clean
        rm $(PKG_BUILD_DIR)/.built

package/helloworld/ipkg/hello.control

The control file, as you might have guessed, controls the package information reported by ipkg.

Anyone familiar with Debian packaging will be aware of the format - a deeper description than provided here is available in the ipkg documentation.

Package: hello
Priority: optional
Section: misc
Description: The GNU hello world program

The following fields are available:

  • Package - should be the package name, as in the Makefile.

Priority - should be set to optional for almost all packages. Section - indicates the type of package - useful sections include comm, editors, graphics, libs, net, text, web, or if you can't decide, misc. Description - a short description of the package. (You can include a longer description here in a similar manner to the help text in Config.in. Start a new line after the short description, and use a line containing a single full stop ('.') as a replacement for blank lines. Depends (not in the example above) - a list of package names that this package requires to operate. Use package names without versions here where possible (e.g. openssh-client).

Note: had to modify package/rules.mk changing ./ipkg/$(2) to the real directory ./ did not work for me

package/helloworld/patches/100-hello.patch

This example applies a Debian patch, which isn't essential for (so you can skip this point).

Other Linux and free UNIX distributions are often an excellent source of patches for non-portable programs. You might like to try searching for packages from Ubuntu, Gentoo, or FreeBSD's Ports.

cd package/helloworld/patches
wget http://ftp.debian.org/debian/pool/main/h/hello/hello_2.1.1-4.diff.gz
gunzip hello_2.1.1-4.diff.gz
mv hello_2.1.1-4.diff 100-hello.patch

TIP: You can apply as many patches as you like. To apply them in a special order name them like:

100-xxx.patch
200-xxx.patch

Compile the package

The make command below compiles every package that you have created in the package directory.

cd ~/OpenWrt-SDK-Linux-i686-1
make clean && make world

Note that there is a fault in the default package/rules.mk file. There is ".." following the "$(PKG_BUILD_DIR)/" which causes the files to be extracted to the wrong directory. Here is the corrected version:

ifneq ($(strip $(PKG_CAT)),)
$(PKG_BUILD_DIR)/.prepared: $(DL_DIR)/$(PKG_SOURCE)
	rm -rf $(PKG_BUILD_DIR)
	mkdir -p $(PKG_BUILD_DIR)
	$(PKG_CAT) $(DL_DIR)/$(PKG_SOURCE) | tar -C $(PKG_BUILD_DIR)/ $(TAR_OPTIONS)
	if [ -d ./patches ]; then \
		$(PATCH) $(PKG_BUILD_DIR) ./patches ; \
	fi
	touch $(PKG_BUILD_DIR)/.prepared
endif

NOTE: If you are using GNU make 3.80 (current "latest") and get a "virtual memory exhausted" message while making, see this page.

For Slackware users there is a fixed make package here and sources + patch are here.

When the compiling is finished you have a ready to use ipkg package for OpenWrt in the

~/OpenWrt-SDK-Linux-i686-1/bin/packages
directory.

cd bin/packages; ls -al hello_2.1.1-1_mipsel.ipk
-rw-r--r--  1 openwrt-dev openwrt-dev 3976 Sep 14 13:03 hello_2.1.1-1_mipsel.ipk

Contribute your new ported program

When you like you can contribute your program/package to the OpenWrt community. It may be included in further versions of OpenWrt.

To do this create a patch from your

package/
directory with:

cd ~/OpenWrt-SDK-Linux-i686-1
diff -ruN package/.orig package/ > -.patch

Once you have created a patch open a ticket and submit your new package (the patch).

Native Development

You need 150Mb storage unit (USB or SD Card)

- Download the file Native Mipsel Toolchain (24Mb)

- Bunzip2 (120mb) it to the storage unit in a ext2 partition.

- unmount partition

- Execute this script, I have it at /sbin/devel.sh

#!/bin/sh
# Kill unusefull tasks (uncoment it) we need memory
#killall logger
#killall syslogd
#killall telnetd
#killall crond
#killall klogd
#killall udhcpc
#killall httpd
#rmmod ext3
#rmmod jbd
#My SD card have 2 partitions 1.ext2  2.swap
mount /dev/mmc/disc0/part1 /mnt -o noatime async
# Swap for large sources. I have 30Mb
#swapoff -a
#mkswap  /dev/mmc/disc0/part2
#swapon  /dev/mmc/disc0/part2
mount -o move /tmp /mnt/tmp
echo " *** exit *** to back - Para volver al sistema"
chroot /mnt/ /bin/ash -
echo " *** Me are here again - De vuelta al sistema original ***"
mount -o move /mnt/tmp/ /tmp/
umount /mnt

- Go /home

- download the source. Example: Didiwiki-0.5.tar.gz from http://www.didiwiki.org

- tar -xvzf didiwiki-0.5.tar.gz

- cd didiwiki-0.5

- configure (1 minute)

- make (1 minute)

- You have your new Binary in the SRC directory (didiwiki)

- copy it to the /tmp directori

- type exit

You have the binary in /tmp directory. copy it to /usr/bin

The result didiwiki.mipsel.binary.gz a small wiki for our router at 8000 port. If you don't use storage unit, you must create /home to store new pages. /home/.didiwiki/*

Links

You can find an useful reference for the packaging process in nbd's paper to the 'OpenWrt Hacking' talk on the 22C3:
- http://events.ccc.de/congress/2005/fahrplan/attachments/567-Paper_HackingOpenWRT.pdf

Full buildroot documentation (for compiling kernel modules and such things, for the rest the SDK should be used)
- http://downloads.openwrt.org/docs/buildroot-documentation.html

doc/howto/obtain.firmware.sdk.txt · Last modified: 2014/07/08 06:19 by theoradicus