Baking a QML Project into a Yocto Image

113 Views Asked by At

I am trying to get more familiar with the toolchain to compile a QML project with CMake and bake it into a Yocto image. However, I am having issues with the configurations.

I am using the QML example "Coffee Machine" from Qt Creator. The file tree looks like this:

CoffeeMachine/
|
-- CMakeLists.txt
-- CoffeeMachine.qmlproject
-- main.qml
-- qmlmodules
-- qtquickcontrols2.conf
-- content/
   |
   -- CMakeLists.txt
   -- qtquickcontrols2.conf
   -- <*.qml files>
   -- fonts/
      |
      -- fonts.txt
      -- <ttf file>
   -- images/
      |
      -- <subdirs of png files>
-- imports/
   |
   -- CMakeLists.txt
   -- CoffeeMachine/
      |
      -- <more qml files>
-- src/
   |
   -- import_qml_plugins.h
   -- main.cpp

I have created a meta-coffeemachine layer in my yocto build directory and created a recipe file. I have copied the project files into the "files" directory in my layer according to the tree above.

SUMMARY = "QML Coffee Machine"
LICENSE = "CLOSED"

inherit qt6-cmake

SRC_URI = "file://CMakeLists.txt                \
           file://qmlmodules                    \
           file://main.qml                      \
           file://CoffeeMachine.qmlproject      \
           file://qtquickcontrols2.conf         \       
           file://content/                      \
           file://imports/                      \
           file://src/                          \
          "

DEPENDS += "qtbase                      \
            qtdeclarative               \
            qtdeclarative-native        \
            qtquick3d                   \
            qtquicktimeline             \
           "

S = "${WORKDIR}"

do_install() {
  install -d ${D}${bindir}/coffeemachine
  install -m 0755 coffeemachine ${D}${bindir}/coffeemachine

  install -m 0755 ${S}/content/*.qml ${D}${bindir}/coffeemachine
  install -m 0755 ${S}/content/qtquickcontrols2.conf ${D}${bindir}/coffeemachine        

  install -d ${D}${datadir}/content/
  install -d ${D}${datadir}/content/fonts/
  install -d ${D}${datadir}/content/images/
  install -m 0755 ${S}/content/fonts/* ${D}${datadir}/content/fonts/
  install -m 0755 ${S}/content/images/* ${D}${datadir}/content/images/

FILES:${PN} += "${datadir}/content/images/cup_structure \
            ${datadir}/content/images/ui_controls \
            ${datadir}/content/images/icons \
            ${datadir}/content/fonts \
            ${bindir}/coffeemachine/content/*.qml \
            ${bindir}/coffeemachine/content/qtquickcontrols2.conf \
            ${bindir}/coffeemachine/main.qml"

The CMakeLists.txt file looks like this:

cmake_minimum_required(VERSION 3.18)

project(CoffeeMachine LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

find_package(Qt6 COMPONENTS Gui Qml Quick)
add_executable(CoffeeMachineApp src/main.cpp)

target_link_libraries(CoffeeMachineApp PRIVATE
    Qt${QT_VERSION_MAJOR}::Core
    Qt${QT_VERSION_MAJOR}::Gui
    Qt${QT_VERSION_MAJOR}::Quick
    Qt${QT_VERSION_MAJOR}::Qml
)

include(${CMAKE_CURRENT_SOURCE_DIR}/qmlmodules)

install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/content/images/ DESTINATION /usr/share/content/images/)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/content/fonts/ DESTINATION /usr/share/content/fonts/)

When I build my layer using bitbake coffeemachine, I see this error:

ERROR: coffeemachine-0.1-r0 do_package: QA Issue: coffeemachine: Files/directories were installed but not shipped in any package:
  /usr
  /usr/share
  /usr/share/content
  /usr/share/content/fonts
  /usr/share/content/images
  /usr/share/content/fonts/TitilliumWeb-Regular.ttf
  /usr/share/content/fonts/fonts.txt
  /usr/share/content/images/cup_structure
  /usr/share/content/images/ui_controls
  /usr/share/content/images/icons
  /usr/share/content/images/cup_structure/coffee_cup_large.png
  /usr/share/content/images/cup_structure/coffee_cup_outline.png
  /usr/share/content/images/cup_structure/liquids
  /usr/share/content/images/cup_structure/cup_elements
  /usr/share/content/images/cup_structure/liquids/liquid_foam.png
  /usr/share/content/images/cup_structure/liquids/liquid_milk.png
  /usr/share/content/images/cup_structure/liquids/liquid_coffee.png
  /usr/share/content/images/cup_structure/cup_elements/coffee_cup_front.png
  /usr/share/content/images/cup_structure/cup_elements/coffee_cup_back.png
  /usr/share/content/images/cup_structure/cup_elements/coffee_cup_coverplate.png
  /usr/share/content/images/ui_controls/line.png
  /usr/share/content/images/ui_controls/buttons
  /usr/share/content/images/ui_controls/buttons/go
  /usr/share/content/images/ui_controls/buttons/back
  /usr/share/content/images/ui_controls/buttons/go/white.png
  /usr/share/content/images/ui_controls/buttons/back/white.png
  /usr/share/content/images/icons/coffees
  /usr/share/content/images/icons/contents
  /usr/share/content/images/icons/coffees/Espresso.png
  /usr/share/content/images/icons/coffees/Macchiato.png
  /usr/share/content/images/icons/coffees/Americano.png
  /usr/share/content/images/icons/coffees/Cappuccino.png
  /usr/share/content/images/icons/coffees/Latte.png
  /usr/share/content/images/icons/contents/sugar.png
  /usr/share/content/images/icons/contents/milk.png
  /usr/share/content/images/icons/contents/coffee.png
Please set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install.
coffeemachine: 36 installed and not shipped files. [installed-vs-shipped]
ERROR: coffeemachine-0.1-r0 do_package: Fatal QA errors were found, failing task.
ERROR: Logfile of failure stored in: /home/bkeohane/Projekte/yocto/build-rpi/tmp/work/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi/coffeemachine/0.1-r0/temp/log.do_package.41338
ERROR: Task (/home/bkeohane/Projekte/yocto/meta-coffeemachine/recipes-apps/coffeemachine/coffeemachine_0.1.bb:do_package) failed with exit code '1'

However, I am confused where I am actually doing something wrong: In my CMakeLists.txt, in my recipe or do I need to change the file tree? I assume it must be possible to let CMake compile the main.cpp and *.qml files into a binary, install it into the image as specified and install all necessary depending files into another directory in the image (images, fonts)?

Thanks for any hints.

2

There are 2 best solutions below

0
On BEST ANSWER

I have found a solution. It seems that the CMakeLists.txt file was not correct. I assume, something went wrong when I built the project in Qt Creator and copied the files over to my VM.

However, the following CMakeLists.txt was created by Qt Creator, and was slightly adapted by me:

 Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause

cmake_minimum_required(VERSION 3.16)
project(coffee LANGUAGES CXX)

set(CMAKE_AUTOMOC ON)   
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick)

qt_add_executable(coffee
    main.cpp
)

set_target_properties(coffee PROPERTIES
    WIN32_EXECUTABLE TRUE
    MACOSX_BUNDLE TRUE
)

target_link_libraries(coffee PRIVATE
    Qt6::Core
    Qt6::Gui
    Qt6::Qml
    Qt6::Quick
)

# Resources:
set(qml_resource_files
    "ApplicationFlow.qml"
    "ApplicationFlowForm.ui.qml"
    "Brewing.qml"
    "BrewingForm.ui.qml"
    "ChoosingCoffee.ui.qml"
    "CoffeeButton.qml"
    "CupForm.ui.qml"
    "EmptyCupForm.ui.qml"
    "NavigationButton.ui.qml"
    "SideBar.qml"
    "SideBarForm.ui.qml"
    "images/cup_structure/coffee_cup_large.png"
    "images/cup_structure/coffee_cup_outline.png"
    "images/cup_structure/cup_elements/coffee_cup_back.png"
    "images/cup_structure/cup_elements/coffee_cup_coverplate.png"
    "images/cup_structure/cup_elements/coffee_cup_front.png"
    "images/cup_structure/liquids/liquid_coffee.png"
    "images/cup_structure/liquids/liquid_foam.png"
    "images/cup_structure/liquids/liquid_milk.png"
    "images/icons/coffees/Americano.png"
    "images/icons/coffees/Espresso.png"
    "images/icons/coffees/Latte.png"
    "images/icons/coffees/Macchiato.png"
    "images/icons/coffees/cappucino.png"
    "images/icons/contents/coffee.png"
    "images/icons/contents/milk.png"
    "images/icons/contents/sugar.png"
    "images/ui_controls/buttons/back/white.png"
    "images/ui_controls/buttons/go/white.png"
    "images/ui_controls/line.png"
    "imports/Coffee/Constants.qml"
    "imports/Coffee/TitilliumWeb-Regular.ttf"
    "imports/Coffee/qmldir"
    "main.qml"
    "qtquickcontrols2.conf"
)

qt_add_resources(coffee "qml"
    PREFIX
        "/"
    FILES
        ${qml_resource_files}
)

target_link_libraries(coffee
    PRIVATE Qt6::Quick)

include(GNUInstallDirs)
install(TARGETS coffee
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

My recipe was adapted accordingly:

SUMMARY = "CoffeeMachine Application"
LICENSE = "CLOSED"

SRC_URI = " \
        file://ApplicationFlow.qml \
        file://ApplicationFlowForm.ui.qml \
        file://Brewing.qml \
        file://BrewingForm.ui.qml \
        file://ChoosingCoffee.ui.qml \
        file://CMakeLists.txt \
        file://coffee.pro \
        file://coffee.qdoc \
        file://CoffeeButton.qml \
        file://Cup.qml \
        file://CupForm.ui.qml \
        file://EmptyCup.qml \
        file://EmptyCupForm.ui.qml \
        file://main.cpp \
        file://main.qml \
        file://NavigationButton.ui.qml \
        file://qml.qrc \
        file://qt_attribution.json \
        file://qtquickcontrols2.conf \
        file://SideBar.qml \
        file://SideBarForm.ui.qml \
        file://images/ \
        file://images/cup_structure/ \
        file://images/cup_structure/cup_elements/ \
        file://images/cup_structure/liquids/ \
        file://images/icons/ \
        file://images/icons/coffees/ \
        file://images/icons/contents/ \
        file://images/ui_controls/ \
        file://images/ui_controls/buttons/ \
        file://images/ui_controls/buttons/back/ \
        file://images/ui_controls/buttons/go/ \
        file://imports/ \
        file://imports/Coffee/"

DEPENDS += " \
        qtbase \
        qtdeclarative \
        qtdeclarative-native \
        qtquick3d \
        qtquicktimeline"


S = "${WORKDIR}"

Since qt6-cmake takes care of installing the resources, no installing via do_install() nor files packaging using FILES:${PN} is necessary, which is a big plus over qt6-qmake, IMO.

The binaries and resources will be installed to /usr/bin on the yocto image, just in case.

Thanks again for your advice!

Cheers

1
On

The error is telling you that your recipe is installing a bunch of files underneath /usr/share/content that are not defined in the FILES:${PN} variable. You can resolve this by making sure all files installed by the recipe are accounted for.

One way you could do this is with a more simple definition using wildcards.

FILES:${PN} += " \
    ${datadir}/share/content/* \
    ${bindir}/coffeemachine/* \
"