Experience with PREFERRED_PROVIDER
What to do
Implementing the optional use of recipes that build source code and recipes that use prebuilt packages. I could have used PREFERRED_VERSION
, but that doesn't fit the purpose of choosing between multiple recipes, so I used PREFERRED_PROVIDER
.
Definitions to know first
PROVIDES
Official documentation: PROVIDES
PROVIDES is a list of aliases.
Let's see the esample eudev
recipe in the official documentation.
eudev.bb
PROVIDES = "udev"
This example makes eudev
a synonym for udev
.
$ bitbake eudev -e | grep ^PROVIDES=
PROVIDES="eudev udev"
$ bitbake udev -e | grep ^PROVIDES=
PROVIDES="eudev udev"
Because the recipe name(PN) is added to the PROVIDER
list by default, providing udev
in the eudev
recipe causes eudev
and udev
to be treated as synonyms, and the DEPENDS
relationship is also satisfied.
Virtual target
When multiple recipes provide the same name to PROVIDES
, PREFERRED_PROVIDER
is used to select a specific recipe, and the virtual target should be used. This is done by prefixing the recipe name with virtual/
.
If B depends on A, A recipe provides the virtual target by adding it to PROVIDES
. B recipe adds A's virtual target to DEPENDS
, and the virtual target selected by PREFERRED_PROVIDER
is applied.
PREFERRED_PROVIDER
Official documentation: PREFERRED_PROVIDER
Take a look at the code below to get an idea of what it looks like.
# tclibc-baremetal.inc
PREFERRED_PROVIDER_virtual/libc ?= "musl"
PREFERRED_PROVIDER_virtual/libiconv ?= "musl"
PREFERRED_PROVIDER_virtual/libintl ?= "gettext"
# tclibc-glibc.inc
PREFERRED_PROVIDER_virtual/libc ?= "glibc"
PREFERRED_PROVIDER_virtual/libiconv ?= "glibc"
PREFERRED_PROVIDER_virtual/libintl ?= "glibc"
# tclibc-newlib.inc
PREFERRED_PROVIDER_virtual/libc ?= "newlib"
PREFERRED_PROVIDER_virtual/libiconv ?= "newlib"
PREFERRED_PROVIDER_virtual/libintl ?= "newlib"
Depending on which inc
file is included, virtual/libc
, virtual/libiconv
, and virtual/libintl
apply different recipes.
defaultsetup.conf
require conf/distro/include/tclibc-${TCLIBC}.inc
# meta/recipes-core/musl/musl_git.bb
PROVIDES += "virtual/libc virtual/libiconv virtual/libintl virtual/crypt"
# meta/recipes-core/newlib/newlib_git.bb
PROVIDES += "virtual/libc virtual/libiconv virtual/libintl"
# recipes-core/glibc/glibc.inc
PROVIDES = "virtual/libc"
PROVIDES += "virtual/libintl virtual/libiconv"
Implementation
Let's apply the above structure so that the recipe is selected differently depending on whether a certain variable is set or not. The recipe named aa is separated into aa-src
, which builds from source, and aa-prebuilt
, which uses a built image, and the virtual target is specified as virtual/vaa
. aa's DEPENDS
has bb appended to it. The recipe named aa is separated into bb-src
, which builds from source, and bb-prebuilt
, which uses a built image, and the virtual target is specified as virtual/vbb
.
use-prebuilt-packages.inc
PREFERRED_PROVIDER_virtual/vaa = "aa-prebuilt"
PREFERRED_PROVIDER_virtual/vbb = "bb-prebuilt"
build-from-sources.inc
PREFERRED_PROVIDER_virtual/vaa = "aa-src"
PREFERRED_PROVIDER_virtual/vbb = "bb-src"
aa-src.bb, aa-prebuilt.bb
PROVIDES = "virtual/vaa"
DEPENDS = "virtual/vbb"
bb-src.bb, bb-prebuilt.bb
PROVIDES = "virtual/vbb"
recipe is chosen based on the included inc file. RDEPENDS
corresponds to RPROVIDES
.
RPROVIDES:${PN} = "virtual/vbb"
RDEPENDS:${PN} = "virtual/vbb"
Now it's achieved my initial goal by using the virtual target name everywhere we reference aa or bb.
Subscribe to my newsletter
Read articles from sean lee directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by