aboutsummaryrefslogtreecommitdiffstats
path: root/docs/usermanual/embworld-oe.dbk
blob: c75d32fa1c069e348e77290642486ccf74cc54d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
<BASE HREF="/home/vollmann/winuser/conferences/embworld/embworld-oe.dbk">

<?xml version="1.0"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
          "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">

<!-- $Id$ -->

<article lang="en">
  <articleinfo>
    <date>First version January 3, 2006</date>
    <title>OpenEmbedded for Deep Embedded Systems</title>

    <author>
      <firstname>Detlef</firstname>
      <surname>Vollmann</surname>
        <affiliation>
          <orgname>vollmann engineering gmbh</orgname>
          <address>
<pob>P.O. Box 5423</pob>
<city>6000 Luzern 5</city>
<country>Switzerland</country>
<email>dv@vollmann.ch</email>
          </address>
        </affiliation>
    </author>

    <copyright>
      <year>2006</year>
      <holder>Detlef Vollmann</holder>
    </copyright>
  </articleinfo>

<abstract>
<title>Abstract</title>
 <para>
OpenEmbedded has won the TuxMobil GNU/Linux
Award 2005 that honors Free Software projects, which improve Linux
for mobile computers.  OpenEmbedded is a Linux distribution similar
to Debian that has its roots in the PDA domain.  It is today pretty
popular among Linux fans who own Zaurus', iPAQs or similar PDAs.
But OpenEmbedded is targeted at all kinds of embedded Linux systems.
It features a unique cross build environment that generally allows
pretty easy adaption of OpenSource software for cross compilation even
if the original software authors didn't think about cross builds.
That build environment also allows for easy definition and builds of
complete distributions for embedded systems.
 </para>

 <para>
OpenEmbedded also provides a lightweight and fine-grained package
system that enables easy installation of new software packages into
a running system as well as updates of existing software.
These features makes OpenEmbedded a first choice for the creation
of embedded Linux systems.
 </para>
</abstract>


<sect1 label="1" id="introduction">
<title>Introduction</title>
 <para>
When Sharp launched its Zaurus PDA, it came with a Linux based PDA system.
But not all users were happy with the original Sharp configuration and
so the OpenZaurus project was created to share the modifications.
Later, OpenZaurus moved from modifications to the original Sharp image
to a complete distribution based on Debian.
 </para>

 <para>
But the build system for Debian was not really suited for small embedded
systems and so OpenEmbedded was founded with a build system inspired
from Gentoo's <command>portage</command>.  As package system iPKG was used, which is
closely related to Debian's <command>dpkg</command>, but more tuned for small embedded
devices.
Later, distributions for other PDAs like Compaq's iPAQs or the Siemens
SimPad moved to the OpenEmbedded build and package system.
A very interesting distribution based on OpenEmbedded is OpenSLUG
for LinkSys' NSLU device.  The NSLU is not a PDA but originally
an NAS storage system.
 </para>

 <para>
Today, OpenEmbedded describes itself as a "set of recipes and metadata
to build Linux distributions for embedded devices with the BitBake
build system".
 </para>

 <para>
OpenEmbedded provides three major benefits for building a distribution
for an embedded system:
 <itemizedlist mark='bullet'>
<listitem>
 <para>
 a build system that builds everything
 </para>
</listitem>
<listitem>
 <para>
 recipes and metadata to build more that 1000 different programs
   and libraries
 </para>
</listitem>
<listitem>
 <para>
 a binary package system that provides simple configuration and update
   mechanisms
 </para>
</listitem>
 </itemizedlist>
 </para>

 <para>
The remainder of this article focuses on the use of OpenEmbedded
for deep embedded systems like the NSLU opposed to PDA like systems
like the SimPad.
 </para>

</sect1>

<sect1 id="overview">
<title>Overview</title>
 <sect2>
 <title>Build System</title>
   <para>
Like any build tool (make, ant, jam), the OpenEmbedded build tool
BitBake controls how to build things and the build dependencies.
But unlike single project tools like <command>make</command> it is not based on one makefile
or a closed set of inter-dependent makefiles, but collects and manages
an open set of largely independent build descriptions (package recipes) and
builds them in proper order.
 </para>

 <para>
The OpenEmbedded set of package recipes include not only recipes for
target packages, but also recipes for tools on the host required to build
those target packages.  So, OpenEmbedded builds a complete toolchain
for cross-building before building the target packages and image.
   </para>
 </sect2>

 <sect2>
 <title>Metadata</title>
   <para>
The metadata from which an OpenEmbedded distribution is built comes in
three different forms:
   <itemizedlist mark='bullet'>
    <listitem>
      <para>
 configuration files
      </para>
    </listitem>
    <listitem>
      <para>
 class descriptions
      </para>
    </listitem>
    <listitem>
      <para>
 package recipes
      </para>
    </listitem>
   </itemizedlist>
   </para>

   <para>
The configuration files provide general variable definitions to control
the behaviour of BitBake and how things are generally built in
OpenEmbedded.  This includes the build system's directory structure,
version preferences, source code mirror sites as well as specific build
options (e.g. the default optimizing level).
   </para>

   <para>
The class descriptions define common procedures to build things, like
applying the auto-tools for configuration, collecting runtime library
dependencies or building native build tools for the host.
These class descriptions are sometimes quite specific, e.g. there exists a
class to remove NLS parts of a package if NLS support is not wanted.
   </para>

   <para>
The package recipes provide the information how to build a specific
piece of software &dash; a build tool for the host, a library or a
target application.  Such recipes provide the information how to get
and how to build a package and dependencies on other packages.
   </para>

   <para>
Meta package recipes don't build a specific package, but mainly consist
of dependency descriptions to build a complete set of packages, often
a base image for a specific distribution.
   </para>
 </sect2>

 <sect2>
 <title>Package System</title>
   <para>
The iPKG package system is (deliberately) very similar to Debian's <command>dpkg</command>,
but is tuned for small systems.  It contains the package data that is
simply copied to the target system, metadata and optionally
installation scripts.  The metadata includes the (run-time) dependencies
of the package.
   </para>

   <para>
Package systems are mainly for the benefit of users of computer-like
devices who want to install their own specific set of software.
Such package systems provide two major benefits:
   <itemizedlist mark='bullet'>
     <listitem>
      <para>
 easy definition of an initial image, often called 'base system'
      </para>
     </listitem>
     <listitem>
      <para>
 controlled installation, upgrade and de-installation of packages
   on the running system
      </para>
     </listitem>
   </itemizedlist>
   </para>

   <para>
These benefits also apply to (deep) embedded systems.
Different configurations are just different sets of packages.  They can
even share the already built packages from existing configurations.
   </para>

   <para>
In traditional embedded systems for an update first a new
complete image is built that then requires on the target a shutdown,
a complete re-flash of the image and finally a restart of the system.
Contrasting to that image-based process, a package system allows easy
updates on a live, running system that
even allows to have some processes running the old version (though it
is already de-installed) while other processes already run the new version.
   </para>
 </sect2>
</sect1>

<sect1>
 <title>Working with OpenEmbedded</title>
   <para>
To build a system based on OpenEmbedded, normally a small set of
configuration files is needed:
   <itemizedlist mark='bullet'>
     <listitem>
      <para>
 <filename>local.conf</filename> to define what to build and where to get and put it
      </para>
     </listitem>
     <listitem>
      <para>
 a machine configuration to describe the hardware
      </para>
     </listitem>
     <listitem>
      <para>
 a distribution configuration to define global properties of the system
      </para>
     </listitem>
   </itemizedlist>
   </para>


   <para>
Apart from that, typically a meta package for the base image is required.
And then of course the recipes for specific packages, e.g. a kernel
package, packages for additional Open Source applications and
packages for project specific software.
   </para>

 <sect2>
      <title><filename>local.conf</filename></title>
   <para>
The local configuration file <filename>local.conf</filename> defines the local directory
structure, the local build environment, some project specific preferences
and other properties specific to the build system.
   </para>
   <para>
A very simple and short <filename>local.conf</filename> could look like this:
<programlisting>
# DL_DIR specifies the download target directory
DL_DIR = "${PROJECT}/oesrc"

# BBFILES specifies the full set of package recipes to be parsed by BitBake
BBFILES = "${PROJECT}/org.openembedded.dev/packages/*/*.bb"

# BBMASK specifies which package recipes to ignore from the full set above
BBMASK = ""

# ASSUME_PROVIDED defines what local host build tools should
# not be built by BitBake but should be used from the local
# build host's installation
ASSUME_PROVIDED = "flex-native"

# For some tools exist different alternative implementations,
# e.g. for the C runtime library there exist glibc and uClibc.
# PREFERRED_PROVIDERS defines which specific package to build
PREFERRED_PROVIDERS = "virtual/kernel:mymach24"
PREFERRED_PROVIDERS += " virtual/libc:glibc"

# For many packages exist several different recipes.
# PREFERRED_VERSION defines which specific recipe to use
PREFERRED_VERSION_gcc-cross = "3.3.2"

# MACHINE defines for which hardware to build
MACHINE = "mymach"

# DISTRO defines which distribution to build
DISTRO = "mymini"

# IMAGE_FSTYPES defines which kind of images to create
IMAGE_FSTYPES = "jffs2 tar"

# For a number of package recipe versions the source code is fetched directly
# from the original CVS repository head.  To make sure that for separate
# builds this fetches the same source, use CVSDATE.
CVSDATE = "20051122"

# For some packages specific CVS versions are provided as tarballs.
# CVS_TARBALL_STASH defines where to find them.
CVS_TARBALL_STASH = "http://www.oesources.org/source/current/"

# For a number of software sets it is possible to specify local
# mirror sites where to get the software.
export GNU_MIRROR = "http://mirror.switch.ch/ftp/mirror/gnu"

# URL for own stuff
MY_URL = "http://myserver/projects/oe"

</programlisting>

   </para>
 </sect2>

 <sect2>
 <title>Machine Configuration</title>
   <para>
The machine configuration file <filename>conf/machine/mymach.conf</filename> specifies
the hardware for which a distribution is built.  This includes mainly
the CPU architecture, specific hardware kernel modules and some size
specifications.
   </para>
   <para>
A simple example could look like this:
<programlisting>
#@TYPE: Machine
#@NAME: My own hardware
#@DESCRIPTION: Machine configuration for my system XYZ

# the target CPU architecture
TARGET_ARCH = "arm"

# all compatible binary architectures
IPKG_ARCHS = "all arm armv4 armv4t armv5e armv5te ipaqpxa mymach"

# some packages for which we know they work best for our hardware
PREFERRED_PROVIDER_xserver ?= "xserver-kdrive"
PREFERRED_PROVIDER_virtual/kernel ?= "mykernel24"

# some packages we always need for this hardware
BOOTSTRAP_EXTRA_DEPENDS = "virtual/kernel sdmmc-support altboot"
BOOTSTRAP_EXTRA_RDEPENDS = "kernel sdmmc-support altboot"
BOOTSTRAP_EXTRA_RDEPENDS += " kernel-module-usbdcore kernel-module-usbdmonitor"

# autoload on boot
module_autoload_mydriver = "mydriver"

# compile with XScale optimization
include conf/machine/tune-xscale.conf

# some specific settings
SERIAL_CONSOLE = "115200 ttyS0"
ROOT_FLASH_SIZE = "16"
GUI_MACHINE_CLASS = "smallscreen"

</programlisting>

   </para>
 </sect2>

 <sect2>
 <title>Distribution Configuration</title>
   <para>
The distribution configuration file <filename>conf/distro/mymini.conf</filename> specifies
global configuration parameters for the whole software system on the
target.  The main definition here is the OS setting, but included here are
also internationalization settings or a specific target filesystem layout.
   </para>
   <para>
A simple example could look like this:
<programlisting>
#@TYPE: Distribution
#@NAME: MyMini
#@DESCRIPTION: A minimal base system for my system

# some general descriptions
DISTRO = "MyMini"
DISTRO_NAME = "My Minimal Embedded Linux"
DISTRO_VERSION = "1.0"
DISTRO_TYPE = "release"

# feed definitions for ipkg
FEED_URIS += " \
     base##${MY_URL}/${DISTRO_VERSION}/feed/base \
     updates##${MY_URL}/${DISTRO_VERSION}/feed/updates"

# base system
TARGET_FPU = "soft"
TARGET_OS = "linux-uclibc"

# specific software versions
PREFERRED_PROVIDER_xserver ?= "xserver-kdrive"
PREFERRED_VERSION_xserver-kdrive ?= "20050207"

# i18n
USE_NLS = "yes"

# distro is based on udev
UDEV_DEVFS_RULES = "1"

# distro is ipkg based
INHERIT += " package_ipk"

</programlisting>
<!-- note MY_URL here -->

   </para>
 </sect2>

 <sect2>
 <title>An Image Package</title>
   <para>
The image package recipe <filename>packages/meta/my-image.bb</filename>
builds the base system
for the root filesystem image.  It mainly defines the packages that
are included in the base image.
   </para>
   <para>
A simple example could look like this:
<programlisting>
# general description data
DESCRIPTION = "Core packages for a minimal installation for My"
MAINTAINER = "Me &lt;me@myname.org>"
LICENSE = "GPL"
PR = "r0"

MY_PACKAGES = "base-files-my \
        busybox-my initscripts-colibri netbase \
        sysvinit usbutils modutils-initscripts \
        my-modules24 e2fsprogs-mke2fs diffutils ipkg"

# binary architecture for ipkg
PACKAGE_ARCH = "${MACHINE_ARCH}"

# name
export IMAGE_BASENAME = "my"

# which languages to include
export IMAGE_LINGUAS = ""

# which packages to include
export IPKG_INSTALL = ${MY_PACKAGES}

# give the packages again so the build systems knows they must be built
DEPENDS = ${MY_PACKAGES}

# inherit the class that finally builds the image
inherit image_ipk

</programlisting>

   </para>
 </sect2>

 <sect2>
 <title>A Kernel Package</title>
   <para>
The kernel is typically specific to a hardware, so usually an own kernel
package is required.
   </para>
   <para>
A simple example <filename>packages/linux/mymach24_2.4.29-mymach</filename>
could look like this:
<programlisting>
DESCRIPTION = "Linux kernel 2.4 for My hardware"
MAINTAINER = "Me &lt;me@myname.org>"
SECTION = "kernel"
LICENSE = "GPL"
PR = "r0"

# compute the kernel version strings
KV = "${@bb.data.getVar('PV',d,True).split('-')[0]}"
MYV = "${@bb.data.getVar('PV',d,True).split('-')[1]}"

# object suffix dependent on kernel version
KERNEL_OBJECT_SUFFIX = ".o"

# where to get the base kernel
SRC_URI = "${KERNEL_MIRROR}/v2./linux-${KV}.tar.bz2"

# where to get my specific patches
SRC_URI_append = " ${MY_URL}/patches/linux-${KV}-${MYV}.patch.gz;patch=1"

# specify the source directory
# (only necessary where it differs from the package name)
S = "${WORKDIR}/linux-${KV}"

# inherit the class that actually does the work building kernels
inherit kernel

# this not only builds the kernel itself but also the modules
PROVIDES += " my-modules24"
PACKAGES += " my-modules24"

# tell the packager where the files for the modules package are found
FILES_my-modules24 = "/lib/modules"

# which machines are supported by this kernel
COMPATIBLE_HOST = "arm.*-linux"

# nothing special is required to build the kernel, as it comes with
# full support for cross compilation
EXTRA_OEMAKE = ""

# the actual configure command
# oe_runmake just runs make
do_configure() {
        oe_runmake mymach_defconfig
}

# clean up after module installation
do_install_append() {
    rm -f ${D}/lib/modules/*/build
    rm -f ${D}/lib/modules/*/source
}

</programlisting>
Some details for this package recipe are explained in the next section.
   </para>
 </sect2>

 <sect2>
 <title>A Package for an Open Source Project</title>
   <para>
Though OpenEmbedded comes with recipes for many Open Source projects,
sometimes a package is required for which no recipe exists yet.
But providing a recipe for that project is generally quite easy.

Most Open Source projects are based on the configure mechanism to build.
<command>configure</command> is a script to collect information about
the build environment
and creates makefiles based on that information.
   </para>
   <para>
But the configure script itself is normally generated through the auto-tools.
The normal OpenEmbedded build process for such a project is to rebuild the
configure script based on the ultimate source <filename>Makefile.am</filename>
and <filename>configure.ac</filename>.
   </para>
   <para>
So, a simple package file for the <command>at</command> tool looks like this:
<programlisting>
DESCRIPTION = "Delayed job execution and batch processing."
SECTION = "base"
LICENSE="BSD"

PR = "r1"

DEPENDS = "flex-native"

SRC_URI = "${DEBIAN_MIRROR}/main/a/at/at_${PV}-11.tar.gz \
	   file://configure.patch;patch=1 \
	   file://nonrootinstall.patch;patch=1"

inherit autotools

</programlisting>
   </para>
   <para>
That's all.  Here a walkthrough for this recipe:
The first three lines in this package file are just general information
(that are included into the resulting binary package).
   </para>
   <para>
<varname>PR</varname> defines the revision and should be incremented
on each change to the package recipe.
   </para>
   <para>
The <varname>DEPENDS</varname> definition states that the building of
this package depends
on an existing flex installation on the host (therefore the
<filename>-native</filename>).
   </para>
   <para>
The <varname>SRC_URI</varname> defines the place of the source files
to be downloaded:
the main distribution tarball with the URL where to find it, and two
specific patches to build this package with OpenEmbedded.
These patches are located together with the package file.
The <varname>patch=1</varname> specifies that this file is to be
applied as patch with <option>-p1</option>.
The <varname>${PV}</varname> in the tarball URL is expanded from the
recipe version
number.  And the recipe version number is taken from the file name
of the recipe.  So, if this recipe is provided as
<filename>packages/at/at_3.1.8.bb</filename>,
<varname>${PV}</varname> is expanded to <varname>3.1.8</varname>.
   </para>
   <para>
The next line essentially does all the work: it inherits the
<classname>autotools</classname>
class that adds the necessary step (task) to rebuild the configure script.
   </para>
   <para>
And that's all.  The <classname>base</classname> class that is inherited
by all packages
defines all the other tasks to build the binary package:
   <itemizedlist mark='bullet'>
     <listitem>
      <para>
 <function>do_fetch()</function>, which does the download
      </para>
     </listitem>
     <listitem>
      <para>
 <function>do_unpack()</function>, which builds the working directory
   and unpacks all files
      </para>
     </listitem>
     <listitem>
      <para>
 <function>do_patch()</function>, which applies the patches
      </para>
     </listitem>
     <listitem>
      <para>
 <function>do_configure()</function>, which runs the configure script
      </para>
     </listitem>
     <listitem>
      <para>
 <function>do_compile()</function>, which basically calls make
      </para>
     </listitem>
     <listitem>
      <para>
 <function>do_stage()</function>, which installs library and header
   files in the cross build environment for subsequent builds
      </para>
     </listitem>
     <listitem>
      <para>
 <function>do_install()</function>, which installs the built files
   into a special packaging area
      </para>
     </listitem>
     <listitem>
      <para>
 <function>do_package()</function>, which collects the files from
   the packaging area and creates (possibly several) packages
      </para>
     </listitem>
   </itemizedlist>
   </para>
   <para>
All these tasks can be overwritten: in the kernel package example above
the <function>do_configure()</function> is redefined to run make with
a special target, and in the inherited <classname>autotools</classname> class
for this example the <function>do_configure()</function> is redefined to
add a <command>autoreconfig</command>
run to rebuild the configure script before the actual configure.
   </para>
 </sect2>

 <sect2>
 <title>Own Software</title>
   <para>
For own software projects it is possible also to use the
<command>auto</command>-tools and <command>configure</command> to create
the makefiles.  But this requires some familiarity
with those tools and is not really necessary.  A standard makefile will
suffice, if some simple rules are observed:
   <itemizedlist mark='bullet'>
     <listitem>
      <para>
 don't use fix pathnames for include, library and install directories,
   use variables for those directories.
      </para>
     </listitem>
     <listitem>
      <para>
 use variables for all building commands (including <command>ar</command>
and <command>nm</command>, if used).
      </para>
     </listitem>
     <listitem>
      <para>
 provide an <varname>install</varname> target.
      </para>
     </listitem>
   </itemizedlist>
   </para>
   <para>
So, a makefile for the standard "Hello, World" example would look like this:
<programlisting>
CC = arm-linux-gcc
LD = arm-linux-ld
CXX = arm-linux-g++
INSTALL = install

prefix = ""
bindir = $(prefix)/usr/bin

TARGETS = hello

all: $(TARGETS)

hello: hello.cxx
        $(CXX) $(CXXFLAGS) -o $@ $<

clean:
        rm -f *.o $(TARGETS) *~

install:
        $(INSTALL) hello $(bindir)

</programlisting>
   </para>
   <para>
The next decision to make is how to provide the source code:
it might either be available through some download mechanism, possibly
from a local CVS server, or it might be added as a local tarball to the
package file.
   </para>
   <para>
Based on that, the actual package recipe file is pretty simple:
<programlisting>
DESCRIPTION = "Hello world example"
SECTION = "base"
LICENSE="BSD"
MAINTAINER = "Me &lt;me@myname.org>"

PR = "r0"

SRC_URI = "file://hello-${PV}.tar.gz"

# just don't do any configuring
do_configure() {
}
</programlisting>
   </para>
   <para>
The recipes shown here are all pretty simple.  But actually 90% of
the recipes in OpenEmbedded are not much more complex.  And for
more complex packages normally some recipes already exist, if not
for exactly the wanted package then for a similar one.
   </para>
   <para>
And for the really complicated cases the OpenEmbedded developers
on the mailing list are always helpful.
   </para>
 </sect2>
</sect1>


<sect1 id="conclusion">
<title>Conclusion</title>
 <para>
Most embedded Linux systems currently follow the full image approach:
if something changes, the complete image is rebuilt and deployed.
 </para>

 <para>
An embedded Linux distribution that provides a package system
follows a different approach: the original image provides only
a base system that is augmented incrementally by separate packages.
 </para>

 <para>
OpenEmbedded provides not only such a package system, but also the
tools to build these packages, i.e. the BitBake build tools
and all the metadata in form of predefined classes for most
common tasks for building an embedded Linux distribution.
 </para>

 <para>
And OpenEmbedded comes with lots of ready-to-use package recipes
for Open Source tools, libraries and applications.
 </para>

 <para>
But OpenEmbedded has also drawbacks:
It is quite complex and though this complexity is often hidden
in the provided classes, it is sometimes necessary to understand
that complexity.  And though most package recipes are quite simple,
even these simple things must be learned, and documentation is a bit scarce.
But the OpenEmbedded developers on the mailing list are generally
friendly and willingly provide some pointers to solve simple
and complex tasks.
 </para>

 <para>
Another drawback is the amounts of resources required to build
OpenEmbedded: to build a basic distribution including a GUI
takes several hours; to build everything takes nearly two
days on a Pentium M @ 2GHz.  And it takes about 30GHz disk space.
 </para>

 <para>
A last drawback is the SCM monotone used by OpenEmbedded:
pulling and updating is quite slow.
 </para>

 <para>
Some of these drawbacks are just due to the fact that OpenEmbedded
now provides a huge repository of recipes: to build one package
and its dependencies, OpenEmbedded must parse all recipes to know
which recipe provides what, and with more than 3000 recipes this
takes some time.  But the OpenEmbedded developers are aware especially
of the performance problems (they are bitten themselves most by them)
and try to solve at least some of them.
 </para>
</sect1>

 <bibliography>
  <title>References</title>
  <biblioentry id="OpenEmbeddedBib">
   <title>OpenEmbedded Homepage</title>
   <bibliomisc>
    <ulink url="http://www.openembedded.org/">
http://www.openembedded.org/
    </ulink>
   </bibliomisc>
  </biblioentry>

  <biblioentry>
   <title>Developer Documentation</title>
   <bibliomisc>
    <ulink url="http://oe.handhelds.org/cgi-bin/moin.cgi">
http://oe.handhelds.org/cgi-bin/moin.cgi
    </ulink>
   </bibliomisc>
  </biblioentry>

  <biblioentry>
   <title>OpenEmbedded recipe hints</title>
   <bibliomisc>
    <ulink url="http://oe.handhelds.org/cgi-bin/moin.cgi/bb_20file">
http://oe.handhelds.org/cgi-bin/moin.cgi/bb_20file
    </ulink>
   </bibliomisc>
  </biblioentry>

  <biblioentry>
   <title>BitBake manual</title>
   <bibliomisc>
    <ulink url="http://bitbake.berlios.de/manual/">
http://bitbake.berlios.de/manual/
    </ulink>
   </bibliomisc>
  </biblioentry>

  <biblioentry>
   <title>iPKG</title>
   <bibliomisc>
    <ulink url="http://www.handhelds.org/moin/moin.cgi/Ipkg">
http://www.handhelds.org/moin/moin.cgi/Ipkg
    </ulink>
   </bibliomisc>
  </biblioentry>

  <biblioentry>
   <title>OpenEmbedded monotone hints</title>
   <bibliomisc>
    <ulink url="http://oe.handhelds.org/cgi-bin/moin.cgi/MonotonePhraseBook">
http://oe.handhelds.org/cgi-bin/moin.cgi/MonotonePhraseBook
    </ulink>
   </bibliomisc>
  </biblioentry>

</bibliography>

</article>