qt5base-lts/cmake/QtResource.cmake.in
Leander Beernaert 46603d655d Replace invalid symbols with underscore
When building tests for android some resources names had the "#"
character in them which triggered a CMake error when use in conjunction
with add_custom_target()

Change-Id: If5f471eebb027683e86b0c4e38c2f34ff8891b7a
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2019-08-22 13:49:58 +00:00

272 lines
11 KiB
CMake

#
# All things resource related
#
function(__qt_get_relative_resource_path_for_file output_alias file)
get_property(alias SOURCE ${file} PROPERTY QT_RESOURCE_ALIAS)
if (NOT alias)
set(alias "${file}")
endif()
set(${output_alias} ${alias} PARENT_SCOPE)
endfunction()
function(__qt_propagate_generated_resource target resource_name generated_source_code output_generated_target)
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}")
target_link_libraries(${target} INTERFACE "$<TARGET_OBJECTS:${resource_target}>")
set(${output_generated_target} "${resource_target}" PARENT_SCOPE)
else()
set(${output_generated_target} "" PARENT_SCOPE)
target_sources(${target} PRIVATE ${generated_source_code})
endif()
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)
cmake_parse_arguments(arg
"" "PREFIX;OUTPUT_REMAINING_RESOURCES;OUTPUT_RESOURCE_NAME;OUTPUT_GENERATED_TARGET" "FILES" ${ARGN}
)
set(qml_files)
set(resource_files)
set(retained_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_SKIP_QUICKCOMPILER)
get_source_file_property(retain_compiler_check ${file} QT_RETAIN_QUICKCOMPILER)
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})
if (retain_compiler_check)
list(APPEND retained_files ${file})
list(APPEND resource_files ${file})
endif()
else()
list(APPEND resource_files ${file})
endif()
endforeach()
if (NOT TARGET @QT_CMAKE_EXPORT_NAMESPACE@::qmlcachegen AND qml_files)
message(WARNING "QT@PROJECT_VERSION_MAJOR@_PROCESS_RESOURCE: Qml files were detected but the qmlcachgen target is not defined. Consider adding QmlTools to your find_package command.")
endif()
set(retained_resource_paths)
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(file_resource_path ${file})
if (arg_PREFIX STREQUAL "/")
# TO_CMAKE_PATH does not clean up cases such as //Foo
set(file_resource_path "/${file_resource_path}")
else()
set(file_resource_path "${arg_PREFIX}/${file_resource_path}")
endif()
if (file IN_LIST retained_files)
list(APPEND retained_resource_paths ${file_resource_path})
endif()
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})
string(REGEX REPLACE "[\$#\?]+" "_" compiled_file ${compiled_file})
set(compiled_file "${CMAKE_CURRENT_BINARY_DIR}/qmlcache/${resource_name}/${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()
if (retained_resource_paths)
set(retained_loader_list "${CMAKE_CURRENT_BINARY_DIR}/qmlcache/${resource_name}/retained_file_list.rsp")
file(GENERATE
OUTPUT ${retained_loader_list}
CONTENT "$<JOIN:${retained_resource_paths},\n>"
)
set(retained_args "--retain" "@${retained_loader_list}")
endif()
add_custom_command(
OUTPUT ${qmlcache_loader_file}
DEPENDS ${qmlcache_loader_list}
COMMAND
@QT_CMAKE_EXPORT_NAMESPACE@::qmlcachegen
${retained_args}
--resource-name "${resource_name_arg}"
-o ${qmlcache_loader_file}
"@${qmlcache_loader_list}"
)
__qt_propagate_generated_resource(${target}
${resource_name}
${qmlcache_loader_file}
output_target)
set(${arg_OUTPUT_GENERATED_TARGET} "${output_target}" PARENT_SCOPE)
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()
#
# Process resources via file path instead of QRC files. Behind the
# scnenes, it will generate a qrc file and apply post processing steps
# when applicable. (e.g.: QtQuickCompiler)
#
# The QRC Prefix is set via the PREFIX parameter.
#
# Alias settings for files need to be set via the QT_RESOURCE_ALIAS property
# via the set_soure_files_properties() command.
#
# When using this command with static libraries, a special target will be
# generated. Should you wish to perform additional processing on said target
# pass a value to the OUTPUT_TARGET parameter.
#
function(QT@PROJECT_VERSION_MAJOR@_PROCESS_RESOURCE target resourceName)
cmake_parse_arguments(rcc "" "PREFIX;LANG;BASE;OUTPUT_TARGET" "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}")
__qt_get_relative_resource_path_for_file(alias ${resource_file})
# Handle case where resources were generated from a directory
# different than the one where the main .pro file resides.
# Unless otherwise specified, we should use the original file path
# as alias.
if (alias STREQUAL resource_file)
set_source_files_properties(${resource_file} PROPERTIES QT_RESOURCE_ALIAS ${file})
endif()
file(TO_CMAKE_PATH ${resource_file} resource_file)
list(APPEND resource_files ${resource_file})
endforeach()
else()
set(resource_files ${rcc_FILES})
endif()
if(NOT rcc_PREFIX)
get_target_property(rcc_PREFIX ${target} QT_RESOURCE_PREFIX)
if (NOT rcc_PREFIX)
message(FATAL_ERROR "QT@PROJECT_VERSION_MAJOR@_PROCESS_RESOURCE() was called without a PREFIX and the target does not provide QT_RESOURCE_PREFIX. Please either add a PREFIX or make the target ${target} provide a default.")
endif()
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
OUTPUT_GENERATED_TARGET output_target
)
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 ...>
set(qrcContents "<RCC>\n <qresource")
if (rcc_PREFIX)
string(APPEND qrcContents " prefix=\"${rcc_PREFIX}\"")
endif()
if (rcc_LANG)
string(APPEND qrcContents " lang=\"${rcc_LANG}\"")
endif()
string(APPEND qrcContents ">\n")
foreach(file IN LISTS resources)
__qt_get_relative_resource_path_for_file(file_resource_path ${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=\"${file_resource_path}\">")
string(APPEND qrcContents "${file}</file>\n")
list(APPEND files "${file}")
endforeach()
# </qresource></RCC>
string(APPEND qrcContents " </qresource>\n</RCC>\n")
file(GENERATE OUTPUT "${generatedResourceFile}" CONTENT "${qrcContents}")
# Process .qrc file:
add_custom_command(OUTPUT "${generatedSourceCode}"
COMMAND "@QT_CMAKE_EXPORT_NAMESPACE@::rcc"
ARGS --name "${newResourceName}"
--output "${generatedSourceCode}" "${generatedResourceFile}"
DEPENDS ${resources} ${generatedResourceFile}
COMMENT "RCC ${newResourceName}"
VERBATIM)
get_target_property(type "${target}" TYPE)
# 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}" output_target)
else()
target_sources(${target} PRIVATE "${generatedSourceCode}")
endif()
if (arg_OUTPUT_TARGET)
set(${arg_OUPUT_TARGET} "${output_target}" PARENT_SCOPE)
endif()
endfunction()