C

Qt Quick Ultralite map example

# Copyright (C) 2026 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial
cmake_minimum_required(VERSION 3.21.1)

project(map VERSION 0.0.1 LANGUAGES C CXX ASM)

find_package(QulApp)

# The traveo-t2g variant doesn't include MapMarker.qml (and its icons), and
# uses its own MapParameters.qml with a scripted demo camera instead of the
# interactive one. map.qml and MapContainer.qml additionally have per-board
# (4m/6m) variants.
set(MAP_IS_T2G FALSE)
if(QUL_PLATFORM MATCHES "^tviic2d" AND NOT ARMGCC)
    set(MAP_IS_T2G TRUE)
    if(QUL_PLATFORM MATCHES "^tviic2d4m")
        set(VARIANT "4m")
    elseif(QUL_PLATFORM MATCHES "^tviic2d6m")
        set(VARIANT "6m")
    else()
        return()
    endif()
endif()

if(MAP_IS_T2G)
    set(MAP_QML_FILES
        +t2g/+${VARIANT}/map.qml
        MapButton.qml
        +t2g/+${VARIANT}/MapContainer.qml
        +t2g/MapParameters.qml
        CopyrightText.qml
    )
    set(MAP_ICONS
        icons/24px/plus.png icons/24px/minus.png
        icons/24px/rotate-right.png icons/24px/rotate-left.png
    )
else()
    set(MAP_QML_FILES
        map.qml
        MapButton.qml
        MapContainer.qml
        MapParameters.qml
        MapMarker.qml
        CopyrightText.qml
    )
    set(MAP_ICONS
        icons/24px/plus.png icons/24px/minus.png
        icons/24px/rotate-right.png icons/24px/rotate-left.png
        icons/24px/nav-arrow.png icons/24px/location-marker.png
        icons/24px/start-resume.png icons/24px/pause.png icons/24px/stop.png
    )
endif()

if (QUL_PLATFORM STREQUAL "qt")
    find_package(Qt6 6.2 COMPONENTS Gui QUIET)
    if(NOT Qt6Gui_FOUND)
        set(DEFAULT_QT6_VERSION 6.2.4)
        if(WIN32)
            set(DEFAULT_QT6_PATH C:\\Qt\\${DEFAULT_QT6_VERSION}\\msvc2019_64)
        else()
            set(DEFAULT_QT6_PATH $HOME/Qt/${DEFAULT_QT6_VERSION}/gcc_64)
        endif()
        message(FATAL_ERROR "Qt6 is required to build the map example. "
                            "Use -DCMAKE_PREFIX_PATH=${DEFAULT_QT6_PATH} or similar to specify the location of Qt6, "
                            "depending on which Qt version is used and where it is installed. "
                            "Alternatively, check the documentation for this example for more detailed instructions."
                          )
    endif()

    qul_add_executable(map os/baremetal/main.cpp)
elseif(QUL_PLATFORM MATCHES "^stm32u5")
    if (NOT QUL_PLATFORM_ENABLE_EMMC)
        message(WARNING "For the image decoder to load from a filesystem, "
                        "QUL_PLATFORM_ENABLE_EMMC needs to be enabled. "
                        "Without eMMC, you have to change the QML project to not load "
                        "the images from external storage")
        return()
    endif()
    set(STM32XX "stm32u5")
    qul_add_executable(map os/${QUL_OS_LOWERCASE}/main.cpp)
elseif(QUL_PLATFORM MATCHES "^stm32f769i")
    set(STM32XX "stm32f7")
    qul_add_executable(map os/baremetal/main.cpp)
elseif(MAP_IS_T2G)
    if(VARIANT STREQUAL "6m")
        # In CI we test with the 500-BGA variant with graphics driver TVII_GRAPHICS_DRIVER_DIR_1_1_0_4M6M
        # (infineon-traveo-t2g-cyt4dn-baremetal-500-bga-windows-ghs-arm)
        # and to be able to build the imagedecoder backend an SDL upgrade is required.
        if(QUL_TVIIC2D6M_BOARD_REVISION STREQUAL "500-BGA")
            return()
        endif()
    endif()
    if(QUL_OS_LOWERCASE STREQUAL "autosar")
        qul_add_library(map)
        target_sources(map PRIVATE os/autosar/qul_run.cpp)
    else()
        qul_add_executable(map os/baremetal/main.cpp)
    endif()
else()
    return()
endif()

qul_add_qml_module(map
    URI MapApp
    QML_FILES ${MAP_QML_FILES}
)

# The QML files refer to these by bare filename ("plus.png"). A relative image
# uri resolves under the resource prefix of the QML module it is used from, so
# the icons go below the MapApp prefix, with BASE stripping the "icons/24px/"
# source subdirectory from their resource paths.
qul_add_resources(map
    FILES ${MAP_ICONS}
    BASE "icons/24px"
    PREFIX "MapApp"
)

qul_target_generate_interfaces(map dummy_position_source/indexmanager.h)

target_link_libraries(map PRIVATE Qul::Positioning Qul::Location)

if (QUL_PLATFORM STREQUAL "qt")
    # On desktop the files by default need to be available next
    # to the built binary on the filesystem
    set(TILES_BASE_DIR "offline_tiles_provider/tiles/")
    set(PLACEHOLDER_TILE "${TILES_BASE_DIR}placeholder-tile.jpeg")
    add_custom_command(
        TARGET map POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E echo
            "Copying map tiles to $<TARGET_FILE_DIR:map>/${TILES_BASE_DIR}"
        COMMAND ${CMAKE_COMMAND} -E copy_directory
                ${CMAKE_CURRENT_SOURCE_DIR}/${TILES_BASE_DIR}
                $<TARGET_FILE_DIR:map>/${TILES_BASE_DIR}
        COMMENT "Copying map tiles to build directory"
    )

    target_compile_definitions(map PRIVATE
                                TILES_BASE_DIR="${TILES_BASE_DIR}"
                                PLACEHOLDER_TILE="${PLACEHOLDER_TILE}"
                                MAX_CACHE_SIZE=100
                            )
    target_link_libraries(map PRIVATE Qt6::Gui)

    target_include_directories(map PRIVATE
                                ../fileloading/posix/
                                ../imagedecoder/desktop/
                            )
    target_sources(map PRIVATE
                          ${CMAKE_CURRENT_SOURCE_DIR}/desktop/board_config.cpp
                          ${CMAKE_CURRENT_SOURCE_DIR}/offline_tiles_provider/offlinetilefetcher.cpp
                          ${CMAKE_CURRENT_SOURCE_DIR}/dummy_position_source/dummypositionsource.cpp
                          ${CMAKE_CURRENT_SOURCE_DIR}/dummy_position_source/dummypositiondata.cpp
                          ../imagedecoder/desktop/desktopimagedecoder.cpp
                          ../fileloading/posix/posixfilesystem.cpp
                      )

    qul_set_maximum_resource_cache_size(map CACHE_SIZE 4000000)

    if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
        target_compile_options(map PRIVATE -Wno-maybe-uninitialized) # desktopimagedecoder.cpp:129ff read into a byte array.
    endif()
elseif(QUL_PLATFORM MATCHES "^stm32u5")
    # user sets it to the location of tiles images on an external storage
    set(TILES_BASE_DIR "tiles/")
    set(PLACEHOLDER_TILE "${TILES_BASE_DIR}placeholder-tile.jpeg")

    target_compile_definitions(map PRIVATE
                               TILES_BASE_DIR="${TILES_BASE_DIR}"
                               PLACEHOLDER_TILE="${PLACEHOLDER_TILE}"
                               MAX_CACHE_SIZE=40
                               USE_JPEG_DECODER=1
                               #USE_DMA_BASED_JPEG_DECODING
                               SUPPORT_FILESYSTEM
                               FF_FS_READONLY
    )
    target_sources(map PRIVATE
                   ${CMAKE_CURRENT_SOURCE_DIR}/offline_tiles_provider/offlinetilefetcher.cpp
                   ${CMAKE_CURRENT_SOURCE_DIR}/stm/${STM32XX}/board_config.cpp
                   ${QUL_BOARD_SDK_DIR}/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_hal_dma_ex.c
                   ${QUL_BOARD_SDK_DIR}/Drivers/STM32U5xx_HAL_Driver/Src/stm32u5xx_hal_jpeg.c
                   ../fileloading/3rdparty/FatFs/src/diskio.c
                   ../fileloading/3rdparty/FatFs/src/ff.c
                   ../fileloading/3rdparty/FatFs/src/ff_gen_drv.c
                   ../fileloading/3rdparty/FatFs/src/option/unicode.c
                   ../imagedecoder/3rdparty/stm/Utilities/JPEG/jpeg_utils.c
                   ../imagedecoder/common/jpeg.cpp
                   ../imagedecoder/stm/${STM32XX}/buffer_config.cpp
                   ../imagedecoder/stm/${STM32XX}/stm32u5xx_hal_msp.c
                   ../imagedecoder/stm/stmimagedecoder.cpp
    )
    target_include_directories(map PRIVATE
                               ${QUL_PLATFORM_BOARDS_DIR}/st/stm32u5x9-discovery-common
                               ../fileloading/
                               ../fileloading/3rdparty/FatFs/src/
                               ../imagedecoder/stm/${STM32XX}
                               ../imagedecoder/stm
                               ${QUL_BOARD_SDK_DIR}/Utilities/JPEG
    )
    target_link_libraries(map PRIVATE Qul::PlatformBSPConfig)

    qul_set_maximum_resource_cache_size(map CACHE_SIZE 4000000)

    if(NOT IAR)
        target_compile_options(map PRIVATE -Wno-unused-parameter)
    endif()
elseif(QUL_PLATFORM MATCHES "^stm32f769i")
    # user sets it to the location of tiles images on an external storage
    set(TILES_BASE_DIR "tiles/")
    set(PLACEHOLDER_TILE "${TILES_BASE_DIR}placeholder-tile.jpeg")

    target_compile_definitions(map PRIVATE
                                TILES_BASE_DIR="${TILES_BASE_DIR}"
                                PLACEHOLDER_TILE="${PLACEHOLDER_TILE}"
                                MAX_CACHE_SIZE=40
                            )

    target_include_directories(map PRIVATE
                                ../fileloading/3rdparty/FatFs/src
                                ../fileloading/fatfs
                                ../imagedecoder/stm/${STM32XX}
                                ../imagedecoder/stm
                                ${QUL_BOARD_SDK_DIR}/Utilities/JPEG
                            )
    target_sources(map PRIVATE
                    ${CMAKE_CURRENT_SOURCE_DIR}/offline_tiles_provider/offlinetilefetcher.cpp
                    ${CMAKE_CURRENT_SOURCE_DIR}/dummy_position_source/dummypositionsource.cpp
                    ${CMAKE_CURRENT_SOURCE_DIR}/dummy_position_source/dummypositiondata.cpp
                    ${CMAKE_CURRENT_SOURCE_DIR}/stm/${STM32XX}/board_config.cpp
                )
    # file system sources
    target_sources(map PRIVATE
            ../fileloading/3rdparty/FatFs/src/diskio.c
            ../fileloading/3rdparty/FatFs/src/ff.c
            ../fileloading/3rdparty/FatFs/src/ff_gen_drv.c
            ../fileloading/3rdparty/FatFs/src/sd_diskio.c
            ../fileloading/3rdparty/FatFs/src/option/unicode.c
            ${QUL_BOARD_SDK_DIR}/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_ll_sdmmc.c
            ${QUL_BOARD_SDK_DIR}/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_sd.c
            ${QUL_BOARD_SDK_DIR}/Drivers/BSP/STM32F769I-Discovery/stm32f769i_discovery_sd.c
        )
    # jpeg decoder sources
    target_sources(map PRIVATE
            ${QUL_BOARD_SDK_DIR}/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_jpeg.c
            ../imagedecoder/stm/${STM32XX}/stm32f7xx_hal_msp.c
            ../imagedecoder/stm/${STM32XX}/buffer_config.cpp
            ../imagedecoder/stm/stmimagedecoder.cpp
            ../imagedecoder/common/jpeg.cpp
            ../imagedecoder/3rdparty/stm/Utilities/JPEG/jpeg_utils.c
        )

    target_compile_definitions(map PRIVATE
                                FF_FS_READONLY
                                DISABLE_SD_INIT
                                USE_JPEG_DECODER=1
                                USE_DMA_BASED_JPEG_DECODING
                                PLATFORM_OS=baremetal
                            )

    target_link_libraries(map PRIVATE Qul::PlatformBSPConfig)

    qul_set_maximum_resource_cache_size(map CACHE_SIZE 4000000)

    if(NOT IAR)
     target_compile_options(map PRIVATE -Wno-unused-parameter)
    endif()

    app_target_setup_os(map)
elseif(MAP_IS_T2G)
    # user sets it to the location of tiles images on an external storage
    set(TILES_BASE_DIR "tiles/")
    set(PLACEHOLDER_TILE "${TILES_BASE_DIR}placeholder-tile.jpeg")

    target_compile_definitions(map PRIVATE
        TILES_BASE_DIR="${TILES_BASE_DIR}"
        PLACEHOLDER_TILE="${PLACEHOLDER_TILE}"
        MAX_CACHE_SIZE=40
    )

    target_sources(map PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/offline_tiles_provider/offlinetilefetcher.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/t2g-traveo/board_config.cpp
    )

    # Offline tiles are embedded resources on this platform (no SD-card/posix
    # filesystem access), unlike qt/stm32f769i/stm32u5 above.
    set(MAP_T2G_TILES
        offline_tiles_provider/tiles/1/0/0.jpeg
        offline_tiles_provider/tiles/1/0/1.jpeg
        offline_tiles_provider/tiles/1/1/1.jpeg
        offline_tiles_provider/tiles/1/1/0.jpeg
        offline_tiles_provider/tiles/placeholder-tile.jpeg
        offline_tiles_provider/tiles/3/4/6.jpeg
        offline_tiles_provider/tiles/3/4/2.jpeg
        offline_tiles_provider/tiles/3/4/1.jpeg
        offline_tiles_provider/tiles/3/4/0.jpeg
        offline_tiles_provider/tiles/3/4/5.jpeg
        offline_tiles_provider/tiles/3/4/7.jpeg
        offline_tiles_provider/tiles/3/4/3.jpeg
        offline_tiles_provider/tiles/3/4/4.jpeg
        offline_tiles_provider/tiles/3/0/6.jpeg
        offline_tiles_provider/tiles/3/0/2.jpeg
        offline_tiles_provider/tiles/3/0/1.jpeg
        offline_tiles_provider/tiles/3/0/0.jpeg
        offline_tiles_provider/tiles/3/0/5.jpeg
        offline_tiles_provider/tiles/3/0/7.jpeg
        offline_tiles_provider/tiles/3/0/3.jpeg
        offline_tiles_provider/tiles/3/0/4.jpeg
        offline_tiles_provider/tiles/3/7/6.jpeg
        offline_tiles_provider/tiles/3/7/2.jpeg
        offline_tiles_provider/tiles/3/7/1.jpeg
        offline_tiles_provider/tiles/3/7/0.jpeg
        offline_tiles_provider/tiles/3/7/5.jpeg
        offline_tiles_provider/tiles/3/7/7.jpeg
        offline_tiles_provider/tiles/3/7/3.jpeg
        offline_tiles_provider/tiles/3/7/4.jpeg
        offline_tiles_provider/tiles/3/1/6.jpeg
        offline_tiles_provider/tiles/3/1/2.jpeg
        offline_tiles_provider/tiles/3/1/1.jpeg
        offline_tiles_provider/tiles/3/1/0.jpeg
        offline_tiles_provider/tiles/3/1/5.jpeg
        offline_tiles_provider/tiles/3/1/7.jpeg
        offline_tiles_provider/tiles/3/1/3.jpeg
        offline_tiles_provider/tiles/3/1/4.jpeg
        offline_tiles_provider/tiles/3/6/6.jpeg
        offline_tiles_provider/tiles/3/6/2.jpeg
        offline_tiles_provider/tiles/3/6/1.jpeg
        offline_tiles_provider/tiles/3/6/0.jpeg
        offline_tiles_provider/tiles/3/6/5.jpeg
        offline_tiles_provider/tiles/3/6/7.jpeg
        offline_tiles_provider/tiles/3/6/3.jpeg
        offline_tiles_provider/tiles/3/6/4.jpeg
        offline_tiles_provider/tiles/3/5/6.jpeg
        offline_tiles_provider/tiles/3/5/2.jpeg
        offline_tiles_provider/tiles/3/5/1.jpeg
        offline_tiles_provider/tiles/3/5/0.jpeg
        offline_tiles_provider/tiles/3/5/5.jpeg
        offline_tiles_provider/tiles/3/5/7.jpeg
        offline_tiles_provider/tiles/3/5/3.jpeg
        offline_tiles_provider/tiles/3/5/4.jpeg
        offline_tiles_provider/tiles/3/3/6.jpeg
        offline_tiles_provider/tiles/3/3/2.jpeg
        offline_tiles_provider/tiles/3/3/1.jpeg
        offline_tiles_provider/tiles/3/3/0.jpeg
        offline_tiles_provider/tiles/3/3/5.jpeg
        offline_tiles_provider/tiles/3/3/7.jpeg
        offline_tiles_provider/tiles/3/3/3.jpeg
        offline_tiles_provider/tiles/3/3/4.jpeg
        offline_tiles_provider/tiles/3/2/6.jpeg
        offline_tiles_provider/tiles/3/2/2.jpeg
        offline_tiles_provider/tiles/3/2/1.jpeg
        offline_tiles_provider/tiles/3/2/0.jpeg
        offline_tiles_provider/tiles/3/2/5.jpeg
        offline_tiles_provider/tiles/3/2/7.jpeg
        offline_tiles_provider/tiles/3/2/3.jpeg
        offline_tiles_provider/tiles/3/2/4.jpeg
        offline_tiles_provider/tiles/2/0/2.jpeg
        offline_tiles_provider/tiles/2/0/1.jpeg
        offline_tiles_provider/tiles/2/0/0.jpeg
        offline_tiles_provider/tiles/2/0/3.jpeg
        offline_tiles_provider/tiles/2/1/2.jpeg
        offline_tiles_provider/tiles/2/1/1.jpeg
        offline_tiles_provider/tiles/2/1/0.jpeg
        offline_tiles_provider/tiles/2/1/3.jpeg
        offline_tiles_provider/tiles/2/3/2.jpeg
        offline_tiles_provider/tiles/2/3/1.jpeg
        offline_tiles_provider/tiles/2/3/0.jpeg
        offline_tiles_provider/tiles/2/3/3.jpeg
        offline_tiles_provider/tiles/2/2/2.jpeg
        offline_tiles_provider/tiles/2/2/1.jpeg
        offline_tiles_provider/tiles/2/2/0.jpeg
        offline_tiles_provider/tiles/2/2/3.jpeg
    )

    set_source_files_properties(${MAP_T2G_TILES} PROPERTIES
        QUL_RESOURCE_CACHE_POLICY "OnDemand"
        QUL_RESOURCE_STORAGE_SECTION "QulResourceDataInExternalFlash"
    )
    if(VARIANT STREQUAL "4m")
        set_source_files_properties(${MAP_T2G_TILES} PROPERTIES
            QUL_RESOURCE_IMAGE_PIXEL_FORMAT "RGB565"
        )
    else()
        set_source_files_properties(${MAP_T2G_TILES} PROPERTIES
            QUL_RESOURCE_KEEP_RAW_DATA ON
        )
    endif()

    qul_add_resources(map
        FILES ${MAP_T2G_TILES}
        BASE "offline_tiles_provider"
    )

    if(VARIANT STREQUAL "4m")
        qul_set_maximum_resource_cache_size(map CACHE_SIZE 1400000)
    else()
        qul_set_maximum_resource_cache_size(map CACHE_SIZE 3000000)
    endif()

    if(QUL_PLATFORM MATCHES "^tviic2d6m[^-]*-baremetal")
        set(TRAVEO_T2G_IMAGEDECODER_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../imagedecoder/traveo-t2g")
        include("${TRAVEO_T2G_IMAGEDECODER_SOURCE_DIR}/tvii_jpeg_driver_lib.cmake") # will provide `TVII_JPEG_DRIVER_LIB`.

        target_sources(map PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}/../imagedecoder/traveo-t2g/traveot2gimagedecoder.cpp
            ${CMAKE_CURRENT_SOURCE_DIR}/../imagedecoder/traveo-t2g/tvii_jpeg.c
            ${CMAKE_CURRENT_SOURCE_DIR}/../imagedecoder/common/jpeg.cpp
        )

        target_compile_definitions(map PRIVATE T2G_JPEG_SUPPORT_ENABLED)

        list(APPEND CMAKE_MODULE_PATH ${QUL_PLATFORM_TARGET_DIR}/../common/cmake/modules)
        # Old path needed for platform compatibility checks after UL-5159 (renamed folder from tvii-shared to common)
        list(APPEND CMAKE_MODULE_PATH ${QUL_PLATFORM_TARGET_DIR}/../tvii-shared/cmake/modules)
        find_package(TVII-SDK REQUIRED COMPONENTS basic_graphics util freetype)

        target_include_directories(map PRIVATE
            ${CMAKE_CURRENT_SOURCE_DIR}/../imagedecoder/traveo-t2g/
            ${TVII_JPEG_DRIVER_DIR}/Source/jpgdec/include
            ${TVII_SDK_INCLUDE_DIRS}
        )

        target_link_libraries(map PRIVATE Qul::PlatformBSPConfig ${TVII_JPEG_DRIVER_LIB})
        if(GREENHILLS)
            target_link_libraries(map PRIVATE -T ${CMAKE_CURRENT_SOURCE_DIR}/../imagedecoder/traveo-t2g/JPEGDEC_register_map.ld)
        endif()

        if(IAR)
            target_compile_options(map PRIVATE --diag_suppress=Pe940) # Pe940 missing return statement at end of non-void function (graphics driver 1.2.1)
        endif()
    endif()
    app_target_setup_os(map)
endif()