qt_target_qml_from_svg() command in cmake

This adds a build command for generating QML files out of SVG
files automatically. It works by first calling svgtoqml on the
sources and then adding these to the QML module for the target.

[ChangeLog][svgtoqml] Added a cmake api for automatically
generating QML files from SVG files in an application.

Task-number: QTBUG-128915
Change-Id: I44e70f0ada4ca8ac9ac8253d46832d3a286da927
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2025-08-11 09:38:59 +02:00
parent 93ea1a12ec
commit 018b10ff71
5 changed files with 163 additions and 0 deletions

View File

@ -56,6 +56,7 @@ if(ANDROID)
include("${CMAKE_CURRENT_LIST_DIR}/src/qml/Qt6AndroidQmlMacros.cmake")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/src/qml/Qt6QmlPublicCMakeHelpers.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/tools/svgtoqml/Qt6SvgToQmlMacros.cmake")
# special case end
if(NOT QT_FEATURE_commandlineparser)

View File

@ -60,6 +60,9 @@ In addition, it supports the following options:
\li Display a preview of the Qt Quick item as it will be generated.
\endtable
The tool can be invoked automatically from the build by using the \l{qt_target_qml_from_svg()}
cmake function.
\section1 Comparison to other options
There are multiple options for including SVG content in Qt Quick. The following will give an
overview of where \c svgtoqml fits into the story.

View File

@ -0,0 +1,62 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qt_target_qml_from_svg.html
\ingroup cmake-commands-qtquick
\title qt_target_qml_from_svg
\keyword qt6_target_qml_from_svg
\summary {Generates QML code based on an SVG file.}
The command is defined in the \c QuickTools component of the \c Qt6 package, which can
be loaded like this:
\badcode
find_package(Qt6 REQUIRED COMPONENTS QuickTools)
\endcode
\cmakecommandsince 6.11
\section1 Synopsis
\badcode
qt_target_qml_from_svg(target
[CURVE_RENDERER]
[OPTIMIZE_PATHS]
[OUTLINE_STROKE_MODE]
[TYPE_NAME "MyShapeName"]
[COPYRIGHT_STATEMENT "Copyright (C) Company1"]
FILES file1.svg [file2.svg ...]
OUTPUTS File1.qml [File2.qml ...]
)
\endcode
\versionlessCMakeCommandsNote qt6_target_qml_from_svg()
\section1 Description
qt_target_qml_from_svg() creates the build steps to run \l{svgtoqml} on the list of SVG images in
\c FILES. The names of the generated files should be specified in \c OUTPUTS. The length of this
list must be the same as \c FILES, and the first element corresponds to the first element in
\c FILES and so forth. The names provided in \c OUTPUTS will be the names of the QML types as they
appear in the module. These can in turn be instantiated in the application code.
The generated QML files will be added to the QML module of \c{target}. You must use
\l{qt_add_qml_module()} to define a module for the \c{target} first.
Optionally, a \c COPYRIGHT_STATEMENT argument can be provided to insert copyright information
into the generated files.
\c TYPE_NAME is also optional, and can be used to replace all instances of the \l{Shape} type in
the generated file with a custom type. This can be useful to make general customizations to all
the shapes in the provided SVG files. The \c{TYPE_NAME} should refer to a QML type which is
available in the \c{target} QML module.
The options \c CURVE_RENDERER, \c OPTIMIZE_PATHS and \c OUTLINE_STROKE_MODE correspond to the
\c{--curve-renderer}, \c{--optimize-paths} and \c{--outline-stroke-mode} in \l{svgtoqml}
respectively.
*/

View File

@ -9,6 +9,10 @@ qt_get_tool_target_name(target_name svgtoqml)
qt_internal_add_tool(${target_name}
TARGET_DESCRIPTION "SVG to QML Converter"
TOOLS_TARGET Quick
EXTRA_CMAKE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}SvgToQmlMacros.cmake"
EXTRA_CMAKE_INCLUDES
"${QT_CMAKE_EXPORT_NAMESPACE}SvgToQmlMacros.cmake"
SOURCES
main.cpp
LIBRARIES

View File

@ -0,0 +1,93 @@
# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
function(qt6_target_qml_from_svg target)
set(opt_args
CURVE_RENDERER
OPTIMIZE_PATHS
OUTLINE_STROKE_MODE)
set(single_args
TYPE_NAME
COPYRIGHT_STATEMENT)
set(multi_args
FILES
OUTPUTS)
cmake_parse_arguments(PARSE_ARGV 1 arg "${opt_args}" "${single_args}" "${multi_args}")
_qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_FILES)
message(FATAL_ERROR "qt6_target_qml_from_svg: Missing input files.")
endif()
if(NOT arg_OUTPUTS)
message(FATAL_ERROR "qt6_target_qml_from_svg: Missing output files.")
endif()
get_target_property(val ${target} _qt_qml_module_uri)
if("${val}" MATCHES "-NOTFOUND$")
message(FATAL_ERROR "qt6_target_qml_from_svg: Target '${target}' must be a QML module.")
endif()
math(EXPR file_index "0")
foreach(filepath IN LISTS arg_FILES)
get_filename_component(filename "${filepath}" NAME_WLE)
get_filename_component(file_absolute ${filepath} ABSOLUTE)
set(svgtoqml_args "")
if (arg_CURVE_RENDERER)
list(APPEND svgtoqml_args "-c")
endif()
if (arg_OPTIMIZE_PATHS)
list(APPEND svgtoqml_args "-p")
endif()
if (arg_OUTLINE_STROKE_MODE)
list(APPEND svgtoqml_args "--outline-stroke-mode")
endif()
if(arg_COPYRIGHT_STATEMENT)
list(APPEND svgtoqml_args "--copyright-statement" "${arg_COPYRIGHT_STATEMENT}")
endif()
if (arg_TYPE_NAME)
list(APPEND svgtoqml_args "-t" "${arg_TYPE_NAME}")
endif()
list(GET arg_OUTPUTS ${file_index} output_file)
set(svgtoqml_result "${CMAKE_CURRENT_BINARY_DIR}/.qt/svgtoqml/${output_file}")
list(APPEND svgtoqml_args "${file_absolute}")
list(APPEND svgtoqml_args "${svgtoqml_result}")
add_custom_command(
OUTPUT "${svgtoqml_result}"
COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::svgtoqml ${svgtoqml_args}
DEPENDS
"${file_absolute}"
${QT_CMAKE_EXPORT_NAMESPACE}::svgtoqml
)
list(APPEND svgtoqml_files "${svgtoqml_result}")
set_source_files_properties("${svgtoqml_result}"
PROPERTIES
QT_RESOURCE_ALIAS
"${output_file}")
math(EXPR file_index "${file_index}+1")
endforeach()
qt6_target_qml_sources(
${target}
QML_FILES ${svgtoqml_files}
NO_LINT
)
endfunction()
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
function(qt_target_qml_from_svg)
qt6_target_qml_from_svg(${ARGV})
endfunction()
endif()