'How to copy whole directories containing subdirectories to /boot (i.e bootfs) in Yocto while inheriting core-image class?

I have a directory which again contains subdirectories, which are built has part of other recipe and moved to DEPLOY_DIR_IMAGE using deploy bb class. So now I want to copy it to main image boot partition.

If it was a single file then appending required filename to IMAGE_EFI_BOOT_FILES variable, then yocto copies it to /boot. But same doesn't work for directories containing subdirectories please provide style to include even the subdirectories. Thank you

PS: I have tried appending IMAGE_EFI_BOOT_FILES += "parent_dir/*" didnt work.



Solution 1:[1]

Note: I am looking for Yocto built-in which can achieve solution for above mentioned , would like to share other way to resolve the functionality for community's benefit.

Add following in bb file if you are using one or refer to talel-belhadjsalem answer to use utils.bbclass.

def add_directory_bootfs(d, dirname, bootfs_dir):
    file_list = list()
    boot_files_list = list()
    deploy_dir_image = d.getVar('DEPLOY_DIR_IMAGE')
    for (dirpath, dirnames, filenames) in os.walk(os.path.join(deploy_dir_image, dirname)):
        file_list += [os.path.join(dirpath, file) for file in filenames]
    for file in file_list:
        file_rel_path = os.path.relpath(file, os.path.join(deploy_dir_image, dirname))
        boot_file_entry = os.path.join(dirname, file_rel_path) + ';' + os.path.join(bootfs_dir, dirname, file_rel_path)
        boot_files_list.append(boot_file_entry)
    return ' '.join(boot_files_list)

IMAGE_EFI_BOOT_FILES += "${@add_directory_bootfs(d, 'relative_path_to_dir_in_deploy_dir_image', 'EFI/BOOT')}"

Solution 2:[2]

It is obvious that IMAGE_EFI_BOOT_FILES is acting like the well known IMAGE_BOOT_FILES and other variables that are responsible for having the files necessary to be shipped in the boot partition. And that needs files and not directories.

So, if you do not need to specify all the files by hand, but instead you want to pass the directory, I suggest you use a python method to collect the files for you and append them to the variable.

See the following example I developed and tested:

def get_files(d, dir):
    import os
    dir_path = dir
    if not os.path.exists(os.path.dirname(dir)):
        dir_path = d.getVar(dir)
    return ' '.join(f for f in os.listdir(d.getVar(dir)) if os.path.isfile(f))

IMAGE_EFI_BOOT_FILES += "${@get_files(d, 'DEPLOY_DIR_IMAGE')}"

The method will test if the argument is a real path then it will directly check for files, if not it will assume that it is a bitbake variable and it will get its content, so if DEPLOY_DIR_IMAGE is, for example, /home/user/dir, passing DEPLOY_DIR_IMAGE or /home/usr/dir will give the same result.

IMPORTANT

It is obvious also that IMAGE_EFI_BOOT_FILES is used in a .conf file such as local.conf or a custom machine configuration file. So adding that python function in .conf file will not work. I suggest creating a class for it and inherit it globally in your .conf file:

  • meta-custom/classes/utils.bbclass

  • local.conf:

INHERIT += "utils"
IMAGE_EFI_BOOT_FILES += "${@get_files(d, 'DEPLOY_DIR_IMAGE')}"

Try this and let me know in the comments.

EDIT

I have just realized that bitbake already imports os within python expressions expansions, so you can do it in one line without any need for a separate python function:

PATH = "/path/to/directory/"  or
PATH = "A variable containing the path"
IMAGE_EFI_BOOT_FILES += "${@' '.join('%s' % f for f in os.listdir('${PATH}') if os.path.isfile(f))}"

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 geralt rivia
Solution 2