Last Updated on November 2, 2025
Objectives
This blog post aims to show how to replace the content of a variable in a recipe (BitBake). This recipe resides in a third-party layer. If you’re wondering how to replace the content of a variable in a BitBake recipe of a third-party layer, it is recommended that you start with part 1 (Part 1). Here we show more methods.
The main recipe: in a third-party layer
We have got a third-party layer from somewhere with a recipe called mod-var_1.0.bb. This raises the question: how can you replace a variable’s content?
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
Replace the content of the variable
Append File — python task + prefuncs
In your BitBake manual, you can find: “It is possible to have functions run before and after a task’s main function (task main function). This is done using the [prefuncs] and [postfuncs] flags of the task that lists the functions to run.”
[postfuncs]: List of functions to call after the completion of the task.[prefuncs]: List of functions to call before the task executes.
What’s not mentioned in the BitBake manual is, that although do_mod_var in the recipe is a shell task, we can use this neat trick to set the variable from a python task. (mod-var_1.0.bbappend)
# introduce a python function to set BOOTENV_OVERLAYS_APPEND
#
# but how to call it from a shell function?
#
# The problem is, that we can not call a python function from a shell function,
# but a shell function form a python function
# so let's try with prefuncs
do_mod_var:append() {
bbwarn "bbappend from do_mod_var:append BOOTENV_OVERLAYS_APPEND: ${BOOTENV_OVERLAYS_APPEND}"
}
python do_mod_var_py () {
d.setVar('BOOTENV_OVERLAYS_APPEND', "from-do_mod_var_py-bbappend-imx93-phyboard-nash-jtag.dtbo")
bootenv_overlays_append = d.getVar("BOOTENV_OVERLAYS_APPEND", True)
bb.warn("bbappend BOOTENV_OVERLAYS_APPEND from do_mod_var_py is %s" %bootenv_overlays_append)
}
addtask do_mod_var_py
do_mod_var[prefuncs] += "do_mod_var_py"
bitbake mod-var -c do_mod_var
WARNING: mod-var-1.0-r0 do_mod_var: bbappend BOOTENV_OVERLAYS_APPEND from do_mod_var_py is from-do_mod_var_py-bbappend-imx93-phyboard-nash-jtag.dtbo
WARNING: mod-var-1.0-r0 do_mod_var: bb BOOTENV_OVERLAYS_APPEND: from-do_mod_var_py-bbappend-imx93-phyboard-nash-jtag.dtbo
WARNING: mod-var-1.0-r0 do_mod_var: bbappend from do_mod_var:append BOOTENV_OVERLAYS_APPEND: from-do_mod_var_py-bbappend-imx93-phyboard-nash-jtag.dtbo
bitbake-getvar -r mod-var BOOTENV_OVERLAYS_APPEND
#
# $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"
The output from bitbake-getvar is totally wrong: [prefuncs] are ignored. This stems from the fact, how bitbake-getvar works. It functions like this:
bitbake mod-var -e | awk '/^# \$BOOTENV_OVERLAYS_APPEND \[/,/^BOOTENV_OVERLAYS_APPEND/'
How does this work? The Python task (do_mod_var_py) comes before the shell task (do_mod_var). Line 14 of the .bbappend file overwrites the variable’s content (line 5 of the recipe).
Append File — python task + postfuncs
# introduce a python function to set BOOTENV_OVERLAYS_APPEND
#
# but how to call it from a shell function?
#
# The problem is, that we can not call a python function from a shell function,
# but a shell function form a python function
# so let's try with prefuncs
do_mod_var:append() {
bbwarn "bbappend from do_mod_var:append BOOTENV_OVERLAYS_APPEND: ${BOOTENV_OVERLAYS_APPEND}"
}
python do_mod_var_py () {
d.setVar('BOOTENV_OVERLAYS_APPEND', "from-do_mod_var_py-bbappend-imx93-phyboard-nash-jtag.dtbo")
bootenv_overlays_append = d.getVar("BOOTENV_OVERLAYS_APPEND", True)
bb.warn("bbappend BOOTENV_OVERLAYS_APPEND from do_mod_var_py is %s" %bootenv_overlays_append)
}
addtask do_mod_var_py
do_mod_var[postfuncs] += "do_mod_var_py"
bitbake mod-var -c do_mod_var
WARNING: mod-var-1.0-r0 do_mod_var: bb BOOTENV_OVERLAYS_APPEND: from-bb-imx93-phyboard-nash-jtag.dtbo
WARNING: mod-var-1.0-r0 do_mod_var: bbappend from do_mod_var:append BOOTENV_OVERLAYS_APPEND: from-bb-imx93-phyboard-nash-jtag.dtbo
WARNING: mod-var-1.0-r0 do_mod_var: bbappend BOOTENV_OVERLAYS_APPEND from do_mod_var_py is from-do_mod_var_py-bbappend-imx93-phyboard-nash-jtag.dtbo
bitbake-getvar -r mod-var BOOTENV_OVERLAYS_APPEND
#
# $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"
The output from bitbake-getvar is totally wrong: the [postfuncs] are ignored. If we examine it more closely, this can be clearly seen.
How does it work? The output above shows, that it does what it is supposed to do, but that’s not what we want. [postfuncs] are called after do_mod_var(), but also after do_mod_var():append where the variable content replacement takes place.
Append File — Anonymous Python Code
Anonymous Python Functions: Sometimes it is useful to set variables or perform other operations programmatically during parsing. To do this, you can define special Python functions, called anonymous Python functions, that run at the end of parsing, which means before executing tasks. They’re especially useful for replacing variable content in a BitBake recipe’s treatment of a third-party layer. (mod-var_1.0.bbappend)
# introduce an anonymous python function to replace BOOTENV_OVERLAYS_APPEND
python __anonymous () {
d.setVar('BOOTENV_OVERLAYS_APPEND', "from-python-anonymous-bbappend-imx93-phyboard-nash-jtag.dtbo")
bootenv_overlays_append = d.getVar("BOOTENV_OVERLAYS_APPEND", True)
bb.warn("bbappend BOOTENV_OVERLAYS_APPEND from anonymous python is %s" %bootenv_overlays_append)
}
do_mod_var:append() {
bbwarn "bbappend BOOTENV_OVERLAYS_APPEND: ${BOOTENV_OVERLAYS_APPEND}"
}
bitbake mod-var -c do_mod_var
WARNING: bbappend BOOTENV_OVERLAYS_APPEND from anonymous python is from-python-anonymous-bbappend-imx93-phyboard-nash-jtag.dtbo
WARNING: mod-var-1.0-r0 do_mod_var: bb BOOTENV_OVERLAYS_APPEND: from-python-anonymous-bbappend-imx93-phyboard-nash-jtag.dtbo
WARNING: mod-var-1.0-r0 do_mod_var: bbappend BOOTENV_OVERLAYS_APPEND: from-python-anonymous-bbappend-imx93-phyboard-nash-jtag.dtbo
bitbake-getvar -r mod-var BOOTENV_OVERLAYS_APPEND
WARNING: bbappend BOOTENV_OVERLAYS_APPEND from anonymous python is from-python-anonymous-bbappend-imx93-phyboard-nash-jtag.dtbo
#
# $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 mod-var_1.0.bbappend:4 [__anon_7__workdir_sources_meta_bb_syntax_recipes_mod_var_mod_var_mod_var_1_0_bbappend]
# "from-python-anonymous-bbappend-imx93-phyboard-nash-jtag.dtbo"
# pre-expansion value:
# "from-python-anonymous-bbappend-imx93-phyboard-nash-jtag.dtbo"
BOOTENV_OVERLAYS_APPEND="from-python-anonymous-bbappend-imx93-phyboard-nash-jtag.dtbo"
How does this work? As you can see above, the anonymous Python function is executed before the other tasks are executed. This means, that the variable (BOOTENV_OVERLAYS_APPEND) is set from it.
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 in BitBake recipes and their layers. Stay tuned for part 3.
Appendix
To learn how Embedded Linux works, take a look here. To learn more about the Yocto Project® take a look here.