summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@qt.io>2022-07-14 17:23:15 +0200
committerJoerg Bornemann <joerg.bornemann@qt.io>2022-08-09 15:21:52 +0200
commit9ce5709fb1b4e5d563ea1d90a6cf1fc6e365d3d9 (patch)
tree282332f6641ed4230584e647353a021efbee03b3 /src/corelib
parent0ce5c0a9969bc8c763ab50b6271e203c2bcb90de (diff)
CMake: Support big resources in qt_add_resources
[ChangeLog][CMake] The target-based variant of qt6_add_resource gained the option BIG_RESOURCES. This can be used instead of qt6_add_big_resources, which is not target-based. Fixes: QTBUG-100268 Change-Id: Ib3fa783cbfbfd10f59c2f952bc88508a91f25e26 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/Qt6CoreMacros.cmake310
-rw-r--r--src/corelib/doc/src/cmake/qt_add_resources.qdoc11
2 files changed, 228 insertions, 93 deletions
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index 75f4170249..1612d23b10 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -439,26 +439,58 @@ function(qt6_add_big_resources outfiles )
add_custom_command(OUTPUT ${tmpoutfile}
COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::rcc ${rcc_options} --name ${outfilename} --pass 1 --output ${tmpoutfile} ${infile}
DEPENDS ${infile} ${_rc_depends} "${out_depends}" ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
+ COMMENT "Running rcc pass 1 for resource ${outfilename}"
VERBATIM)
add_custom_target(big_resources_${outfilename} ALL DEPENDS ${tmpoutfile})
- add_library(rcc_object_${outfilename} OBJECT ${tmpoutfile})
- _qt_internal_set_up_static_runtime_library(rcc_object_${outfilename})
- target_compile_definitions(rcc_object_${outfilename} PUBLIC "$<TARGET_PROPERTY:Qt6::Core,INTERFACE_COMPILE_DEFINITIONS>")
- set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOMOC OFF)
- set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOUIC OFF)
+ _qt_internal_add_rcc_pass2(
+ RESOURCE_NAME ${outfilename}
+ RCC_OPTIONS ${rcc_options}
+ OBJECT_LIB rcc_object_${outfilename}
+ QRC_FILE ${infile}
+ PASS1_OUTPUT_FILE ${tmpoutfile}
+ OUT_OBJECT_FILE ${outfile}
+ )
add_dependencies(rcc_object_${outfilename} big_resources_${outfilename})
- # The modification of TARGET_OBJECTS needs the following change in cmake
- # https://gitlab.kitware.com/cmake/cmake/commit/93c89bc75ceee599ba7c08b8fe1ac5104942054f
- add_custom_command(OUTPUT ${outfile}
- COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
- ARGS ${rcc_options} --name ${outfilename} --pass 2 --temp $<TARGET_OBJECTS:rcc_object_${outfilename}> --output ${outfile} ${infile}
- DEPENDS rcc_object_${outfilename} $<TARGET_OBJECTS:rcc_object_${outfilename}> ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
- VERBATIM)
- list(APPEND ${outfiles} ${outfile})
+ list(APPEND ${outfiles} ${outfile})
endforeach()
set(${outfiles} ${${outfiles}} PARENT_SCOPE)
endfunction()
+function(_qt_internal_add_rcc_pass2)
+ set(options)
+ set(oneValueArgs
+ RESOURCE_NAME
+ OBJECT_LIB
+ QRC_FILE
+ PASS1_OUTPUT_FILE
+ OUT_OBJECT_FILE
+ )
+ set(multiValueArgs
+ RCC_OPTIONS
+ )
+ cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ add_library(${arg_OBJECT_LIB} OBJECT ${arg_PASS1_OUTPUT_FILE})
+ _qt_internal_set_up_static_runtime_library(${arg_OBJECT_LIB})
+ target_compile_definitions(${arg_OBJECT_LIB} PUBLIC
+ "$<TARGET_PROPERTY:Qt6::Core,INTERFACE_COMPILE_DEFINITIONS>")
+ set_target_properties(${arg_OBJECT_LIB} PROPERTIES
+ AUTOMOC OFF
+ AUTOUIC OFF)
+ # The modification of TARGET_OBJECTS needs the following change in cmake
+ # https://gitlab.kitware.com/cmake/cmake/commit/93c89bc75ceee599ba7c08b8fe1ac5104942054f
+ add_custom_command(
+ OUTPUT ${arg_OUT_OBJECT_FILE}
+ COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
+ ${arg_RCC_OPTIONS} --name ${arg_RESOURCE_NAME} --pass 2
+ --temp $<TARGET_OBJECTS:${arg_OBJECT_LIB}>
+ --output ${arg_OUT_OBJECT_FILE} ${arg_QRC_FILE}
+ DEPENDS ${arg_OBJECT_LIB} $<TARGET_OBJECTS:${arg_OBJECT_LIB}>
+ ${QT_CMAKE_EXPORT_NAMESPACE}::rcc
+ COMMENT "Running rcc pass 2 for resource ${arg_RESOURCE_NAME}"
+ VERBATIM)
+endfunction()
+
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
function(qt_add_big_resources outfiles)
if(QT_DEFAULT_MAJOR_VERSION EQUAL 5)
@@ -1963,56 +1995,36 @@ function(__qt_get_relative_resource_path_for_file output_alias file)
set(${output_alias} ${alias} PARENT_SCOPE)
endfunction()
-# Performs linking and propagation of the object library via the target's usage requirements.
-# Arguments:
-# NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET skip linking of ${object_library} to ${target}, only
-# propagate $<TARGET_OBJECTS:${object_library}> by linking it to ${target}. It's useful in case
-# if ${object_library} depends on the ${target}. E.g. resource libraries depend on the Core
-# library so linking them back to Core will cause a CMake error.
+# Performs linking and propagation of the specified objects via the target's usage requirements.
+# The objects may be given as generator expression.
#
-# EXTRA_CONDITIONS object library specific conditions to be checked before link the object library
-# to the end-point executable.
-function(__qt_internal_propagate_object_library target object_library)
- set(options NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET)
+# Arguments:
+# EXTRA_CONDITIONS
+# Conditions to be checked before linking the object files to the end-point executable.
+# EXTRA_TARGET_LINK_LIBRARIES_CONDITIONS
+# Conditions for the target_link_libraries call.
+# EXTRA_TARGET_SOURCES_CONDITIONS
+# Conditions for the target_sources call.
+function(__qt_internal_propagate_object_files target objects)
+ set(options "")
set(single_args "")
- set(multi_args EXTRA_CONDITIONS)
- cmake_parse_arguments(arg "${options}" "${single_args}" "${multi_args}" ${ARGN})
-
- get_target_property(is_imported ${object_library} IMPORTED)
- if(NOT is_imported)
- target_link_libraries(${object_library} PRIVATE ${QT_CMAKE_EXPORT_NAMESPACE}::Platform)
- _qt_internal_copy_dependency_properties(${object_library} ${target} PRIVATE_ONLY)
- endif()
-
- # After internal discussion we decided to not rely on the linker order that CMake
- # offers, until CMake provides the guaranteed linking order that suites our needs in a
- # future CMake version.
- # All object libraries mark themselves with the _is_qt_propagated_object_library property.
- # Using a finalizer approach we walk through the target dependencies and look for libraries
- # using the _is_qt_propagated_object_library property. Then, objects of the collected libraries
- # are moved to the beginning of the linker line using target_sources.
- #
- # Note: target_link_libraries works well with linkers other than ld. If user didn't enforce
- # a finalizer we rely on linker to resolve circular dependencies between objects and static
- # libraries.
- set_property(TARGET ${object_library} PROPERTY _is_qt_propagated_object_library TRUE)
- if(NOT is_imported)
- set_property(TARGET ${object_library} APPEND PROPERTY
- EXPORT_PROPERTIES _is_qt_propagated_object_library
- )
- endif()
-
- # Keep the implicit linking if finalizers are not used.
- set(not_finalizer_mode_condition
- "$<NOT:$<BOOL:$<TARGET_PROPERTY:_qt_object_libraries_finalizer_mode>>>"
+ set(extra_conditions_args
+ EXTRA_CONDITIONS
+ EXTRA_TARGET_LINK_LIBRARIES_CONDITIONS
+ EXTRA_TARGET_SOURCES_CONDITIONS
)
+ set(multi_args ${extra_conditions_args})
+ cmake_parse_arguments(arg "${options}" "${single_args}" "${multi_args}" ${ARGN})
- # Collect object library specific conditions.
- if(arg_EXTRA_CONDITIONS)
- list(JOIN arg_EXTRA_CONDITIONS "," extra_conditions)
- else()
- set(extra_conditions "$<BOOL:TRUE>")
- endif()
+ # Collect additional conditions.
+ foreach(arg IN LISTS extra_conditions_args)
+ string(TOLOWER "${arg}" lcvar)
+ if(arg_${arg})
+ list(JOIN arg_${arg} "," ${lcvar})
+ else()
+ set(${lcvar} "$<BOOL:TRUE>")
+ endif()
+ endforeach()
# Do not litter the static libraries
set(not_static_condition
@@ -2038,17 +2050,14 @@ function(__qt_internal_propagate_object_library target object_library)
"$<BOOL:$<GENEX_EVAL:${cmp0099_policy_check_property}>>"
)
- # Use TARGET_NAME to have the correct namespaced name in the exports.
- set(objects "$<TARGET_OBJECTS:$<TARGET_NAME:${object_library}>>")
-
# Collect link conditions for the target_sources call.
string(JOIN "" target_sources_genex
"$<"
"$<AND:"
- "${not_finalizer_mode_condition},"
"${not_static_condition},"
"${platform_link_order_condition},"
"$<NOT:${link_objects_using_link_options_condition}>,"
+ "${extra_target_sources_conditions},"
"${extra_conditions}"
">"
":${objects}>"
@@ -2081,9 +2090,9 @@ function(__qt_internal_propagate_object_library target object_library)
string(JOIN "" target_link_libraries_genex
"$<"
"$<AND:"
- "${not_finalizer_mode_condition},"
"${not_static_condition},"
"$<NOT:${platform_link_order_condition}>,"
+ "${extra_target_link_libraries_conditions},"
"${extra_conditions}"
">"
":${objects}>"
@@ -2091,6 +2100,60 @@ function(__qt_internal_propagate_object_library target object_library)
target_link_libraries(${target} INTERFACE
"${target_link_libraries_genex}"
)
+endfunction()
+
+# Performs linking and propagation of the object library via the target's usage requirements.
+# Arguments:
+# NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET skip linking of ${object_library} to ${target}, only
+# propagate $<TARGET_OBJECTS:${object_library}> by linking it to ${target}. It's useful in case
+# if ${object_library} depends on the ${target}. E.g. resource libraries depend on the Core
+# library so linking them back to Core will cause a CMake error.
+#
+# EXTRA_CONDITIONS object library specific conditions to be checked before link the object library
+# to the end-point executable.
+function(__qt_internal_propagate_object_library target object_library)
+ set(options NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET)
+ set(single_args "")
+ set(multi_args EXTRA_CONDITIONS)
+ cmake_parse_arguments(arg "${options}" "${single_args}" "${multi_args}" ${ARGN})
+
+ get_target_property(is_imported ${object_library} IMPORTED)
+ if(NOT is_imported)
+ target_link_libraries(${object_library} PRIVATE ${QT_CMAKE_EXPORT_NAMESPACE}::Platform)
+ _qt_internal_copy_dependency_properties(${object_library} ${target} PRIVATE_ONLY)
+ endif()
+
+ # After internal discussion we decided to not rely on the linker order that CMake
+ # offers, until CMake provides the guaranteed linking order that suites our needs in a
+ # future CMake version.
+ # All object libraries mark themselves with the _is_qt_propagated_object_library property.
+ # Using a finalizer approach we walk through the target dependencies and look for libraries
+ # using the _is_qt_propagated_object_library property. Then, objects of the collected libraries
+ # are moved to the beginning of the linker line using target_sources.
+ #
+ # Note: target_link_libraries works well with linkers other than ld. If user didn't enforce
+ # a finalizer we rely on linker to resolve circular dependencies between objects and static
+ # libraries.
+ set_property(TARGET ${object_library} PROPERTY _is_qt_propagated_object_library TRUE)
+ if(NOT is_imported)
+ set_property(TARGET ${object_library} APPEND PROPERTY
+ EXPORT_PROPERTIES _is_qt_propagated_object_library
+ )
+ endif()
+
+ # Keep the implicit linking if finalizers are not used.
+ set(not_finalizer_mode_condition
+ "$<NOT:$<BOOL:$<TARGET_PROPERTY:_qt_object_libraries_finalizer_mode>>>"
+ )
+
+ # Use TARGET_NAME to have the correct namespaced name in the exports.
+ set(objects "$<TARGET_OBJECTS:$<TARGET_NAME:${object_library}>>")
+
+ __qt_internal_propagate_object_files(${target} ${objects}
+ EXTRA_CONDITIONS ${arg_EXTRA_CONDITIONS}
+ EXTRA_TARGET_SOURCES_CONDITIONS ${not_finalizer_mode_condition}
+ EXTRA_TARGET_LINK_LIBRARIES_CONDITIONS ${not_finalizer_mode_condition}
+ )
if(NOT arg_NO_LINK_OBJECT_LIBRARY_REQUIREMENTS_TO_TARGET)
# It's necessary to link the object library target, since we want to pass the object library
@@ -2199,11 +2262,32 @@ endfunction()
# targets pass a value to the OUTPUT_TARGETS parameter.
#
function(_qt_internal_process_resource target resourceName)
-
- cmake_parse_arguments(rcc "" "PREFIX;LANG;BASE;OUTPUT_TARGETS;DESTINATION" "FILES;OPTIONS" ${ARGN})
+ cmake_parse_arguments(rcc "BIG_RESOURCES"
+ "PREFIX;LANG;BASE;OUTPUT_TARGETS;DESTINATION" "FILES;OPTIONS" ${ARGN})
if("${rcc_OPTIONS}" MATCHES "-binary")
set(isBinary TRUE)
+ if(arg_BIG_RESOURCES)
+ message(FATAL_ERROR "BIG_RESOURCES cannot be used together with the -binary option.")
+ endif()
+ endif()
+
+ if(arg_BIG_RESOURCES AND CMAKE_GENERATOR STREQUAL "Xcode" AND IOS)
+ message(WARNING
+ "Due to CMake limitations, the BIG_RESOURCES option can't be used when building "
+ "for iOS. "
+ "See https://bugreports.qt.io/browse/QTBUG-103497 for details. "
+ "Falling back to using regular resources. "
+ )
+ set(arg_BIG_RESOURCES OFF)
+ endif()
+
+ if(arg_BIG_RESOURCES AND CMAKE_VERSION VERSION_LESS "3.17")
+ message(WARNING
+ "The BIG_RESOURCES option does not work reliably with CMake < 3.17. "
+ "Consider upgrading to a more recent CMake version or disable the BIG_RESOURCES "
+ "option for older CMake versions."
+ )
endif()
string(REPLACE "/" "_" resourceName ${resourceName})
@@ -2305,9 +2389,10 @@ function(_qt_internal_process_resource target resourceName)
configure_file("${template_file}" "${generatedResourceFile}")
set(rccArgs --name "${resourceName}" "${generatedResourceFile}")
+ set(rccArgsAllPasses "")
if(rcc_OPTIONS)
- list(APPEND rccArgs ${rcc_OPTIONS})
+ list(APPEND rccArgsAllPasses ${rcc_OPTIONS})
endif()
# When cross-building, we use host tools to generate target code. If the host rcc was compiled
@@ -2317,7 +2402,7 @@ function(_qt_internal_process_resource target resourceName)
# If the target does not support zstd (feature is disabled), tell rcc not to generate
# zstd related code.
if(NOT QT_FEATURE_zstd)
- list(APPEND rccArgs "--no-zstd")
+ list(APPEND rccArgsAllPasses "--no-zstd")
endif()
set_property(SOURCE "${generatedResourceFile}" PROPERTY SKIP_AUTOGEN ON)
@@ -2334,51 +2419,90 @@ function(_qt_internal_process_resource target resourceName)
set(generatedOutfile "${rcc_DESTINATION}.rcc")
endif()
endif()
+ elseif(rcc_BIG_RESOURCES)
+ set(generatedOutfile "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qrc_${resourceName}_tmp.cpp")
else()
set(generatedOutfile "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qrc_${resourceName}.cpp")
endif()
+ set(pass_msg)
+ if(rcc_BIG_RESOURCES)
+ list(PREPEND rccArgs --pass 1)
+ set(pass_msg " pass 1")
+ endif()
+
list(PREPEND rccArgs --output "${generatedOutfile}")
# Process .qrc file:
add_custom_command(OUTPUT "${generatedOutfile}"
- COMMAND "${QT_CMAKE_EXPORT_NAMESPACE}::rcc" ${rccArgs}
+ COMMAND "${QT_CMAKE_EXPORT_NAMESPACE}::rcc" ${rccArgs} ${rccArgsAllPasses}
DEPENDS
${resource_dependencies}
${generatedResourceFile}
"${QT_CMAKE_EXPORT_NAMESPACE}::rcc"
- COMMENT "Running rcc for resource ${resourceName}"
+ COMMENT "Running rcc${pass_msg} for resource ${resourceName}"
VERBATIM)
- set(output_targets "")
if(isBinary)
# Add generated .rcc target to 'all' set
add_custom_target(binary_resource_${resourceName} ALL DEPENDS "${generatedOutfile}")
- else()
- # We can't rely on policy CMP0118 since user project controls it.
- # We also want SKIP_AUTOGEN known in the target's scope, where we can.
- set(scope_args)
- if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
- set(scope_args TARGET_DIRECTORY ${target})
- endif()
- set_source_files_properties(${generatedOutfile} ${scope_args} PROPERTIES
- SKIP_AUTOGEN TRUE
- GENERATED TRUE
- SKIP_UNITY_BUILD_INCLUSION TRUE
- SKIP_PRECOMPILE_HEADERS TRUE
+ return()
+ endif()
+
+ # We can't rely on policy CMP0118 since user project controls it.
+ # We also want SKIP_AUTOGEN known in the target's scope, where we can.
+ set(scope_args)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY ${target})
+ endif()
+ set_source_files_properties(${generatedOutfile} ${scope_args} PROPERTIES
+ SKIP_AUTOGEN TRUE
+ GENERATED TRUE
+ SKIP_UNITY_BUILD_INCLUSION TRUE
+ SKIP_PRECOMPILE_HEADERS TRUE
+ )
+
+ get_target_property(target_source_dir ${target} SOURCE_DIR)
+ if(NOT target_source_dir STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ # We have to create a separate target in this scope that depends on
+ # the generated file, otherwise the original target won't have the
+ # required dependencies in place to ensure correct build order.
+ add_custom_target(${target}_${resourceName} DEPENDS ${generatedOutfile})
+ add_dependencies(${target} ${target}_${resourceName})
+ endif()
+
+ if(rcc_BIG_RESOURCES)
+ set(pass1OutputFile ${generatedOutfile})
+ set(generatedOutfile
+ "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qrc_${resourceName}${CMAKE_CXX_OUTPUT_EXTENSION}")
+ _qt_internal_add_rcc_pass2(
+ RESOURCE_NAME ${resourceName}
+ RCC_OPTIONS ${rccArgsAllPasses}
+ OBJECT_LIB ${target}_${resourceName}_obj
+ QRC_FILE ${generatedResourceFile}
+ PASS1_OUTPUT_FILE ${pass1OutputFile}
+ OUT_OBJECT_FILE ${generatedOutfile}
)
- get_target_property(target_source_dir ${target} SOURCE_DIR)
- if(NOT target_source_dir STREQUAL CMAKE_CURRENT_SOURCE_DIR)
- # We have to create a separate target in this scope that depends on
- # the generated file, otherwise the original target won't have the
- # required dependencies in place to ensure correct build order.
- add_custom_target(${target}_${resourceName} DEPENDS ${generatedOutfile})
- add_dependencies(${target} ${target}_${resourceName})
+ get_target_property(type ${target} TYPE)
+ if(type STREQUAL STATIC_LIBRARY)
+ # Create a custom target to trigger the generation of ${generatedOutfile}
+ set(pass2_target ${target}_${resourceName}_pass2)
+ add_custom_target(${pass2_target} DEPENDS ${generatedOutfile})
+ add_dependencies(${target} ${pass2_target})
+
+ # Propagate the object files to the target.
+ __qt_internal_propagate_object_files(${target} "${generatedOutfile}")
+ else()
+ target_sources(${target} PRIVATE ${generatedOutfile})
endif()
- set_property(TARGET ${target} APPEND PROPERTY _qt_generated_qrc_files "${generatedResourceFile}")
-
- __qt_propagate_generated_resource(${target} ${resourceName} "${generatedOutfile}" output_targets)
+ else()
+ __qt_propagate_generated_resource(${target} ${resourceName} "${generatedOutfile}"
+ output_targets)
endif()
+
+ set_property(TARGET ${target}
+ APPEND PROPERTY _qt_generated_qrc_files "${generatedResourceFile}")
+
if (rcc_OUTPUT_TARGETS)
set(${rcc_OUTPUT_TARGETS} "${output_targets}" PARENT_SCOPE)
endif()
diff --git a/src/corelib/doc/src/cmake/qt_add_resources.qdoc b/src/corelib/doc/src/cmake/qt_add_resources.qdoc
index 7de9b94854..8a61ec769e 100644
--- a/src/corelib/doc/src/cmake/qt_add_resources.qdoc
+++ b/src/corelib/doc/src/cmake/qt_add_resources.qdoc
@@ -28,6 +28,7 @@ qt_add_resources(<TARGET> <RESOURCE_NAME>
[PREFIX <PATH>]
[LANG <LANGUAGE>]
[BASE <PATH>]
+ [BIG_RESOURCES]
[OUTPUT_TARGETS <VARIABLE_NAME>]
[FILES ...] [OPTIONS ...])
\endcode
@@ -69,6 +70,16 @@ example, if \c BASE is \c{"assets"} and \c FILES is
Alias settings for files need to be set via the \c QT_RESOURCE_ALIAS source file
property.
+\c BIG_RESOURCES can be specified to enable support for big resources. This
+directly generates object files (\c .o, \c .obj) instead of C++ source code.
+This allows embedding bigger resources, without having to compile generated C++
+sources, which can be too time consuming and memory intensive.
+
+Note that \c BIG_RESOURCES is not compatible with iOS due to restrictions of
+CMake's Xcode project generator. See
+\l{https://bugreports.qt.io/browse/QTBUG-103497}{QTBUG-103497} for details.
+Also, \c BIG_RESOURCES only works reliably from CMake 3.17 onwards.
+
When using this command with static libraries, one or more special targets will
be generated. Should you wish to perform additional processing on these targets,
pass a variable name to the \c OUTPUT_TARGETS parameter. The \c qt_add_resources