C

Qt Quick Ultralite static_library Example

Demonstrates how to create and use Qt Quick Ultralite static library.

Overview

This example shows how to create and integrate Qt Quick Ultralite static library with different application. It contains two targets: a Qt Quick Ultralite GUI compiled as a static library and an executable application that links to the static library. Application also provides a simple API to simulate sensor data. The Qt Quick Ultralite GUI uses this interface to receive sensor data and display it on screen.

You can read more about building Qt Quick Ultralite as a static library here.

Note: The static library setup does not work on FreeRTOS.

Project structure

Project includes two subprojects: a Qt Quick Ultralite GUI static library and an executable application. Both these projects have their own CMakeLists.txt file, which create corresponding target and add dependent files.

Static library CMake project

To create static library target STATIC_LIBRARY option must be provided as an argument to the qul_add_target function.

...
qul_add_target(Qt4MCU_GUI STATIC_LIBRARY QML_PROJECT qt4mcu.qmlproject)
...

Next, use the InterfaceFiles.files in the library's QmlProject file to register the sensorData.h header file as a Qt Quick Ultralite interface. It enables receive sensor data from the main application. Methods from that interface are used in mainGui.qml, which is added to project using the QmlFiles.files .

        QmlFiles {
                files: ["mainGui.qml"]
        }

        InterfaceFiles {
                files: ["sensorData.h"]
        }

Add the folder containting the sensorAPI.h header file to the include directories list.

Note: EXAMPLE_ROOT_DIR is derived from the application CMake file.

...
target_include_directories(Qt4MCU_GUI
    PRIVATE
        ${EXAMPLE_ROOT_DIR}/include
)
...

The mainGui.qml uses the QtQuick.Controls QML module, which requires linking the Qt4MCU_GUI target to the Qul::Controls library. For more information please refer to the Qt Quick Ultralite styling Example.

        ModuleFiles {
                MCU.qulModules: ["Controls"]
        }

Add the app_target_default_entrypoint towards the end to generate default entrypoint for the static library. It generates the qul_run.h header file, containing qul_run() entrypoint function. The application must call this function to configure and start the Qt Quick Ultralite engine.

...
app_target_default_entrypoint(Qt4MCU_GUI mainGui)
...

Note: Qul::initHardware() won't get called if qul_run() is called with initializeHardware set to false.

Application CMake project

To create a Qt Quick Ultralite application, call the add_executable CMake function. In addition, include the main.cpp file in the target sources list.

...
add_executable(static_library_example
        src/main.cpp
)
...

The Qt Quick Ultralite static libraries in release configuration come with inter-procedural optimization (link time optimization) enabled. This means that the application linking to such libraries must have the same setup. The following snippet demonstrates how to do IPO config check on the Qt Quick Ultralite static library and apply the same to the application.

...
get_target_property(QUL_LIB_IPO_CONFIG Qt4MCU_GUI INTERPROCEDURAL_OPTIMIZATION)
set_target_properties(static_library_example PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${QUL_LIB_IPO_CONFIG})
...

The application must include the Qt Quick Ultralite root directory and path to folder containing qul_run.h. In this example though, sensorAPI.h is an additional header file that is included.

...
target_include_directories(static_library_example
    PRIVATE
        # Add include folder from QtForMCU installation folder
        ${Qul_DIR}/include
        # Add folder containing qul_run.h header file
        ${CMAKE_CURRENT_BINARY_DIR}/lib/Qt_for_MCU
        # Add folder containing sensorAPI.h header file
        ${CMAKE_CURRENT_SOURCE_DIR}/include
)
...

The application must also link to all the libraries that the static library links to.

Note: Qt Quick Ultralite contains cyclic dependency between some libraries. You can resolve it by linking to Qul::Core and the GUI lib at the end of the list, as shown as in the following example.

target_link_libraries(static_library_example
    PRIVATE
        # Static library containing UI and interfaces
        Qt4MCU_GUI

        # Depending on which function the Qt4MCU_GUI static library is using,
        # you need to link the proper static library to the executable.
        # In this example list of the libraries which are changing depending on
        # CMake variables configuration are described. Just uncomment those which
        # apply to your setup. Config which applies to this example is uncommented.

        # Font engines:
        #   - Spark font engine (QUL_FONT_ENGINE == Spark):
        #       - QUL_PLATFORM_REQUIRED_IMAGE_ALIGNMENT == 1
        # Qul::MonotypeFontEngine
        #       - QUL_PLATFORM_REQUIRED_IMAGE_ALIGNMENT not set or 0
        # Qul::MonotypeFontEngineAligned
        #       - QUL_COMPLEX_TEXT_RENDERING == ON
        # Qul::MonotypeShaperEngine
        # Qul::MonotypeUnicodeEngine
        #       - QUL_COMPLEX_TEXT_RENDERING not set
        # Qul::MonotypeUnicodeEngineShaperDisabled
        #   - Static font engine (QUL_FONT_ENGINE == Static)
        Qul::MonotypeUnicodeEngineShaperDisabled

        # PNG decoder (add when project uses PNG images):
        #   - QUL_RESOURCE_COMPRESSION == ON
        # Qul::PNGDecoderLodePNG
        #   - QUL_RESOURCE_COMPRESSION not set or OFF
        # Qul::PNGDecoderNull

        # Additional lib which needs to be linked along to Qt QuickUltralite Core
        $<$<BOOL:${CMAKE_CROSSCOMPILING}>:Qul::DeviceLink>

        # Static library with Qt QuickUltralite Core
        Qul::Core
        # Static library with Qt QuickUltralite Platform abstraction.
        # Should be replaced by custom implementation adapted to target board
        Qul::Platform
        # All additional Qul libraries used by QtForMCU GUI needs to be also
        # linked with application
        Qul::Controls
        # Satisfy cyclic dependency between Qt4MCU_GUI and Qul::Core
        # libraries (Qul::Core depends on symbols autogenerated
        # in Qt4MCU_GUI build process)
        # Same sets of libraries chosen above need to match those below.
        # For example if above we choose Qul::MonotypeUnicodeEngineShaperDisabled
        # then here below we add the same library as cyclic dependency to Qul::Core.
        Qul::Core
        $<$<BOOL:${CMAKE_CROSSCOMPILING}>:Qul::DeviceLink>
        Qul::MonotypeUnicodeEngineShaperDisabled
        Qt4MCU_GUI
)
Interfacing with the Qt Quick Ultralite static library

As mentioned earliers, the example application provides sensor data through an API. The Qt Quick Ultralite static library is using this API to get sensor data and expose it to QML using the Qt Quick Ultralite C++ interface.

Note: Qt Quick Ultralite does not provide a thread-safe way to change QML properties from a separate task.

...
#include "sensorAPI.h"

struct SensorData : Qul::Singleton<SensorData>
{
    SensorData()
        : sensorRawValue(0)
    {}
    Qul::Property<int> sensorRawValue;
    void updateSensorValue() { sensorRawValue.setValue(getSensorValue()); }
};
...

The getSensorValue() function in this example is returns a random value.

...
int getSensorValue()
{
    return randomEngine() % 100;
}
...

Files:

Available under certain Qt licenses.
Find out more.