Add support for QML plugins
Add the necessary code to both the QtBuild and pro2cmake to be able to handle qml plugins in qt declarative. Add condition replacement for QTDIR_build to QT_BUILDING_QT so that certain qml examples work correctly when being built in the build directory. Fix add_qt_resources not being updated during build after changes were made. Files list used as dependencies were not populated. Add missing module mappings for qtdeclarative. Change-Id: I0f71d0a3a0e7e97ba96807950d11cffaee04d9b2 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> Reviewed-by: Qt CMake Build Bot
This commit is contained in:
parent
faac0ef8c6
commit
30b3746370
@ -1455,10 +1455,19 @@ function(add_qt_plugin target)
|
|||||||
qt_internal_set_qt_known_plugins("${QT_KNOWN_PLUGINS}" "${target}")
|
qt_internal_set_qt_known_plugins("${QT_KNOWN_PLUGINS}" "${target}")
|
||||||
|
|
||||||
qt_parse_all_arguments(arg "add_qt_plugin" "STATIC;EXCEPTIONS"
|
qt_parse_all_arguments(arg "add_qt_plugin" "STATIC;EXCEPTIONS"
|
||||||
"TYPE;CLASS_NAME;OUTPUT_DIRECTORY;INSTALL_DIRECTORY;ARCHIVE_INSTALL_DIRECTORY"
|
"TYPE;CLASS_NAME;OUTPUT_DIRECTORY;INSTALL_DIRECTORY;ARCHIVE_INSTALL_DIRECTORY;QML_TARGET_PATH"
|
||||||
"${__default_private_args};${__default_public_args};DEFAULT_IF" ${ARGN})
|
"${__default_private_args};${__default_public_args};DEFAULT_IF" ${ARGN})
|
||||||
|
|
||||||
set(output_directory_default "${QT_BUILD_DIR}/${INSTALL_PLUGINSDIR}/${arg_TYPE}")
|
set(output_directory_default "${QT_BUILD_DIR}/${INSTALL_PLUGINSDIR}/${arg_TYPE}")
|
||||||
|
set(install_directory_default "${INSTALL_PLUGINSDIR}/${arg_TYPE}")
|
||||||
|
set(archive_install_directory_default "${INSTALL_LIBDIR}/${arg_TYPE}")
|
||||||
|
|
||||||
|
if (arg_QML_TARGET_PATH)
|
||||||
|
set(target_path "${arg_QML_TARGET_PATH}")
|
||||||
|
set(output_directory_default "${QT_BUILD_DIR}/${INSTALL_QMLDIR}/${target_path}")
|
||||||
|
set(install_directory_default "${INSTALL_QMLDIR}/${target_path}")
|
||||||
|
set(archive_install_directory_default "${INSTALL_QMLDIR}/${target_path}")
|
||||||
|
endif()
|
||||||
|
|
||||||
if ("x${arg_CLASS_NAME}" STREQUAL x)
|
if ("x${arg_CLASS_NAME}" STREQUAL x)
|
||||||
message(AUTHOR_WARNING "add_qt_plugin called without setting CLASS_NAME.")
|
message(AUTHOR_WARNING "add_qt_plugin called without setting CLASS_NAME.")
|
||||||
@ -1467,10 +1476,10 @@ function(add_qt_plugin target)
|
|||||||
qt_internal_check_directory_or_type(OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}" "${arg_TYPE}"
|
qt_internal_check_directory_or_type(OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}" "${arg_TYPE}"
|
||||||
"${output_directory_default}" output_directory)
|
"${output_directory_default}" output_directory)
|
||||||
qt_internal_check_directory_or_type(INSTALL_DIRECTORY "${arg_INSTALL_DIRECTORY}" "${arg_TYPE}"
|
qt_internal_check_directory_or_type(INSTALL_DIRECTORY "${arg_INSTALL_DIRECTORY}" "${arg_TYPE}"
|
||||||
"${INSTALL_PLUGINSDIR}/${arg_TYPE}" install_directory)
|
"${install_directory_default}" install_directory)
|
||||||
qt_internal_check_directory_or_type(ARCHIVE_INSTALL_DIRECTORY
|
qt_internal_check_directory_or_type(ARCHIVE_INSTALL_DIRECTORY
|
||||||
"${arg_ARCHIVE_INSTALL_DIRECTORY}" "${arg_TYPE}"
|
"${arg_ARCHIVE_INSTALL_DIRECTORY}" "${arg_TYPE}"
|
||||||
"${INSTALL_LIBDIR}/${arg_TYPE}" archive_install_directory)
|
"${archive_install_directory_default}" archive_install_directory)
|
||||||
|
|
||||||
if(arg_STATIC OR NOT BUILD_SHARED_LIBS)
|
if(arg_STATIC OR NOT BUILD_SHARED_LIBS)
|
||||||
add_library("${target}" STATIC)
|
add_library("${target}" STATIC)
|
||||||
@ -1614,6 +1623,135 @@ function(add_qt_plugin target)
|
|||||||
qt_internal_add_linker_version_script(${target})
|
qt_internal_add_linker_version_script(${target})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# Generate custom ${target}_qmltypes target for Qml Plugins
|
||||||
|
function(qt_add_qmltypes_target target)
|
||||||
|
|
||||||
|
# Do nothing when cross compiling
|
||||||
|
if (CMAKE_CROSSCOMPILING)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
qt_parse_all_arguments(arg "qt_generate_qmltypes"
|
||||||
|
""
|
||||||
|
"TARGET_PATH;IMPORT_VERSION;IMPORT_NAME;CXX_MODULE;QML_PLUGINDUMP_DENDENCIES"
|
||||||
|
""
|
||||||
|
${ARGN})
|
||||||
|
|
||||||
|
# scan repos for qml repositories
|
||||||
|
foreach(repo IN LISTS QT_REPOS)
|
||||||
|
if (IS_DIRECTORY "${repo}/qml")
|
||||||
|
list(APPEND import_paths "${repo}/qml")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
list(REMOVE_DUPLICATES import_paths)
|
||||||
|
if (UNIX)
|
||||||
|
list(JOIN import_paths ":" import_paths_env)
|
||||||
|
else()
|
||||||
|
list(JOIN import_paths "\;" import_paths_env)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT arg_IMPORT_NAME)
|
||||||
|
string(REGEX REPLACE "\\.\\d+$" "" import_name ${arg_TARGET_PATH})
|
||||||
|
else()
|
||||||
|
set(import_name ${arg_IMPORT_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT arg_IMPORT_VERSION)
|
||||||
|
if(NOT arg_CXX_MODULE)
|
||||||
|
if (NOT ${CMAKE_PROJECT_VERSION_MAJOR} OR NOT ${CMAKE_PROJECT_VERSION_MINOR})
|
||||||
|
message(FATAL_ERROR "Please specify import version using IMPORT_VERSION")
|
||||||
|
endif()
|
||||||
|
set(import_version "${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}")
|
||||||
|
else()
|
||||||
|
if(NOT TARGET arg_CXX_MODULE)
|
||||||
|
message(FATAL_ERROR "CXX_MODULE parameter must be a cmake target")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_target_property(qt_major_version ${arg_CXX_MODULE} INTERFACE_QT_MAJOR_VERSION)
|
||||||
|
if (NOT qt_major_version)
|
||||||
|
message(FATAL_ERROR "CXX_MODULE(${arg_CXX_MODULE} is not a valid Qt module")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_target_property(cxx_module_alias ${arg_CXX_MODULE} ALIASED_TARGET)
|
||||||
|
if (cxx_module_alias)
|
||||||
|
set(cxx_module_target ${cxx_module_alias})
|
||||||
|
else()
|
||||||
|
set(cxx_module_target ${arg_CXX_MODULE})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(import_version "${${cxx_module_target}_VERSION_MAJOR}.${${cxx_module_target}_VERSION_MINOR}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(import_version ${arg_IMPORT_VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_target_property(source_dir ${target} SOURCE_DIR)
|
||||||
|
|
||||||
|
# qml1_target check is no longer required
|
||||||
|
set(qmltypes_command_args "-nonrelocatable")
|
||||||
|
if (NOT arg_QML_PLUGINDUMP_DENDENCIES AND EXISTS "${source_dir}/dependencies.json")
|
||||||
|
list(APPEND qmltypes_command_args "-dependencies" "${source_dir}/dependencies.json")
|
||||||
|
elseif(arg_QML_PLUGINDUMP_DENDENCIES)
|
||||||
|
list(APPEND qmltypes_command_args "-dependencies" "${arg_QML_PLUGINDUMP_DENDENCIES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
string(REPLACE "/" "." import_name_arg ${import_name})
|
||||||
|
|
||||||
|
list(APPEND qmltypes_command_args "${import_name_arg}" "${import_version}")
|
||||||
|
|
||||||
|
add_custom_target(
|
||||||
|
"${target}_qmltypes"
|
||||||
|
DEPENDS qmlplugindump
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E env "QML2_IMPORTPATH=${import_paths_env}"
|
||||||
|
$<TARGET_FILE:qmlplugindump> ${qmltypes_command_args} > "${source_dir}/plugins.qmltypes"
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(add_qml_module target)
|
||||||
|
qt_parse_all_arguments(arg "add_qml_module"
|
||||||
|
""
|
||||||
|
"TARGET_PATH;IMPORT_VERSION;IMPORT_NAME;CXX_MODULE;QML_PLUGINDUMP_DENDENCIES"
|
||||||
|
"QML_FILES" ${ARGN})
|
||||||
|
|
||||||
|
if (NOT arg_TARGET_PATH)
|
||||||
|
message(FATAL_ERROR "add_qml_module called without a TARGET_PATH.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
qt_add_qmltypes_target(${target}
|
||||||
|
TARGET_PATH "${arg_TARGET_PATH}"
|
||||||
|
IMPORT_VERSION "${arg_IMPORT_VERSION}"
|
||||||
|
IMPORT_NAME "${arg_IMPORT_NAME}"
|
||||||
|
CXX_MODULE "${arg_CXX_MODULE}"
|
||||||
|
QML_PLUGINDUMP_DENDENCIES "${arg_QML_PLUGINDUMP_DENDENCIES}")
|
||||||
|
|
||||||
|
set(plugin_types "${CMAKE_CURRENT_SOURCE_DIR}/plugins.qmltypes")
|
||||||
|
if (EXISTS ${plugin_types})
|
||||||
|
qt_copy_or_install(FILES ${plugin_types}
|
||||||
|
DESTINATION "${INSTALL_QMLDIR}/${arg_TARGET_PATH}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
qt_copy_or_install(
|
||||||
|
FILES
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
|
||||||
|
DESTINATION
|
||||||
|
"${INSTALL_QMLDIR}/${arg_TARGET_PATH}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT QT_BUILD_SHARED_LIBS)
|
||||||
|
string(REPLACE "." "_" uri_target ${arg_TARGET_PATH})
|
||||||
|
add_qt_resource(${target} ${uri_target}
|
||||||
|
FILES ${arg_QML_FILES} "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
|
||||||
|
PREFIX "/qt-project.org/import/${arg_TARGET_PATH}")
|
||||||
|
else()
|
||||||
|
if(arg_QML_FILES)
|
||||||
|
qt_copy_or_install(FILES ${arg_QML_FILES}
|
||||||
|
DESTINATION "${INSTALL_QMLDIR}/${arg_TARGET_PATH}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endfunction()
|
||||||
|
|
||||||
# This function creates a CMake target for a generic console or GUI binary.
|
# This function creates a CMake target for a generic console or GUI binary.
|
||||||
# Please consider to use a more specific version target like the one created
|
# Please consider to use a more specific version target like the one created
|
||||||
@ -1910,6 +2048,7 @@ function(add_qt_resource target resourceName)
|
|||||||
# <file ...>...</file>
|
# <file ...>...</file>
|
||||||
string(APPEND qrcContents " <file alias=\"${alias}\">")
|
string(APPEND qrcContents " <file alias=\"${alias}\">")
|
||||||
string(APPEND qrcContents "${CMAKE_CURRENT_SOURCE_DIR}/${based_file}</file>\n")
|
string(APPEND qrcContents "${CMAKE_CURRENT_SOURCE_DIR}/${based_file}</file>\n")
|
||||||
|
list(APPEND files "${CMAKE_CURRENT_SOURCE_DIR}/${based_file}")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# </qresource></RCC>
|
# </qresource></RCC>
|
||||||
|
@ -176,6 +176,8 @@ _qt_library_map = [
|
|||||||
LibraryMapping('xkbcommon_support', 'Qt6', 'Qt::XkbCommonSupport', extra = ['COMPONENTS', 'XkbCommonSupport']),
|
LibraryMapping('xkbcommon_support', 'Qt6', 'Qt::XkbCommonSupport', extra = ['COMPONENTS', 'XkbCommonSupport']),
|
||||||
LibraryMapping('xmlpatterns', 'Qt6', 'Qt::XmlPatterns', extra = ['COMPONENTS', 'XmlPatterns']),
|
LibraryMapping('xmlpatterns', 'Qt6', 'Qt::XmlPatterns', extra = ['COMPONENTS', 'XmlPatterns']),
|
||||||
LibraryMapping('xml', 'Qt6', 'Qt::Xml', extra = ['COMPONENTS', 'Xml']),
|
LibraryMapping('xml', 'Qt6', 'Qt::Xml', extra = ['COMPONENTS', 'Xml']),
|
||||||
|
LibraryMapping('qmlworkerscript', 'Qt6', 'Qt::QmlWorkerScript', extra = ['COMPONENTS', 'QmlWorkerScript']),
|
||||||
|
LibraryMapping('quickparticles', 'Qt6', 'Qt::QuickParticles', extra = ['COMPONENTS', 'QuickParticles'])
|
||||||
# qtzlib: No longer supported.
|
# qtzlib: No longer supported.
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1441,6 +1441,7 @@ def recursive_evaluate_scope(scope: Scope, parent_condition: str = '',
|
|||||||
|
|
||||||
|
|
||||||
def map_to_cmake_condition(condition: typing.Optional[str]) -> str:
|
def map_to_cmake_condition(condition: typing.Optional[str]) -> str:
|
||||||
|
condition = condition.replace("QTDIR_build", "QT_BUILDING_QT")
|
||||||
condition = re.sub(r'\bQT_ARCH___equals___([a-zA-Z_0-9]*)',
|
condition = re.sub(r'\bQT_ARCH___equals___([a-zA-Z_0-9]*)',
|
||||||
r'(TEST_architecture_arch STREQUAL "\1")', condition or '')
|
r'(TEST_architecture_arch STREQUAL "\1")', condition or '')
|
||||||
condition = re.sub(r'\bQT_ARCH___contains___([a-zA-Z_0-9]*)',
|
condition = re.sub(r'\bQT_ARCH___contains___([a-zA-Z_0-9]*)',
|
||||||
@ -1490,7 +1491,6 @@ def write_extend_target(cm_fh: typing.IO[str], target: str,
|
|||||||
|
|
||||||
write_resources(cm_fh, target, scope, indent)
|
write_resources(cm_fh, target, scope, indent)
|
||||||
|
|
||||||
|
|
||||||
def flatten_scopes(scope: Scope) -> typing.List[Scope]:
|
def flatten_scopes(scope: Scope) -> typing.List[Scope]:
|
||||||
result = [scope] # type: typing.List[Scope]
|
result = [scope] # type: typing.List[Scope]
|
||||||
for c in scope.children:
|
for c in scope.children:
|
||||||
@ -1770,8 +1770,14 @@ def write_plugin(cm_fh, scope, *, indent: int = 0):
|
|||||||
extra = []
|
extra = []
|
||||||
|
|
||||||
plugin_type = scope.get_string('PLUGIN_TYPE')
|
plugin_type = scope.get_string('PLUGIN_TYPE')
|
||||||
|
is_qml_plugin = any('qml_plugin' == s for s in scope.get('_LOADED'))
|
||||||
|
target_path = scope.get_string('TARGETPATH')
|
||||||
|
|
||||||
if plugin_type:
|
if plugin_type:
|
||||||
extra.append('TYPE {}'.format(plugin_type))
|
extra.append('TYPE {}'.format(plugin_type))
|
||||||
|
elif is_qml_plugin:
|
||||||
|
extra.append('TYPE {}'.format('qml_plugin'))
|
||||||
|
extra.append('QML_TARGET_PATH "{}"'.format(target_path))
|
||||||
|
|
||||||
plugin_class_name = scope.get_string('PLUGIN_CLASS_NAME')
|
plugin_class_name = scope.get_string('PLUGIN_CLASS_NAME')
|
||||||
if plugin_class_name:
|
if plugin_class_name:
|
||||||
@ -1780,13 +1786,56 @@ def write_plugin(cm_fh, scope, *, indent: int = 0):
|
|||||||
write_main_part(cm_fh, plugin_name, 'Plugin', 'add_qt_plugin', scope,
|
write_main_part(cm_fh, plugin_name, 'Plugin', 'add_qt_plugin', scope,
|
||||||
indent=indent, extra_lines=extra, known_libraries={}, extra_keys=[])
|
indent=indent, extra_lines=extra, known_libraries={}, extra_keys=[])
|
||||||
|
|
||||||
|
if is_qml_plugin:
|
||||||
|
extra = []
|
||||||
|
extra.append('TARGET_PATH "{}"'.format(target_path))
|
||||||
|
|
||||||
|
write_qml_plugin(cm_fh, plugin_name, scope, indent=indent, extra_lines=extra)
|
||||||
|
|
||||||
|
|
||||||
|
def write_qml_plugin(cm_fh: typing.IO[str],
|
||||||
|
target: str,
|
||||||
|
scope: Scope, *,
|
||||||
|
extra_lines: typing.List[str] = [],
|
||||||
|
indent: int = 0,
|
||||||
|
**kwargs: typing.Any):
|
||||||
|
# Collect other args if available
|
||||||
|
cxx_module = scope.get_string('CXX_MODULE')
|
||||||
|
if cxx_module:
|
||||||
|
extra_lines.append('CXX_MODULE "{}"'.format(cxx_module))
|
||||||
|
import_version = scope.get_string('IMPORT_VERSION')
|
||||||
|
if import_version:
|
||||||
|
import_version = import_version.replace("$$QT_MINOR_VERSION","${CMAKE_PROJECT_VERSION_MINOR}")
|
||||||
|
extra_lines.append('IMPORT_VERSION "{}"'.format(import_version))
|
||||||
|
import_name = scope.get_string('IMPORT_NAME')
|
||||||
|
if import_name:
|
||||||
|
extra_lines.append('IMPORT_NAME "{}"'.format(import_name))
|
||||||
|
plugindump_dep = scope.get_string('QML_PLUGINDUMP_DEPENDENCIES')
|
||||||
|
if plugindump_dep:
|
||||||
|
extra_lines.append('QML_PLUGINDUMP_DEPENDENCIES "{}"'.format(plugindump_dep))
|
||||||
|
|
||||||
|
cm_fh.write('\n{}{}({}\n'.format(spaces(indent), 'add_qml_module', target))
|
||||||
|
indent += 1
|
||||||
|
for extra_line in extra_lines:
|
||||||
|
cm_fh.write('{}{}\n'.format(spaces(indent), extra_line))
|
||||||
|
|
||||||
|
qml_files = scope.expand('QML_FILES')
|
||||||
|
if qml_files:
|
||||||
|
cm_fh.write('{}{}\n'.format(spaces(indent), 'QML_FILES'))
|
||||||
|
write_list(cm_fh, qml_files, '', indent=indent + 1)
|
||||||
|
|
||||||
|
# Footer:
|
||||||
|
indent -= 1
|
||||||
|
cm_fh.write('{})\n'.format(spaces(indent)))
|
||||||
|
|
||||||
|
|
||||||
def handle_app_or_lib(scope: Scope, cm_fh: typing.IO[str], *,
|
def handle_app_or_lib(scope: Scope, cm_fh: typing.IO[str], *,
|
||||||
indent: int = 0, is_example: bool=False) -> None:
|
indent: int = 0, is_example: bool=False) -> None:
|
||||||
assert scope.TEMPLATE in ('app', 'lib')
|
assert scope.TEMPLATE in ('app', 'lib')
|
||||||
|
|
||||||
is_lib = scope.TEMPLATE == 'lib'
|
is_lib = scope.TEMPLATE == 'lib'
|
||||||
is_plugin = any('qt_plugin' == s for s in scope.get('_LOADED'))
|
is_qml_plugin = any('qml_plugin' == s for s in scope.get('_LOADED'))
|
||||||
|
is_plugin = any('qt_plugin' == s for s in scope.get('_LOADED')) or is_qml_plugin
|
||||||
|
|
||||||
if is_lib or 'qt_module' in scope.get('_LOADED'):
|
if is_lib or 'qt_module' in scope.get('_LOADED'):
|
||||||
assert not is_example
|
assert not is_example
|
||||||
|
Loading…
x
Reference in New Issue
Block a user