Experience with PREFERRED_PROVIDER

sean leesean lee
3 min read

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.

0
Subscribe to my newsletter

Read articles from sean lee directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

sean lee
sean lee