Refactor Metatypes dependency propagation
Every metatypes.json files is now added as an INTERFACE source file to a target. This enables us later to correctly collect all the metatypes.json files from dependent targets. This information is also correctly exported via export()/install(). To avoid the metatypes.json appearing in every target's source list, the file path is wrapped in a generator expression which will only be evaluated when the consuming target has the property QT_CONSUMES_METATYPES set to true. At the moment this is limited to targets which need to interact with qmltyperegistrar. Change-Id: I0ffebcd069a923383f7ed11cde2c94ecf2fb13f3 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
parent
360d9fba23
commit
c431e2d33c
@ -1862,8 +1862,6 @@ set(QT_CMAKE_EXPORT_NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE})")
|
||||
set(args INSTALL_DIR "${metatypes_install_dir}")
|
||||
endif()
|
||||
qt6_generate_meta_types_json_file(${target} ${args})
|
||||
get_target_property(QT_MODULE_META_TYPES_FILE ${target} INTERFACE_QT_META_TYPES_INSTALL_FILE)
|
||||
get_target_property(QT_MODULE_META_TYPES_DEP_FILE ${target} INTERFACE_QT_META_TYPES_INSTALL_DEP_FILE)
|
||||
endif()
|
||||
configure_package_config_file(
|
||||
"${QT_CMAKE_DIR}/QtModuleConfig.cmake.in"
|
||||
|
@ -45,27 +45,6 @@ if(NOT _qt_module_target_type STREQUAL "INTERFACE_LIBRARY")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Apply meta types properties
|
||||
if (@QT_MODULE_HAS_META_TYPES_FILE@)
|
||||
if (NOT QT_NO_CREATE_TARGETS)
|
||||
set_target_properties("@INSTALL_CMAKE_NAMESPACE@::@target@" PROPERTIES
|
||||
INTERFACE_QT_MODULE_HAS_META_TYPES TRUE
|
||||
INTERFACE_QT_META_TYPES_INSTALL_FILE "@QT_MODULE_META_TYPES_FILE@"
|
||||
INTERFACE_QT_META_TYPES_INSTALL_DEP_FILE "@QT_MODULE_META_TYPES_DEP_FILE@"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT QT_NO_CREATE_VERSIONLESS_TARGETS)
|
||||
get_target_property(is_alias_target "Qt::@target@" ALIASED_TARGET)
|
||||
if (NOT is_alias_target)
|
||||
set_target_properties("Qt::@target@" PROPERTIES
|
||||
INTERFACE_QT_MODULE_HAS_META_TYPES TRUE
|
||||
INTERFACE_QT_META_TYPES_INSTALL_FILE "@QT_MODULE_META_TYPES_FILE@"
|
||||
INTERFACE_QT_META_TYPES_INSTALL_DEP_FILE "@QT_MODULE_META_TYPES_DEP_FILE@"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Load Module's BuildIntenals should any exist
|
||||
if (@INSTALL_CMAKE_NAMESPACE@BuildInternals_DIR AND
|
||||
|
@ -321,6 +321,15 @@ if(NOT BUILD_SHARED_LIBS)
|
||||
)
|
||||
endif()
|
||||
|
||||
# Core_qobject is never exported so we need to duplicate the metatypes file
|
||||
# interface on Core
|
||||
get_target_property(core_qobject_metatypes_file_genex_build Core_qobject QT_MODULE_META_TYPES_FILE_GENEX_BUILD)
|
||||
get_target_property(core_qobject_metatypes_file_genex_install Core_qobject QT_MODULE_META_TYPES_FILE_GENEX_INSTALL)
|
||||
target_sources(Core INTERFACE
|
||||
${core_qobject_metatypes_file_genex_build}
|
||||
${core_qobject_metatypes_file_genex_install}
|
||||
)
|
||||
|
||||
set_property(TARGET Core APPEND PROPERTY
|
||||
PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig.h")
|
||||
set_property(TARGET Core APPEND PROPERTY
|
||||
|
@ -595,102 +595,7 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
|
||||
endfunction()
|
||||
endif()
|
||||
|
||||
# Generate metatypes dependency file. This function extracts the list of
|
||||
# metatypes files as well as the dependency file from the direct library
|
||||
# dependencies of a target via generator expressions.
|
||||
# Parameters:
|
||||
# dep_file: Location where to generate the dependency file for build time
|
||||
# dependencies.
|
||||
# dep_file_install: Location where to generate the dependency file which
|
||||
# is expected to be installed.
|
||||
function(qt6_generate_meta_types_dep_file target dep_file dep_file_install)
|
||||
# Due to generator expressions it is not possible to recursively evaluate
|
||||
# the LINK_LIBRARIES of target. Therefore we generate a dependency file for
|
||||
# every module with metatypes which can be evaluated at build time.
|
||||
# When generating this file we need to take into account that there are two
|
||||
# levels at which dependencies can be expressed: build and install.
|
||||
# Build dependencies refer to targets which are being built along side the
|
||||
# original target. These targets' install dependencies are not available
|
||||
# at this point in time. We set a special property on these targets that's
|
||||
# only available at build time.
|
||||
# Install dependencies refer to targets which are found via a find_package()
|
||||
# call.
|
||||
# Both install and build targets have the
|
||||
# INTERFACE_QT_META_TYPES_INSTALL_[DEP_FILE|FILE]. When building the target,
|
||||
# INTERFACE_QT_META_TYPES_INSTALL_... refer to the expected install
|
||||
# directory to be appended to CMAKE_INSTALL_PREFIX.
|
||||
# Only build target have the INTERFACE_QT_META_TYPES_[DEP_FILE|FILE] which
|
||||
# point to the files that have been produced during build time.
|
||||
# Finally, to make sure the targets actually have a metatypes files, we
|
||||
# check if they have the INTERFACE_QT_MODULE_HAS_META_TYPES property.
|
||||
#
|
||||
# Note: All properties start with INTERFACE_ since it is the only way to
|
||||
# set properties on interface targets that get generated in the
|
||||
# QtModuleConfig.in
|
||||
#
|
||||
get_target_property(link_dependencies ${target} LINK_LIBRARIES)
|
||||
set(prop_dep "INTERFACE_QT_META_TYPES_BUILD_DEP_FILE")
|
||||
set(prop_file "INTERFACE_QT_META_TYPES_BUILD_FILE")
|
||||
set(prop_file_install "INTERFACE_QT_META_TYPES_INSTALL_FILE")
|
||||
set(prop_dep_install "INTERFACE_QT_META_TYPES_INSTALL_DEP_FILE")
|
||||
set(prop_is_local "INTERFACE_QT_MODULE_META_TYPES_FROM_BUILD")
|
||||
set(prop_has_metatypes "INTERFACE_QT_MODULE_HAS_META_TYPES")
|
||||
|
||||
set(gen_exp "")
|
||||
set(gen_exp_install "")
|
||||
foreach(dep IN LISTS link_dependencies)
|
||||
# Skip over any flags starting with -, like -framework or -lboo.
|
||||
if("${dep}" MATCHES "^-")
|
||||
continue()
|
||||
endif()
|
||||
# replace LINK_ONLY with true, or we will get an error evaluating that
|
||||
# generator expression
|
||||
string(REPLACE "$<LINK_ONLY:" "$<1:" genex_target "$<GENEX_EVAL:${dep}>")
|
||||
string(REPLACE "$<TARGET_OBJECTS:" "$<1:" genex_target "${genex_target}")
|
||||
set(genex_check_is_local
|
||||
"$<TARGET_GENEX_EVAL:${genex_target},$<TARGET_PROPERTY:${genex_target},${prop_is_local}>>"
|
||||
)
|
||||
set(genex_is_target "$<TARGET_EXISTS:$<IF:$<BOOL:${genex_target}>,${genex_target},-NOTFOUND>>")
|
||||
set(genex_has_metatypes
|
||||
"$<TARGET_GENEX_EVAL:${genex_target},$<TARGET_PROPERTY:${genex_target},${prop_has_metatypes}>>"
|
||||
)
|
||||
set(genex_get_metatypes
|
||||
"$<TARGET_GENEX_EVAL:${genex_target},$<TARGET_PROPERTY:${genex_target},${prop_file}>>"
|
||||
)
|
||||
set(genex_get_metatypes_dep
|
||||
"$<TARGET_GENEX_EVAL:${genex_target},$<TARGET_PROPERTY:${genex_target},${prop_dep}>>"
|
||||
)
|
||||
set(genex_get_metatypes_install
|
||||
"$<TARGET_GENEX_EVAL:${genex_target},$<TARGET_PROPERTY:${genex_target},${prop_file_install}>>"
|
||||
)
|
||||
set(genex_get_metatypes_install_dep
|
||||
"$<TARGET_GENEX_EVAL:${genex_target},$<TARGET_PROPERTY:${genex_target},${prop_dep_install}>>"
|
||||
)
|
||||
set(get_local_or_install
|
||||
"$<IF:$<BOOL:${genex_check_is_local}>,${genex_get_metatypes}=${genex_get_metatypes_dep},${genex_get_metatypes_install}=${genex_get_metatypes_install_dep}>"
|
||||
)
|
||||
|
||||
list(APPEND gen_exp
|
||||
"$<$<AND:$<BOOL:${genex_target}>,$<BOOL:${genex_has_metatypes}>>:${get_local_or_install}>"
|
||||
)
|
||||
|
||||
list(APPEND gen_exp_install
|
||||
"$<$<AND:$<BOOL:${genex_target}>,$<BOOL:${genex_get_metatypes_install}>>:${genex_get_metatypes_install}=${genex_get_metatypes_install_dep}>"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
file(GENERATE
|
||||
OUTPUT "${dep_file}"
|
||||
CONTENT "$<JOIN:$<GENEX_EVAL:${gen_exp}>,\n>"
|
||||
)
|
||||
|
||||
file(GENERATE
|
||||
OUTPUT "${dep_file_install}"
|
||||
CONTENT "$<JOIN:$<GENEX_EVAL:${gen_exp_install}>,\n>"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
#
|
||||
# Generate Qt metatypes.json for a target. By default we check whether AUTOMOC
|
||||
# has been enabled and we extract the information from that target. Should you
|
||||
# not wish to use automoc you need to pass in all the generated json files via the
|
||||
@ -808,36 +713,62 @@ function(qt6_generate_meta_types_json_file target)
|
||||
|
||||
set(metatypes_file_name "qt6${target_lowercase}_metatypes.json")
|
||||
set(metatypes_file "${target_binary_dir}/meta_types/${metatypes_file_name}")
|
||||
set(metatypes_file_gen "${target_binary_dir}/meta_types/${metatypes_file_name}.gen")
|
||||
|
||||
set(metatypes_dep_file_name "qt6${target_lowercase}_metatypes_dep.txt")
|
||||
set(metatypes_dep_file "${target_binary_dir}/meta_types/${metatypes_dep_file_name}")
|
||||
|
||||
add_custom_command(OUTPUT ${metatypes_file}
|
||||
# Due to generated source file dependency rules being tied to the directory
|
||||
# scope in which they are created it is not possible for other targets which
|
||||
# are defined in a separate scope to see these rules. This leads to failures
|
||||
# in locating the generated source files.
|
||||
# To work around this we write a dummy file to disk to make sure targets
|
||||
# which link against the current target do not produce the error. This dummy
|
||||
# file is then replaced with the contents of the generated file during
|
||||
# build.
|
||||
if (NOT EXISTS ${metatypes_file})
|
||||
file(MAKE_DIRECTORY "${target_binary_dir}/meta_types")
|
||||
file(TOUCH ${metatypes_file})
|
||||
endif()
|
||||
add_custom_command(OUTPUT ${metatypes_file_gen} ${metatypes_file}
|
||||
DEPENDS ${QT_CMAKE_EXPORT_NAMESPACE}::moc ${automoc_dependencies} ${manual_dependencies}
|
||||
COMMAND ${QT_CMAKE_EXPORT_NAMESPACE}::moc
|
||||
-o ${metatypes_file}
|
||||
-o ${metatypes_file_gen}
|
||||
--collect-json ${automoc_args} ${manual_args}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${metatypes_file_gen}
|
||||
${metatypes_file}
|
||||
COMMENT "Runing automoc with --collect-json"
|
||||
)
|
||||
|
||||
target_sources(${target} PRIVATE ${metatypes_file})
|
||||
# We still need to add this file as a source of Core, otherwise the file
|
||||
# rule above is not triggered. INTERFACE_SOURCES do not properly register
|
||||
# as dependencies to build the current target.
|
||||
target_sources(${target} PRIVATE ${metatypes_file_gen})
|
||||
set(metatypes_file_genex_build)
|
||||
set(metatypes_file_genex_install)
|
||||
if (arg_COPY_OVER_INSTALL)
|
||||
set(metatypes_file_genex_build
|
||||
"$<BUILD_INTERFACE:$<$<BOOL:$<TARGET_PROPERTY:QT_CONSUMES_METATYPES>>:${arg_INSTALL_DIR}/${metatypes_file_name}>>"
|
||||
)
|
||||
else()
|
||||
set(metatypes_file_genex_build
|
||||
"$<BUILD_INTERFACE:$<$<BOOL:$<TARGET_PROPERTY:QT_CONSUMES_METATYPES>>:${metatypes_file}>>"
|
||||
)
|
||||
set(metatypes_file_genex_install
|
||||
"$<INSTALL_INTERFACE:$<$<BOOL:$<TARGET_PROPERTY:QT_CONSUMES_METATYPES>>:$<INSTALL_PREFIX>/${arg_INSTALL_DIR}/${metatypes_file_name}>>"
|
||||
)
|
||||
endif()
|
||||
set_source_files_properties(${metatypes_file} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
# Set the required properties. See documentation of
|
||||
# qt6_generate_meta_types_dep_file()
|
||||
set_target_properties(${target} PROPERTIES
|
||||
INTERFACE_QT_MODULE_HAS_META_TYPES YES
|
||||
INTERFACE_QT_MODULE_META_TYPES_FROM_BUILD YES
|
||||
INTERFACE_QT_META_TYPES_BUILD_FILE ${metatypes_file}
|
||||
INTERFACE_QT_META_TYPES_BUILD_DEP_FILE ${metatypes_dep_file}
|
||||
INTERFACE_QT_META_TYPES_INSTALL_FILE "${arg_INSTALL_DIR}/${metatypes_file_name}"
|
||||
INTERFACE_QT_META_TYPES_INSTALL_DEP_FILE "${arg_INSTALL_DIR}/${metatypes_dep_file_name}"
|
||||
QT_MODULE_META_TYPES_FILE_GENEX_BUILD "${metatypes_file_genex_build}"
|
||||
QT_MODULE_META_TYPES_FILE_GENEX_INSTALL "${metatypes_file_genex_install}"
|
||||
)
|
||||
|
||||
qt6_generate_meta_types_dep_file(${target}
|
||||
"${metatypes_dep_file}"
|
||||
"${metatypes_dep_file}.install"
|
||||
)
|
||||
target_sources(${target} INTERFACE ${metatypes_file_genex_build} ${metatypes_file_genex_install})
|
||||
|
||||
if (arg_COPY_OVER_INSTALL)
|
||||
get_target_property(target_type ${target} TYPE)
|
||||
@ -845,13 +776,10 @@ function(qt6_generate_meta_types_json_file target)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${metatypes_file}"
|
||||
"${arg_INSTALL_DIR}/${metatypes_file_name}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${metatypes_dep_file}.install"
|
||||
"${arg_INSTALL_DIR}/${metatypes_dep_file_name}"
|
||||
)
|
||||
if (target_type STREQUAL "OBJECT_LIBRARY")
|
||||
add_custom_target(${target}_metatypes_copy
|
||||
DEPENDS "${metatypes_file}" "${metatypes_dep_file}"
|
||||
DEPENDS "${metatypes_file}"
|
||||
${command_args}
|
||||
)
|
||||
add_dependencies(${target} ${target}_metatypes_copy)
|
||||
@ -864,10 +792,6 @@ function(qt6_generate_meta_types_json_file target)
|
||||
install(FILES "${metatypes_file}"
|
||||
DESTINATION "${arg_INSTALL_DIR}"
|
||||
)
|
||||
install(FILES "${metatypes_dep_file}.install"
|
||||
DESTINATION "${arg_INSTALL_DIR}"
|
||||
RENAME "${metatypes_dep_file_name}"
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user