diff --git a/cmake/QtQmakeHelpers.cmake b/cmake/QtQmakeHelpers.cmake index fcfee7c3018..f64032a77de 100644 --- a/cmake/QtQmakeHelpers.cmake +++ b/cmake/QtQmakeHelpers.cmake @@ -49,23 +49,6 @@ function(qt_generate_qconfig_cpp in_file out_file) set(QT_CONFIG_STR_OFFSETS_FIRST "${QT_CONFIG_STR_OFFSETS}") set(QT_CONFIG_STRS_FIRST "${QT_CONFIG_STRS}") - # Start second part. - set(QT_CONFIG_STR_OFFSETS "") - set(QT_CONFIG_STRS "") - - qt_add_string_to_qconfig_cpp("") # config.input.sysroot - qt_add_string_to_qconfig_cpp("false") # qmake_sysrootify - qt_add_string_to_qconfig_cpp("${INSTALL_BINDIR}") - qt_add_string_to_qconfig_cpp("${INSTALL_LIBEXECDIR}") - qt_add_string_to_qconfig_cpp("${INSTALL_LIBDIR}") - qt_add_string_to_qconfig_cpp("${hostdatadir}") - qt_add_string_to_qconfig_cpp("${QT_QMAKE_TARGET_MKSPEC}") - qt_add_string_to_qconfig_cpp("${QT_QMAKE_HOST_MKSPEC}") - - # Save second part. - set(QT_CONFIG_STR_OFFSETS_SECOND "${QT_CONFIG_STR_OFFSETS}") - set(QT_CONFIG_STRS_SECOND "${QT_CONFIG_STRS}") - # Settings path / sysconf dir. set(QT_SYS_CONF_DIR "${INSTALL_SYSCONFDIR}") diff --git a/qmake/CMakeLists.txt b/qmake/CMakeLists.txt index 2a46a6f3c83..c068a8db2de 100644 --- a/qmake/CMakeLists.txt +++ b/qmake/CMakeLists.txt @@ -12,14 +12,6 @@ if(NOT QT_FEATURE_qmake) return() endif() -# The QT_CONFIGURE_HOSTBINDIR_TO_*PREFIX_PATH defines are exclusively used by qmake to determine -# the prefix from the location of the qmake executable. In our build of qmake host_prefix is -# always the same as ext_prefix, and we can just use CMAKE_INSTALL_PREFIX for the calculation of -# the relative path between /bin and . -file(RELATIVE_PATH QT_CONFIGURE_RELATIVE_PREFIX_PATH - "${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}" "${CMAKE_INSTALL_PREFIX}" -) - qt_get_tool_target_name(target_name qmake) qt_internal_add_tool(${target_name} TOOLS_TARGET Core # special case @@ -65,22 +57,20 @@ qt_internal_add_tool(${target_name} QT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} # special case QT_VERSION_MINOR=${PROJECT_VERSION_MINOR} # special case QT_VERSION_PATCH=${PROJECT_VERSION_PATCH} # special case - QT_CONFIGURE_RELATIVE_PREFIX_PATH="${QT_CONFIGURE_RELATIVE_PREFIX_PATH}" + QT_HOST_MKSPEC="${QT_QMAKE_HOST_MKSPEC}" + QT_TARGET_MKSPEC="${QT_QMAKE_TARGET_MKSPEC}" INCLUDE_DIRECTORIES generators generators/mac generators/unix generators/win32 library - "${CMAKE_CURRENT_BINARY_DIR}/library" # for qmakeconfig.cpp PRECOMPILED_HEADER "qmake_pch.h" LIBRARIES Qt::CorePrivate ) -qt_generate_qconfig_cpp(../src/corelib/global/qconfig.cpp.in library/qmakeconfig.cpp) - #### Keys ignored in scope 1:.:.:qmake.pro:: # _OPTION = "host_build" diff --git a/qmake/qmakelibraryinfo.cpp b/qmake/qmakelibraryinfo.cpp index e8bb70071ed..4398e911f1b 100644 --- a/qmake/qmakelibraryinfo.cpp +++ b/qmake/qmakelibraryinfo.cpp @@ -47,7 +47,7 @@ #include #include -#include +#include QT_BEGIN_NAMESPACE @@ -110,7 +110,7 @@ void QMakeLibrarySettings::load() haveEffectiveSourcePaths || children.contains(QLatin1String("EffectivePaths")); // Backwards compat: an existing but empty file is claimed to contain the Paths section. havePaths = (!haveDevicePaths && !haveEffectivePaths - && !children.contains(QLatin1String(platformsSection))) + && !children.contains(QLatin1String("Platforms"))) || children.contains(QLatin1String("Paths")); } else { haveDevicePaths = false; @@ -138,24 +138,83 @@ void QMakeLibraryInfo::sysrootify(QString &path) } } -QString QMakeLibraryInfo::getPrefix() -{ - const QString canonicalQMakePath = QFileInfo(binaryAbsLocation).canonicalPath(); - return QDir::cleanPath(canonicalQMakePath + QLatin1Char('/') - + QLatin1String(QT_CONFIGURE_RELATIVE_PREFIX_PATH)); -} - QString QMakeLibraryInfo::path(int loc) { QString ret = rawLocation(loc, QMakeLibraryInfo::FinalPaths); // Automatically prepend the sysroot to target paths - if (loc < QMakeLibraryInfo::SysrootPath || loc > QMakeLibraryInfo::LastHostPath) + if (loc < QMakeLibraryInfo::FirstHostPath) sysrootify(ret); return ret; } +static QLibraryInfo::LibraryPath hostToTargetPathEnum(int loc) +{ + static std::pair mapping[] = { + { QMakeLibraryInfo::HostBinariesPath, QLibraryInfo::BinariesPath }, + { QMakeLibraryInfo::HostLibraryExecutablesPath, QLibraryInfo::LibraryExecutablesPath }, + { QMakeLibraryInfo::HostLibrariesPath, QLibraryInfo::LibrariesPath }, + { QMakeLibraryInfo::HostDataPath, QLibraryInfo::DataPath }, + { QMakeLibraryInfo::HostPrefixPath, QLibraryInfo::PrefixPath } + }; + for (size_t i = 0; i < sizeof(mapping) / sizeof(mapping[0]); ++i) { + if (mapping[i].first == loc) + return mapping[i].second; + } + qFatal("Unhandled host path %d in hostToTargetPathEnum.", loc); +} + +// from qlibraryinfo.cpp: +void qlibraryinfo_keyAndDefault(QLibraryInfo::LibraryPath loc, QString *key, QString *value); + +struct LocationInfo +{ + QString key; + QString defaultValue; +}; + +static LocationInfo defaultLocationInfo(int loc) +{ + LocationInfo result; + + if (loc < QMakeLibraryInfo::FirstHostPath) { + qlibraryinfo_keyAndDefault(static_cast(loc), + &result.key, &result.defaultValue); + } else if (loc <= QMakeLibraryInfo::LastHostPath) { + qlibraryinfo_keyAndDefault(hostToTargetPathEnum(loc), &result.key, &result.defaultValue); + result.key.prepend(QStringLiteral("Host")); + } else if (loc == QMakeLibraryInfo::SysrootPath) { + result.key = QStringLiteral("Sysroot"); + } else if (loc == QMakeLibraryInfo::SysrootifyPrefixPath) { + result.key = QStringLiteral("SysrootifyPrefix"); + } else if (loc == QMakeLibraryInfo::TargetSpecPath) { + result.key = QStringLiteral("TargetSpec"); + } else if (loc == QMakeLibraryInfo::HostSpecPath) { + result.key = QStringLiteral("HostSpec"); + } + return result; +} + +static QString storedPath(int loc) +{ + QString result; + if (loc < QMakeLibraryInfo::FirstHostPath) { + result = QLibraryInfo::path(static_cast(loc)); + } else if (loc <= QMakeLibraryInfo::LastHostPath) { + result = QLibraryInfo::path(hostToTargetPathEnum(loc)); + } else if (loc == QMakeLibraryInfo::SysrootPath) { + // empty result + } else if (loc == QMakeLibraryInfo::SysrootifyPrefixPath) { + result = QStringLiteral("false"); + } else if (loc == QMakeLibraryInfo::TargetSpecPath) { + result = QT_TARGET_MKSPEC; + } else if (loc == QMakeLibraryInfo::HostSpecPath) { + result = QT_HOST_MKSPEC; + } + return result; +} + QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group) { QString ret; @@ -175,19 +234,8 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group || (group = orig_group, false)) { fromConf = true; - QString key; - QString defaultValue; - if (unsigned(loc) < sizeof(qtConfEntries) / sizeof(qtConfEntries[0])) { - key = QLatin1String(qtConfEntries[loc].key); - defaultValue = QLatin1String(qtConfEntries[loc].value); - } -#ifndef Q_OS_WIN // On Windows we use the registry - else if (loc == QLibraryInfo::SettingsPath) { - key = QLatin1String("Settings"); - defaultValue = QLatin1String("."); - } -#endif - if (!key.isNull()) { + LocationInfo locinfo = defaultLocationInfo(loc); + if (!locinfo.key.isNull()) { QSettings *config = QMakeLibraryInfo::configuration(); config->beginGroup(QLatin1String(group == DevicePaths ? "DevicePaths" : group == EffectiveSourcePaths @@ -195,17 +243,16 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group : group == EffectivePaths ? "EffectivePaths" : "Paths")); - ret = config->value(key, defaultValue).toString(); + ret = config->value(locinfo.key, locinfo.defaultValue).toString(); if (ret.isEmpty()) { - if (loc == HostPrefixPath) - ret = config->value(QLatin1String(qtConfEntries[QLibraryInfo::PrefixPath].key), - QLatin1String( - qtConfEntries[QLibraryInfo::PrefixPath].value)) - .toString(); - else if (loc == TargetSpecPath || loc == HostSpecPath - || loc == SysrootifyPrefixPath) + if (loc == HostPrefixPath) { + locinfo = defaultLocationInfo(QLibraryInfo::PrefixPath); + ret = config->value(locinfo.key, locinfo.defaultValue).toString(); + } else if (loc == TargetSpecPath || loc == HostSpecPath + || loc == SysrootifyPrefixPath) { fromConf = false; + } // The last case here is SysrootPath, which can be legitimately empty. // All other keys have non-empty fallbacks to start with. } @@ -238,30 +285,8 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group } } - if (!fromConf) { - // "volatile" here is a hack to prevent compilers from doing a - // compile-time strlen() on "path". The issue is that Qt installers - // will binary-patch the Qt installation paths -- in such scenarios, Qt - // will be built with a dummy path, thus the compile-time result of - // strlen is meaningless. - const char *volatile path = nullptr; - if (loc == QLibraryInfo::PrefixPath) { - ret = getPrefix(); - } else if (unsigned(loc) - <= sizeof(qt_configure_str_offsets) / sizeof(qt_configure_str_offsets[0])) { - path = qt_configure_strs + qt_configure_str_offsets[loc - 1]; -#ifndef Q_OS_WIN // On Windows we use the registry - } else if (loc == QLibraryInfo::SettingsPath) { - path = QT_CONFIGURE_SETTINGS_PATH; -#endif - } else if (loc == HostPrefixPath) { - static const QByteArray hostPrefixPath = getPrefix().toLatin1(); - path = hostPrefixPath.constData(); - } - - if (path) - ret = QString::fromLocal8Bit(path); - } + if (!fromConf) + ret = storedPath(loc); // These values aren't actually paths and thus need to be returned verbatim. if (loc == TargetSpecPath || loc == HostSpecPath || loc == SysrootifyPrefixPath) @@ -274,7 +299,7 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group // loc == PrefixPath while a sysroot is set would make no sense here. // loc == SysrootPath only makes sense if qmake lives inside the sysroot itself. baseDir = QFileInfo(libraryInfoFile()).absolutePath(); - } else if (loc > SysrootPath && loc <= LastHostPath) { + } else if (loc >= FirstHostPath && loc <= LastHostPath) { // We make any other host path absolute to the host prefix directory. baseDir = rawLocation(HostPrefixPath, group); } else { diff --git a/qmake/qmakelibraryinfo.h b/qmake/qmakelibraryinfo.h index a1983951277..896181493c2 100644 --- a/qmake/qmakelibraryinfo.h +++ b/qmake/qmakelibraryinfo.h @@ -57,18 +57,21 @@ struct QMakeLibraryInfo /* This enum has to start after the last value in QLibraryInfo::LibraryPath(NOT SettingsPath!). * See qconfig.cpp.in and QLibraryInfo for details. + * When adding enum values between FirstHostPath and LastHostPath, make sure to adjust + * the hostToTargetPathEnum(int) function. */ enum LibraryPathQMakeExtras { - SysrootPath = QLibraryInfo::TestsPath + 1, - SysrootifyPrefixPath, - HostBinariesPath, + HostBinariesPath = QLibraryInfo::TestsPath + 1, + FirstHostPath = HostBinariesPath, HostLibraryExecutablesPath, HostLibrariesPath, HostDataPath, - TargetSpecPath, - HostSpecPath, HostPrefixPath, LastHostPath = HostPrefixPath, + TargetSpecPath, + HostSpecPath, + SysrootPath, + SysrootifyPrefixPath }; enum PathGroup { FinalPaths, EffectivePaths, EffectiveSourcePaths, DevicePaths }; static QString rawLocation(int loc, PathGroup group); @@ -80,7 +83,6 @@ struct QMakeLibraryInfo static QString qtconfManualPath; private: - static QString getPrefix(); static QString libraryInfoFile(); }; diff --git a/src/corelib/global/qconfig.cpp.in b/src/corelib/global/qconfig.cpp.in index b529e198305..a552f6bfffb 100644 --- a/src/corelib/global/qconfig.cpp.in +++ b/src/corelib/global/qconfig.cpp.in @@ -1,102 +1,25 @@ -/* This file is used to generate the Qt configuration info for the Core library - * and the qmake executable. The 'qt_generate_qconfig_cpp' cmake routine +/* This file is used to generate the Qt configuration info for the Core library. + * The 'qt_generate_qconfig_cpp' cmake routine * contains variables that replace '@' entires in this file. It's important to * align these values with the following: * * - QLibraryInfo::LibraryPath enum in qtbase/src/corelib/global/qlibraryinfo.h - * - qtConfEntries in this file - * - QMakeLibraryInfo::LibraryPathQMakeExtras enum in - * qtbase/qmake/library/qmakelibraryinfo.h + * - qtConfEntries in qtbase/src/corelib/global/qlibraryinfo.cpp * - * The reason for this is pointer mathematics in the QMakeLibraryInfo and - * QLibraryInfo implementation when iterating qt_configure_strs. Also - * qtConfEntries are strongly bound to QLibraryInfo::LibraryPath and - * QMakeLibraryInfo::LibraryPathQMakeExtras enums. + * The reason for this is pointer mathematics in the QLibraryInfo implementation when iterating + * qt_configure_strs. Also qtConfEntries are strongly bound to QLibraryInfo::LibraryPath. */ /* 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@"; -#ifdef QT_BUILD_QMAKE -static const char qt_configure_ext_prefix_path_str [12+256] = "qt_epfxpath=@QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX@"; -static const char qt_configure_host_prefix_path_str [12+256] = "qt_hpfxpath=@QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX@"; -#endif static const short qt_configure_str_offsets[] = { @QT_CONFIG_STR_OFFSETS_FIRST@ -#ifdef QT_BUILD_QMAKE -@QT_CONFIG_STR_OFFSETS_SECOND@ -#endif }; static const char qt_configure_strs[] = @QT_CONFIG_STRS_FIRST@ -#ifdef QT_BUILD_QMAKE -@QT_CONFIG_STRS_SECOND@ -#endif ; #define QT_CONFIGURE_SETTINGS_PATH "@QT_SYS_CONF_DIR@" #define QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH "@QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH@" #define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12 -#ifdef QT_BUILD_QMAKE -# define QT_CONFIGURE_EXT_PREFIX_PATH qt_configure_ext_prefix_path_str + 12 -# define QT_CONFIGURE_HOST_PREFIX_PATH qt_configure_host_prefix_path_str + 12 -#endif - - -/* Entries below are shared between qmake and the Core library. Please pay - * attention and read the adding rules here and inside QLibraryInfo header. - * - * To add a new entry in QLibraryInfo::LibraryPath, add it to the enum - * in qtbase/src/corelib/global/qlibraryinfo.h and: - * - add its relative path in the qtConfEntries[] array below - * (the key is what appears in a qt.conf file) - * - add a property name in qmake/property.cpp propList[] array - * (it's used with qmake -query) - * - add to qt_config.prf, qt_module.prf, qt_module_fwdpri.prf - */ - -#ifdef QT_BUILD_QMAKE -constexpr size_t qtConfEntriesKeySize = 23; -#else -constexpr size_t qtConfEntriesKeySize = 19; -#endif - -static const struct { - char key[qtConfEntriesKeySize], value[13]; -} qtConfEntries[] = { - { "Prefix", "." }, - { "Documentation", "doc" }, // should be ${Data}/doc - { "Headers", "include" }, - { "Libraries", "lib" }, -#ifdef Q_OS_WIN - { "LibraryExecutables", "bin" }, -#else - { "LibraryExecutables", "libexec" }, // should be ${ArchData}/libexec -#endif - { "Binaries", "bin" }, - { "Plugins", "plugins" }, // should be ${ArchData}/plugins - { "Qml2Imports", "qml" }, // should be ${ArchData}/qml - { "ArchData", "." }, - { "Data", "." }, - { "Translations", "translations" }, // should be ${Data}/translations - { "Examples", "examples" }, - { "Tests", "tests" }, -// Put new entries above this line ONLY! -#ifdef QT_BUILD_QMAKE - { "Sysroot", "" }, - { "SysrootifyPrefix", "" }, - { "HostBinaries", "bin" }, -#ifdef Q_OS_WIN - { "HostLibraryExecutables", "bin" }, -#else - { "HostLibraryExecutables", "libexec" }, -#endif - { "HostLibraries", "lib" }, - { "HostData", "." }, - { "TargetSpec", "" }, - { "HostSpec", "" }, - { "HostPrefix", "" }, -#endif -}; - -static const char platformsSection[] = "Platforms"; diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index b48b1b5d955..4d06ec6e3f1 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -122,7 +122,7 @@ void QLibrarySettings::load() haveEffectivePaths = haveEffectiveSourcePaths || children.contains(QLatin1String("EffectivePaths")); // Backwards compat: an existing but empty file is claimed to contain the Paths section. havePaths = (!haveDevicePaths && !haveEffectivePaths - && !children.contains(QLatin1String(platformsSection))) + && !children.contains(QLatin1String("Platforms"))) || children.contains(QLatin1String("Paths")); if (!havePaths) settings.reset(nullptr); @@ -284,7 +284,6 @@ QLibraryInfo::isDebugBuild() #endif } -#ifndef QT_BOOTSTRAPPED /*! \since 5.8 Returns the version of the Qt library. @@ -295,7 +294,35 @@ QVersionNumber QLibraryInfo::version() noexcept { return QVersionNumber(QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH); } -#endif // QT_BOOTSTRAPPED + +/* + * To add a new entry in QLibraryInfo::LibraryPath, add it to the enum + * in qtbase/src/corelib/global/qlibraryinfo.h and: + * - add its relative path in the qtConfEntries[] array below + * (the key is what appears in a qt.conf file) + */ + +static const struct { + char key[19], value[13]; +} qtConfEntries[] = { + { "Prefix", "." }, + { "Documentation", "doc" }, // should be ${Data}/doc + { "Headers", "include" }, + { "Libraries", "lib" }, +#ifdef Q_OS_WIN + { "LibraryExecutables", "bin" }, +#else + { "LibraryExecutables", "libexec" }, // should be ${ArchData}/libexec +#endif + { "Binaries", "bin" }, + { "Plugins", "plugins" }, // should be ${ArchData}/plugins + { "Qml2Imports", "qml" }, // should be ${ArchData}/qml + { "ArchData", "." }, + { "Data", "." }, + { "Translations", "translations" }, // should be ${Data}/translations + { "Examples", "examples" }, + { "Tests", "tests" }, +}; static QString prefixFromAppDirHelper() { @@ -476,6 +503,25 @@ static QString getPrefix() #endif } +Q_CORE_EXPORT void qlibraryinfo_keyAndDefault(QLibraryInfo::LibraryPath loc, QString *key, + QString *value) +{ + if (unsigned(loc) < sizeof(qtConfEntries)/sizeof(qtConfEntries[0])) { + *key = QLatin1String(qtConfEntries[loc].key); + *value = QLatin1String(qtConfEntries[loc].value); + } +#ifndef Q_OS_WIN // On Windows we use the registry + else if (loc == QLibraryInfo::SettingsPath) { + *key = QLatin1String("Settings"); + *value = QLatin1String("."); + } +#endif + else { + key->clear(); + value->clear(); + } +} + /*! \fn QString QLibraryInfo::location(LibraryLocation loc) \obsolete Use path() instead. @@ -499,17 +545,7 @@ QString QLibraryInfo::path(LibraryPath p) QString key; QString defaultValue; - if (unsigned(loc) < sizeof(qtConfEntries)/sizeof(qtConfEntries[0])) { - key = QLatin1String(qtConfEntries[loc].key); - defaultValue = QLatin1String(qtConfEntries[loc].value); - } -#ifndef Q_OS_WIN // On Windows we use the registry - else if (loc == SettingsPath) { - key = QLatin1String("Settings"); - defaultValue = QLatin1String("."); - } -#endif - + qlibraryinfo_keyAndDefault(loc, &key, &defaultValue); if (!key.isNull()) { QSettings *config = QLibraryInfoPrivate::configuration(); config->beginGroup(QLatin1String("Paths")); @@ -594,7 +630,7 @@ QStringList QLibraryInfo::platformPluginArguments(const QString &platformName) #if QT_CONFIG(settings) QScopedPointer settings(QLibraryInfoPrivate::findConfiguration()); if (!settings.isNull()) { - const QString key = QLatin1String(platformsSection) + const QString key = QLatin1String("Platforms") + QLatin1Char('/') + platformName + QLatin1String("Arguments"); diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index d3fe8791b7b..2b607ac5be7 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1377,8 +1377,7 @@ bool QIcon::hasThemeIcon(const QString &name) */ void QIcon::setIsMask(bool isMask) { - if (d) - detach(); + detach(); if (!d) d = new QIconPrivate(new QPixmapIconEngine); d->is_mask = isMask;