Bitbake

From Gumstix User Wiki
Jump to: navigation, search

This page contains a tutorial marked for inclusion to the gumstix.org developer's site. Please help edit it so it can be as good as possible.


At the core of OpenEmbedded is the Bitbake Tool. Users wanting to create new Bitbake recipes and OpenEmbedded packages may find this tutorial helpful.

OpenEmbedded provides a powerful means of creating customized root file systems and cross-compiling, packaging, and deploying software; to harness this power, it is necessary to write Bitbake recipes. If you just want to compile a some code for your Gumstix COM, you may consider native compilation or direct cross-compilation instead. This tutorial steps through the creation of a basic recipe---the configuration file that tells Bitbake how to build your source code. Further, it highlights some useful features and provides references to further documentation. We'll start by writing a simple Hello, World! C program, add a patch to our recipe, then learn how to fetch an autotools-based project from a SVN repository.

Hello, World! Start by making a hello.c file with the following content.

#include "stdio.h"
void main() {
   printf("hello, world\n");
}

Now, create a helloworld_0.0.bb Bitbake recipe file which instructs Bitbake to cross-compile and package our hello world program. The standard format for a recipe name is packagename_versionnumber.bb. Our final output will be an opkg, a package file very similar to dpkg files used in Debian systems or rpm files on Red Hat Linux boxes. For more information on usingopkg, see this page (TODO).

DESCRIPTION = "hello world sample program"
PR = "r0"
SRC_URI = "file://hello.c"
S = "${WORKDIR}"
do_compile () {
 ${CC} ${CFLAGS} ${LDFLAGS} -o hello hello.c
}
do_install () {
 install -d ${D}${bindir}/
 install -m 0755 ${S}/hello ${D}${bindir}/
}
FILES_${PN} = "${bindir}/hello"

Let's look at this recipe line by line. The DESCRIPTION specifies the text that will be displayed by the package management sytem to describe this package. The PR variable specifies the package revision; any time you change the recipe and want your package to be rebuilt, you should increment this variable (in Bitbake-speak, you need to 'bump the PR'). The SRC_URI variable specifies where the source code can be found. In this case, we are listing a single file stored in the same directory as our recipe file. We can just as easily specify an archive file such as a zip or tar, a list of files, a web link where Bitbake can download the source, or even a variety of source control systems such as SVN or Git. The exact syntax of this field is specified in the Fetchers section of the OpenEmbedded Bitbake Manual (TODO).

Bitbake builds a recipe by executing a series of steps: fetching code, unpacking, compiling, linking, staging, and packaging. More details of this process are given here (TODO). The S variable refers to the directory where Bitbake unpacks the source; by default the WORKDIR variable from which Bitbake runs the subsequent compilation steps also points to this directory. In many cases though, an archive file will expand into a subdirectory into which contains the source. As we want to run our compilation step from here, we need to change the value of WORKDIR. In this case though, our WORKDIR is the same as our S directory.

The do_compile function does exactly what you would expect, it gives the details of how to compile the package. We are using the standard C cross-compiler with the standard compiler and linker settings, we're specifying that the output file should be called hello, and that the source file is hello.c. After this step is complete, we should have the newly created binary sitting in S.

A note about staging: often we need to compile packages as dependencies but don't need them on our embedded system (i.e. they aren't runtime dependencies). A common case is header files---we rely on many headers to build a file system image but need very few in our system. Instead, we can ask Bitbake to stage the files, that is, install them in a 'development' version of our root filesystem on our development machine. By contrast, the do_install function deals with files we actually want in our embedded system. It tells the package management system how in install our program. In this case, we are using the Linux install command to create the directory where we wish to our hello program if the directory doesn't yet exist and then asks it to copy our application to this directory. Note that the special

${bindir} variable typically expands to /usr/bin. To learn more about the special BitBake variables often used in recipes, see the (TODO) section of the the OpenEmbedded Bitbake manual.

Note: this article is not yet finished and requires additional content.··Thanks for your patience and check back soon.


Dependencies

Most useful code depends on other libraries; we can specify any packages our code needs in our recipe so Bibbake and our package management tool know what other packages need to be built or installed. If our code needs a library to compile, we specify this using the DEPENDS or the RECOMMENDS keyword in our recipe. Sometimes though, code is dynamically-linked to libraries and needs them at runtime. To specify runtime dependencies, use the RDEPENDS and RRECOMMENDS keywords. The PROVIDES and RPROVIDES variables are, correspondingly, the names given to your recipe in case other packages rely on your package.

Adding A Patch The most common type of Bitbake recipe downloads code from an external source, applies a few patches to ensure the code compiles properly using Bitbake, and then packages the binaries as normal.


Fetching from Repositories git, svn fetchers.

Using Autotools different makers.

Build your own Image

(With Thanks to Alex Gibson) It is often desirable to build a custom image for a particular application. This can be achieved in Bitbake using a image recipe. Start by creating a new bitbake recipe e.g. rtos.bb. The standard location would be the images/ directory i.e.

  • <top>/user.collection/recipes/images/, or
  • <top>/org.openembedded.dev/recipes/images/.

Image recipes should:

  • inherit the image class
  • depend on a basic task such as 'task-base', 'task-base-extended', or 'task-boot'

Our image recipe might start like this:

# rtos.bb custom image for gumstix
# includes gcc, g++ , python and all modules
inherit image
DEPENDS = "task-base "

Note that images are rebuilt every time they are bitbaked and they are just a collection of other packages. As such, developers typically leave out the version information. Next, add the desired packages, tools and libraries to the recipe.

# rtos.bb custom image for gumstix
# includes gcc, g++ , python and all modules
inherit image
DEPENDS = "task-base "
BASE_INSTALL = " \
  task-base-extended \
 "
FIRMWARE_INSTALL = " \
  linux-firmware \
 "
TOOLS_INSTALL = " \
 bash \
 bzip2 \
 cpp \
 cpp-symlinks \
 devmem2 \
 dropbear \
 ffmpeg \
 gcc \
 gccmakedep-dev \
 gcc-symlinks \
 gdb \
 g++ \
 g++-symlinks \
 gzip \
 i2c-tools \
 libc6-dev \
 libstdc++-dev \
 nano \  
 python \
 python-modules \
 sudo \
 vim \
 tar \  
 wget \
"
IMAGE_INSTALL += " \
 ${BASE_INSTALL} \  
 ${FIRMWARE_INSTALL} \
 ${TOOLS_INSTALL} \
"
IMAGE_PREPROCESS_COMMAND = "create_etc_timestamp"
#ROOTFS_POSTPROCESS_COMMAND += '${@base_conditional("DISTRO_TYPE", "release", "zap_root_password; ", "",d)}'

Finally, bitbake your new image: bitbake rtos