aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeander Beernaert <leander.beernaert@qt.io>2020-01-28 13:28:57 +0100
committerLeander Beernaert <leander.beernaert@qt.io>2020-01-29 14:33:47 +0000
commitba0ac519e3f4acb3fb73ff68393624ec855918aa (patch)
treef91e7b75fd750522f45bed72bea85bb7257f61f8
parent7590f07278ae2cc4ddade7668b5c34ce16751260 (diff)
Update qmltypes to use the new metatypes dependency format
The foreign types list for qmltypesregistrar is now generated by recursively processing the ${targets}_metatypes_dep.txt file. At build time we now use a custom script (Qt6QmlResolveDependencies.cmake) to generate the final foreign types file. qmltypesregistrar has also been updated in order to support the resolution of response files supplied to the command line arguments. Change-Id: Ib61d82fa92bf5d5a24631f461248f81147aad947 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
-rw-r--r--cmake/QtDeclarativeSetup.cmake10
-rw-r--r--src/qml/Qt6QmlMacros.cmake95
-rw-r--r--src/qml/Qt6QmlResolveMetatypesDependencies.cmake60
-rw-r--r--src/qmltyperegistrar/qmltyperegistrar.cpp35
4 files changed, 150 insertions, 50 deletions
diff --git a/cmake/QtDeclarativeSetup.cmake b/cmake/QtDeclarativeSetup.cmake
index 2cd6f56127..116b6013a0 100644
--- a/cmake/QtDeclarativeSetup.cmake
+++ b/cmake/QtDeclarativeSetup.cmake
@@ -46,3 +46,13 @@ function(qt_declarative_generate_reg_exp_jit_tables consuming_target)
target_sources(${consuming_target} PRIVATE ${output_file})
target_include_directories(${consuming_target} PRIVATE $<BUILD_INTERFACE:${generate_dir}>)
endfunction()
+
+# special case to set the qmltype resolve dependencies script at build time
+set(QT_QMTYPES_RESOLVE_DEPENDENCIES_SCRIPT
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/qml/Qt6QmlResolveMetatypesDependencies.cmake"
+)
+
+# install QmlResolveDependency script
+qt_copy_or_install(FILES "src/qml/Qt6QmlResolveMetatypesDependencies.cmake"
+ DESTINATION "${QT_CONFIG_INSTALL_DIR}/${INSTALL_CMAKE_NAMESPACE}Qml"
+)
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
index 8b8ec045d3..dfd556375e 100644
--- a/src/qml/Qt6QmlMacros.cmake
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -416,42 +416,33 @@ function(qt6_target_qml_files target)
file(APPEND ${qmldir_file} ${file_contents})
endfunction()
-function(__qt6_extract_dependencies target out_list)
- set(dep_list)
- get_target_property(link_dependencies ${target} INTERFACE_LINK_LIBRARIES)
- foreach(dep IN LISTS link_dependencies)
- string(FIND ${dep} "Qt::" qt_loc)
- if (NOT ${qt_loc} EQUAL -1)
-
- if (NOT ${qt_loc} EQUAL 0)
- # probably stuck in a generator expression
- string(SUBSTRING "${dep}" ${qt_loc} -1 dep_fixed)
- string(FIND ${dep_fixed} ">" qt_loc)
- if (${qt_loc} EQUAL -1)
- message(FATAL_ERROR "Expected generator expression for ${target}' depdency ${dep}")
- endif()
- string(SUBSTRING ${dep_fixed} 0 ${qt_loc} dep)
- endif()
-
- list(APPEND dep_list ${dep})
- __qt6_extract_dependencies(${dep} recurse_list)
- list(APPEND dep_list ${recurse_list})
- endif()
- endforeach()
- set(${out_list} ${dep_list} PARENT_SCOPE)
-endfunction()
-
function(qt6_qml_type_registration target)
+
get_target_property(import_name ${target} QT_QML_MODULE_URI)
if (NOT import_name)
message(FATAL_ERROR "Target ${target} is not a QML module")
endif()
- qt6_generate_meta_types_json_file(${target})
+ cmake_parse_arguments(args "COPY_OVER_INSTALL" "INSTALL_DIR" "" ${ARGN})
+
+ set(meta_types_args)
+ if (arg_INSTALL_DIR)
+ list(APPEND meta_types_args INSTALL_DIR "${arg_INSTALL_DIR}")
+ endif()
+ if (arg_COPY_OVER_INSTALL)
+ list(APPEND meta_types_args COPY_OVER_INSTALL)
+ endif()
+
+ qt6_generate_meta_types_json_file(${target} ${meta_types_args})
get_target_property(import_version ${target} QT_QML_MODULE_VERSION)
get_target_property(target_source_dir ${target} SOURCE_DIR)
get_target_property(target_binary_dir ${target} BINARY_DIR)
+ get_target_property(target_metatypes_dep_file ${target} INTERFACE_QT_META_TYPES_BUILD_DEP_FILE)
+ get_target_property(target_metatypes_file ${target} INTERFACE_QT_META_TYPES_BUILD_FILE)
+ if (NOT target_metatypes_dep_file)
+ message(FATAL_ERROR "Target ${target} does not have a meta types dependency file")
+ endif()
# Extract major and minor version
if (NOT import_version MATCHES "[0-9]+\\.[0-9]+")
@@ -474,28 +465,34 @@ function(qt6_qml_type_registration target)
--minor-version=${minor_version}
)
- # Extra metatypes.json
- set(foreign_types)
- set(link_dependencies)
- __qt6_extract_dependencies(${target} link_dependencies)
- list(REMOVE_DUPLICATES link_dependencies)
- foreach(dep IN LISTS link_dependencies)
- string(SUBSTRING ${dep} 4 -1 module_name)
- string(TOLOWER "qt6${module_name}_${CMAKE_BUILD_TYPE}_metatypes.json" metatypes_file)
-
- set(module_metatypes_file "${CMAKE_BINARY_DIR}/lib/metatypes/${metatypes_file}")
- set(installed_metatypes_file "${Qt6_DIR}/../../metatypes/${metatypes_file}")
- if (EXISTS ${module_metatypes_file})
- list(APPEND foreign_types ${module_metatypes_file})
- elseif (EXISTS ${installed_metatypes_file})
- list(APPEND foreign_types ${installed_metatypes_file})
- endif()
- endforeach()
+ # Run a script to recursively evaluate all the metatypes.json files in order
+ # to collect all foreign types.
+ set(foreign_types_file "${target_binary_dir}/qmltypes/foreign_types.txt")
+ set(foreign_types_file_tmp "${target_binary_dir}/qmltypes/foreign_types.txt.tmp")
+
+ if (NOT QT_QMTYPES_RESOLVE_DEPENDENCIES_SCRIPT)
+ set("${Qt6Qml_DIR}/Qt6QmlResolveMetatypesDependencies.cmake")
+ endif()
+
+ add_custom_target(${target}_resolve_foreign_types
+ DEPENDS ${target_metatypes_file}
+ COMMAND ${CMAKE_COMMAND}
+ -DOUTPUT_FILE:PATH="${foreign_types_file_tmp}"
+ -DMAIN_DEP_FILE:PATH="${target_metatypes_dep_file}"
+ -DQT_INSTALL_DIR:PATH="${Qt6_DIR}/../../.."
+ -P "${QT_QMTYPES_RESOLVE_DEPENDENCIES_SCRIPT}"
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${foreign_types_file_tmp}"
+ "${foreign_types_file}"
+ BYPRODUCTS ${foreign_types_file}
+ COMMAND_EXPAND_LISTS
+ COMMENT "Resolving foreign type dependencies for target ${target}"
+ )
+
+ add_dependencies(${target}_resolve_foreign_types ${target}_autogen)
- list(REMOVE_DUPLICATES foreign_types)
- string(REPLACE ";" "," foreign_types_list "${foreign_types}")
list(APPEND cmd_args
- "--foreign-types=${foreign_types_list}"
+ "@${foreign_types_file}"
)
set(dependencies_json_file "${target_source_dir}/dependencies.json")
@@ -507,7 +504,7 @@ function(qt6_qml_type_registration target)
list(APPEND cmd_args --private-includes)
endif()
- get_target_property(target_metatypes_json_file ${target} QT_MODULE_META_TYPES_FILE)
+ get_target_property(target_metatypes_json_file ${target} INTERFACE_QT_META_TYPES_BUILD_FILE)
if (NOT target_metatypes_json_file)
message(FATAL_ERROR "Need target metatypes.json file")
endif()
@@ -516,15 +513,15 @@ function(qt6_qml_type_registration target)
set(type_registration_cpp_file "${target_binary_dir}/${type_registration_cpp_file}")
add_custom_command(OUTPUT ${type_registration_cpp_file}
- DEPENDS ${foreign_types} ${target_metatypes_json_file}
+ DEPENDS ${foreign_types_file} ${target_metatypes_json_file}
COMMAND
${CMAKE_COMMAND} -E env PATH=${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}
$<TARGET_FILE:${QT_CMAKE_EXPORT_NAMESPACE}::qmltyperegistrar>
${cmd_args}
-o ${type_registration_cpp_file}
${target_metatypes_json_file}
- COMMENT "Automatic QML type registration for target ${target}"
COMMAND_EXPAND_LISTS
+ COMMENT "Automatic QML type registration for target ${target}"
)
target_sources(${target} PRIVATE ${type_registration_cpp_file})
diff --git a/src/qml/Qt6QmlResolveMetatypesDependencies.cmake b/src/qml/Qt6QmlResolveMetatypesDependencies.cmake
new file mode 100644
index 0000000000..0626b18a62
--- /dev/null
+++ b/src/qml/Qt6QmlResolveMetatypesDependencies.cmake
@@ -0,0 +1,60 @@
+#
+# Resolve dependencies
+#
+
+if (NOT MAIN_DEP_FILE)
+ message(FATAL_ERROR "MAIN_DEP_FILE file not specified")
+endif()
+
+if (NOT QT_INSTALL_DIR)
+ message(FATAL_ERROR "QT_INSTALL_DIR was not specified")
+endif()
+
+if (NOT OUTPUT_FILE)
+ message(FATAL_ERROR "OUTPUT_FILE not specified")
+endif()
+
+# Read main dep file
+if (NOT EXISTS "${MAIN_DEP_FILE}")
+ message(FATAL_ERROR "${MAIN_DEP_FILE} does not exist")
+endif()
+
+file(STRINGS "${MAIN_DEP_FILE}" remaining)
+set(metatypes_list)
+while(remaining)
+
+ # Pop element off the list
+ list(POP_FRONT remaining current)
+
+ string(REPLACE "=" ";" file_list "${current}")
+ list(GET file_list 0 metatypes_file)
+ list(GET file_list 1 metatypes_dep_file)
+
+ if (NOT IS_ABSOLUTE "${metatypes_file}")
+ set(metatypes_file "${QT_INSTALL_DIR}/${metatypes_file}")
+ set(metatypes_dep_file "${QT_INSTALL_DIR}/${metatypes_dep_file}")
+ endif()
+
+ if (NOT EXISTS "${metatypes_file}")
+ message(FATAL_ERROR "${metatypes_file} does not exist")
+ endif()
+ if (NOT EXISTS "${metatypes_dep_file}")
+ message(FATAL_ERROR "${metatypes_dep_file} does not exist")
+ endif()
+
+ list(APPEND metatypes_list "${metatypes_file}")
+
+ file(STRINGS ${metatypes_dep_file} dep_string)
+ if (dep_string)
+ list(APPEND remaining "${dep_string}")
+ endif()
+endwhile()
+
+list(REMOVE_DUPLICATES metatypes_list)
+list(JOIN metatypes_list "," metatypes)
+
+if (metatypes)
+ file(WRITE ${OUTPUT_FILE} "--foreign-types=${metatypes}\n")
+else()
+ file(WRITE ${OUTPUT_FILE} "\n")
+endif()
diff --git a/src/qmltyperegistrar/qmltyperegistrar.cpp b/src/qmltyperegistrar/qmltyperegistrar.cpp
index 49c9fccb66..4738e28314 100644
--- a/src/qmltyperegistrar/qmltyperegistrar.cpp
+++ b/src/qmltyperegistrar/qmltyperegistrar.cpp
@@ -57,6 +57,35 @@ static bool acceptClassForQmlTypeRegistration(const QJsonObject &classDef)
return false;
}
+static bool argumentsFromCommandLineAndFile(QStringList &allArguments, const QStringList &arguments)
+{
+ allArguments.reserve(arguments.size());
+ for (const QString &argument : arguments) {
+ // "@file" doesn't start with a '-' so we can't use QCommandLineParser for it
+ if (argument.startsWith(QLatin1Char('@'))) {
+ QString optionsFile = argument;
+ optionsFile.remove(0, 1);
+ if (optionsFile.isEmpty()) {
+ fprintf(stderr, "The @ option requires an input file");
+ return false;
+ }
+ QFile f(optionsFile);
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ fprintf(stderr, "Cannot open options file specified with @");
+ return false;
+ }
+ while (!f.atEnd()) {
+ QString line = QString::fromLocal8Bit(f.readLine().trimmed());
+ if (!line.isEmpty())
+ allArguments << line;
+ }
+ } else {
+ allArguments << argument;
+ }
+ }
+ return true;
+}
+
static QVector<QJsonObject> foreignRelatedTypes(const QVector<QJsonObject> &types,
const QVector<QJsonObject> &foreignTypes)
{
@@ -229,7 +258,11 @@ int main(int argc, char **argv)
parser.addPositionalArgument(QStringLiteral("[MOC generated json file]"),
QStringLiteral("MOC generated json output."));
- parser.process(app);
+ QStringList arguments;
+ if (!argumentsFromCommandLineAndFile(arguments, app.arguments()))
+ return EXIT_FAILURE;
+
+ parser.process(arguments);
FILE *output = stdout;
QScopedPointer<FILE, ScopedPointerFileCloser> outputFile;