cf12defd28
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
259 lines
9.8 KiB
CMake
259 lines
9.8 KiB
CMake
#
|
|
# SPDX-FileCopyrightText: 2023 Arjen Hiemstra <ahiemstra@heimr.nl>
|
|
#
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
# Qt 6 implementation of ECMQmlModule
|
|
|
|
set(QT_NO_CREATE_VERSIONLESS_FUNCTIONS ON)
|
|
find_package(Qt6 COMPONENTS Core Qml CONFIG)
|
|
unset(QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
|
|
|
|
if (NOT TARGET Qt6::Qml)
|
|
message(WARNING "Target Qt6::Qml was not found. ECMQmlModule requires the QML module when building with Qt 6")
|
|
return()
|
|
endif()
|
|
|
|
# Match KDECMakeSettings' RUNTIME_OUTPUT_DIRECTORY so that we can load plugins from
|
|
# the build directory when running tests. But only if we don't yet have an output directory.
|
|
if (NOT QT_QML_OUTPUT_DIRECTORY)
|
|
set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
|
endif()
|
|
|
|
# Stop warning about a changed import prefix.
|
|
qt6_policy(SET QTP0001 NEW)
|
|
|
|
function(ecm_add_qml_module ARG_TARGET)
|
|
cmake_parse_arguments(PARSE_ARGV 1 ARG "NO_PLUGIN;QT_NO_PLUGIN;GENERATE_PLUGIN_SOURCE" "URI;VERSION;CLASSNAME;OUTPUT_TARGETS" "")
|
|
|
|
if ("${ARG_TARGET}" STREQUAL "")
|
|
message(FATAL_ERROR "ecm_add_qml_module called without a valid target name.")
|
|
endif()
|
|
|
|
if ("${ARG_URI}" STREQUAL "")
|
|
message(FATAL_ERROR "ecm_add_qml_module called without a valid module URI.")
|
|
endif()
|
|
|
|
string(FIND "${ARG_URI}" " " "_space")
|
|
if (${_space} GREATER_EQUAL 0)
|
|
message(FATAL_ERROR "ecm_add_qml_module called without a valid module URI.")
|
|
endif()
|
|
|
|
set(_arguments ${ARG_TARGET} URI ${ARG_URI})
|
|
|
|
if (ARG_VERSION)
|
|
list(APPEND _arguments VERSION ${ARG_VERSION})
|
|
endif()
|
|
|
|
if (ARG_CLASSNAME)
|
|
message(AUTHOR_WARNING "The CLASSNAME argument to ecm_add_qml_module is deprecated for Qt 6; Use CLASS_NAME instead.")
|
|
list(APPEND _arguments CLASS_NAME ${ARG_CLASSNAME})
|
|
endif()
|
|
|
|
if (ARG_NO_PLUGIN)
|
|
message(AUTHOR_WARNING "The NO_PLUGIN argument to ecm_add_qml_module is deprecated for Qt 6; For Qt 6 QML modules always require a plugin library. Use GENERATE_PLUGIN_SOURCE instead. If you wish to use the NO_PLUGIN feature from qt_add_qml_module, use QT_NO_PLUGIN.")
|
|
set(ARG_GENERATE_PLUGIN_SOURCE TRUE)
|
|
endif()
|
|
|
|
if (ARG_QT_NO_PLUGIN)
|
|
list(APPEND _arguments NO_PLUGIN)
|
|
endif()
|
|
|
|
if (NOT ARG_GENERATE_PLUGIN_SOURCE)
|
|
list(APPEND _arguments NO_GENERATE_PLUGIN_SOURCE)
|
|
endif()
|
|
|
|
if (NOT TARGET ${ARG_TARGET})
|
|
list(APPEND _arguments PLUGIN_TARGET ${ARG_TARGET})
|
|
if (BUILD_SHARED_LIBS)
|
|
list(APPEND _arguments SHARED)
|
|
else()
|
|
list(APPEND _arguments STATIC)
|
|
endif()
|
|
endif()
|
|
|
|
# make qmlimportscanner also find QML modules installed
|
|
# outside of the Qt prefix
|
|
if(IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${KDE_INSTALL_QMLDIR}")
|
|
list(APPEND _import_paths "${CMAKE_INSTALL_PREFIX}/${KDE_INSTALL_QMLDIR}")
|
|
endif()
|
|
foreach(_prefix ${CMAKE_PREFIX_PATH})
|
|
if(IS_DIRECTORY "${_prefix}/${KDE_INSTALL_QMLDIR}")
|
|
list(APPEND _import_paths "${_prefix}/${KDE_INSTALL_QMLDIR}")
|
|
endif()
|
|
endforeach()
|
|
list(APPEND _arguments IMPORT_PATH ${_import_paths})
|
|
|
|
list(APPEND _arguments ${ARG_UNPARSED_ARGUMENTS})
|
|
|
|
qt6_add_qml_module(${_arguments} OUTPUT_TARGETS _out_targets)
|
|
if (ARG_OUTPUT_TARGETS)
|
|
set(${ARG_OUTPUT_TARGETS} ${_out_targets} PARENT_SCOPE)
|
|
endif()
|
|
set_target_properties(${ARG_TARGET} PROPERTIES _ecm_output_targets "${_out_targets}")
|
|
|
|
# KDECMakeSettings sets the prefix of MODULE targets to empty but Qt will
|
|
# not load a QML plugin without prefix. So we need to force it here.
|
|
qt6_query_qml_module(${ARG_TARGET} PLUGIN_TARGET _plugin_target)
|
|
if (NOT WIN32 AND TARGET ${_plugin_target})
|
|
set_target_properties(${_plugin_target} PROPERTIES PREFIX "lib")
|
|
endif()
|
|
|
|
option(VERBOSE_QML_COMPILER "Enable verbose output for qmlcachegen" OFF)
|
|
|
|
if (VERBOSE_QML_COMPILER)
|
|
set_target_properties(${ARG_TARGET} PROPERTIES
|
|
QT_QMLCACHEGEN_ARGUMENTS "--verbose"
|
|
)
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
function(ecm_add_qml_module_dependencies ARG_TARGET)
|
|
message(AUTHOR_WARNING "ecm_add_qml_module_dependencies is deprecated for Qt 6; use the DEPENDENCIES argument to ecm_add_qml_module() instead.")
|
|
endfunction()
|
|
|
|
function(ecm_target_qml_sources ARG_TARGET)
|
|
cmake_parse_arguments(PARSE_ARGV 1 ARG "PRIVATE" "VERSION;PATH;OUTPUT_TARGETS" "SOURCES")
|
|
|
|
if ("${ARG_SOURCES}" STREQUAL "")
|
|
message(FATAL_ERROR "ecm_target_qml_sources called without required argument SOURCES")
|
|
endif()
|
|
|
|
if (ARG_VERSION)
|
|
set_source_files_properties(${ARG_SOURCES} PROPERTIES QT_QML_SOURCE_VERSIONS "${ARG_VERSION}")
|
|
endif()
|
|
|
|
if (ARG_PRIVATE)
|
|
set_source_files_properties(${ARG_SOURCES} PROPERTIES QT_QML_INTERNAL_TYPE TRUE)
|
|
endif()
|
|
|
|
set(_QML_FILES)
|
|
set(_RESOURCES)
|
|
foreach(_path ${ARG_SOURCES})
|
|
get_filename_component(_file "${_path}" NAME)
|
|
get_filename_component(_ext "${_path}" EXT)
|
|
set(_resource_alias "${_file}")
|
|
if (ARG_PATH)
|
|
set(_resource_alias "${ARG_PATH}/${_file}")
|
|
endif()
|
|
set_source_files_properties("${_path}" PROPERTIES QT_RESOURCE_ALIAS "${_resource_alias}")
|
|
if ("${_ext}" MATCHES "(.qml|.js|.mjs)")
|
|
list(APPEND _QML_FILES "${_path}")
|
|
else()
|
|
list(APPEND _RESOURCES "${_path}")
|
|
endif()
|
|
endforeach()
|
|
|
|
if(_QML_FILES)
|
|
qt6_target_qml_sources(${ARG_TARGET} QML_FILES ${_QML_FILES} OUTPUT_TARGETS _out_targets_qml ${ARG_UNPARSED_ARGUMENTS})
|
|
endif()
|
|
if(_RESOURCES)
|
|
qt6_target_qml_sources(${ARG_TARGET} RESOURCES ${_RESOURCES} OUTPUT_TARGETS _out_targets_qrc ${ARG_UNPARSED_ARGUMENTS})
|
|
endif()
|
|
list(APPEND _out_targets "${_out_targets_qml}" "${_out_targets_qrc}")
|
|
if (ARG_OUTPUT_TARGETS)
|
|
set(${ARG_OUTPUT_TARGETS} ${_out_targets} PARENT_SCOPE)
|
|
endif()
|
|
get_target_property(_ecm_output_targets ${ARG_TARGET} _ecm_output_targets)
|
|
list(APPEND _ecm_output_targets ${_out_targets})
|
|
set_target_properties(${ARG_TARGET} PROPERTIES _ecm_output_targets "${_ecm_output_targets}")
|
|
|
|
endfunction()
|
|
|
|
function(ecm_finalize_qml_module ARG_TARGET)
|
|
cmake_parse_arguments(PARSE_ARGV 1 ARG "" "DESTINATION;VERSION;EXPORT" "")
|
|
|
|
if (NOT ARG_DESTINATION)
|
|
set(ARG_DESTINATION "${KDE_INSTALL_QMLDIR}")
|
|
endif()
|
|
|
|
if ("${ARG_DESTINATION}" STREQUAL "")
|
|
message(FATAL_ERROR "ecm_finalize_qml_module called without required argument DESTINATION and KDE_INSTALL_QMLDIR is not set")
|
|
endif()
|
|
|
|
if (NOT ARG_VERSION)
|
|
set(ARG_VERSION "${PROJECT_VERSION}")
|
|
endif()
|
|
|
|
# This is effectively a workaround for missing upstream API, see QTBUG-100102
|
|
|
|
qt6_query_qml_module(${ARG_TARGET}
|
|
URI module_uri
|
|
VERSION module_version
|
|
PLUGIN_TARGET module_plugin_target
|
|
TARGET_PATH module_target_path
|
|
QMLDIR module_qmldir
|
|
TYPEINFO module_typeinfo
|
|
QML_FILES module_qml_files
|
|
RESOURCES module_resources
|
|
)
|
|
|
|
set(module_dir "${ARG_DESTINATION}/${module_target_path}")
|
|
|
|
if (NOT TARGET "${module_plugin_target}")
|
|
return()
|
|
endif()
|
|
|
|
if (ARG_EXPORT AND NOT BUILD_SHARED_LIBS)
|
|
set(_install_targets_args EXPORT "${ARG_EXPORT}")
|
|
endif()
|
|
install(TARGETS "${module_plugin_target}"
|
|
${_install_targets_args}
|
|
LIBRARY DESTINATION "${module_dir}"
|
|
RUNTIME DESTINATION "${module_dir}"
|
|
)
|
|
|
|
# Install dependent targets created for static builds
|
|
get_target_property(_ecm_output_targets ${ARG_TARGET} _ecm_output_targets)
|
|
if (_ecm_output_targets AND ARG_EXPORT)
|
|
install(TARGETS ${_ecm_output_targets}
|
|
EXPORT ${ARG_EXPORT}
|
|
LIBRARY DESTINATION "${module_dir}"
|
|
RUNTIME DESTINATION "${module_dir}"
|
|
OBJECTS DESTINATION "${module_dir}"
|
|
)
|
|
endif()
|
|
|
|
# Install the QML module meta information.
|
|
install(FILES "${module_qmldir}" DESTINATION "${module_dir}")
|
|
install(FILES "${module_typeinfo}" DESTINATION "${module_dir}")
|
|
|
|
# Install QML files, possibly renamed.
|
|
# see Kirigami::StyleSelector::resolveFileX, on Android we never use QML files from disk
|
|
# but rather always the ones from qrc
|
|
if (NOT ANDROID)
|
|
list(LENGTH module_qml_files num_files)
|
|
if (NOT "${module_qml_files}" MATCHES "NOTFOUND" AND ${num_files} GREATER 0)
|
|
qt6_query_qml_module(${ARG_TARGET} QML_FILES_DEPLOY_PATHS qml_files_deploy_paths)
|
|
|
|
math(EXPR last_index "${num_files} - 1")
|
|
foreach(i RANGE 0 ${last_index})
|
|
list(GET module_qml_files ${i} src_file)
|
|
list(GET qml_files_deploy_paths ${i} deploy_path)
|
|
get_filename_component(dst_name "${deploy_path}" NAME)
|
|
get_filename_component(dest_dir "${deploy_path}" DIRECTORY)
|
|
install(FILES "${src_file}" DESTINATION "${module_dir}/${dest_dir}" RENAME "${dst_name}")
|
|
endforeach()
|
|
endif()
|
|
endif()
|
|
|
|
# Install resources, possibly renamed.
|
|
list(LENGTH module_resources num_files)
|
|
if (NOT "${module_resources}" MATCHES "NOTFOUND" AND ${num_files} GREATER 0)
|
|
qt6_query_qml_module(${ARG_TARGET} RESOURCES_DEPLOY_PATHS resources_deploy_paths)
|
|
|
|
math(EXPR last_index "${num_files} - 1")
|
|
foreach(i RANGE 0 ${last_index})
|
|
list(GET module_resources ${i} src_file)
|
|
list(GET resources_deploy_paths ${i} deploy_path)
|
|
get_filename_component(dst_name "${deploy_path}" NAME)
|
|
get_filename_component(dest_dir "${deploy_path}" DIRECTORY)
|
|
install(FILES "${src_file}" DESTINATION "${module_dir}/${dest_dir}" RENAME "${dst_name}")
|
|
endforeach()
|
|
endif()
|
|
|
|
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET}-kde-qmlmodule.version" CONTENT "${ARG_VERSION}\n")
|
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET}-kde-qmlmodule.version" DESTINATION "${module_dir}" RENAME "kde-qmlmodule.version")
|
|
endfunction()
|