Last Updated on November 2, 2025

Objectives

This blog post aims to show how to replace the content of a variable in a BitBake recipe (BitBake). The recipe resides in a third-party layer. Understanding how to replace the content of a variable in a BitBake recipe of a third-party layer is essential for customization. By following the process outlined, you’ll be able to make the necessary modifications effectively.

A recipe in a third party layer (layer)

We have got a third-party layer from somewhere with a recipe called mod-var_1.0.bb:

SUMMARY = "Test case for overwriting/replacing a variable"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

BOOTENV_OVERLAYS_APPEND = "from-bb-imx93-phyboard-nash-jtag.dtbo"

do_mod_var() {
    bbwarn "bb BOOTENV_OVERLAYS_APPEND: ${BOOTENV_OVERLAYS_APPEND}"
}
addtask do_mod_var

Let’s bake it with BitBake. We’ll utilize the procedure on how to replace the content of a variable in a BitBake recipe of a third-party layer further down.

bitbake mod-var -c do_mod_var

And it will output something like this:

WARNING: mod-var-1.0-r0 do_mod_var: bb BOOTENV_OVERLAYS_APPEND: from-bb-imx93-phyboard-nash-jtag.dtbo

We can try to investigate it a bit further and trying to find out who sets the variable (BOOTENV_OVERLAYS_APPEND):

bitbake-getvar -r mod-var BOOTENV_OVERLAYS_APPEND

This will show something like this:

#
# $BOOTENV_OVERLAYS_APPEND
#   set /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bb:5
#     "from-bb-imx93-phyboard-nash-jtag.dtbo"
BOOTENV_OVERLAYS_APPEND="from-bb-imx93-phyboard-nash-jtag.dtbo"

This tells us: The content of the variable BOOTENV_OVERLAYS_APPEND is "from-bb-imx93-phyboard-nash-jtag.dtbo". It was modified in line 5 of this file: mod-var_1.0.bb. When replacing the content of a variable in a BitBake recipe of a third-party layer, consider the specifics of the following examples.

Replace the content of the variable

Append File — Lazy Assignment

The BitBake manual says: “Append files are used to extend or override information in an existing (third-party) recipe file. They have the .bbappend file extension.” Take a look at Basic Variable Setting and Variable Expansion.

In other words: We make a .bbappend file, and we place it in our layer (layer). The directory structure has to be the same as the corresponding third-party layer. Like this, BitBake can find the .bb file. Such as mod-var_1.0.bbappend:

# let the bbappend replace BOOTENV_OVERLAYS_APPEND

BOOTENV_OVERLAYS_APPEND = "from-bbappend-imx93-phyboard-nash-jtag.dtbo"

do_mod_var:append() {
    bbwarn "bbappend BOOTENV_OVERLAYS_APPEND: ${BOOTENV_OVERLAYS_APPEND}"
}
bitbake mod-var -c do_mod_var
WARNING: mod-var-1.0-r0 do_mod_var: bb BOOTENV_OVERLAYS_APPEND: from-bbappend-imx93-phyboard-nash-jtag.dtbo
WARNING: mod-var-1.0-r0 do_mod_var: bbappend BOOTENV_OVERLAYS_APPEND: from-bbappend-imx93-phyboard-nash-jtag.dtbo
bitbake-getvar -r mod-var BOOTENV_OVERLAYS_APPEND
#
# $BOOTENV_OVERLAYS_APPEND [2 operations]
#   set /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bb:5
#     "from-bb-imx93-phyboard-nash-jtag.dtbo"
#   set /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bbappend:3
#     "from-bbappend-imx93-phyboard-nash-jtag.dtbo"
# pre-expansion value:
#   "from-bbappend-imx93-phyboard-nash-jtag.dtbo"
BOOTENV_OVERLAYS_APPEND="from-bbappend-imx93-phyboard-nash-jtag.dtbo"

How does this work? The .bbappend file comes after the .bb file. Line 3 of the .bbappend overwrites the variable’s content (from line 5 of the .bb file).

Append File — Immediate Assignment

Let’s try in our .bbappend (line 3): Immediate Variable Expansion Operator. It would not make any difference to the result:

# let the bbappend replace BOOTENV_OVERLAYS_APPEND

BOOTENV_OVERLAYS_APPEND := "from-bbappend-imx93-phyboard-nash-jtag.dtbo"

do_mod_var:append() {
    bbwarn "bbappend BOOTENV_OVERLAYS_APPEND: ${BOOTENV_OVERLAYS_APPEND}"
}
bitbake mod-var -c do_mod_var
WARNING: mod-var-1.0-r0 do_mod_var: bb BOOTENV_OVERLAYS_APPEND: from-bbappend-imx93-phyboard-nash-jtag.dtbo
WARNING: mod-var-1.0-r0 do_mod_var: bbappend BOOTENV_OVERLAYS_APPEND: from-bbappend-imx93-phyboard-nash-jtag.dtbo
bitbake-getvar -r mod-var BOOTENV_OVERLAYS_APPEND
#
# $BOOTENV_OVERLAYS_APPEND [2 operations]
#   set /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bb:5
#     "from-bb-imx93-phyboard-nash-jtag.dtbo"
#   immediate /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bbappend:3
#     "from-bbappend-imx93-phyboard-nash-jtag.dtbo"
# pre-expansion value:
#   "from-bbappend-imx93-phyboard-nash-jtag.dtbo"
BOOTENV_OVERLAYS_APPEND="from-bbappend-imx93-phyboard-nash-jtag.dtbo"

Append File — Lazy Assignment — Inline Python Code

Inline Python variable expansion: Can be used to set variables. They work just like variable expansions insofar as the “=” and “:=” operators (operators) are concerned. Important note: Utilizing lazy assignment (lazy assignment): Whenever the variable (BOOTENV_OVERLAYS_APPEND) is expanded, what is being executed?⇾ d.SetVar (line 13). Check out the mod-var_1.0.bbappend file.

# let the bbappend replace BOOTENV_OVERLAYS_APPEND
# 
# Note
#
# Inline Python expressions work just like variable expansions insofar as the “=” and “:=” operators are concerned. 
# Given the following assignment, foo() is called each time FOO is expanded:
#
# FOO = "${@foo()}"
# Contrast this with the following immediate assignment, where foo() is only called once, while the assignment is parsed:
#
# FOO := "${@foo()}"

BOOTENV_OVERLAYS_APPEND = "${@d.setVar('BOOTENV_OVERLAYS_APPEND', 'from-bbappend-d.setVar')}"

do_mod_var:append() {
    bbwarn "bbappend BOOTENV_OVERLAYS_APPEND: ${BOOTENV_OVERLAYS_APPEND}"
}
bitbake mod-var -c do_mod_var
WARNING: mod-var-1.0-r0 do_mod_var: bb BOOTENV_OVERLAYS_APPEND: from-bbappend-d.setVar
WARNING: mod-var-1.0-r0 do_mod_var: bbappend BOOTENV_OVERLAYS_APPEND: from-bbappend-d.setVar
bitbake-getvar -r mod-var BOOTENV_OVERLAYS_APPEND
#
# $BOOTENV_OVERLAYS_APPEND [3 operations]
#   set /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bb:5
#     "from-bb-imx93-phyboard-nash-jtag.dtbo"
#   set /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bbappend:13
#     "${@d.setVar('BOOTENV_OVERLAYS_APPEND', 'from-bbappend-d.setVar')}"
#   set Var <BOOTENV_OVERLAYS_APPEND>:1 [<module>]
#     "from-bbappend-d.setVar"
# pre-expansion value:
#   "from-bbappend-d.setVar"
BOOTENV_OVERLAYS_APPEND="from-bbappend-d.setVar"

How does this work? Whenever the variable (BOOTENV_OVERLAYS_APPEND) is expanded, what is being executed?⇾ d.SetVar (line 13).

Append File — Immediate Assignment — Inline Python Code

If we use the Immediate Variable Expansion Operator in line 13 of our file, it would not work. d.setVar is only called once, while the assignment is parsed. The value of BOOTENV_OVERLAYS_APPEND is “None” at this point, since it’s not a global variable, I guess. Understanding the process of how to replace the content of a variable in a BitBake recipe of a third-party layer can help when dealing with assignment issues.


This would result in:

# let the bbappend replace BOOTENV_OVERLAYS_APPEND
# 
# Note
#
# Inline Python expressions work just like variable expansions insofar as the “=” and “:=” operators are concerned. 
# Given the following assignment, foo() is called each time FOO is expanded:
#
# FOO = "${@foo()}"
# Contrast this with the following immediate assignment, where foo() is only called once, while the assignment is parsed:
#
# FOO := "${@foo()}"

BOOTENV_OVERLAYS_APPEND := "${@d.setVar('BOOTENV_OVERLAYS_APPEND', 'from-bbappend-d.setVar')}"

do_mod_var:append() {
    bbwarn "bbappend BOOTENV_OVERLAYS_APPEND: ${BOOTENV_OVERLAYS_APPEND}"
}
bitbake mod-var -c do_mod_var
WARNING: mod-var-1.0-r0 do_mod_var: bb BOOTENV_OVERLAYS_APPEND: None
WARNING: mod-var-1.0-r0 do_mod_var: bbappend BOOTENV_OVERLAYS_APPEND: None
bitbake-getvar -r mod-var BOOTENV_OVERLAYS_APPEND
#
# $BOOTENV_OVERLAYS_APPEND [2 operations]
#   set /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bb:5
#     "from-bb-imx93-phyboard-nash-jtag.dtbo"
#   immediate /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bbappend:13
#     "${@d.setVar('BOOTENV_OVERLAYS_APPEND', 'from-bbappend-d.setVar')}"
# pre-expansion value:
#   "None"
BOOTENV_OVERLAYS_APPEND="None"

There is not much to argue here. That’s the output of the log file (run.do_mod_var):

# line: 7, file: /workdir/sources/meta-bb-syntax/recipes-mod-var/mod-var/mod-var_1.0.bb
do_mod_var() {
    bbwarn "bb BOOTENV_OVERLAYS_APPEND: None"
    bbwarn "bbappend BOOTENV_OVERLAYS_APPEND: None"
}

Conclusion

As always, read the fine print carefully, ask, and experiment. I am writing these kinds of test cases to show attendees of my training sessions how things work and, for me, to understand subtle syntax differences. Stay tuned for part 2 and part3.

Appendix

To learn how Embedded Linux works, take a look here. To learn more about the Yocto Project® take a look here.

Upcoming Events

Our 3 points

of differentiation

We provide host and target hardware during all our teaching.

Three or more people from the same company? We provide private customized training – consulting included.

Subject matter experts develop high-quality, job-related, up-to-date, authentic courseware.

Reliable Embedded Systems
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.