Open Embedded: An alternative way to build embedded Linux distributions
OE Recipe FilesOE recipes can be written in shell script, with possible Python snippets, and are divided in five categories:
- classes
- packages
- tasks
- images
- meta
These are hierarchical with an image being the top level recipe. The image recipe defines what goes into a particular root file system image. The recipe simply defines a set of tasks required to build the image. A task recipe is a group of related packages required to bring a block of related features or functionality. For example, a distribution intended for a smart phone might have digital music, digital camera, and contacts book tasks that bring in all the packages needed to provide a particular capability. One of the reasons of such indirection is to abstract sets of packages in tasks, so tasks can be easily re-used in different images.
It is common practice for distributions to have multiple image files to offer a variety of functionality/footprint tradeoffs. For example, Arago includes a base image, console image, digital video demonstration image, and gstreamer image. As can be seen from its image recipe (see Listing #1), the gstreamer image is created by building four different task recipes. The other image recipes are similar, with the base image, for example, simply omitting the console, dvsdk, and gstreamer tasks and having a different image name and root file system size.
Listing #1: Example Image Recipe
# Arago GStreamer image
# gives you an image with DVSDK libs and GStreamer demo
require arago-image.inc
COMPATIBLE_MACHINE = "(?!arago)"
# The size of the uncompressed ramdisk is 150MB
ROOTFS_SIZE = "153600"
IMAGE_INSTALL += "\
task-arago-base \
task-arago-console \
task-arago-dvsdk \
task-arago-gst \
"
export IMAGE_BASENAME = "arago-gst-image"
Task recipes represent individual aggregations of packages. For
example, the arago-base task builds about 15 packages. This recipe (see Listing #2)
introduces some standard BitBake variables you will need to become
familiar with. PR represents the Package Revision, which is the version
number for package recipe file. PN represents the Package Name, while PV
(not used here) represents the Package Version, which is the version
for the actual package source files. The tasks do not specify most
package versions as these are set in the configurations files.
Listing #2: Example Task Recipe
LICENSE = "MIT"
PR = "r9"
inherit task
# these can be set in machine config to supply packages needed to get machine booting
MACHINE_ESSENTIAL_EXTRA_RDEPENDS ?= ""
MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS ?= ""
ARAGO_ALSA_BASE = "\
alsa-lib \
alsa-utils-aplay \
"
ARAGO_BASE = "\
${ARAGO_ALSA_BASE} \
ldd \
mtd-utils \
curl \
arago-feed-configs \
initscript-telnetd \
devmem2 \
"
# minimal set of packages - needed to boot
RDEPENDS_${PN} = "\
base-files \
base-passwd \
busybox \
initscripts \
modutils-initscripts \
netbase \
update-alternatives \
module-init-tools \
${ARAGO_BASE} \
${MACHINE_ESSENTIAL_EXTRA_RDEPENDS} \
"
RRECOMMENDS_${PN} = "\
${MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS} \
"
The package recipes address the specific needs of each package. A relatively simple example (see Listing #3) for a GStreamer-based application illustrates some of the key functions of a package recipe. The build mechanism is specified by inheriting the autotools and pkgconfig classes, dependencies are identified, package version and revision numbers identified, and the location of the package sources is given.
Listing #3: Example Package Recipe
DESCRIPTION = "gstd: a GStreamer-based streaming server"
HOMEPAGE = "http://sourceforge.net/projects/harrier/"
LICENSE = "BSD"
SECTION = "multimedia"
PRIORITY = "optional"
inherit autotools pkgconfig
DEPENDS = "dbus dbus-glib gstreamer"
RDEPENDS_${PN} = "dbus dbus-glib gstreamer gst-plugins-base"
RRECOMENDS_${PN} = "gstreamer-ti"
SRCREV = "f3e22c93f4fd7ca47d6309b8450788127550ecb9"
PV = "1.0"
PR = "r13"
PR_append = "+gitr${SRCREV}"
SRC_URI = "git://gstd.git.sourceforge.net/gitroot/gstd/gstd;protocol=git \"
S = "${WORKDIR}/git"
# We don't want to run autoconf or automake, unless you have
# automake > 1.11 with vala support
do_configure() {
oe_runconf
}
FILES_${PN} += "${datadir}/dbus-1/*/*.service"
FILES_${PN}-dev += "${datadir}/dbus-1/interfaces/*.xml"
In the package recipe (see Listing #3), there is a line that states ‘inherit autotools pkgconfig’. This line is utilizing the remaining recipes type – a BitBake class. Classes have a peer-to-peer relationship with the other recipes rather than a hierarchical one. They are used to factor out common recipe elements that can then be reused, through the inherit command. The most frequent use of classes is to inherit functions or portions of recipes for commonly used build tools like the GNU autotools. An example (see Listing #4) is the class used for the pkgconfig tool (pkgconfig.bbclass):
Listing #4: An Example Class Recipe
inherit base
DEPENDS_prepend = "pkgconfig-native "
do_install_prepend () {
for i in `find ${S}/ -name "*.pc" -type f` ; do \
sed -i -e 's:-L${STAGING_LIBDIR}::g' $i
done
}
do_stage_append () {
install -d ${PKG_CONFIG_DIR}
for pc in `find ${S} -name '*.pc' -type f | grep -v -- '-uninstalled.pc$'`; do
pcname=`basename $pc`
cat $pc > ${PKG_CONFIG_DIR}/$pcname
done
}


Loading comments... Write a comment