I've recently made a foray into building Linux-based embedded systems, a far cry from my usual embedded stuff where I have total control over everything.
As part of that, I'm looking into the Yocto/bitbake/OpenEmbedded build system.
There's one thing I'm grappling with and that's the layering concept, so I'm trying to both figure out the way in which layers use/affect other layers.
From my understanding to date, a .bb
recipe file uses require
to simply include another file, similar to C's #include "myheader.h"
which generally looks locally.
A .bbappend
file in an "upper" layer will auto-magically include the base file then make changes to it, sort of an inherent require
.
In contrast, the inherit
keyword looks for a .bbclass
class file in much the same way as it locates the .bb
files, and inherits all the detials from them (sort of like #include <stdio.h>
which, again generally, looks in the system area(a)).
So the first part of my question is: is my understanding correct? Or am I being too simplistic?
The second part of my question then involves the use of BBEXTENDS
in the light of my current understanding. If we already have the ability to extend a recipe by using require
, what is the purpose of listing said recipes in a BBEXTENDS
variable?
(a) Yes, I'm aware they're both totally implementation dependent in terms of where the headers come from, I'm simply talking about their common use.
The learning curve for Yocto is different than other building systems, that's why I understand your confusion. But trust me, this is worth it. Your questions are related to BitBake so I recommend the BitBake User Manual. Just ensure that you're reading the same version as your poky revision.
require
and include
.require
is similar to include
and can be compared to #include
from C and C++ just like you have written.
Although generally both of them should be used to add some extensions to a recipe (*.bb) which are common to some amount of recipes (simply - can be reused).
For instance: definitions of paths, custom tasks used by couple recipes. The common purpose is to make recipe cleaner and separate some constants for re-usage.
The very important thing -> difference between include
and require
(from BitBake manual):
The include directive does not produce an error when the file cannot be found. Consequently, it is recommended that if the file you are including is expected to exist, you should use require instead of include. Doing so makes sure that an error is produced if the file cannot be found.
As a result: when you include a file to *.bb and it hasn't been found, the BitBake will not raise an error during parsing this recipe.
If you would use require
, the error will be raised. You should use require when the pointed file must exist because it contains important variables/tasks that are mandatory to process.
*.bbappend
mechanism.In the case of *.bbappend
- it's very powerful. The typical usage is whey you are adding some custom modifications to the recipe from other layer (located above layer where original recipe is) by *.bbappend
because (e.g): you are not the maintainer of original recipe or the modifications are only used in your project (then it should be located in your meta-layer). But you can also bbappend
the recipe on the same layer. BitBake parses all layers and then 'creates' an output and executes it. More in chapter Execution from BitBake man.
inherit
.The inherit
mechanism can be used to inherit *.bbclass
where common tasks for some specific purpose are defined so you don't need to write them on your own, e.g: you use inhert cmake
or inherit autotools
to your recipe when it needs to provide output for sources that are built correspondingly by CMake (and you have CMakeLists.txt defined) or autotools (Makefile.am etc.).
The definitions of classes provided by OpenEmbedded are located under /meta/classes/ if you are using Yocto release with poky.
You can check them and you will see that for example autotools.bbclass
has defined (among others) task: autotools_do_configure()
so you don't need to write it from the scratch.
However, you can redefine it in your recipe (by just providing your own definition of this function). If the recipe can't be changed, then you can simply create a *.bbappend
file and write your own function do_configure()
which will override the function from *.bbclass
. Just like in OO languages such as C++ or Java.