DEV Community

AngryMane
AngryMane

Posted on

Let's use bitbake commands from python!

First of all

I'm working on building a custom linux build using yocto.
In this job, I often get requests like

  • I need a list of files that inherit from a specific bbclass (like core-image.bbclass).
  • I need to list the variables (e.g. PE, PV, PR) with all packages
  • I need to list the bbappend files for a specific package (e.g. gcc).

Isn't that a pain in the ass? I don't want to grep, and I don't want to build because it takes too long...

Let's use Bitbake from python.

It's a pain in the ass I think, so let's investigate how to do something about it. First of all, the build mechanism by bitbake command is roughly like this.

How to build with bitbake

This Tinfoil is a little bit complicated, so it's not easy to use. The actual code is here. On the other hand, IF between server_client is defined somewhat nicely here. Considering these circumstances, it seems like I should do like below.

How to implement bbclient

If I make this bbclient in python, it will be easy to use from language server and so on.

What I made

Based on the results of the study so far, the bbclient I made is shown in below.

https://pypi.org/project/bbclient/

I've also prepared some documentation.

What you can do

There are so many IFs that I can't show you all of them, but for now, let's try to implement the use case I mentioned at the beginning of this article.
First of all, the way to initialize the bbclient instance is shown in below.

import bbclient

# Initialize bbclient instance
project_path: str = "/PATH/TO/POKY"
init_command: str = ". oe-init-build-env"
client: BBClient = BBClient(project_path, init_command)

# launch server 
server_adder: str = "localhost"
server_port: int = 8081
client.start_server(server_adder, server_port)

# set event filter
ui_handler: int = client.get_uihandler_num()
client.set_event_mask(ui_handler, logging.DEBUG, {}, ["*"])

# paser recipes and create caches
ret = client.parse_files()
client.wait_done_async()
Enter fullscreen mode Exit fullscreen mode

You can use this client to implement each of the following use cases.

I need a list of recipe files that inherit a specific bbclass (like core-image.bbclass).

ret: List[GetRecipeInheritsResult] = client.get_recipe_inherits()
recipes_inherit = [i for i in ret if "/PATH/TO/core-image.bbclass" in i.inherit_file_paths]
for i in recipes_inherit:
    print(i.recipe_file_path)
Enter fullscreen mode Exit fullscreen mode

I need you to list the variables (e.g. PE, PV, PR) with all packages

ret: List[GetRecipesResult] = client.get_recipes()
for i in ret:
    data_store_index: int = client.parse_recipe_file(i.recipe_files)
    pe: Any = client.data_store_connector_cmd(data_store_index, "getVar", "PE")
    pv: Any = client.data_store_connector_cmd(data_store_index, "getVar", "PE")
    pr: Any = client.data_store_connector_cmd(data_store_index, "getVar", "PE")
    print(pe, pv, pr)
Enter fullscreen mode Exit fullscreen mode

I need you to list the bbappend files for a specific package (e.g. gcc).

ret: List[str] = client.find_best_provider("gcc")
target_recipe_file_path: str = ret[3]
ret: List[str] = client.get_file_appends(target_recipe_file_path)
print(ret)
Enter fullscreen mode Exit fullscreen mode

You can also build images from this client and generate dependency taskdepends files.

Finally

If you would like to try it, please use it!

Top comments (0)