3 Recipe Style Guide
3.1 Recipe Naming Conventions
In general, most recipes should follow the naming convention
recipes-category/package/packagename_version.bb
. Recipes for related
projects may share the same package directory. packagename
, category
,
and package
may contain hyphens, but hyphens are not allowed in version
.
If the recipe is tracking a Git revision that does not correspond to a released
version of the software, version
may be git
(e.g. packagename_git.bb
)
3.2 Version Policy
Our versions follow the form <package epoch>:<package version>-<package revision>
or in BitBake variable terms ${PE}:${PV}-${PR}. We
generally follow the Debian
version policy which defines these terms.
In most cases the version PV will be set automatically from the recipe file name. It is recommended to use released versions of software as these are revisions that upstream are expecting people to use.
Package versions should always compare and sort correctly so that upgrades work
as expected. With conventional versions such as 1.4
upgrading to 1.5
this happens naturally, but some versions don’t sort. For example,
1.5 Release Candidate 2
could be written as 1.5rc2
but this sorts after
1.5
, so upgrades from feeds won’t happen correctly.
Instead the tilde (~
) operator can be used, which sorts before the empty
string so 1.5~rc2
comes before 1.5
. There is a historical syntax which
may be found where PV is set as a combination of the prior version
+
the pre-release version, for example PV=1.4+1.5rc2
. This is a valid
syntax but the tilde form is preferred.
For version comparisons, the opkg-compare-versions
program from
opkg-utils
can be useful when attempting to determine how two version
numbers compare to each other. Our definitive version comparison algorithm is
the one within bitbake which aims to match those of the package managers and
Debian policy closely.
When a recipe references a git revision that does not correspond to a released version of software (e.g. is not a tagged version), the PV variable should include the Git revision using the following to make the version clear:
PV = "<version>+git${SRCPV}"
In this case, <version>
should be the most recently released version of the
software from the current source revision (git describe
can be useful for
determining this). Whilst not recommended for published layers, this format is
also useful when using AUTOREV to set the recipe to increment source
control revisions automatically, which can be useful during local development.
3.3 Version Number Changes
The PR variable is used to indicate different revisions of a recipe that reference the same upstream source version. It can be used to force a new version of a package to be installed onto a device from a package feed. These once had to be set manually but in most cases these can now be set and incremented automatically by a PR Server connected with a package feed.
When PV increases, any existing PR value can and should be removed.
If PV changes in such a way that it does not increase with respect to the previous value, you need to increase PE to ensure package managers will upgrade it correctly. If unset you should set PE to “1” since the default of empty is easily confused with “0” depending on the package manager. PE can only have an integer value.
3.4 Recipe formatting
3.4.1 Variable Formatting
Variable assignment should a space around each side of the operator, e.g.
FOO = "bar"
, notFOO="bar"
.Double quotes should be used on the right-hand side of the assignment, e.g.
FOO = "bar"
notFOO = 'bar'
Spaces should be used for indenting variables, with 4 spaces per tab
Long variables should be split over multiple lines when possible by using the continuation character (
\
)When splitting a long variable over multiple lines, all continuation lines should be indented (with spaces) to align with the start of the quote on the first line:
FOO = "this line is \ long \ "
Instead of:
FOO = "this line is \ long \ "
3.4.2 Python Function formatting
Spaces must be used for indenting Python code, with 4 spaces per tab
3.4.3 Shell Function formatting
The formatting of shell functions should be consistent within layers. Some use tabs, some use spaces.
3.5 Recipe metadata
3.5.1 Required Variables
The following variables should be included in all recipes:
SUMMARY: a one line description of the upstream project
DESCRIPTION: an extended description of the upstream project, possibly with multiple lines. If no reasonable description can be written, this may be omitted as it defaults to SUMMARY.
HOMEPAGE: the URL to the upstream projects homepage.
BUGTRACKER: the URL upstream projects bug tracking website, if applicable.
3.5.2 Recipe Ordering
When a variable is defined in recipes and classes, variables should follow the general order when possible:
inherit ...
Build class specific variables such as
EXTRA_QMAKEVARS_POST
and EXTRA_OECONFTasks such as do_configure
There are some cases where ordering is important and these cases would override this default order. Examples include:
PACKAGE_ARCH needing to be set before
inherit packagegroup
Tasks should be ordered based on the order they generally execute. For commonly used tasks this would be:
Custom tasks should be sorted similarly.
Package specific variables are typically grouped together, e.g.:
RDEPENDS:${PN} = “foo”
RDEPENDS:${PN}-libs = “bar”
RRECOMMENDS:${PN} = “one”
RRECOMMENDS:${PN}-libs = “two”
3.5.3 Recipe License Fields
Recipes need to define both the LICENSE and LIC_FILES_CHKSUM variables:
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
, LICENSE, andREADME
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 LICENSE as follows:LICENSE = "GPL-2.0-only"
The licenses you specify within 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 SPDXLICENSEMAP flag names defined inmeta/conf/licenses.conf
.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 LIC_FILES_CHKSUM variable, see the “Tracking License Changes” section.
To determine the correct checksum string, you can list the appropriate files in the 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 “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.
3.5.4 Tips and Guidelines for Writing Recipes
Use BBCLASSEXTEND instead of creating separate recipes such as
-native
and-nativesdk
ones, whenever possible. This avoids having to maintain multiple recipe files at the same time.
3.6 Patch Upstream Status
In order to keep track of patches applied by recipes and ultimately reduce the number of patches that need maintaining, the OpenEmbedded build system requires information about the upstream status of each patch.
In its description, each patch should provide detailed information about the bug that it addresses, such as the URL in a bug tracking system and links to relevant mailing list archives.
Then, you should also add an Upstream-Status:
tag containing one of the
following status strings:
Pending
No determination has been made yet or not yet submitted to upstream.
Submitted [where]
Submitted to upstream, waiting for approval. Optionally include where it was submitted, such as the author, mailing list, etc.
Accepted
Accepted in upstream, expect it to be removed at next update, include expected version info.
Backport
Backported from new upstream version, because we are at a fixed version, include upstream version info.
Denied
Not accepted by upstream, include reason in patch.
Inactive-Upstream [lastcommit: when (and/or) lastrelease: when]
The upstream is no longer available. This typically means a defunct project where no activity has happened for a long time — measured in years. To make that judgement, it is recommended to look at not only when the last release happened, but also when the last commit happened, and whether newly made bug reports and merge requests since that time receive no reaction. It is also recommended to add to the patch description any relevant links where the inactivity can be clearly seen.
Inappropriate [reason]
The patch is not appropriate for upstream, include a brief reason on the same line enclosed with
[]
. The reason can be:not author
(you are not the author and do not intend to upstream this, the source must be listed in the comments)native
licensing
configuration
enable feature
disable feature
bugfix
(add bug URL here)embedded specific
other
(give details in comments)
The various Inappropriate [reason]
status items are meant to indicate that
the person responsible for adding this patch to the system does not intend to
upstream the patch for a specific reason.
Of course, if another person later takes care of submitting this patch upstream,
the status should be changed to Submitted [where]
, and an additional
Signed-off-by:
line should be added to the patch by the person claiming
responsibility for upstreaming.
For example, if the patch has been submitted upstream:
rpm: Adjusted the foo setting in bar
[RPM Ticket #65] -- http://rpm5.org/cvs/tktview?tn=65,5
The foo setting in bar was decreased from X to X-50% in order to
ensure we don't exhaust all system memory with foobar threads.
Upstream-Status: Submitted [rpm5-devel@rpm5.org]
Signed-off-by: Joe Developer <joe.developer@example.com>
A future update can change the value to Accepted
or Denied
as
appropriate.