From fef850c51a069ed89ba400e6ffccbbea4b0cbb9f Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Tue, 9 Mar 2021 18:03:21 +0100 Subject: Extend qtpaths functionally to replicate the 'qmake -query' behavior 'qt-version', 'install-prefix', 'binaries-dir' and 'plugin-dir' are covered by the introduced qt-query option. So make them obsolete and hidden in the application help. Note that the 'qtconf' option will affect the output of options associated with QLibraryInfo. [ChangeLog][Tools] qtpaths got new --qt-query argument that can be used instead of qmake -query. The new --qtconf, --query-format arguments allow you to further tweak its output. [ChangeLog][Tools] The qt-version, install-prefix, binaries-dir and plugin-dir options of the qtpaths tool are deprecated. [ChangeLog][Tools] The qtpaths tool has been moved from the qttools repository to the qtbase repository. Fixes: QTBUG-75870 Change-Id: I949acf79c8ce321811ee81cf707c1ae0eccb547d Reviewed-by: hjk Reviewed-by: Alexandru Croitor --- src/tools/qtpaths/CMakeLists.txt | 7 ++++ src/tools/qtpaths/qtpaths.cpp | 75 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tools/qtpaths/CMakeLists.txt b/src/tools/qtpaths/CMakeLists.txt index 412ef5a0f9..e1df1d6422 100644 --- a/src/tools/qtpaths/CMakeLists.txt +++ b/src/tools/qtpaths/CMakeLists.txt @@ -12,11 +12,18 @@ qt_internal_add_tool(${target_name} qtpaths.cpp DEFINES QT_NO_FOREACH + QTPATHS_VERSION_STR="2.0" ) ## Scopes: ##################################################################### +qt_internal_extend_target(${target_name} CONDITION QT_FEATURE_settings + LIBRARIES + QtLibraryInfo + Qt::CorePrivate +) + if(WIN32 AND TARGET ${target_name}) set_target_properties(${target_name} PROPERTIES WIN32_EXECUTABLE FALSE diff --git a/src/tools/qtpaths/qtpaths.cpp b/src/tools/qtpaths/qtpaths.cpp index 93e2e42a5f..16fc1284f5 100644 --- a/src/tools/qtpaths/qtpaths.cpp +++ b/src/tools/qtpaths/qtpaths.cpp @@ -58,6 +58,13 @@ #include +#if QT_CONFIG(settings) +# include +# include +# include +# include +#endif + QT_USE_NAMESPACE /** @@ -162,7 +169,7 @@ static QString searchStringOrError(QCommandLineParser *parser) int main(int argc, char **argv) { QCoreApplication app(argc, argv); - app.setApplicationVersion("1.0"); + app.setApplicationVersion(QTPATHS_VERSION_STR); #ifdef Q_OS_WIN const QLatin1Char pathsep(';'); @@ -171,8 +178,10 @@ int main(int argc, char **argv) #endif QCommandLineParser parser; - parser.setApplicationDescription(QCoreApplication::translate("qtpaths", "Command line client to QStandardPaths")); + parser.setApplicationDescription(QCoreApplication::translate("qtpaths", "Command line client to QStandardPaths and QLibraryInfo")); parser.addPositionalArgument(QCoreApplication::translate("qtpaths", "[name]"), QCoreApplication::tr("Name of file or directory")); + parser.addPositionalArgument(QCoreApplication::translate("qtpaths", "[properties]"), QCoreApplication::tr("List of the Qt properties to query by the --qt-query argument.")); + parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); parser.addHelpOption(); parser.addVersionOption(); @@ -216,23 +225,51 @@ int main(int argc, char **argv) parser.addOption(testmode); QCommandLineOption qtversion(QStringLiteral("qt-version"), QCoreApplication::translate("qtpaths", "Qt version.")); + qtversion.setFlags(QCommandLineOption::HiddenFromHelp); parser.addOption(qtversion); QCommandLineOption installprefix(QStringLiteral("install-prefix"), QCoreApplication::translate("qtpaths", "Installation prefix for Qt.")); + installprefix.setFlags(QCommandLineOption::HiddenFromHelp); parser.addOption(installprefix); QCommandLineOption bindir(QStringList() << QStringLiteral("binaries-dir") << QStringLiteral("binaries-directory"), QCoreApplication::translate("qtpaths", "Location of Qt executables.")); + bindir.setFlags(QCommandLineOption::HiddenFromHelp); parser.addOption(bindir); QCommandLineOption plugindir(QStringList() << QStringLiteral("plugin-dir") << QStringLiteral("plugin-directory"), QCoreApplication::translate("qtpaths", "Location of Qt plugins.")); + plugindir.setFlags(QCommandLineOption::HiddenFromHelp); parser.addOption(plugindir); + QCommandLineOption query( + QStringList() << QStringLiteral("qt-query") << QStringLiteral("query"), + QCoreApplication::translate("qtpaths", + "List of Qt properties. Can be used standalone or with the " + "--query-format and --qtconf options.")); + parser.addOption(query); + + QCommandLineOption queryformat(QStringLiteral("query-format"), + QCoreApplication::translate("qtpaths", "Output format for --qt-query.\nSupported formats: qmake (default), json"), + QCoreApplication::translate("qtpaths", "format")); + queryformat.setDefaultValue("qmake"); + parser.addOption(queryformat); + + QCommandLineOption qtconf(QStringLiteral("qtconf"), + QCoreApplication::translate("qtpaths", "Path to qt.conf file that will be used to override the queried Qt properties."), + QCoreApplication::translate("qtpaths", "path")); + parser.addOption(qtconf); + parser.process(app); QStandardPaths::setTestModeEnabled(parser.isSet(testmode)); +#if QT_CONFIG(settings) + if (parser.isSet(qtconf)) { + QLibraryInfoPrivate::qtconfManualPath = parser.value(qtconf); + } +#endif + QStringList results; if (parser.isSet(qtversion)) { QString qtversionstring = QString::fromLatin1(qVersion()); @@ -310,6 +347,40 @@ int main(int argc, char **argv) QStringList paths = QStandardPaths::locateAll(location.enumvalue, searchitem, QStandardPaths::LocateFile); results << location.mapName(paths.join(pathsep)); } + +#if !QT_CONFIG(settings) + if (parser.isSet(query) || parser.isSet(qtconf) || parser.isSet(queryformat)) { + error(QStringLiteral("--qt-query, --qtconf and --query-format options are not supported. The 'settings' feature is missing.")); + } +#else + if (parser.isSet(query)) { + if (!results.isEmpty()) { + QString errorMessage = QCoreApplication::translate("qtpaths", "Several options given, only one is supported at a time."); + error(errorMessage); + } + + PropertyPrinter printer; + if (parser.isSet(queryformat)) { + QString formatValue = parser.value(queryformat); + if (formatValue == "json") { + printer = jsonPropertyPrinter; + } else if (formatValue != "qmake") { + QString errorMessage = QCoreApplication::translate("qtpaths", "Invalid output format %1. Supported formats: qmake, json").arg(formatValue); + error(errorMessage); + } + } + + QStringList optionProperties = parser.positionalArguments(); + QMakeProperty prop; + if (printer) { + return prop.queryProperty(optionProperties, printer); + } + return prop.queryProperty(optionProperties); + } else if (parser.isSet(queryformat)) { + error(QCoreApplication::translate("qtpaths", "--query-format is set, but --qt-query is not requested.")); + } +#endif + if (results.isEmpty()) { parser.showHelp(); } else if (results.size() == 1) { -- cgit v1.2.3 From 04df85bbecdc034876d509b9c96a4f17fc990293 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Fri, 19 Mar 2021 13:45:46 +0100 Subject: CMake: Get rid of the Core_qobject static library The Core_qobject target was problematic for a few reasons. In the very beginning, Core_qobject was an OBJECT library, explaining its existence with the following comment "requires to spill internals into users". The object library contained qobject.cpp and qproperty.cpp and their manually generated moc files. It was was a dependency of Core. Afterwards it got converted into a static library instead, presumably to circumvent some issues with metatype generation. Unfortunately making it a static library was wrong, because it leads to linker failures (undefined symbols) in a static Qt build when trying to link a project that uses only QtCore. Both Core and Core_qobject refer to each other's symbols, and whichever library came first on the link line, many of its symbols were discarded by the linker. Transforming Core_qobject back into an object library could be an option, but that leads to trouble with creating proper prl files (our infrastructure doesn't quite support that for object libraries yet). Furthermore, there was some internal discussion and concern about how to merge the two metatype json file lists (Core and Core_qobject) into a single file. Instead of using an object library, move qobject.cpp and qproperty.cpp to be directly a part of Core again and remove the Core_qobject target. In order to do that, we have to circumvent some issues with AUTOMOC. First, we have to disable AUTOMOC for qobject.cpp and its headers. qobject.cpp contains Q_GADGET, Q_NAMESPACE, etc keywords in its doc comments. That confuses AUTOMOC, because it expects a qobject.moc file which is not included by qobject.cpp. See e2ff9e3b9957f844d6530cc92096bed3c16fa46a for some details on the Q_GADGET + AUTOMOC issue. We still need to run moc on on qobject.h and compile moc_qobject.cpp, so we manually run moc on the header file. Because qobject.cpp directly includes moc_qobject.cpp, we need to adjust the header include path to the generated file. Second, we remove the direct inclusion of moc_qnamespace.cpp in qobject.cpp to prevent duplicate symbol compilation, because the symbols were compiled both as part of qobject.cpp and mocs_compilation.cpp. Finally, because manual moc is used on qobject.h, the generated json file needs to be explicitly passed to Core's metatype generation step. Amends e57a94cbd8f28ccab8b3368afc4365237c533a4f Amends 3c4c02b3f1cec8ebc0134fd05b0e51f1f771937d Pick-to: 6.1 Task-number: QTBUG-87580 Change-Id: I859a7d2f95508eda211a0a0b4ec132540b78bda4 Reviewed-by: Alexey Edelev Reviewed-by: Joerg Bornemann --- src/corelib/CMakeLists.txt | 73 +++++++++++++++--------------------------- src/corelib/kernel/qobject.cpp | 1 - 2 files changed, 25 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 95c3116753..d8baa4952b 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -27,7 +27,6 @@ endif() ##################################################################### qt_internal_add_module(Core - GENERATE_METATYPES QMAKE_MODULE_CONFIG moc resources EXCEPTIONS SOURCES @@ -44,7 +43,7 @@ qt_internal_add_module(Core global/qlibraryinfo.cpp global/qlibraryinfo.h global/qlibraryinfo_p.h global/qlogging.cpp global/qlogging.h global/qmalloc.cpp - # global/qnamespace.h # special case + global/qnamespace.h # this header is specified on purpose so AUTOMOC processes it global/qnumeric.cpp global/qnumeric.h global/qnumeric_p.h global/qoperatingsystemversion.cpp global/qoperatingsystemversion.h global/qoperatingsystemversion_p.h global/qprocessordetection.h @@ -110,7 +109,7 @@ qt_internal_add_module(Core kernel/qmetaobjectbuilder.cpp kernel/qmetaobjectbuilder_p.h kernel/qmetatype.cpp kernel/qmetatype.h kernel/qmetatype_p.h kernel/qmimedata.cpp kernel/qmimedata.h - # kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h # special case + kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h kernel/qobject_impl.h kernel/qobjectcleanuphandler.cpp kernel/qobjectcleanuphandler.h kernel/qobjectdefs.h @@ -245,6 +244,7 @@ qt_internal_add_module(Core QT_NO_USING_NAMESPACE INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/global" # special case + "${CMAKE_CURRENT_BINARY_DIR}/kernel" # for moc_qobject.cpp to be found by qobject.cpp # ../3rdparty/md4 # special case remove # ../3rdparty/md5 # special case remove # ../3rdparty/sha3 # special case remove @@ -288,49 +288,31 @@ if(QT_FEATURE_thread) target_link_libraries(Platform INTERFACE Threads::Threads) endif() -# Handle QObject: Automoc does not work for this as it would -# require to spill internals into users: -qt_internal_add_module(Core_qobject STATIC - NO_SYNC_QT - NO_CONFIG_HEADER_FILE - NO_MODULE_HEADERS - INTERNAL_MODULE - SKIP_DEPENDS_INCLUDE -) -set_target_properties(Core_qobject PROPERTIES AUTOMOC OFF) -qt_manual_moc(qobject_moc_files OUTPUT_MOC_JSON_FILES core_qobject_metatypes_json_list kernel/qobject.h global/qnamespace.h) +# Skip AUTOMOC processing of qobject.cpp and its headers. +# We do this on purpose, because qobject.cpp contains a bunch of Q_GADGET, Q_NAMESPACE, etc +# keywords and AUTOMOC gets confused about wanting to compile a qobject.moc file as well. +# Instead use manual moc. +set_source_files_properties(kernel/qobject.cpp kernel/qobject.h kernel/qobject_p.h + PROPERTIES SKIP_AUTOMOC TRUE) + +qt_manual_moc(qobject_moc_files + OUTPUT_MOC_JSON_FILES core_qobject_metatypes_json_list + kernel/qobject.h) +# The moc file is included directly by qobject.cpp set_source_files_properties(${qobject_moc_files} PROPERTIES HEADER_FILE_ONLY ON) -target_sources(Core_qobject PRIVATE - global/qnamespace.h - kernel/qobject.cpp kernel/qproperty.cpp kernel/qproperty.h kernel/qproperty_p.h kernel/qobject.h kernel/qobject_p.h ${qobject_moc_files}) -set_target_properties(Core_qobject PROPERTIES - COMPILE_OPTIONS $ - COMPILE_DEFINITIONS $ - INCLUDE_DIRECTORIES $ -) -target_include_directories(Core_qobject PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/kernel") # for moc_qobject.cpp -target_link_libraries(Core_qobject PRIVATE Qt::Platform Qt::GlobalConfig) -qt_internal_extend_target(Core LIBRARIES Qt::Core_qobject) -add_dependencies(Core_qobject ${QT_CMAKE_EXPORT_NAMESPACE}::moc) - -set(core_qobject_metatypes_json_args) -if (NOT QT_WILL_INSTALL) - set(core_qobject_metatypes_json_args INSTALL_DIR "${QT_BUILD_DIR}/${INSTALL_LIBDIR}/metatypes") -endif() -qt6_extract_metatypes(Core_qobject - MANUAL_MOC_JSON_FILES ${core_qobject_metatypes_json_list} - ${core_qobject_metatypes_json_args} -) +set(core_metatype_args MANUAL_MOC_JSON_FILES ${core_qobject_metatypes_json_list}) -# 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(metatypes_install_dir ${INSTALL_LIBDIR}/metatypes) +if (NOT QT_WILL_INSTALL) + list(APPEND core_metatype_args + COPY_OVER_INSTALL INSTALL_DIR "${QT_BUILD_DIR}/${metatypes_install_dir}") +else() + list(APPEND core_metatype_args INSTALL_DIR "${metatypes_install_dir}") +endif() +# Use qt6_extract_metatypes instead of GENERATE_METATYPES so that we can manually pass the +# additional json files. +qt6_extract_metatypes(Core ${core_metatype_args}) set_property(TARGET Core APPEND PROPERTY PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/global/qconfig.h") @@ -1341,11 +1323,6 @@ endif() # special case end qt_internal_create_tracepoints(Core qtcore.tracepoints) -# special case begin -if(TARGET Core_tracepoints_header) - add_dependencies(Core_qobject Core_tracepoints_header) -endif() -# special case end qt_internal_add_docs(Core doc/qtcore.qdocconf ) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 4d2f801c7b..343922581c 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -5243,5 +5243,4 @@ bool QMetaObject::Connection::isConnected_helper() const QT_END_NAMESPACE -#include "moc_qnamespace.cpp" #include "moc_qobject.cpp" -- cgit v1.2.3 From 59c3be711728ab0aa644bfdf50e91a1b020f95bb Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Tue, 23 Mar 2021 17:47:58 +0100 Subject: CMake: Fix qconfig.cpp embedded prefix in the CI In the CI on a windows we configure Qt with the following prefix -DCMAKE_INSTALL_PREFIX:PATH=\Users\qt\work\install Note the lack of the drive letter. This is intentional, so that we can abuse CMake's DESTDIR installation mechanism to install into a custom path. This causes trouble for static Qt builds in the CI. Specifically when there is no qt.conf file next to qmake, qmake -query will report a QT_INSTALL_PREFIX:/Users/qt/work/install and ultimately qmake will fail to locate the module .pri files in such a path, showing errors like: Project ERROR: Unknown module(s) in QT: core gui? If a qt.conf is placed next to qmake (even an empty one), a differenct code path is used in qmake to resolve the prefix, which returns a path with a drive letter. In a shared build, because the 'relocatable' feature is enabled by default, a different code path is used and thus the prefix is also successfully resolved. So the problem is specific to static Windows Qt builds that have no qt.conf file next to qmake. This is the exact scenario that we encounter when running static Qt tests (tst_qmake in particular). To circumvent the issue, prepend a drive letter to the prefix hardcoded into qconfig.cpp. Do that with get_filename_component(REALPATH) which apparently resolves to a fully qualified path. Pick-to: 6.1 Task-number: QTBUG-87580 Change-Id: I17c885f29bfdee45bec1d6aac7c3b26723e761a3 Reviewed-by: Joerg Bornemann --- src/corelib/global/qconfig.cpp.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/global/qconfig.cpp.in b/src/corelib/global/qconfig.cpp.in index a552f6bfff..e6a85feffd 100644 --- a/src/corelib/global/qconfig.cpp.in +++ b/src/corelib/global/qconfig.cpp.in @@ -13,7 +13,7 @@ /* Installation date */ static const char qt_configure_installation [12+11] = "qt_instdate=2012-12-20"; /* Installation Info */ -static const char qt_configure_prefix_path_str [12+256] = "qt_prfxpath=@QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX@"; +static const char qt_configure_prefix_path_str [12+256] = "qt_prfxpath=@QT_CONFIGURE_PREFIX_PATH_STR@"; static const short qt_configure_str_offsets[] = { @QT_CONFIG_STR_OFFSETS_FIRST@ }; -- cgit v1.2.3