summaryrefslogtreecommitdiffstats
path: root/cmake
diff options
context:
space:
mode:
authorLeander Beernaert <leander.beernaert@qt.io>2019-08-02 11:25:59 +0200
committerLeander Beernaert <leander.beernaert@qt.io>2019-08-09 07:33:55 +0000
commit2d484909405941f69f9005250723518cb7da1587 (patch)
tree247b8c711d03e41f314bec18f10ca5da42b8f56c /cmake
parentc894c224d1973f44498ad01c5bd8e29f6af51f2f (diff)
Enable quick compiler for qml files in add_qt_resource
File passed into add_qt_resource are check to see if they match valid qml files extension. Those which match the latter are then processed by the qt quick compiler should the qmlcachegen target be present. We also ensure that any remaining resources are properly chainloaded. If the qmlcachegen target can't be located a warning be will be issued asking for the inclusion of QmlTools in the find_package command. Change-Id: Ieecd38670e15c21d94dc549b31c7d87f2383d9af Reviewed-by: Qt CMake Build Bot Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'cmake')
-rw-r--r--cmake/QtBuild.cmake322
1 files changed, 158 insertions, 164 deletions
diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake
index 724c7de4dd..8d828127c5 100644
--- a/cmake/QtBuild.cmake
+++ b/cmake/QtBuild.cmake
@@ -1872,143 +1872,6 @@ Please add QmlTools to your find_package command."
endfunction()
-# Create a custom target that will ensure all js and qml files are processed
-# by the qmlcachegen tool during build and their output embedded into the target
-# binary.
-#
-# TARGET_PATH: QML target path
-# QML_FILES: List of QML Files
-# RESOURCE_PREFIX: Resource prefix to be prepended to the module's TARGET_PATH
-#
-function(add_quick_compiler_target target)
-
- if (NOT TARGET ${QT_CMAKE_EXPORT_NAMESPACE}::qmlcachegen)
- message(FATAL_ERROR "Could not locate qmlcachegen tool. \
-Please add QmlTools to your find_package command."
- )
- endif()
-
- qt_parse_all_arguments(arg "add_quick_compiler_target"
- "" "TARGET_PATH;RESOURCE_PREFIX" "QML_FILES" ${ARGN}
- )
-
- if (NOT arg_RESOURCE_PREFIX)
- message(FATAL_ERROR "add_quick_compiler_target: no resource prefix specified, please specify one using the RESOURCE_PREFIX")
- endif()
-
- if (NOT arg_TARGET_PATH)
- message(FATAL_ERROR "add_quick_compiler_target: no target path specified, please specify one using the TARGET_PATH")
- endif()
-
- if (arg_QML_FILES)
-
- # enable quick compiler and qml loader
- foreach(file IN LISTS arg_QML_FILES)
- get_filename_component(file_absolute ${file} ABSOLUTE)
- file(RELATIVE_PATH file_relative ${CMAKE_CURRENT_SOURCE_DIR} ${file_absolute})
- qt_get_relative_resource_path_for_file(alias ${file})
- set(file_resource_path "${arg_RESOURCE_PREFIX}/${arg_TARGET_PATH}/${alias}")
- list(APPEND file_resource_paths ${file_resource_path})
- string(REGEX REPLACE "\.js$" "_js" compiled_file ${file_relative})
- string(REGEX REPLACE "\.mjs$" "_mjs" compiled_file ${compiled_file})
- string(REGEX REPLACE "\.qml$" "_qml" compiled_file ${compiled_file})
- set(compiled_file "${CMAKE_CURRENT_BINARY_DIR}/qmlcache/${compiled_file}.cpp")
- add_custom_command(
- OUTPUT ${compiled_file}
- DEPENDS ${file_absolute}
- COMMAND
- ${QT_CMAKE_EXPORT_NAMESPACE}::qmlcachegen
- --resource-path ${file_resource_path}
- -o ${compiled_file}
- ${file_absolute}
- )
- target_sources(${target} PRIVATE ${compiled_file})
- endforeach()
-
- # Use hash of the current list of qml files so the generated loader
- # cpp file and list should be unique between invocation of this
- # function
- string(MD5 unique_id "${arg_QML_FILES}")
- set(qmlcache_loader_list "${CMAKE_CURRENT_BINARY_DIR}/qmlcache/${unique_id}_${target}_qml_loader_file_list.rsp")
- file(GENERATE
- OUTPUT ${qmlcache_loader_list}
- CONTENT "$<JOIN:${file_resource_paths},\n>"
- )
-
- set(qmlcache_loader_file "${CMAKE_CURRENT_BINARY_DIR}/qmlcache/${unique_id}_qmlcache_loader.cpp")
- string(REPLACE "/" "_" resource_name ${arg_TARGET_PATH})
- string(REPLACE "." "_" resource_name ${resource_name})
- set(resource_name "qmake_${resource_name}.qrc")
- add_custom_command(
- OUTPUT ${qmlcache_loader_file}
- DEPENDS ${qmlcache_loader_list}
- COMMAND
- ${QT_CMAKE_EXPORT_NAMESPACE}::qmlcachegen
- --resource-name "${resource_name}"
- -o ${qmlcache_loader_file}
- "@${qmlcache_loader_list}"
- )
- target_sources(${target} PRIVATE ${qmlcache_loader_file})
- endif()
-endfunction()
-
-# Note this function is a temporary implementation that will be removed
-# in the next patch. It just aggregates all special processing that used
-# to be done on qml files.
-function(target_qml_files target)
- set(qml_files ${ARGV})
- list(REMOVE_ITEM qml_files ${target})
-
- if (NOT qml_files)
- message(FATAL_ERROR "Calling target_qml_files without any qml files.")
- endif()
-
- get_target_property(target_path ${target} QT_QML_MODULE_TARGET_PATH)
- if (NOT target_path)
- message(FATAL_ERROR "Calling target_qml_files on a target has not been created via add_qml_module.")
- endif()
-
- foreach (qml_file IN LISTS qml_files)
- if (NOT ${qml_file} MATCHES "\.js$"
- AND NOT ${qml_file} MATCHES "\.mjs$"
- AND NOT ${qml_file} MATCHES "\.qml$")
- message(FATAL_ERROR "target_qml_files, '${qml_file}' is not a valid qml file. Valid extensions are: .js, .mjs and .qml.")
- endif()
- endforeach()
-
-
- get_target_property(install_qml_files ${target} QT_QML_MODULE_INSTALL_QML_FILES)
- get_target_property(embed_qml_files ${target} QT_QML_MODULE_EMBED_QML_FILES)
-
- # Only generate compiled caches if we are not embedding
- if (NOT embed_qml_files AND install_qml_files)
- add_qmlcachegen_target(${target}
- QML_FILES ${qml_files}
- TARGET_PATH ${target_path}
- )
- endif()
-
- if(NOT QT_BUILD_SHARED_LIBS OR embed_qml_files)
- get_target_property(prefix ${target} QT_QML_MODULE_RESOURCE_PREFIX)
- string(REPLACE "/" "." uri ${target_path})
- string(REPLACE "." "_" uri_target ${uri})
-
- add_quick_compiler_target(${target}
- TARGET_PATH ${target_path}
- QML_FILES ${qml_files}
- RESOURCE_PREFIX ${prefix}
- )
- endif()
-
- if (QT_BUILD_SHARED_LIBS AND arg_QML_FILES AND arg_INSTALL_QML_FILES)
- qt_copy_or_install(FILES ${arg_QML_FILES}
- DESTINATION "${qml_module_install_dir}"
- )
- endif()
-
-endfunction()
-
-
function(qt_install_qml_files target)
qt_parse_all_arguments(arg "qt_install_qml_files"
@@ -2024,7 +1887,6 @@ function(qt_install_qml_files target)
message(FATAL_ERROR "Target ${target} is not a qml module.")
endif()
-
qt_path_join(qml_module_install_dir ${QT_INSTALL_DIR} "${INSTALL_QMLDIR}/${target_path}")
qt_copy_or_install(FILES ${arg_FILES}
DESTINATION ${qml_module_install_dir}
@@ -2543,6 +2405,121 @@ function(qt_get_relative_resource_path_for_file output_alias file)
set(${output_alias} ${alias} PARENT_SCOPE)
endfunction()
+# Inspect all files passed to a call to add_qt_resource. If there are any
+# files present, invoke the quick compiler and return the remaining resource
+# files that have not been prossed in REMAING_RESOURCES as well as the new
+# name for the resource in OUTPUT_RESOURCE_NAME.
+function(qt_quick_compiler_process_resources target resource_name)
+
+ qt_parse_all_arguments(arg "qt_qtuick_compiler_process_resources"
+ "" "PREFIX;OUTPUT_REMAINING_RESOURCES;OUTPUT_RESOURCE_NAME" "FILES" ${ARGN}
+ )
+
+ set(qml_files)
+ # scan for qml files
+ foreach(file IN LISTS arg_FILES)
+ # check whether this resource should not be processed by the qt quick
+ # compiler
+ get_source_file_property(skip_compiler_check ${file} QT_QUICKCOMPILER_SKIPPED_RESOURCE)
+ if (skip_compiler_check)
+ list(APPEND resource_files ${file})
+ continue()
+ endif()
+
+ if (${file} MATCHES "\.js$"
+ OR ${file} MATCHES "\.mjs$"
+ OR ${file} MATCHES "\.qml$")
+ list(APPEND qml_files ${file})
+ else()
+ list(APPEND resource_files ${file})
+ endif()
+ endforeach()
+ if (NOT TARGET ${QT_CMAKE_EXPORT_NAMESPACE}::qmlcachegen AND qml_files)
+ message(WARNING "add_qt_resource: Qml files were detected but the qmlcachgen target is not defined. Consider adding QmlTools to your find_package command.")
+ endif()
+
+ if (TARGET ${QT_CMAKE_EXPORT_NAMESPACE}::qmlcachegen AND qml_files)
+ # Enable qt quick compiler support
+ set(qml_resource_file "${CMAKE_CURRENT_BINARY_DIR}/${resource_name}.qrc")
+ if (resource_files)
+ set(chained_resource_name "${resource_name}_qmlcache")
+ endif()
+
+ foreach(file IN LISTS qml_files)
+ get_filename_component(file_absolute ${file} ABSOLUTE)
+ file(RELATIVE_PATH file_relative ${CMAKE_CURRENT_SOURCE_DIR} ${file_absolute})
+ qt_get_relative_resource_path_for_file(alias ${file})
+ set(file_resource_path "${arg_PREFIX}/${alias}")
+ file(TO_CMAKE_PATH ${file_resource_path} file_resource_path)
+ list(APPEND file_resource_paths ${file_resource_path})
+ string(REGEX REPLACE "\.js$" "_js" compiled_file ${file_relative})
+ string(REGEX REPLACE "\.mjs$" "_mjs" compiled_file ${compiled_file})
+ string(REGEX REPLACE "\.qml$" "_qml" compiled_file ${compiled_file})
+ set(compiled_file "${CMAKE_CURRENT_BINARY_DIR}/qmlcache/${compiled_file}.cpp")
+ add_custom_command(
+ OUTPUT ${compiled_file}
+ DEPENDS ${file_absolute}
+ COMMAND
+ ${QT_CMAKE_EXPORT_NAMESPACE}::qmlcachegen
+ --resource-path ${file_resource_path}
+ -o ${compiled_file}
+ ${file_absolute}
+ )
+ target_sources(${target} PRIVATE ${compiled_file})
+ endforeach()
+
+ set(qmlcache_loader_list "${CMAKE_CURRENT_BINARY_DIR}/qmlcache/${resource_name}_qml_loader_file_list.rsp")
+ file(GENERATE
+ OUTPUT ${qmlcache_loader_list}
+ CONTENT "$<JOIN:${file_resource_paths},\n>"
+ )
+
+ set(qmlcache_loader_file "${CMAKE_CURRENT_BINARY_DIR}/qmlcache/${resource_name}_qmlcache_loader.cpp")
+ set(resource_name_arg "${resource_name}.qrc")
+ if (chained_resource_name)
+ set(resource_name_arg "${resource_name_arg}=${chained_resource_name}")
+ endif()
+ add_custom_command(
+ OUTPUT ${qmlcache_loader_file}
+ DEPENDS ${qmlcache_loader_list}
+ COMMAND
+ ${QT_CMAKE_EXPORT_NAMESPACE}::qmlcachegen
+ --resource-name "${resource_name_arg}"
+ -o ${qmlcache_loader_file}
+ "@${qmlcache_loader_list}"
+ )
+
+ qt_propagate_generated_resource(${target} ${resource_name} ${qmlcache_loader_file})
+
+ if (resource_files)
+ set(resource_name ${chained_resource_name})
+ endif()
+ else()
+ set(resource_files ${arg_FILES})
+ endif()
+
+ set(${arg_OUTPUT_REMAINING_RESOURCES} ${resource_files} PARENT_SCOPE)
+ set(${arg_OUTPUT_RESOURCE_NAME} ${resource_name} PARENT_SCOPE)
+
+endfunction()
+
+
+function(qt_propagate_generated_resource target resource_name generated_source_code)
+ get_target_property(type ${target} TYPE)
+ if(type STREQUAL STATIC_LIBRARY)
+ set(resource_target "${target}_resources_${resourceName}")
+ add_library("${resource_target}" OBJECT "${generated_source_code}")
+ qt_internal_add_target_aliases("${resource_target}")
+ qt_install(TARGETS "${resource_target}"
+ EXPORT "${INSTALL_CMAKE_NAMESPACE}${target}Targets"
+ DESTINATION ${INSTALL_LIBDIR}
+ )
+ target_link_libraries(${target} INTERFACE "$<TARGET_OBJECTS:${INSTALL_CMAKE_NAMESPACE}::${resource_target}>")
+ else()
+ target_sources(${target} PRIVATE ${generated_source_code})
+ endif()
+endfunction()
+
function(add_qt_resource target resourceName)
# Don't try to add resources when cross compiling, and the target is actually a host target
# (like a tool).
@@ -2553,6 +2530,35 @@ function(add_qt_resource target resourceName)
qt_parse_all_arguments(rcc "add_qt_resource" "" "PREFIX;LANG;BASE" "FILES" ${ARGN})
+ string(REPLACE "/" "_" resourceName ${resourceName})
+ string(REPLACE "." "_" resourceName ${resourceName})
+
+ # Apply base to all files
+ if (rcc_BASE)
+ foreach(file IN LISTS rcc_FILES)
+ set(resource_file "${rcc_BASE}/${file}")
+ file(TO_CMAKE_PATH ${resource_file} resource_file)
+ list(APPEND resource_files ${resource_file})
+ endforeach()
+ else()
+ set(resource_files ${rcc_FILES})
+ endif()
+
+
+ # Apply quick compiler pass
+ qt_quick_compiler_process_resources(${target} ${resourceName}
+ FILES ${resource_files}
+ PREFIX ${rcc_PREFIX}
+ OUTPUT_REMAINING_RESOURCES resources
+ OUTPUT_RESOURCE_NAME newResourceName
+ )
+
+ if (NOT resources)
+ return()
+ endif()
+ set(generatedResourceFile "${CMAKE_CURRENT_BINARY_DIR}/generated_${newResourceName}.qrc")
+ set(generatedSourceCode "${CMAKE_CURRENT_BINARY_DIR}/qrc_${newResourceName}.cpp")
+
# Generate .qrc file:
# <RCC><qresource ...>
@@ -2565,52 +2571,40 @@ function(add_qt_resource target resourceName)
endif()
string(APPEND qrcContents ">\n")
- foreach(file ${rcc_FILES})
- if(rcc_BASE)
- set(based_file "${rcc_BASE}/${file}")
- else()
- set(based_file "${file}")
- endif()
-
- qt_get_relative_resource_path_for_file(alias ${based_file})
+ foreach(file IN LISTS resources)
+ qt_get_relative_resource_path_for_file(alias ${file})
- if (NOT IS_ABSOLUTE ${based_file})
- set(based_file "${CMAKE_CURRENT_SOURCE_DIR}/${based_file}")
+ if (NOT IS_ABSOLUTE ${file})
+ set(file "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
endif()
### FIXME: escape file paths to be XML conform
# <file ...>...</file>
string(APPEND qrcContents " <file alias=\"${alias}\">")
- string(APPEND qrcContents "${based_file}</file>\n")
- list(APPEND files "${based_file}")
+ string(APPEND qrcContents "${file}</file>\n")
+ list(APPEND files "${file}")
endforeach()
# </qresource></RCC>
string(APPEND qrcContents " </qresource>\n</RCC>\n")
- set(generatedResourceFile "${CMAKE_CURRENT_BINARY_DIR}/generated_${resourceName}.qrc")
file(GENERATE OUTPUT "${generatedResourceFile}" CONTENT "${qrcContents}")
# Process .qrc file:
- set(generatedSourceCode "${CMAKE_CURRENT_BINARY_DIR}/qrc_${resourceName}.cpp")
add_custom_command(OUTPUT "${generatedSourceCode}"
COMMAND "${QT_CMAKE_EXPORT_NAMESPACE}::rcc"
- ARGS --name "${resourceName}"
+ ARGS --name "${newResourceName}"
--output "${generatedSourceCode}" "${generatedResourceFile}"
- DEPENDS ${files}
- COMMENT "RCC ${resourceName}"
+ DEPENDS ${resources}
+ COMMENT "RCC ${newResourceName}"
VERBATIM)
get_target_property(type "${target}" TYPE)
- if(type STREQUAL STATIC_LIBRARY)
- set(resourceTarget "${target}_resources_${resourceName}")
- add_library("${resourceTarget}" OBJECT "${generatedSourceCode}")
- qt_internal_add_target_aliases("${resourceTarget}")
- qt_install(TARGETS "${resourceTarget}"
- EXPORT "${INSTALL_CMAKE_NAMESPACE}${target}Targets"
- DESTINATION ${INSTALL_LIBDIR}
- )
- target_link_libraries(${target} INTERFACE "$<TARGET_OBJECTS:${INSTALL_CMAKE_NAMESPACE}::${resourceTarget}>")
+ # Only do this if newResourceName is the same as resourceName, since
+ # the resource will be chainloaded by the qt quickcompiler
+ # qml cache loader
+ if(newResourceName STREQUAL resourceName)
+ qt_propagate_generated_resource(${target} ${resourceName} "${generatedSourceCode}")
else()
target_sources(${target} PRIVATE "${generatedSourceCode}")
endif()