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.