Pular para conteúdo

Dicas Extras e Avançadas


Configurando Hostname sem receita

Uma maneira de configurar o Hostname do TARGET sem criar receita é no <build>/conf/local.conf configurar a variável:

hostname_pn-base-files = "masterBoard"


Adicionando Rotinas na receita da Imagem após gerar RootFS

Utilizando a variável ROOTFS_POSTPROCESS_COMMAND:

create_dir_data() {
    install -dm 0775 ${IMAGE_ROOTFS}/data/
    install -dm 0775 ${IMAGE_ROOTFS}/data/database
}

ROOTFS_POSTPROCESS_COMMAND += " create_dir_data ; "


Baixar Camadas com bitbake-layers

Exemplo, baixando as camadas meta-qt5, meta-java e meta-clang do branch scarthgap:

Executar no HOST
bitbake-layers layerindex-fetch -b scarthgap meta-qt5 meta-clang meta-java


Receita com Auto Revision do Git

Caso queira criar uma receita de um projeto que utilizar repositório Git e sempre baixar os últimos commits utilize a variável AUTOREV, exemplo:

SRC_URI = " \
          git://[email protected]/<EMPRESA>/<PROJETO>.git;protocol=ssh;branch=main \
          "

SRCREV = "${AUTOREV}"
S = "${WORKDIR}/git"


PACKAGEGROUP

Os packagegroups resumidamente é uma receita .bb que herda da classe packagegroup.bbclass e cria uma lista de pacotes separados em grupos para utilizar em mais de uma receita de imagem, evitando duplicidade e mantendo organizado, agrupando pacotes na instalação.

Não é uma regra mas um packagegroup pode estar no mesmo nível de diretório das imagens, exemplo:

meta-<camada>/recipes-core/images/b2open-core-image.bb
meta-<camada>/recipes-core/packagegroups/packagegroup-b2open-wireless.bb


Exemplo do packagegroup-b2open-wireless.bb:

SUMMARY = "Packages Wireless B2Open"
LICENSE = "MIT"

PACKAGE_ARCH = "${MACHINE_ARCH}"

inherit packagegroup

RDEPENDS:${PN} = "\
    crda \
    hostapd \
    iw \
    linux-firmware-wl12xx \
    wireless-regdb
    wpa-supplicant \
    "


Exemplo do packagegroup-b2open-3g.bb:

SUMMARY = "Packages 3G B2Open"
LICENSE = "MIT"

PACKAGE_ARCH = "${MACHINE_ARCH}"

inherit packagegroup

RDEPENDS:${PN} = "\
    modemmanager \
    kernel-module-cdc-acm \
    kernel-module-cdc-ether \
    kernel-module-cdc-mbim \
    kernel-module-cdc-ncm \
    kernel-module-cdc-wdm \
   "


Para incluir os pacotes em uma receita de imagem:

IMAGE_INSTALL:append = " \
                        packagegroup-b2open-3g \
                        packagegroup-b2open-wireless \
                        "


Outra opção é um único arquivo com diversos pacotes agrupados, como packagegroup-b2open-full.bb:

DESCRIPTION = "B2Open Package Groups"

inherit packagegroup

PACKAGE_ARCH = "${MACHINE_ARCH}"

PACKAGES = "\
    ${PN}-apps \
    ${PN}-tools \
    ${PN}-networking \
    "

SUMMARY:${PN}-apps = "Applications B2Open"
RDEPENDS:${PN}-apps = "\
    app1 \
    app2 \
    app3 \
"

SUMMARY:${PN}-tools = "Tools B2Open"
RDEPENDS:${PN}-tools = "\
    minicom \
    picocom \
    lsof \
    can-utils \
    dosfstools \
    e2fsprogs-mke2fs \
    libgpiod-tools \
    libsoc \
    u-boot-fw-utils \
    uhubctl \
"    

SUMMARY:${PN}-networking = "Networking B2Open"
RDEPENDS:${PN}-networking = " \
    iproute2 \
    curl \
    ppp \
    ptpd \
    linuxptp \
    "


Para incluir os pacotes em uma receita de imagem:

IMAGE_INSTALL:append = " \
                packagegroup-b2open-full-apps \
                packagegroup-b2open-full-networking \
                "


Exemplo Python e Shell Script em Receitas

No ambiente de BuildSystem com Yocto Project a duas maneiras de estender recursos/funcionalidades e utilizar de programação, através de Shell Script e Python.

Um exemplo de como alimentar uma variável com uma simples rotina em Python:

PKG_DT = " \
Date Generate: ${@time.strftime('%Y%m%d',time.gmtime())} \
"


Outra possibilidade é utilizando funções, e incluir esta função em uma sequência para ser chamada, como ficaria em uma receita .bb:

python do_display_banner() {
    var_branch="local"
    var_uuid="ce762bb6-a3d0-43bc-ad97-c3c27d889a69"

    bb.plain("***************************************");
    bb.plain("*  Branch: %s" % var_branch);
    bb.plain("*  UUID  : %s" % var_uuid);
    bb.plain("***************************************");
}

addtask display_banner before do_build


Da mesma forma que Python, é possível com Shell Script diferenciando apenas no template da função e nas rotinas a serem executadas.

do_deploy_bins() {
    # Install binaries
    cp ${D}/*.bin ${DEPLOYDIR}/

    # Set 0644 permission for binaries
    chmod 0644 ${DEPLOYDIR}/*
}
addtask deploy_bins after do_install


Configurando rotinas para executar no primeiro boot

Uma configuração interessante é a possibilidade de um dado pacote, exemplo b2-sniffer_git.bb poder especificar uma rotina na instalação deste pacote a ser executada apenas no primeiro boot com pkg_postinst_ontarget:${PN}, exemplo:

pkg_postinst_ontarget:${PN}() {
    setcap cap_net_raw,cap_net_admin+eip/usr/bin/b2-sniffer
}

O comando acima permite no primeiro boot executar capacidades específicas ao binário de um programa Bluetooth para acesso RAW a SocketNET e Admin.


Configurando rotinas executar ao gerar o rootfs

Outra possibilidade é executar uma rotina no processo de instalar o pacote no rootfs antes de gerar a imagem, utilizando pkg_postinst:${PN}.

pkg_postinst:${PN}() {
    setcap cap_net_raw,cap_net_admin+eip $D/${bindir}/b2-sniffer
}

O comando acima permite no primeiro boot executar capacidades específicas ao binário de um programa Bluetooth para acesso RAW a SocketNET e Admin.


Otimizando uso de disco

A seguir duas configurações úteis para otimizar espaço em disco e liberar espaço após o build, configurar em conf/local.conf.

RM_OLD_IMAGE - Manterá apenas a última imagem gerada em deploy/
RM_WORK_EXCLUDE - Lista de pacotes que pode ignorar na lista de exclusão

INHERIT += "rm_work"
RM_WORK_EXCLUDE += " \
                    qtbase \
                    virtual/bootloader \
                    virtual/kernel \
                    "

RM_OLD_IMAGE = "1"


Removendo sstate duplicado


Executar no HOST
../layers/openembedded-core/scripts/sstate-cache-management.sh --yes --remove-duplicated --cache-dir=<dir-sstate>


Ignorando Verificação de Conectividade

Às vezes o bitbake pode falhar ao checar conectividade, ele pode usar os seguintes valores: https://www.yoctoproject.org/connectivity.html ou https://example.com/. Pode-se ignorar esta verificação com CONNECTIVITY_CHECK_URIS no conf/local.conf.

CONNECTIVITY_CHECK_URIS=""


Listando Dependências com oe-pkgdata-util

Utilizando o script oe-pkgdata-util para listar dependências de runtime de um pacote instalado, exemplo python3-asyncio.

Executar no HOST
oe-pkgdata-util read-value RDEPENDS python3-asyncio

Resultado:

python3-core python3-io python3-logging python3-netclient
python3-numbers python3-stringold glibc (>= 2.35)


Executar no HOST
oe-pkgdata-util read-value RDEPENDS fping

Resultado:

glibc (>= 2.35)


Listando todos os pacotes gerados:

Executar no HOST
oe-pkgdata-util list-pkgs


Executar no HOST
oe-pkgdata-util list-pkgs fping
Resultado:


Executar no HOST
oe-pkgdata-util list-pkgs abc123

Resultado:

ERROR: Unable to find any package matching ['abc123']


Listando os arquivos que estão dentro de um pacote específico:

Executar no HOST
oe-pkgdata-util list-pkg-files fping

Resultado:

fping:
    /usr/sbin/fping


Listando o pacote filtrando por um path específico de binário, biblioteca ou arquivo de configuração:

Executar no HOST
oe-pkgdata-util find-path *libcpufreq*

Resultado:

cpufrequtils-dbg: /usr/lib/.debug/libcpufreq.so.0.0.0
cpufrequtils-dev: /usr/lib/libcpufreq.so
cpufrequtils: /usr/lib/libcpufreq.so.0
cpufrequtils: /usr/lib/libcpufreq.so.0.0.0


Executar no HOST
oe-pkgdata-util find-path /usr/lib/libcpufreq.so.0

Resultado:

cpufrequtils: /usr/lib/libcpufreq.so.0


Configurar para Build sem Internet

Por razões de segurança ou políticas internas o ambiente de build com Yocto Project em alguns casos irá executar em ambientes sem conexões com internet, mas você deverá executar a primeira vez em um ambiente com internet e configurar o Bitbake para gerar tarball dos repositórios baixados, configurando BB_GENERATE_MIRROR_TARBALLS no conf/local.conf.

BB_GENERATE_MIRROR_TARBALLS = "1"


Outra configuração é o BB_NO_NETWORK para permitir somente acesso a mirrors e fontes configuradas localmente, mas cuidado, comandos como git ls-remote.

BB_NO_NETWORK = "1"


Uma configuração completa especificando um mirror local ficaria como a seguir:

# Packages source mirrors
SOURCE_MIRROR_URL = "http://<INTERNAL_IP>/yocto-mirrors/mirrored-sources/"
INHERIT += "own-mirrors"
BB_GENERATE_MIRROR_TARBALLS = "1"

# The sstate-cache mirrors
STATE_MIRRORS = "http://<INTERNAL_IP>/yocto-mirrors/sstate-cache/"

# Restrict Access Network
BB_NO_NETWORK = "1"


Configurando Limites para bitbake

Edite o conf/local.conf e adicione no final:

BB_NUMBER_THREADS = "8"
PARALLEL_MAKE = "-j 8"
PARALLEL_MAKEINST = "-j 8"

OE_TERMINAL = "tmux"


Verificando camada com yocto-check-layer

Executando o script yocto-check-layer para analisar se a camada, receitas e customizações passam no teste de compatibilidade de camadas do Yocto Project para submeter para o OpenEmbedded Layer Index.

Executar no HOST
yocto-check-layer ../meta-treinamento

Resultada da camada meta-treinamento:

INFO: Detected layers:
INFO: meta-treinamento: LayerType.SOFTWARE, /home/b2open/treinamento/yp/poky/meta-treinamento
INFO: 
INFO: Setting up for meta-treinamento(LayerType.SOFTWARE), /home/b2open/treinamento/yp/poky/meta-treinamento
INFO: Getting initial bitbake variables ...
INFO: Getting initial signatures ...
INFO: Adding layer meta-treinamento
INFO: Starting to analyze: meta-treinamento
INFO: ----------------------------------------------------------------------
INFO: skipped "BSPCheckLayer: Layer meta-treinamento isn't BSP one."
INFO: test_layerseries_compat (common.CommonCheckLayer)
INFO:  ... ok
INFO: test_parse (common.CommonCheckLayer)
INFO:  ... ok
INFO: test_patches_upstream_status (common.CommonCheckLayer)
INFO:  ... unexpected success
INFO: test_readme (common.CommonCheckLayer)
INFO:  ... ok
INFO: test_show_environment (common.CommonCheckLayer)
INFO:  ... ok
INFO: test_signatures (common.CommonCheckLayer)
INFO:  ... ok
INFO: test_world (common.CommonCheckLayer)
INFO:  ... ok
INFO: test_world_inherit_class (common.CommonCheckLayer)
INFO:  ... ok
INFO: skipped "DistroCheckLayer: Layer meta-treinamento isn't Distro one."
INFO: ----------------------------------------------------------------------
INFO: Ran 8 tests in 2272.583s
INFO: OK
INFO:  (skipped=2, unexpected successes=1)
INFO: 
INFO: Summary of results:
INFO: 
INFO: meta-treinamento ... PASS


Tabela Variáveis de caminhos expandida

VARIÁVEL VALOR EXPANDIDO
${base_bindir} /bin
${base_sbindir} /sbin
${sysconfdir} /etc
${localstatedir} /var
${datadir} /usr/share
${bindir} /usr/bin
${sbindir} /usr/sbin
${libdir} /usr/lib ou /usr/lib64
${libexecdir} /usr/libexec
${includedir} /usr/include