Contribution guide
The Bob Build Tool and the Basement project are open-source, community-based projects. Contributions are very welcome. The following sections should give some guidance how to create new recipes or improve existing ones.
Before you start
Please read the following chapters about the recipe style. Adhering to the guidelines helps to make the process as frictionless as possible.
The YAML files are checked automatically on Github for some common style
errors. This is done with the help of pre-commit.
You can either install pre-commit for the repository by running pre-commit
install or run it manually before committing via pre-commit run on all
modified files.
Anatomy of a recipe
The general structure of a recipe building some C/C++ code looks like the following:
inherit: [autotools]
depends:
- libs::pcre-lib-1-dev
- use: []
depends:
- libs::pcre-lib-1-tgt
metaEnvironment:
PKG_VERSION: "3.11"
PKG_LICENSE: "GPL-3.0-or-later"
checkoutSCM:
scm: url
url: ${GNU_MIRROR}/grep/grep-${PKG_VERSION}.tar.xz
digestSHA1: "955146a0a4887eca33606e391481bbef37055b86"
stripComponents: 1
buildScript: |
autotoolsBuild $1 \
--without-included-regex
packageScript: |
autotoolsPackageTgt
provideDeps: [ "*-tgt" ]
Any classes that are inherited are named at the top of the recipe. Only include classes that are actually needed.
Usually, recipes depend on other recipes because the package needs other libraries to work. They are named in the depends section. Notice that each dependency is usually listed twice: the build time library dependency (
-dev) that has the headers and the static or dynamic libraries. The same dependencies are again listed as runtime dependency. These packages end with the-tgtsuffix by convention.The metaEnvironment variables describe the package. See Standard meta variables for more details.
The checkoutSCM part fetches the source code. Always make sure that the checkout is determinisitc. This can be a hash sum for tarballs like the example above or a git commit id. If tarballs or other archives are available, they are very much preferred. Only use git clones or other “real” SCMs if release tarballs are not available.
The build script does the actual job of building the package. In case of standard build systems, this should only be a couple of lines, passing necessary configuration options to the standard build system wrappers.
In the
packageScriptthe desired output is fetched from the build tree of the package.As a last step, all runtime dependencies are passed downstream by the provideDeps property.
This pattern is the basis for almost all recipes. Some sections might not be necessary while others need additional things. See the following sections for more information about the various package types.
C / C++ libraries
Libraries with applications
Recipe style guide
There are a couple of general coding style rules:
Indent by 4 spaces
Lines should break after 80 characters. The hard line length limit is 120 characters.
…
Standard meta variables
Meta variables, like the name suggests, hold meta information like the version or license about the recipe. So far, the following standard variables have been defined:
PKG_VERSIONThe version of the package that is built. Must be present when the recipe downloads a source code package. The version number should be exactly like the upstream package declared it. For packages that do not have an exact version number, like untagged git commits, a sensible version string should still be used e.g.,
v0.25.0-4-gee29e75c.PKG_LICENSEThe license of the package as SPDX License Identifier. Must be present when the recipe downloads a source code package. In the best case, a single identifier applies. Sometimes, a more complicated license expression (e.g.
GPL-2.0-only OR BSD-3-Clause) is required. See the SPDX specification for details how licenses are expressed.
Declaring configuration variables
Configuration variables of a recipe are used to parametrize the build of the package. They are used for example to enable or disable certain features.
Such variables should be named like the base name of the recipe. For example,
the recipes/devel/gcc.yaml recipe declares multiple packages but all
configuration variables have a common GCC_ prefix. Rationale: there are
usually no two recipes with the same name in different categories and we want
to keep variable names short. This naming scheme only applies to “public”
variables, though. Variables declared in privateEnvironment can be named as
needed without any restrictions.
Avoid any other prefixes like CONFIG_ or FEATURE_. They usually don’t
add and information about the variable but make it longer.
To make configuration variables discoverable, a dedicated config plugin is
used by the basement project that adds an optional Config recipe key. It be
used to describe configuration variables in a machine-readable format.
Examples:
Config:
FOO_VERSION:
help: overrides the default package version
FOO_DEBUG:
type: bool
help: Enable debugging. Disabled by default.
default: False
FOO_COLOR:
type: choice
required: True
choice:
red:
help: It's red
green:
blue:
FOO_REQUIRED_VAR:
type: str # this is the default type anyway
required: True # But variable must be present
FOO_USERS:
type: int # A C/C++ integer literal
range: [1, 10]
default: 5
FOO_BASE_ADDRESS:
type: hex
prefix: True # Require "0x" prefix
range: [0x00, 0xffffffff] # The range is optional
FOO_NUM:
type: decimal
FOO_MODE:
type: octal
prefix: False # Prevent leading "0"
range: [0, 07777]
Variables declared in this way do not need to be present. You can set the
required key to True to enforce the presence of the variable. Even
though variables in Bob are always string, the format can be constrained by the
Config definition. The following types (type: ...) are available:
strAn arbitrary string. This is the default and does not need to be named.
boolA boolean string that is either
0or1.choiceAn enumeration of allowed values. Each value can optionally have a help string.
intA C/C++ integer literal.
hexA hexadecimal number. By default, a
0xprefix is accepted but not required. SetprefixtoTruewhen requiring a0xprefix. SettingprefixtoFalserejects a0xprefix.decimalA decimal number. Unlike the
inttype, leading zeros are accepted and do not change the interpretation.octalAn octal number. By default, leading zeroes are accepted and do not change the interpretation. Set
prefixtoTruewhen requiring a leading zero. SettingprefixtoFalserejects a leading zero.
All number types (int, hex, decimal, octal) can optionally have
a range property:
type: int
range: [0, 100]
Optionally, a default property might set a default value if the variable is
not present.
Enforced checks:
A
requiredvariable must be present.The
booltype checks that the variable is either0or1.The
choicetype checks that only one of the declared choices is used.Number types are checked that they can be parsed. The
hexandoctaltypes may have prefixes. Their presence or absence is checked depending on theprefixsetting.All number types can have an optional range that is checked.
Class style guide
Regarding the functions in classes, the function name should start with the
class name. The rest of the name is using camel case. For example, for class
foo might define functions fooBuild and fooBarBaz.
Classes should typically have no side effect. They should just declare functions and variables in checkout/build/packageSetup.
Recipe naming
When creating new recipes, the respective layer must be chosen first. Almost
always, the basement-gnu-linux layer is the right one. The only reason to
put something new into the basement layer is when it is required to support
a (new) build system or standard toolchain.
New recipes should be placed next to similar other recipes. Recipes are placed into different categories. The following list should provide some guideline to choose the right category. It is not uncommon that multiple categories apply. In this case, the first matching category of the following list should be used. If in doubt, create a discussion on Github or ask on the mailing list.
libsC and C++ libraries to make other programs work. Libraries are packages that provide header files and static and/or dynamic libraries that are used by other packages. Even if the package additionally provides some application based on the library, the
libscategory should be used.Other languages (e.g. Python) have their own category and libraries of these languages should be placed there. On the other hand, there are sometimes large collections of libraries that are related to each other. Such libraries are further put into sub-categories:
gnomeLibraries that are coming from the Gnome project.
xorgLibraries that are related to the X.Org project.
Some interpreted languages have their own category. This includes the interpreter itself, libraries and applications written in this language.
perlEverything about Perl.
pythonEverything about Python 3. Support for Python 2 has been removed.
The other categories do not really have a preference between each other.
bspAnything with links to specific hardware or hardware configuration information. These are for example firmware like the Arm Trusted Firmware or boot loaders like Grub and U-Boot. On the other hand, this should not include packages of other categories just because they have been modified for a particular SOC. They should stay in their respective category and either get a dedicated sub-category or a vendor suffix.
If BSP components have been modified by a SOC vendor, they should go into a corresponding sub-category. Examples:
imxNXP i.MX series BSP components.
rpiRaspberryPi specific components.
coreBasic files and daemons that are essential to boot the system. This includes utilities to administer system resources, manage user accounts, etc.
dbDatabase Servers and Clients.
develDevelopment utilities, compilers, development environments, libraries, etc. Basically anything that is required to build other software.
editorsSoftware to edit files. Programming environments.
graphicsApplications, utilities and files that are graphics related.
fontsFonts.
gnomeApplications of the GNOME desktop environment.
waylandWayland specific applications and utilities.
xorgX11 specific applications and utilities.
kernelOperating System Kernels and related modules.
multimediaCodecs and support utilities for audio, images and video.
netDaemons and clients to connect the system to the world.
textText processing applications and utilities. This includes dictionaries and converters.
utilsShells, utilities for file/disk manipulation, backup and archive tools, system monitoring, input systems, etc. Basically any tool that does not fit in any of the other categories.
virtualVirtual packages. Inside the virtual category the sub-categories form the same hierarchy like it would for non-virtual packages. That is, any of the main categories can be present.