Let's use bitbake commands from python!
Tags: python, yocto, showdev
Published: 2022-08-20 12:36:37

## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tapctn2pmysdw1sq5sis.png)

This Tinfoil is a little bit complicated, so it's not easy to use. The actual code is [here](https://git.yoctoproject.org/poky/tree/bitbake/lib/bb/tinfoil.py?h=kirkstone). On the other hand, IF between server_client is defined somewhat nicely [here](https://git.yoctoproject.org/poky/tree/bitbake/lib/bb/command.py?h=kirkstone). Considering these circumstances, it seems like I should do like below.

![How to implement bbclient](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mm9rd1kykc8bip9nkm5h.png)
 
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.

- [IF Specifications](https://angrymane.github.io/bbclient/bbclient.html)
- [Concrete use case](https://angrymane.github.io/bbclient/usecase.html)

## 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.

```Python
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()
```

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).

```Python
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)
```

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

```Python
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)
```

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

```Python
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)
```

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


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