123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674 |
- .. SPDX-License-Identifier: CC-BY-SA-2.0-UK
- Writing a New Recipe
- ********************
- Recipes (``.bb`` files) are fundamental components in the Yocto Project
- environment. Each software component built by the OpenEmbedded build
- system requires a recipe to define the component. This section describes
- how to create, write, and test a new recipe.
- .. note::
- For information on variables that are useful for recipes and for
- information about recipe naming issues, see the
- ":ref:`ref-manual/varlocality:recipes`" section of the Yocto Project
- Reference Manual.
- Overview
- ========
- The following figure shows the basic process for creating a new recipe.
- The remainder of the section provides details for the steps.
- .. image:: figures/recipe-workflow.png
- :align: center
- :width: 50%
- Locate or Automatically Create a Base Recipe
- ============================================
- You can always write a recipe from scratch. However, there are three choices
- that can help you quickly get started with a new recipe:
- - ``devtool add``: A command that assists in creating a recipe and an
- environment conducive to development.
- - ``recipetool create``: A command provided by the Yocto Project that
- automates creation of a base recipe based on the source files.
- - *Existing Recipes:* Location and modification of an existing recipe
- that is similar in function to the recipe you need.
- .. note::
- For information on recipe syntax, see the
- ":ref:`dev-manual/new-recipe:recipe syntax`" section.
- Creating the Base Recipe Using ``devtool add``
- ----------------------------------------------
- The ``devtool add`` command uses the same logic for auto-creating the
- recipe as ``recipetool create``, which is listed below. Additionally,
- however, ``devtool add`` sets up an environment that makes it easy for
- you to patch the source and to make changes to the recipe as is often
- necessary when adding a recipe to build a new piece of software to be
- included in a build.
- You can find a complete description of the ``devtool add`` command in
- the ":ref:`sdk-manual/extensible:a closer look at \`\`devtool add\`\``" section
- in the Yocto Project Application Development and the Extensible Software
- Development Kit (eSDK) manual.
- Creating the Base Recipe Using ``recipetool create``
- ----------------------------------------------------
- ``recipetool create`` automates creation of a base recipe given a set of
- source code files. As long as you can extract or point to the source
- files, the tool will construct a recipe and automatically configure all
- pre-build information into the recipe. For example, suppose you have an
- application that builds using Autotools. Creating the base recipe using
- ``recipetool`` results in a recipe that has the pre-build dependencies,
- license requirements, and checksums configured.
- To run the tool, you just need to be in your :term:`Build Directory` and
- have sourced the build environment setup script (i.e.
- :ref:`structure-core-script`). To get help on the tool, use the following
- command::
- $ recipetool -h
- NOTE: Starting bitbake server...
- usage: recipetool [-d] [-q] [--color COLOR] [-h] <subcommand> ...
- OpenEmbedded recipe tool
- options:
- -d, --debug Enable debug output
- -q, --quiet Print only errors
- --color COLOR Colorize output (where COLOR is auto, always, never)
- -h, --help show this help message and exit
- subcommands:
- create Create a new recipe
- newappend Create a bbappend for the specified target in the specified
- layer
- setvar Set a variable within a recipe
- appendfile Create/update a bbappend to replace a target file
- appendsrcfiles Create/update a bbappend to add or replace source files
- appendsrcfile Create/update a bbappend to add or replace a source file
- Use recipetool <subcommand> --help to get help on a specific command
- Running ``recipetool create -o OUTFILE`` creates the base recipe and
- locates it properly in the layer that contains your source files.
- Following are some syntax examples:
- - Use this syntax to generate a recipe based on source. Once generated,
- the recipe resides in the existing source code layer::
- recipetool create -o OUTFILE source
- - Use this syntax to generate a recipe using code that
- you extract from source. The extracted code is placed in its own layer
- defined by :term:`EXTERNALSRC`.
- ::
- recipetool create -o OUTFILE -x EXTERNALSRC source
- - Use this syntax to generate a recipe based on source. The options
- direct ``recipetool`` to generate debugging information. Once generated,
- the recipe resides in the existing source code layer::
- recipetool create -d -o OUTFILE source
- Locating and Using a Similar Recipe
- -----------------------------------
- Before writing a recipe from scratch, it is often useful to discover
- whether someone else has already written one that meets (or comes close
- to meeting) your needs. The Yocto Project and OpenEmbedded communities
- maintain many recipes that might be candidates for what you are doing.
- You can find a good central index of these recipes in the
- :oe_layerindex:`OpenEmbedded Layer Index <>`.
- Working from an existing recipe or a skeleton recipe is the best way to
- get started. Here are some points on both methods:
- - *Locate and modify a recipe that is close to what you want to do:*
- This method works when you are familiar with the current recipe
- space. The method does not work so well for those new to the Yocto
- Project or writing recipes.
- Some risks associated with this method are using a recipe that has
- areas totally unrelated to what you are trying to accomplish with
- your recipe, not recognizing areas of the recipe that you might have
- to add from scratch, and so forth. All these risks stem from
- unfamiliarity with the existing recipe space.
- - *Use and modify the following skeleton recipe:* If for some reason
- you do not want to use ``recipetool`` and you cannot find an existing
- recipe that is close to meeting your needs, you can use the following
- structure to provide the fundamental areas of a new recipe.
- ::
- DESCRIPTION = ""
- HOMEPAGE = ""
- LICENSE = ""
- SECTION = ""
- DEPENDS = ""
- LIC_FILES_CHKSUM = ""
- SRC_URI = ""
- Storing and Naming the Recipe
- =============================
- Once you have your base recipe, you should put it in your own layer and
- name it appropriately. Locating it correctly ensures that the
- OpenEmbedded build system can find it when you use BitBake to process
- the recipe.
- - *Storing Your Recipe:* The OpenEmbedded build system locates your
- recipe through the layer's ``conf/layer.conf`` file and the
- :term:`BBFILES` variable. This
- variable sets up a path from which the build system can locate
- recipes. Here is the typical use::
- BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
- ${LAYERDIR}/recipes-*/*/*.bbappend"
- Consequently, you need to be sure you locate your new recipe inside
- your layer such that it can be found.
- You can find more information on how layers are structured in the
- ":ref:`dev-manual/layers:understanding and creating layers`" section.
- - *Naming Your Recipe:* When you name your recipe, you need to follow
- this naming convention::
- basename_version.bb
- Use lower-cased characters and do not include the reserved suffixes
- ``-native``, ``-cross``, ``-initial``, or ``-dev`` casually (i.e. do not use
- them as part of your recipe name unless the string applies). Here are some
- examples:
- .. code-block:: none
- cups_1.7.0.bb
- gawk_4.0.2.bb
- irssi_0.8.16-rc1.bb
- Running a Build on the Recipe
- =============================
- Creating a new recipe is usually an iterative process that requires
- using BitBake to process the recipe multiple times in order to
- progressively discover and add information to the recipe file.
- Assuming you have sourced the build environment setup script (i.e.
- :ref:`structure-core-script`) and you are in the :term:`Build Directory`, use
- BitBake to process your recipe. All you need to provide is the
- ``basename`` of the recipe as described in the previous section::
- $ bitbake basename
- During the build, the OpenEmbedded build system creates a temporary work
- directory for each recipe
- (``${``\ :term:`WORKDIR`\ ``}``)
- where it keeps extracted source files, log files, intermediate
- compilation and packaging files, and so forth.
- The path to the per-recipe temporary work directory depends on the
- context in which it is being built. The quickest way to find this path
- is to have BitBake return it by running the following::
- $ bitbake -e basename | grep ^WORKDIR=
- As an example, assume a Source Directory
- top-level folder named ``poky``, a default :term:`Build Directory` at
- ``poky/build``, and a ``qemux86-poky-linux`` machine target system.
- Furthermore, suppose your recipe is named ``foo_1.3.0.bb``. In this
- case, the work directory the build system uses to build the package
- would be as follows::
- poky/build/tmp/work/qemux86-poky-linux/foo/1.3.0-r0
- Inside this directory you can find sub-directories such as ``image``,
- ``packages-split``, and ``temp``. After the build, you can examine these
- to determine how well the build went.
- .. note::
- You can find log files for each task in the recipe's ``temp``
- directory (e.g. ``poky/build/tmp/work/qemux86-poky-linux/foo/1.3.0-r0/temp``).
- Log files are named ``log.taskname`` (e.g. ``log.do_configure``,
- ``log.do_fetch``, and ``log.do_compile``).
- You can find more information about the build process in
- ":doc:`/overview-manual/development-environment`"
- chapter of the Yocto Project Overview and Concepts Manual.
- Fetching Code
- =============
- The first thing your recipe must do is specify how to fetch the source
- files. Fetching is controlled mainly through the
- :term:`SRC_URI` variable. Your recipe
- must have a :term:`SRC_URI` variable that points to where the source is
- located. For a graphical representation of source locations, see the
- ":ref:`overview-manual/concepts:sources`" section in
- the Yocto Project Overview and Concepts Manual.
- The :ref:`ref-tasks-fetch` task uses
- the prefix of each entry in the :term:`SRC_URI` variable value to determine
- which :ref:`fetcher <bitbake:bitbake-user-manual/bitbake-user-manual-fetching:fetchers>` to use to get your
- source files. It is the :term:`SRC_URI` variable that triggers the fetcher.
- The :ref:`ref-tasks-patch` task uses
- the variable after source is fetched to apply patches. The OpenEmbedded
- build system uses
- :term:`FILESOVERRIDES` for
- scanning directory locations for local files in :term:`SRC_URI`.
- The :term:`SRC_URI` variable in your recipe must define each unique location
- for your source files. It is good practice to not hard-code version
- numbers in a URL used in :term:`SRC_URI`. Rather than hard-code these
- values, use ``${``\ :term:`PV`\ ``}``,
- which causes the fetch process to use the version specified in the
- recipe filename. Specifying the version in this manner means that
- upgrading the recipe to a future version is as simple as renaming the
- recipe to match the new version.
- Here is a simple example from the
- ``meta/recipes-devtools/strace/strace_5.5.bb`` recipe where the source
- comes from a single tarball. Notice the use of the
- :term:`PV` variable::
- SRC_URI = "https://strace.io/files/${PV}/strace-${PV}.tar.xz \
- Files mentioned in :term:`SRC_URI` whose names end in a typical archive
- extension (e.g. ``.tar``, ``.tar.gz``, ``.tar.bz2``, ``.zip``, and so
- forth), are automatically extracted during the
- :ref:`ref-tasks-unpack` task. For
- another example that specifies these types of files, see the
- ":ref:`dev-manual/new-recipe:autotooled package`" section.
- Another way of specifying source is from an SCM. For Git repositories,
- you must specify :term:`SRCREV` and you should specify :term:`PV` to include
- the revision with :term:`SRCPV`. Here is an example from the recipe
- ``meta/recipes-core/musl/gcompat_git.bb``::
- SRC_URI = "git://git.adelielinux.org/adelie/gcompat.git;protocol=https;branch=current"
- PV = "1.0.0+1.1+git${SRCPV}"
- SRCREV = "af5a49e489fdc04b9cf02547650d7aeaccd43793"
- If your :term:`SRC_URI` statement includes URLs pointing to individual files
- fetched from a remote server other than a version control system,
- BitBake attempts to verify the files against checksums defined in your
- recipe to ensure they have not been tampered with or otherwise modified
- since the recipe was written. Two checksums are used:
- ``SRC_URI[md5sum]`` and ``SRC_URI[sha256sum]``.
- If your :term:`SRC_URI` variable points to more than a single URL (excluding
- SCM URLs), you need to provide the ``md5`` and ``sha256`` checksums for
- each URL. For these cases, you provide a name for each URL as part of
- the :term:`SRC_URI` and then reference that name in the subsequent checksum
- statements. Here is an example combining lines from the files
- ``git.inc`` and ``git_2.24.1.bb``::
- SRC_URI = "${KERNELORG_MIRROR}/software/scm/git/git-${PV}.tar.gz;name=tarball \
- ${KERNELORG_MIRROR}/software/scm/git/git-manpages-${PV}.tar.gz;name=manpages"
- SRC_URI[tarball.md5sum] = "166bde96adbbc11c8843d4f8f4f9811b"
- SRC_URI[tarball.sha256sum] = "ad5334956301c86841eb1e5b1bb20884a6bad89a10a6762c958220c7cf64da02"
- SRC_URI[manpages.md5sum] = "31c2272a8979022497ba3d4202df145d"
- SRC_URI[manpages.sha256sum] = "9a7ae3a093bea39770eb96ca3e5b40bff7af0b9f6123f089d7821d0e5b8e1230"
- Proper values for ``md5`` and ``sha256`` checksums might be available
- with other signatures on the download page for the upstream source (e.g.
- ``md5``, ``sha1``, ``sha256``, ``GPG``, and so forth). Because the
- OpenEmbedded build system only deals with ``sha256sum`` and ``md5sum``,
- you should verify all the signatures you find by hand.
- If no :term:`SRC_URI` checksums are specified when you attempt to build the
- recipe, or you provide an incorrect checksum, the build will produce an
- error for each missing or incorrect checksum. As part of the error
- message, the build system provides the checksum string corresponding to
- the fetched file. Once you have the correct checksums, you can copy and
- paste them into your recipe and then run the build again to continue.
- .. note::
- As mentioned, if the upstream source provides signatures for
- verifying the downloaded source code, you should verify those
- manually before setting the checksum values in the recipe and
- continuing with the build.
- This final example is a bit more complicated and is from the
- ``meta/recipes-sato/rxvt-unicode/rxvt-unicode_9.20.bb`` recipe. The
- example's :term:`SRC_URI` statement identifies multiple files as the source
- files for the recipe: a tarball, a patch file, a desktop file, and an
- icon.
- ::
- SRC_URI = "http://dist.schmorp.de/rxvt-unicode/Attic/rxvt-unicode-${PV}.tar.bz2 \
- file://xwc.patch \
- file://rxvt.desktop \
- file://rxvt.png"
- When you specify local files using the ``file://`` URI protocol, the
- build system fetches files from the local machine. The path is relative
- to the :term:`FILESPATH` variable
- and searches specific directories in a certain order:
- ``${``\ :term:`BP`\ ``}``,
- ``${``\ :term:`BPN`\ ``}``, and
- ``files``. The directories are assumed to be subdirectories of the
- directory in which the recipe or append file resides. For another
- example that specifies these types of files, see the
- ":ref:`dev-manual/new-recipe:single .c file package (hello world!)`" section.
- The previous example also specifies a patch file. Patch files are files
- whose names usually end in ``.patch`` or ``.diff`` but can end with
- compressed suffixes such as ``diff.gz`` and ``patch.bz2``, for example.
- The build system automatically applies patches as described in the
- ":ref:`dev-manual/new-recipe:patching code`" section.
- Fetching Code Through Firewalls
- -------------------------------
- Some users are behind firewalls and need to fetch code through a proxy.
- See the ":doc:`/ref-manual/faq`" chapter for advice.
- Limiting the Number of Parallel Connections
- -------------------------------------------
- Some users are behind firewalls or use servers where the number of parallel
- connections is limited. In such cases, you can limit the number of fetch
- tasks being run in parallel by adding the following to your ``local.conf``
- file::
- do_fetch[number_threads] = "4"
- Unpacking Code
- ==============
- During the build, the
- :ref:`ref-tasks-unpack` task unpacks
- the source with ``${``\ :term:`S`\ ``}``
- pointing to where it is unpacked.
- If you are fetching your source files from an upstream source archived
- tarball and the tarball's internal structure matches the common
- convention of a top-level subdirectory named
- ``${``\ :term:`BPN`\ ``}-${``\ :term:`PV`\ ``}``,
- then you do not need to set :term:`S`. However, if :term:`SRC_URI` specifies to
- fetch source from an archive that does not use this convention, or from
- an SCM like Git or Subversion, your recipe needs to define :term:`S`.
- If processing your recipe using BitBake successfully unpacks the source
- files, you need to be sure that the directory pointed to by ``${S}``
- matches the structure of the source.
- Patching Code
- =============
- Sometimes it is necessary to patch code after it has been fetched. Any
- files mentioned in :term:`SRC_URI` whose names end in ``.patch`` or
- ``.diff`` or compressed versions of these suffixes (e.g. ``diff.gz`` are
- treated as patches. The
- :ref:`ref-tasks-patch` task
- automatically applies these patches.
- The build system should be able to apply patches with the "-p1" option
- (i.e. one directory level in the path will be stripped off). If your
- patch needs to have more directory levels stripped off, specify the
- number of levels using the "striplevel" option in the :term:`SRC_URI` entry
- for the patch. Alternatively, if your patch needs to be applied in a
- specific subdirectory that is not specified in the patch file, use the
- "patchdir" option in the entry.
- As with all local files referenced in
- :term:`SRC_URI` using ``file://``,
- you should place patch files in a directory next to the recipe either
- named the same as the base name of the recipe
- (:term:`BP` and
- :term:`BPN`) or "files".
- Licensing
- =========
- Your recipe needs to have both the
- :term:`LICENSE` and
- :term:`LIC_FILES_CHKSUM`
- variables:
- - :term:`LICENSE`: This variable specifies the license for the software.
- If you do not know the license under which the software you are
- building is distributed, you should go to the source code and look
- for that information. Typical files containing this information
- include ``COPYING``, :term:`LICENSE`, and ``README`` files. You could
- also find the information near the top of a source file. For example,
- given a piece of software licensed under the GNU General Public
- License version 2, you would set :term:`LICENSE` as follows::
- LICENSE = "GPL-2.0-only"
- The licenses you specify within :term:`LICENSE` can have any name as long
- as you do not use spaces, since spaces are used as separators between
- license names. For standard licenses, use the names of the files in
- ``meta/files/common-licenses/`` or the :term:`SPDXLICENSEMAP` flag names
- defined in ``meta/conf/licenses.conf``.
- - :term:`LIC_FILES_CHKSUM`: The OpenEmbedded build system uses this
- variable to make sure the license text has not changed. If it has,
- the build produces an error and it affords you the chance to figure
- it out and correct the problem.
- You need to specify all applicable licensing files for the software.
- At the end of the configuration step, the build process will compare
- the checksums of the files to be sure the text has not changed. Any
- differences result in an error with the message containing the
- current checksum. For more explanation and examples of how to set the
- :term:`LIC_FILES_CHKSUM` variable, see the
- ":ref:`dev-manual/licenses:tracking license changes`" section.
- To determine the correct checksum string, you can list the
- appropriate files in the :term:`LIC_FILES_CHKSUM` variable with incorrect
- md5 strings, attempt to build the software, and then note the
- resulting error messages that will report the correct md5 strings.
- See the ":ref:`dev-manual/new-recipe:fetching code`" section for
- additional information.
- Here is an example that assumes the software has a ``COPYING`` file::
- LIC_FILES_CHKSUM = "file://COPYING;md5=xxx"
- When you try to build the
- software, the build system will produce an error and give you the
- correct string that you can substitute into the recipe file for a
- subsequent build.
- Dependencies
- ============
- Most software packages have a short list of other packages that they
- require, which are called dependencies. These dependencies fall into two
- main categories: build-time dependencies, which are required when the
- software is built; and runtime dependencies, which are required to be
- installed on the target in order for the software to run.
- Within a recipe, you specify build-time dependencies using the
- :term:`DEPENDS` variable. Although there are nuances,
- items specified in :term:`DEPENDS` should be names of other
- recipes. It is important that you specify all build-time dependencies
- explicitly.
- Another consideration is that configure scripts might automatically
- check for optional dependencies and enable corresponding functionality
- if those dependencies are found. If you wish to make a recipe that is
- more generally useful (e.g. publish the recipe in a layer for others to
- use), instead of hard-disabling the functionality, you can use the
- :term:`PACKAGECONFIG` variable to allow functionality and the
- corresponding dependencies to be enabled and disabled easily by other
- users of the recipe.
- Similar to build-time dependencies, you specify runtime dependencies
- through a variable -
- :term:`RDEPENDS`, which is
- package-specific. All variables that are package-specific need to have
- the name of the package added to the end as an override. Since the main
- package for a recipe has the same name as the recipe, and the recipe's
- name can be found through the
- ``${``\ :term:`PN`\ ``}`` variable, then
- you specify the dependencies for the main package by setting
- ``RDEPENDS:${PN}``. If the package were named ``${PN}-tools``, then you
- would set ``RDEPENDS:${PN}-tools``, and so forth.
- Some runtime dependencies will be set automatically at packaging time.
- These dependencies include any shared library dependencies (i.e. if a
- package "example" contains "libexample" and another package "mypackage"
- contains a binary that links to "libexample" then the OpenEmbedded build
- system will automatically add a runtime dependency to "mypackage" on
- "example"). See the
- ":ref:`overview-manual/concepts:automatically added runtime dependencies`"
- section in the Yocto Project Overview and Concepts Manual for further
- details.
- Configuring the Recipe
- ======================
- Most software provides some means of setting build-time configuration
- options before compilation. Typically, setting these options is
- accomplished by running a configure script with options, or by modifying
- a build configuration file.
- .. note::
- As of Yocto Project Release 1.7, some of the core recipes that
- package binary configuration scripts now disable the scripts due to
- the scripts previously requiring error-prone path substitution. The
- OpenEmbedded build system uses ``pkg-config`` now, which is much more
- robust. You can find a list of the ``*-config`` scripts that are disabled
- in the ":ref:`migration-1.7-binary-configuration-scripts-disabled`" section
- in the Yocto Project Reference Manual.
- A major part of build-time configuration is about checking for
- build-time dependencies and possibly enabling optional functionality as
- a result. You need to specify any build-time dependencies for the
- software you are building in your recipe's
- :term:`DEPENDS` value, in terms of
- other recipes that satisfy those dependencies. You can often find
- build-time or runtime dependencies described in the software's
- documentation.
- The following list provides configuration items of note based on how
- your software is built:
- - *Autotools:* If your source files have a ``configure.ac`` file, then
- your software is built using Autotools. If this is the case, you just
- need to modify the configuration.
- When using Autotools, your recipe needs to inherit the
- :ref:`autotools <ref-classes-autotools>` class and it does not have to
- contain a :ref:`ref-tasks-configure` task. However, you might still want to
- make some adjustments. For example, you can set :term:`EXTRA_OECONF` or
- :term:`PACKAGECONFIG_CONFARGS` to pass any needed configure options that
- are specific to the recipe.
- - *CMake:* If your source files have a ``CMakeLists.txt`` file, then
- your software is built using CMake. If this is the case, you just
- need to modify the configuration.
- When you use CMake, your recipe needs to inherit the
- :ref:`cmake <ref-classes-cmake>` class and it does not have to contain a
- :ref:`ref-tasks-configure` task. You can make some adjustments by setting
- :term:`EXTRA_OECMAKE` to pass any needed configure options that are
- specific to the recipe.
- .. note::
- If you need to install one or more custom CMake toolchain files
- that are supplied by the application you are building, install the
- files to ``${D}${datadir}/cmake/Modules`` during :ref:`ref-tasks-install`.
- - *Other:* If your source files do not have a ``configure.ac`` or
- ``CMakeLists.txt`` file, then your software is built using some
- method other than Autotools or CMake. If this is the case, you
- normally need to provide a
- :ref:`ref-tasks-configure` task
- in your recipe unless, of course, there is nothing to configure.
- Even if your software is not being built by Autotools or CMake, you
- still might not need to deal with any configuration issues. You need
- to determine if configuration is even a required step. You might need
- to modify a Makefile or some configuration file used for the build to
- specify necessary build options. Or, perhaps you might need to run a
- provided, custom configure script with the appropriate options.
- For the case involving a custom configure script, you would run
- ``./configure --help`` and look for the options you need to set.
- Once configuration succeeds, it is always good practice to look at the
- ``log.do_configure`` file to ensure that the appropriate options have
- been enabled and no additional build-time dependencies need to be added
- to :term:`DEPENDS`. For example, if the configure script reports that it
- found something not mentioned in :term:`DEPENDS`, or that it did not find
- something that it needed for some desired optional functionality, then
- you would need to add those to :term:`DEPENDS`. Looking at the log might
- also reveal items being checked for, enabled, or both that you do not
- want, or items not being found that are in :term:`DEPENDS`, in which case
- you would need to look at passing extra options to the configure script
- as needed. For reference information on configure options specific to
- the software you are building, you can consult the output of the
- ``./configure --help`` command within ``${S}`` or consult the software's
- upstream documentation.
- Using Headers to Interface with Devices
- =======================================
- If your recipe builds an application that needs to communicate with some
- device or needs an API into a custom kernel, you will need to provide
- appropriate header files. Under no circumstances should you ever modify
- the existing
- ``meta/recipes-kernel/linux-libc-headers/linux-libc-headers.inc`` file.
- These headers are used to build ``libc`` and must not be compromised
- with custom or machine-specific header information. If you customize
- ``libc`` through modified headers all other applications that use
- ``libc`` thus become affected.
- .. note::
- Never copy and customize the ``libc`` header file (i.e.
- ``meta/recipes-kernel/linux-libc-headers/linux-libc-headers.inc``).
- The correct way to interface to a device or custom kernel is to use a
- separate package that provides the additional headers for the driver or
- other unique interfaces. When doing so, your application also becomes
- responsible for creating a dependency on that specific provider.
- Consider the following:
- - Never modify ``linux-libc-headers.inc``. Consider that file to be
- part of the ``libc`` system, and not something you use to access the
- kernel directly. You should access ``libc`` through specific ``libc``
- calls.
- - Applications that must talk directly to devices should either provide
- necessary headers themselves, or establish a dependency on a special
- headers package that is specific to that driver.
- For example, suppose you want to modify an existing header that adds I/O
- control or network support. If the modifications are used by a small
- number programs, providing a unique version of a header is easy and has
- little impact. When doing so, bear in mind the guidelines in the
- previous list.
- .. note::
- If for some reason your changes need to modify the behavior of the ``libc``,
- and subsequently all other applications on the system, use a ``.bbappend``
- to modify the ``linux-kernel-headers.inc`` file. However, take care to not
- make the changes machine specific.
- Consider a case where your kernel is older and you need an older
- ``libc`` ABI. The headers installed by your recipe should still be a
- standard mainline kernel, not your own custom one.
- When you use custom kernel headers you need to get them from
- :term:`STAGING_KERNEL_DIR`,
- which is the directory with kernel headers that are required to build
- out-of-tree modules. Your recipe will also need the following::
- do_configure[depends] += "virtual/kernel:do_shared_workdir"
- Compilation
- ===========
- During a build, the :ref:`ref-tasks-compile` task happens after source is fetched,
- unpacked, and configured. If the recipe passes through :ref:`ref-tasks-compile`
- successfully, nothing needs to be done.
- However, if the compile step fails, you need to diagnose the failure.
- Here are some common issues that cause failures.
- .. note::
- For cases where improper paths are detected for configuration files
- or for when libraries/headers cannot be found, be sure you are using
- the more robust ``pkg-config``. See the note in section
- ":ref:`dev-manual/new-recipe:Configuring the Recipe`" for additional information.
- - *Parallel build failures:* These failures manifest themselves as
- intermittent errors, or errors reporting that a file or directory
- that should be created by some other part of the build process could
- not be found. This type of failure can occur even if, upon
- inspection, the file or directory does exist after the build has
- failed, because that part of the build process happened in the wrong
- order.
- To fix the problem, you need to either satisfy the missing dependency
- in the Makefile or whatever script produced the Makefile, or (as a
- workaround) set :term:`PARALLEL_MAKE` to an empty string::
- PARALLEL_MAKE = ""
- For information on parallel Makefile issues, see the
- ":ref:`dev-manual/debugging:debugging parallel make races`" section.
- - *Improper host path usage:* This failure applies to recipes building
- for the target or ":ref:`nativesdk <ref-classes-nativesdk>`" only. The
- failure occurs when the compilation process uses improper headers,
- libraries, or other files from the host system when cross-compiling for
- the target.
- To fix the problem, examine the ``log.do_compile`` file to identify
- the host paths being used (e.g. ``/usr/include``, ``/usr/lib``, and
- so forth) and then either add configure options, apply a patch, or do
- both.
- - *Failure to find required libraries/headers:* If a build-time
- dependency is missing because it has not been declared in
- :term:`DEPENDS`, or because the
- dependency exists but the path used by the build process to find the
- file is incorrect and the configure step did not detect it, the
- compilation process could fail. For either of these failures, the
- compilation process notes that files could not be found. In these
- cases, you need to go back and add additional options to the
- configure script as well as possibly add additional build-time
- dependencies to :term:`DEPENDS`.
- Occasionally, it is necessary to apply a patch to the source to
- ensure the correct paths are used. If you need to specify paths to
- find files staged into the sysroot from other recipes, use the
- variables that the OpenEmbedded build system provides (e.g.
- :term:`STAGING_BINDIR`, :term:`STAGING_INCDIR`, :term:`STAGING_DATADIR`, and so
- forth).
- Installing
- ==========
- During :ref:`ref-tasks-install`, the task copies the built files along with their
- hierarchy to locations that would mirror their locations on the target
- device. The installation process copies files from the
- ``${``\ :term:`S`\ ``}``,
- ``${``\ :term:`B`\ ``}``, and
- ``${``\ :term:`WORKDIR`\ ``}``
- directories to the ``${``\ :term:`D`\ ``}``
- directory to create the structure as it should appear on the target
- system.
- How your software is built affects what you must do to be sure your
- software is installed correctly. The following list describes what you
- must do for installation depending on the type of build system used by
- the software being built:
- - *Autotools and CMake:* If the software your recipe is building uses
- Autotools or CMake, the OpenEmbedded build system understands how to
- install the software. Consequently, you do not have to have a
- :ref:`ref-tasks-install` task as part of your recipe. You just need to make
- sure the install portion of the build completes with no issues.
- However, if you wish to install additional files not already being
- installed by ``make install``, you should do this using a
- ``do_install:append`` function using the install command as described
- in the "Manual" bulleted item later in this list.
- - *Other (using* ``make install``\ *)*: You need to define a :ref:`ref-tasks-install`
- function in your recipe. The function should call
- ``oe_runmake install`` and will likely need to pass in the
- destination directory as well. How you pass that path is dependent on
- how the ``Makefile`` being run is written (e.g. ``DESTDIR=${D}``,
- ``PREFIX=${D}``, ``INSTALLROOT=${D}``, and so forth).
- For an example recipe using ``make install``, see the
- ":ref:`dev-manual/new-recipe:makefile-based package`" section.
- - *Manual:* You need to define a :ref:`ref-tasks-install` function in your
- recipe. The function must first use ``install -d`` to create the
- directories under
- ``${``\ :term:`D`\ ``}``. Once the
- directories exist, your function can use ``install`` to manually
- install the built software into the directories.
- You can find more information on ``install`` at
- https://www.gnu.org/software/coreutils/manual/html_node/install-invocation.html.
- For the scenarios that do not use Autotools or CMake, you need to track
- the installation and diagnose and fix any issues until everything
- installs correctly. You need to look in the default location of
- ``${D}``, which is ``${WORKDIR}/image``, to be sure your files have been
- installed correctly.
- .. note::
- - During the installation process, you might need to modify some of
- the installed files to suit the target layout. For example, you
- might need to replace hard-coded paths in an initscript with
- values of variables provided by the build system, such as
- replacing ``/usr/bin/`` with ``${bindir}``. If you do perform such
- modifications during :ref:`ref-tasks-install`, be sure to modify the
- destination file after copying rather than before copying.
- Modifying after copying ensures that the build system can
- re-execute :ref:`ref-tasks-install` if needed.
- - ``oe_runmake install``, which can be run directly or can be run
- indirectly by the
- :ref:`autotools <ref-classes-autotools>` and
- :ref:`cmake <ref-classes-cmake>` classes,
- runs ``make install`` in parallel. Sometimes, a Makefile can have
- missing dependencies between targets that can result in race
- conditions. If you experience intermittent failures during
- :ref:`ref-tasks-install`, you might be able to work around them by disabling
- parallel Makefile installs by adding the following to the recipe::
- PARALLEL_MAKEINST = ""
- See :term:`PARALLEL_MAKEINST` for additional information.
- - If you need to install one or more custom CMake toolchain files
- that are supplied by the application you are building, install the
- files to ``${D}${datadir}/cmake/Modules`` during
- :ref:`ref-tasks-install`.
- Enabling System Services
- ========================
- If you want to install a service, which is a process that usually starts
- on boot and runs in the background, then you must include some
- additional definitions in your recipe.
- If you are adding services and the service initialization script or the
- service file itself is not installed, you must provide for that
- installation in your recipe using a ``do_install:append`` function. If
- your recipe already has a :ref:`ref-tasks-install` function, update the function
- near its end rather than adding an additional ``do_install:append``
- function.
- When you create the installation for your services, you need to
- accomplish what is normally done by ``make install``. In other words,
- make sure your installation arranges the output similar to how it is
- arranged on the target system.
- The OpenEmbedded build system provides support for starting services two
- different ways:
- - *SysVinit:* SysVinit is a system and service manager that manages the
- init system used to control the very basic functions of your system.
- The init program is the first program started by the Linux kernel
- when the system boots. Init then controls the startup, running and
- shutdown of all other programs.
- To enable a service using SysVinit, your recipe needs to inherit the
- :ref:`update-rc.d <ref-classes-update-rc.d>` class. The class helps
- facilitate safely installing the package on the target.
- You will need to set the
- :term:`INITSCRIPT_PACKAGES`,
- :term:`INITSCRIPT_NAME`,
- and
- :term:`INITSCRIPT_PARAMS`
- variables within your recipe.
- - *systemd:* System Management Daemon (systemd) was designed to replace
- SysVinit and to provide enhanced management of services. For more
- information on systemd, see the systemd homepage at
- https://freedesktop.org/wiki/Software/systemd/.
- To enable a service using systemd, your recipe needs to inherit the
- :ref:`systemd <ref-classes-systemd>` class. See the ``systemd.bbclass`` file
- located in your :term:`Source Directory` section for more information.
- Packaging
- =========
- Successful packaging is a combination of automated processes performed
- by the OpenEmbedded build system and some specific steps you need to
- take. The following list describes the process:
- - *Splitting Files*: The :ref:`ref-tasks-package` task splits the files produced
- by the recipe into logical components. Even software that produces a
- single binary might still have debug symbols, documentation, and
- other logical components that should be split out. The :ref:`ref-tasks-package`
- task ensures that files are split up and packaged correctly.
- - *Running QA Checks*: The
- :ref:`insane <ref-classes-insane>` class adds a
- step to the package generation process so that output quality
- assurance checks are generated by the OpenEmbedded build system. This
- step performs a range of checks to be sure the build's output is free
- of common problems that show up during runtime. For information on
- these checks, see the
- :ref:`insane <ref-classes-insane>` class and
- the ":ref:`ref-manual/qa-checks:qa error and warning messages`"
- chapter in the Yocto Project Reference Manual.
- - *Hand-Checking Your Packages*: After you build your software, you
- need to be sure your packages are correct. Examine the
- ``${``\ :term:`WORKDIR`\ ``}/packages-split``
- directory and make sure files are where you expect them to be. If you
- discover problems, you can set
- :term:`PACKAGES`,
- :term:`FILES`,
- ``do_install(:append)``, and so forth as needed.
- - *Splitting an Application into Multiple Packages*: If you need to
- split an application into several packages, see the
- ":ref:`dev-manual/new-recipe:splitting an application into multiple packages`"
- section for an example.
- - *Installing a Post-Installation Script*: For an example showing how
- to install a post-installation script, see the
- ":ref:`dev-manual/new-recipe:post-installation scripts`" section.
- - *Marking Package Architecture*: Depending on what your recipe is
- building and how it is configured, it might be important to mark the
- packages produced as being specific to a particular machine, or to
- mark them as not being specific to a particular machine or
- architecture at all.
- By default, packages apply to any machine with the same architecture
- as the target machine. When a recipe produces packages that are
- machine-specific (e.g. the
- :term:`MACHINE` value is passed
- into the configure script or a patch is applied only for a particular
- machine), you should mark them as such by adding the following to the
- recipe::
- PACKAGE_ARCH = "${MACHINE_ARCH}"
- On the other hand, if the recipe produces packages that do not
- contain anything specific to the target machine or architecture at
- all (e.g. recipes that simply package script files or configuration
- files), you should use the
- :ref:`allarch <ref-classes-allarch>` class to
- do this for you by adding this to your recipe::
- inherit allarch
- Ensuring that the package architecture is correct is not critical
- while you are doing the first few builds of your recipe. However, it
- is important in order to ensure that your recipe rebuilds (or does
- not rebuild) appropriately in response to changes in configuration,
- and to ensure that you get the appropriate packages installed on the
- target machine, particularly if you run separate builds for more than
- one target machine.
- Sharing Files Between Recipes
- =============================
- Recipes often need to use files provided by other recipes on the build
- host. For example, an application linking to a common library needs
- access to the library itself and its associated headers. The way this
- access is accomplished is by populating a sysroot with files. Each
- recipe has two sysroots in its work directory, one for target files
- (``recipe-sysroot``) and one for files that are native to the build host
- (``recipe-sysroot-native``).
- .. note::
- You could find the term "staging" used within the Yocto project
- regarding files populating sysroots (e.g. the :term:`STAGING_DIR`
- variable).
- Recipes should never populate the sysroot directly (i.e. write files
- into sysroot). Instead, files should be installed into standard
- locations during the
- :ref:`ref-tasks-install` task within
- the ``${``\ :term:`D`\ ``}`` directory. The
- reason for this limitation is that almost all files that populate the
- sysroot are cataloged in manifests in order to ensure the files can be
- removed later when a recipe is either modified or removed. Thus, the
- sysroot is able to remain free from stale files.
- A subset of the files installed by the :ref:`ref-tasks-install` task are
- used by the :ref:`ref-tasks-populate_sysroot` task as defined by the
- :term:`SYSROOT_DIRS` variable to automatically populate the sysroot. It
- is possible to modify the list of directories that populate the sysroot.
- The following example shows how you could add the ``/opt`` directory to
- the list of directories within a recipe::
- SYSROOT_DIRS += "/opt"
- .. note::
- The `/sysroot-only` is to be used by recipes that generate artifacts
- that are not included in the target filesystem, allowing them to share
- these artifacts without needing to use the :term:`DEPLOY_DIR`.
- For a more complete description of the :ref:`ref-tasks-populate_sysroot`
- task and its associated functions, see the
- :ref:`staging <ref-classes-staging>` class.
- Using Virtual Providers
- =======================
- Prior to a build, if you know that several different recipes provide the
- same functionality, you can use a virtual provider (i.e. ``virtual/*``)
- as a placeholder for the actual provider. The actual provider is
- determined at build-time.
- A common scenario where a virtual provider is used would be for the
- kernel recipe. Suppose you have three kernel recipes whose
- :term:`PN` values map to ``kernel-big``,
- ``kernel-mid``, and ``kernel-small``. Furthermore, each of these recipes
- in some way uses a :term:`PROVIDES`
- statement that essentially identifies itself as being able to provide
- ``virtual/kernel``. Here is one way through the
- :ref:`kernel <ref-classes-kernel>` class::
- PROVIDES += "virtual/kernel"
- Any recipe that inherits the :ref:`kernel <ref-classes-kernel>` class is
- going to utilize a :term:`PROVIDES` statement that identifies that recipe as
- being able to provide the ``virtual/kernel`` item.
- Now comes the time to actually build an image and you need a kernel
- recipe, but which one? You can configure your build to call out the
- kernel recipe you want by using the :term:`PREFERRED_PROVIDER` variable. As
- an example, consider the :yocto_git:`x86-base.inc
- </poky/tree/meta/conf/machine/include/x86/x86-base.inc>` include file, which is a
- machine (i.e. :term:`MACHINE`) configuration file. This include file is the
- reason all x86-based machines use the ``linux-yocto`` kernel. Here are the
- relevant lines from the include file::
- PREFERRED_PROVIDER_virtual/kernel ??= "linux-yocto"
- PREFERRED_VERSION_linux-yocto ??= "4.15%"
- When you use a virtual provider, you do not have to "hard code" a recipe
- name as a build dependency. You can use the
- :term:`DEPENDS` variable to state the
- build is dependent on ``virtual/kernel`` for example::
- DEPENDS = "virtual/kernel"
- During the build, the OpenEmbedded build system picks
- the correct recipe needed for the ``virtual/kernel`` dependency based on
- the :term:`PREFERRED_PROVIDER` variable. If you want to use the small kernel
- mentioned at the beginning of this section, configure your build as
- follows::
- PREFERRED_PROVIDER_virtual/kernel ??= "kernel-small"
- .. note::
- Any recipe that :term:`PROVIDES` a ``virtual/*`` item that is ultimately not
- selected through :term:`PREFERRED_PROVIDER` does not get built. Preventing these
- recipes from building is usually the desired behavior since this mechanism's
- purpose is to select between mutually exclusive alternative providers.
- The following lists specific examples of virtual providers:
- - ``virtual/kernel``: Provides the name of the kernel recipe to use
- when building a kernel image.
- - ``virtual/bootloader``: Provides the name of the bootloader to use
- when building an image.
- - ``virtual/libgbm``: Provides ``gbm.pc``.
- - ``virtual/egl``: Provides ``egl.pc`` and possibly ``wayland-egl.pc``.
- - ``virtual/libgl``: Provides ``gl.pc`` (i.e. libGL).
- - ``virtual/libgles1``: Provides ``glesv1_cm.pc`` (i.e. libGLESv1_CM).
- - ``virtual/libgles2``: Provides ``glesv2.pc`` (i.e. libGLESv2).
- .. note::
- Virtual providers only apply to build time dependencies specified with
- :term:`PROVIDES` and :term:`DEPENDS`. They do not apply to runtime
- dependencies specified with :term:`RPROVIDES` and :term:`RDEPENDS`.
- Properly Versioning Pre-Release Recipes
- =======================================
- Sometimes the name of a recipe can lead to versioning problems when the
- recipe is upgraded to a final release. For example, consider the
- ``irssi_0.8.16-rc1.bb`` recipe file in the list of example recipes in
- the ":ref:`dev-manual/new-recipe:storing and naming the recipe`" section.
- This recipe is at a release candidate stage (i.e. "rc1"). When the recipe is
- released, the recipe filename becomes ``irssi_0.8.16.bb``. The version
- change from ``0.8.16-rc1`` to ``0.8.16`` is seen as a decrease by the
- build system and package managers, so the resulting packages will not
- correctly trigger an upgrade.
- In order to ensure the versions compare properly, the recommended
- convention is to set :term:`PV` within the
- recipe to "previous_version+current_version". You can use an additional
- variable so that you can use the current version elsewhere. Here is an
- example::
- REALPV = "0.8.16-rc1"
- PV = "0.8.15+${REALPV}"
- Post-Installation Scripts
- =========================
- Post-installation scripts run immediately after installing a package on
- the target or during image creation when a package is included in an
- image. To add a post-installation script to a package, add a
- ``pkg_postinst:``\ `PACKAGENAME`\ ``()`` function to the recipe file
- (``.bb``) and replace `PACKAGENAME` with the name of the package you want
- to attach to the ``postinst`` script. To apply the post-installation
- script to the main package for the recipe, which is usually what is
- required, specify
- ``${``\ :term:`PN`\ ``}`` in place of
- PACKAGENAME.
- A post-installation function has the following structure::
- pkg_postinst:PACKAGENAME() {
- # Commands to carry out
- }
- The script defined in the post-installation function is called when the
- root filesystem is created. If the script succeeds, the package is
- marked as installed.
- .. note::
- Any RPM post-installation script that runs on the target should
- return a 0 exit code. RPM does not allow non-zero exit codes for
- these scripts, and the RPM package manager will cause the package to
- fail installation on the target.
- Sometimes it is necessary for the execution of a post-installation
- script to be delayed until the first boot. For example, the script might
- need to be executed on the device itself. To delay script execution
- until boot time, you must explicitly mark post installs to defer to the
- target. You can use ``pkg_postinst_ontarget()`` or call
- ``postinst_intercept delay_to_first_boot`` from ``pkg_postinst()``. Any
- failure of a ``pkg_postinst()`` script (including exit 1) triggers an
- error during the
- :ref:`ref-tasks-rootfs` task.
- If you have recipes that use ``pkg_postinst`` function and they require
- the use of non-standard native tools that have dependencies during
- root filesystem construction, you need to use the
- :term:`PACKAGE_WRITE_DEPS`
- variable in your recipe to list these tools. If you do not use this
- variable, the tools might be missing and execution of the
- post-installation script is deferred until first boot. Deferring the
- script to the first boot is undesirable and impossible for read-only
- root filesystems.
- .. note::
- There is equivalent support for pre-install, pre-uninstall, and post-uninstall
- scripts by way of ``pkg_preinst``, ``pkg_prerm``, and ``pkg_postrm``,
- respectively. These scrips work in exactly the same way as does
- ``pkg_postinst`` with the exception that they run at different times. Also,
- because of when they run, they are not applicable to being run at image
- creation time like ``pkg_postinst``.
- Testing
- =======
- The final step for completing your recipe is to be sure that the
- software you built runs correctly. To accomplish runtime testing, add
- the build's output packages to your image and test them on the target.
- For information on how to customize your image by adding specific
- packages, see ":ref:`dev-manual/customizing-images:customizing images`" section.
- Examples
- ========
- To help summarize how to write a recipe, this section provides some
- examples given various scenarios:
- - Recipes that use local files
- - Using an Autotooled package
- - Using a Makefile-based package
- - Splitting an application into multiple packages
- - Adding binaries to an image
- Single .c File Package (Hello World!)
- -------------------------------------
- Building an application from a single file that is stored locally (e.g.
- under ``files``) requires a recipe that has the file listed in the
- :term:`SRC_URI` variable. Additionally, you need to manually write the
- :ref:`ref-tasks-compile` and :ref:`ref-tasks-install` tasks. The :term:`S` variable defines the
- directory containing the source code, which is set to
- :term:`WORKDIR` in this case --- the
- directory BitBake uses for the build.
- ::
- SUMMARY = "Simple helloworld application"
- SECTION = "examples"
- LICENSE = "MIT"
- LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
- SRC_URI = "file://helloworld.c"
- S = "${WORKDIR}"
- do_compile() {
- ${CC} ${LDFLAGS} helloworld.c -o helloworld
- }
- do_install() {
- install -d ${D}${bindir}
- install -m 0755 helloworld ${D}${bindir}
- }
- By default, the ``helloworld``, ``helloworld-dbg``, and
- ``helloworld-dev`` packages are built. For information on how to
- customize the packaging process, see the
- ":ref:`dev-manual/new-recipe:splitting an application into multiple packages`"
- section.
- Autotooled Package
- ------------------
- Applications that use Autotools such as ``autoconf`` and ``automake``
- require a recipe that has a source archive listed in :term:`SRC_URI` and
- also inherit the :ref:`autotools <ref-classes-autotools>` class,
- which contains the definitions of all the steps needed to build an
- Autotool-based application. The result of the build is automatically
- packaged. And, if the application uses NLS for localization, packages
- with local information are generated (one package per language).
- Following is one example: (``hello_2.3.bb``)
- ::
- SUMMARY = "GNU Helloworld application"
- SECTION = "examples"
- LICENSE = "GPL-2.0-or-later"
- LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
- SRC_URI = "${GNU_MIRROR}/hello/hello-${PV}.tar.gz"
- inherit autotools gettext
- The variable :term:`LIC_FILES_CHKSUM` is used to track source license
- changes as described in the
- ":ref:`dev-manual/licenses:tracking license changes`" section in
- the Yocto Project Overview and Concepts Manual. You can quickly create
- Autotool-based recipes in a manner similar to the previous example.
- Makefile-Based Package
- ----------------------
- Applications that use GNU ``make`` also require a recipe that has the
- source archive listed in :term:`SRC_URI`. You do not need to add a
- :ref:`ref-tasks-compile` step since by default BitBake starts the ``make`` command
- to compile the application. If you need additional ``make`` options, you
- should store them in the
- :term:`EXTRA_OEMAKE` or
- :term:`PACKAGECONFIG_CONFARGS`
- variables. BitBake passes these options into the GNU ``make``
- invocation. Note that a :ref:`ref-tasks-install` task is still required.
- Otherwise, BitBake runs an empty :ref:`ref-tasks-install` task by default.
- Some applications might require extra parameters to be passed to the
- compiler. For example, the application might need an additional header
- path. You can accomplish this by adding to the :term:`CFLAGS` variable. The
- following example shows this::
- CFLAGS:prepend = "-I ${S}/include "
- In the following example, ``lz4`` is a makefile-based package::
- SUMMARY = "Extremely Fast Compression algorithm"
- DESCRIPTION = "LZ4 is a very fast lossless compression algorithm, providing compression speed at 400 MB/s per core, scalable with multi-cores CPU. It also features an extremely fast decoder, with speed in multiple GB/s per core, typically reaching RAM speed limits on multi-core systems."
- HOMEPAGE = "https://github.com/lz4/lz4"
- LICENSE = "BSD-2-Clause | GPL-2.0-only"
- LIC_FILES_CHKSUM = "file://lib/LICENSE;md5=ebc2ea4814a64de7708f1571904b32cc \
- file://programs/COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
- file://LICENSE;md5=d57c0d21cb917fb4e0af2454aa48b956 \
- "
- PE = "1"
- SRCREV = "d44371841a2f1728a3f36839fd4b7e872d0927d3"
- SRC_URI = "git://github.com/lz4/lz4.git;branch=release;protocol=https \
- file://CVE-2021-3520.patch \
- "
- UPSTREAM_CHECK_GITTAGREGEX = "v(?P<pver>.*)"
- S = "${WORKDIR}/git"
- # Fixed in r118, which is larger than the current version.
- CVE_CHECK_IGNORE += "CVE-2014-4715"
- EXTRA_OEMAKE = "PREFIX=${prefix} CC='${CC}' CFLAGS='${CFLAGS}' DESTDIR=${D} LIBDIR=${libdir} INCLUDEDIR=${includedir} BUILD_STATIC=no"
- do_install() {
- oe_runmake install
- }
- BBCLASSEXTEND = "native nativesdk"
- Splitting an Application into Multiple Packages
- -----------------------------------------------
- You can use the variables :term:`PACKAGES` and :term:`FILES` to split an
- application into multiple packages.
- Following is an example that uses the ``libxpm`` recipe. By default,
- this recipe generates a single package that contains the library along
- with a few binaries. You can modify the recipe to split the binaries
- into separate packages::
- require xorg-lib-common.inc
- SUMMARY = "Xpm: X Pixmap extension library"
- LICENSE = "MIT"
- LIC_FILES_CHKSUM = "file://COPYING;md5=51f4270b012ecd4ab1a164f5f4ed6cf7"
- DEPENDS += "libxext libsm libxt"
- PE = "1"
- XORG_PN = "libXpm"
- PACKAGES =+ "sxpm cxpm"
- FILES:cxpm = "${bindir}/cxpm"
- FILES:sxpm = "${bindir}/sxpm"
- In the previous example, we want to ship the ``sxpm`` and ``cxpm``
- binaries in separate packages. Since ``bindir`` would be packaged into
- the main :term:`PN` package by default, we prepend the :term:`PACKAGES` variable
- so additional package names are added to the start of list. This results
- in the extra ``FILES:*`` variables then containing information that
- define which files and directories go into which packages. Files
- included by earlier packages are skipped by latter packages. Thus, the
- main :term:`PN` package does not include the above listed files.
- Packaging Externally Produced Binaries
- --------------------------------------
- Sometimes, you need to add pre-compiled binaries to an image. For
- example, suppose that there are binaries for proprietary code,
- created by a particular division of a company. Your part of the company
- needs to use those binaries as part of an image that you are building
- using the OpenEmbedded build system. Since you only have the binaries
- and not the source code, you cannot use a typical recipe that expects to
- fetch the source specified in
- :term:`SRC_URI` and then compile it.
- One method is to package the binaries and then install them as part of
- the image. Generally, it is not a good idea to package binaries since,
- among other things, it can hinder the ability to reproduce builds and
- could lead to compatibility problems with ABI in the future. However,
- sometimes you have no choice.
- The easiest solution is to create a recipe that uses the
- :ref:`bin_package <ref-classes-bin-package>` class
- and to be sure that you are using default locations for build artifacts.
- In most cases, the :ref:`bin_package <ref-classes-bin-package>` class handles "skipping" the
- configure and compile steps as well as sets things up to grab packages
- from the appropriate area. In particular, this class sets ``noexec`` on
- both the :ref:`ref-tasks-configure`
- and :ref:`ref-tasks-compile` tasks,
- sets ``FILES:${PN}`` to "/" so that it picks up all files, and sets up a
- :ref:`ref-tasks-install` task, which
- effectively copies all files from ``${S}`` to ``${D}``. The
- :ref:`bin_package <ref-classes-bin-package>` class works well when the files extracted into ``${S}``
- are already laid out in the way they should be laid out on the target.
- For more information on these variables, see the
- :term:`FILES`,
- :term:`PN`,
- :term:`S`, and
- :term:`D` variables in the Yocto Project
- Reference Manual's variable glossary.
- .. note::
- - Using :term:`DEPENDS` is a good
- idea even for components distributed in binary form, and is often
- necessary for shared libraries. For a shared library, listing the
- library dependencies in :term:`DEPENDS` makes sure that the libraries
- are available in the staging sysroot when other recipes link
- against the library, which might be necessary for successful
- linking.
- - Using :term:`DEPENDS` also allows runtime dependencies between
- packages to be added automatically. See the
- ":ref:`overview-manual/concepts:automatically added runtime dependencies`"
- section in the Yocto Project Overview and Concepts Manual for more
- information.
- If you cannot use the :ref:`bin_package <ref-classes-bin-package>` class, you need to be sure you are
- doing the following:
- - Create a recipe where the
- :ref:`ref-tasks-configure` and
- :ref:`ref-tasks-compile` tasks do
- nothing: It is usually sufficient to just not define these tasks in
- the recipe, because the default implementations do nothing unless a
- Makefile is found in
- ``${``\ :term:`S`\ ``}``.
- If ``${S}`` might contain a Makefile, or if you inherit some class
- that replaces :ref:`ref-tasks-configure` and :ref:`ref-tasks-compile` with custom
- versions, then you can use the
- ``[``\ :ref:`noexec <bitbake-user-manual/bitbake-user-manual-metadata:variable flags>`\ ``]``
- flag to turn the tasks into no-ops, as follows::
- do_configure[noexec] = "1"
- do_compile[noexec] = "1"
- Unlike
- :ref:`bitbake:bitbake-user-manual/bitbake-user-manual-metadata:deleting a task`,
- using the flag preserves the dependency chain from the
- :ref:`ref-tasks-fetch`,
- :ref:`ref-tasks-unpack`, and
- :ref:`ref-tasks-patch` tasks to the
- :ref:`ref-tasks-install` task.
- - Make sure your :ref:`ref-tasks-install` task installs the binaries
- appropriately.
- - Ensure that you set up :term:`FILES`
- (usually
- ``FILES:${``\ :term:`PN`\ ``}``) to
- point to the files you have installed, which of course depends on
- where you have installed them and whether those files are in
- different locations than the defaults.
- Following Recipe Style Guidelines
- =================================
- When writing recipes, it is good to conform to existing style
- guidelines. The :oe_wiki:`OpenEmbedded Styleguide </Styleguide>` wiki page
- provides rough guidelines for preferred recipe style.
- It is common for existing recipes to deviate a bit from this style.
- However, aiming for at least a consistent style is a good idea. Some
- practices, such as omitting spaces around ``=`` operators in assignments
- or ordering recipe components in an erratic way, are widely seen as poor
- style.
- Recipe Syntax
- =============
- Understanding recipe file syntax is important for writing recipes. The
- following list overviews the basic items that make up a BitBake recipe
- file. For more complete BitBake syntax descriptions, see the
- ":doc:`bitbake:bitbake-user-manual/bitbake-user-manual-metadata`"
- chapter of the BitBake User Manual.
- - *Variable Assignments and Manipulations:* Variable assignments allow
- a value to be assigned to a variable. The assignment can be static
- text or might include the contents of other variables. In addition to
- the assignment, appending and prepending operations are also
- supported.
- The following example shows some of the ways you can use variables in
- recipes::
- S = "${WORKDIR}/postfix-${PV}"
- CFLAGS += "-DNO_ASM"
- CFLAGS:append = " --enable-important-feature"
- - *Functions:* Functions provide a series of actions to be performed.
- You usually use functions to override the default implementation of a
- task function or to complement a default function (i.e. append or
- prepend to an existing function). Standard functions use ``sh`` shell
- syntax, although access to OpenEmbedded variables and internal
- methods are also available.
- Here is an example function from the ``sed`` recipe::
- do_install () {
- autotools_do_install
- install -d ${D}${base_bindir}
- mv ${D}${bindir}/sed ${D}${base_bindir}/sed
- rmdir ${D}${bindir}/
- }
- It is
- also possible to implement new functions that are called between
- existing tasks as long as the new functions are not replacing or
- complementing the default functions. You can implement functions in
- Python instead of shell. Both of these options are not seen in the
- majority of recipes.
- - *Keywords:* BitBake recipes use only a few keywords. You use keywords
- to include common functions (``inherit``), load parts of a recipe
- from other files (``include`` and ``require``) and export variables
- to the environment (``export``).
- The following example shows the use of some of these keywords::
- export POSTCONF = "${STAGING_BINDIR}/postconf"
- inherit autoconf
- require otherfile.inc
- - *Comments (#):* Any lines that begin with the hash character (``#``)
- are treated as comment lines and are ignored::
- # This is a comment
- This next list summarizes the most important and most commonly used
- parts of the recipe syntax. For more information on these parts of the
- syntax, you can reference the
- ":doc:`bitbake:bitbake-user-manual/bitbake-user-manual-metadata`" chapter
- in the BitBake User Manual.
- - *Line Continuation (\\):* Use the backward slash (``\``) character to
- split a statement over multiple lines. Place the slash character at
- the end of the line that is to be continued on the next line::
- VAR = "A really long \
- line"
- .. note::
- You cannot have any characters including spaces or tabs after the
- slash character.
- - *Using Variables (${VARNAME}):* Use the ``${VARNAME}`` syntax to
- access the contents of a variable::
- SRC_URI = "${SOURCEFORGE_MIRROR}/libpng/zlib-${PV}.tar.gz"
- .. note::
- It is important to understand that the value of a variable
- expressed in this form does not get substituted automatically. The
- expansion of these expressions happens on-demand later (e.g.
- usually when a function that makes reference to the variable
- executes). This behavior ensures that the values are most
- appropriate for the context in which they are finally used. On the
- rare occasion that you do need the variable expression to be
- expanded immediately, you can use the
- :=
- operator instead of
- =
- when you make the assignment, but this is not generally needed.
- - *Quote All Assignments ("value"):* Use double quotes around values in
- all variable assignments (e.g. ``"value"``). Following is an example::
- VAR1 = "${OTHERVAR}"
- VAR2 = "The version is ${PV}"
- - *Conditional Assignment (?=):* Conditional assignment is used to
- assign a value to a variable, but only when the variable is currently
- unset. Use the question mark followed by the equal sign (``?=``) to
- make a "soft" assignment used for conditional assignment. Typically,
- "soft" assignments are used in the ``local.conf`` file for variables
- that are allowed to come through from the external environment.
- Here is an example where ``VAR1`` is set to "New value" if it is
- currently empty. However, if ``VAR1`` has already been set, it
- remains unchanged::
- VAR1 ?= "New value"
- In this next example, ``VAR1`` is left with the value "Original value"::
- VAR1 = "Original value"
- VAR1 ?= "New value"
- - *Appending (+=):* Use the plus character followed by the equals sign
- (``+=``) to append values to existing variables.
- .. note::
- This operator adds a space between the existing content of the
- variable and the new content.
- Here is an example::
- SRC_URI += "file://fix-makefile.patch"
- - *Prepending (=+):* Use the equals sign followed by the plus character
- (``=+``) to prepend values to existing variables.
- .. note::
- This operator adds a space between the new content and the
- existing content of the variable.
- Here is an example::
- VAR =+ "Starts"
- - *Appending (:append):* Use the ``:append`` operator to append values
- to existing variables. This operator does not add any additional
- space. Also, the operator is applied after all the ``+=``, and ``=+``
- operators have been applied and after all ``=`` assignments have
- occurred. This means that if ``:append`` is used in a recipe, it can
- only be overridden by another layer using the special ``:remove``
- operator, which in turn will prevent further layers from adding it back.
- The following example shows the space being explicitly added to the
- start to ensure the appended value is not merged with the existing
- value::
- CFLAGS:append = " --enable-important-feature"
- You can also use
- the ``:append`` operator with overrides, which results in the actions
- only being performed for the specified target or machine::
- CFLAGS:append:sh4 = " --enable-important-sh4-specific-feature"
- - *Prepending (:prepend):* Use the ``:prepend`` operator to prepend
- values to existing variables. This operator does not add any
- additional space. Also, the operator is applied after all the ``+=``,
- and ``=+`` operators have been applied and after all ``=``
- assignments have occurred.
- The following example shows the space being explicitly added to the
- end to ensure the prepended value is not merged with the existing
- value::
- CFLAGS:prepend = "-I${S}/myincludes "
- You can also use the
- ``:prepend`` operator with overrides, which results in the actions
- only being performed for the specified target or machine::
- CFLAGS:prepend:sh4 = "-I${S}/myincludes "
- - *Overrides:* You can use overrides to set a value conditionally,
- typically based on how the recipe is being built. For example, to set
- the :term:`KBRANCH` variable's
- value to "standard/base" for any target
- :term:`MACHINE`, except for
- qemuarm where it should be set to "standard/arm-versatile-926ejs",
- you would do the following::
- KBRANCH = "standard/base"
- KBRANCH:qemuarm = "standard/arm-versatile-926ejs"
- Overrides are also used to separate
- alternate values of a variable in other situations. For example, when
- setting variables such as
- :term:`FILES` and
- :term:`RDEPENDS` that are
- specific to individual packages produced by a recipe, you should
- always use an override that specifies the name of the package.
- - *Indentation:* Use spaces for indentation rather than tabs. For
- shell functions, both currently work. However, it is a policy
- decision of the Yocto Project to use tabs in shell functions. Realize
- that some layers have a policy to use spaces for all indentation.
- - *Using Python for Complex Operations:* For more advanced processing,
- it is possible to use Python code during variable assignments (e.g.
- search and replacement on a variable).
- You indicate Python code using the ``${@python_code}`` syntax for the
- variable assignment::
- SRC_URI = "ftp://ftp.info-zip.org/pub/infozip/src/zip${@d.getVar('PV',1).replace('.', '')}.tgz
- - *Shell Function Syntax:* Write shell functions as if you were writing
- a shell script when you describe a list of actions to take. You
- should ensure that your script works with a generic ``sh`` and that
- it does not require any ``bash`` or other shell-specific
- functionality. The same considerations apply to various system
- utilities (e.g. ``sed``, ``grep``, ``awk``, and so forth) that you
- might wish to use. If in doubt, you should check with multiple
- implementations --- including those from BusyBox.
|