configyoctobitbake

How can I modify Bitbake variable using code in the local.conf?


I would like to dynamically modify some configuration variables regarding some others. To do so, I added a Python function (I don't mind using a shell function if that is the way to go) in my local.conf file:

# the variable I want to modify
PERSISTENT_BINDS += "${@add_persistent_binds(d)}"

def add_persistent_binds(d):
    bb.plain("Path: edit persistent bind list")
    binds = []
    for entry in oe.data.typed_value("ENTRIES", d):
        if not entry:
            continue
        ta, tb = line.split(None, 1)
        binds.append("/data/sys/" + ta + " /" + tb + "\n")
    return " ".join(binds)

Unfortunately Bitbake gives an error when it parses the function's definition line:

bb.parse.ParseError: ParseError at /home/user/workspace/yocto/build/conf/local.conf:173: unparsed line: 'def add_persistent_binds(d):'

For instance, the following content set in ENTRIES is expected to produce the following content to be added to PERSISTENT_BINDS:

ENTRIES ??= ""
ENTRIES[type] = "list"
ENTRIES[separator] = "\n"

ENTRIES = "\
    foo bar\n\
    dead beef\n\
"
PERSISTENT_BINDS = " \
    ...
    /data/sys/foo /bar\n\
    /data/sys/dead /beef\n\
"

NOTE I cannot just add this "as is" to the PERSISTENT_BINDS because the variable ENTRIES is used at other locations for other purposes.


Solution

  • I don't know what you are trying to do exactly, but here is a solution on how to define your new custom Python method:

    If you want to add your custom Python library in Yocto, you can use the new feature addpylib : Link

    Example:

    meta-custom
    └── lib
        └── custom
            └── __init__.py
    

    Now, in layer.conf of the meta-custom you add:

    addpylib ${LAYERDIR}/lib custom
    

    Now, in meta-custom/lib/custom/__init__.py add:

    from pkgutil import extend_path
    __path__ = extend_path(__path__, __name__)
    
    import bb 
    import oe 
    
    def add_persistent_binds(d):
        bb.plain("Path: edit persistent bind list")
        binds = []
        for entry in oe.data.typed_value("ENTRIES", d):
            if not entry:
                continue
            ta, tb = entry.split(None, 1)
            binds.append("/data/sys/" + ta + " /" + tb + "\n")
        return " ".join(binds)
    

    In local.conf now:

    ENTRIES ??= ""
    ENTRIES[type] = "list"
    ENTRIES[separator] = "\n"
    
    ENTRIES = "\
        foo bar\n\
        dead beef\n\
    "
    
    # Call the custom function:
    PERSISTENT_BINDS += "${@custom.add_persistent_binds(d)}"
    

    To test it, run:

    bitbake-getvar --value PERSISTENT_BINDS
    

    You should get:

       /data/sys/foo /bar
       /data/sys/dead /beef
    

    **** EDIT ****

    The addpylib solution works only for versions >=4.2

    The solution that comes to mind is to create a class and inherit it globally so local.conf can see the custom function:

    def add_persistent_binds(d):
        bb.plain("Path: edit persistent bind list")
        binds = []
        for entry in oe.data.typed_value("ENTRIES", d):
            if not entry:
                continue
            ta, tb = entry.split(None, 1)
            binds.append("/data/sys/" + ta + " /" + tb + "\n")
        return " ".join(binds)
    

    Then, in your local.conf just add:

    INHERIT += "custom"
    
    PERSISTENT_BINDS += "${@add_persistent_binds(d)}"
    ENTRIES ??= ""
    ENTRIES[type] = "list"
    ENTRIES[separator] = "\n"
    
    ENTRIES = "\
        foo bar\n\
        dead beef\n\
    "
    

    And it should work.

    NOTE, remember that INHERIT inherits classes for all recipes, so you can use add_persistent_binds method from any recipe.