diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app/qbs-setup-android/android-setup.cpp | 29 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/msvcprobe.cpp | 106 | ||||
-rw-r--r-- | src/lib/corelib/language/astpropertiesitemhandler.cpp | 1 | ||||
-rw-r--r-- | src/lib/corelib/tools/persistence.h | 14 | ||||
-rw-r--r-- | src/lib/corelib/tools/vsenvironmentdetector.cpp | 2 | ||||
-rw-r--r-- | src/lib/qtprofilesetup/qtmoduleinfo.cpp | 67 | ||||
-rw-r--r-- | src/lib/qtprofilesetup/templates/core.qbs | 14 |
7 files changed, 191 insertions, 42 deletions
diff --git a/src/app/qbs-setup-android/android-setup.cpp b/src/app/qbs-setup-android/android-setup.cpp index eb5ba92dd..d32cdbc05 100644 --- a/src/app/qbs-setup-android/android-setup.cpp +++ b/src/app/qbs-setup-android/android-setup.cpp @@ -46,6 +46,7 @@ #include <tools/settings.h> #include <tools/version.h> +#include <QtCore/qbytearraylist.h> #include <QtCore/qcoreapplication.h> #include <QtCore/qdir.h> #include <QtCore/qdiriterator.h> @@ -65,10 +66,7 @@ static QStringList expectedArchs() { return QStringList() << QStringLiteral("arm64") - << QStringLiteral("armv5te") << QStringLiteral("armv7a") - << QStringLiteral("mips") - << QStringLiteral("mips64") << QStringLiteral("x86") << QStringLiteral("x86_64"); } @@ -181,6 +179,29 @@ static QString maximumPlatform(const QString &platform1, const QString &platform return prefix + QString::number(std::max(value1, value2)); } +static QString getToolchainType(const QString &ndkDirPath) +{ + QFile sourceProperties(ndkDirPath + qls("/source.properties")); + if (!sourceProperties.open(QIODevice::ReadOnly)) + return QLatin1String("gcc"); // <= r10 + while (!sourceProperties.atEnd()) { + const QByteArray curLine = sourceProperties.readLine().simplified(); + static const QByteArray prefix = "Pkg.Revision = "; + if (!curLine.startsWith(prefix)) + continue; + qbs::Version ndkVersion = qbs::Version::fromString( + QString::fromLatin1(curLine.mid(prefix.size()))); + if (!ndkVersion.isValid()) { + qWarning("Unexpected format of NDK revision string in '%s'", + qPrintable(sourceProperties.fileName())); + return QLatin1String("clang"); + } + return qls(ndkVersion.majorVersion() >= 18 ? "clang" : "gcc"); + } + qWarning("No revision entry found in '%s'", qPrintable(sourceProperties.fileName())); + return QLatin1String("clang"); +} + static void setupNdk(qbs::Settings *settings, const QString &profileName, const QString &ndkDirPath, const QString &qtSdkDirPath) { @@ -194,7 +215,7 @@ static void setupNdk(qbs::Settings *settings, const QString &profileName, const mainProfile.setValue(qls("Android.ndk.ndkDir"), QDir::cleanPath(ndkDirPath)); mainProfile.setValue(qls("Android.sdk.ndkDir"), QDir::cleanPath(ndkDirPath)); } - mainProfile.setValue(qls("qbs.toolchain"), QStringList() << qls("gcc")); + mainProfile.setValue(qls("qbs.toolchainType"), getToolchainType(ndkDirPath)); const QStringList archs = expectedArchs(); const QtInfoPerArch infoPerArch = getQtAndroidInfo(qtSdkDirPath); const QStringList archsForProfile = infoPerArch.empty() diff --git a/src/app/qbs-setup-toolchains/msvcprobe.cpp b/src/app/qbs-setup-toolchains/msvcprobe.cpp index 919f88d12..967d443a2 100644 --- a/src/app/qbs-setup-toolchains/msvcprobe.cpp +++ b/src/app/qbs-setup-toolchains/msvcprobe.cpp @@ -55,9 +55,14 @@ #include <QtCore/qdir.h> #include <QtCore/qfileinfo.h> +#include <QtCore/qjsonarray.h> +#include <QtCore/qjsondocument.h> +#include <QtCore/qjsonobject.h> +#include <QtCore/qprocess.h> #include <QtCore/qsettings.h> #include <QtCore/qstringlist.h> +#include <algorithm> #include <vector> using namespace qbs; @@ -155,15 +160,92 @@ static QString wow6432Key() #endif } -struct MSVCRegistryEntry +struct MSVCInstallInfo { QString version; QString installDir; }; -static std::vector<MSVCRegistryEntry> installedMSVCsFromRegistry() +static QString vswhereFilePath() { - std::vector<MSVCRegistryEntry> result; + static const std::vector<const char *> envVarCandidates{"ProgramFiles", "ProgramFiles(x86)"}; + for (const char * const envVar : envVarCandidates) { + const QString value = QDir::fromNativeSeparators(QString::fromLocal8Bit(qgetenv(envVar))); + const QString cmd = value + + QStringLiteral("/Microsoft Visual Studio/Installer/vswhere.exe"); + if (QFileInfo(cmd).exists()) + return cmd; + } + return QString(); +} + +enum class ProductType { VisualStudio, BuildTools }; +static std::vector<MSVCInstallInfo> retrieveInstancesFromVSWhere(ProductType productType) +{ + std::vector<MSVCInstallInfo> result; + const QString cmd = vswhereFilePath(); + if (cmd.isEmpty()) + return result; + QProcess vsWhere; + QStringList args = productType == ProductType::VisualStudio + ? QStringList({QStringLiteral("-all"), QStringLiteral("-legacy"), + QStringLiteral("-prerelease")}) + : QStringList({QStringLiteral("-products"), + QStringLiteral("Microsoft.VisualStudio.Product.BuildTools")}); + args << QStringLiteral("-format") << QStringLiteral("json") << QStringLiteral("-utf8"); + vsWhere.start(cmd, args); + if (!vsWhere.waitForStarted(-1)) + return result; + if (!vsWhere.waitForFinished(-1)) { + qbsWarning() << Tr::tr("The vswhere tool failed to run: %1").arg(vsWhere.errorString()); + return result; + } + if (vsWhere.exitCode() != 0) { + qbsWarning() << Tr::tr("The vswhere tool failed to run: %1") + .arg(QString::fromLocal8Bit(vsWhere.readAllStandardError())); + return result; + } + QJsonParseError parseError; + QJsonDocument jsonOutput = QJsonDocument::fromJson(vsWhere.readAllStandardOutput(), + &parseError); + if (parseError.error != QJsonParseError::NoError) { + qbsWarning() << Tr::tr("The vswhere tool produced invalid JSON output: %1") + .arg(parseError.errorString()); + return result; + } + for (const QJsonValue &v : jsonOutput.array()) { + const QJsonObject o = v.toObject(); + MSVCInstallInfo info; + info.version = o.value(QStringLiteral("installationVersion")).toString(); + if (productType == ProductType::BuildTools) { + // For build tools, the version is e.g. "15.8.28010.2036", rather than "15.0". + const int dotIndex = info.version.indexOf(QLatin1Char('.')); + if (dotIndex != -1) + info.version = info.version.left(dotIndex); + } + info.installDir = o.value(QStringLiteral("installationPath")).toString(); + if (!info.version.isEmpty() && !info.installDir.isEmpty()) + result.push_back(info); + } + return result; +} + +static std::vector<MSVCInstallInfo> installedMSVCsFromVsWhere() +{ + const std::vector<MSVCInstallInfo> vsInstallations + = retrieveInstancesFromVSWhere(ProductType::VisualStudio); + const std::vector<MSVCInstallInfo> buildToolInstallations + = retrieveInstancesFromVSWhere(ProductType::BuildTools); + std::vector<MSVCInstallInfo> all; + std::copy(vsInstallations.begin(), vsInstallations.end(), std::back_inserter(all)); + std::copy(buildToolInstallations.begin(), buildToolInstallations.end(), + std::back_inserter(all)); + return all; +} + +static std::vector<MSVCInstallInfo> installedMSVCsFromRegistry() +{ + std::vector<MSVCInstallInfo> result; // Detect Visual Studio const QSettings vsRegistry( @@ -172,7 +254,7 @@ static std::vector<MSVCRegistryEntry> installedMSVCsFromRegistry() QSettings::NativeFormat); const auto vsNames = vsRegistry.childKeys(); for (const QString &vsName : vsNames) { - MSVCRegistryEntry entry; + MSVCInstallInfo entry; entry.version = vsName; entry.installDir = vsRegistry.value(vsName).toString(); result.push_back(entry); @@ -189,7 +271,7 @@ static std::vector<MSVCRegistryEntry> installedMSVCsFromRegistry() bool ok; int installed = vcbtRegistry.value(QStringLiteral("Installed")).toInt(&ok); if (ok && installed) { - MSVCRegistryEntry entry; + MSVCInstallInfo entry; entry.version = childGroup; const QSettings vsRegistry( QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE") + wow6432Key() @@ -208,14 +290,16 @@ static std::vector<MSVCRegistryEntry> installedMSVCsFromRegistry() static std::vector<MSVC> installedMSVCs() { std::vector<MSVC> msvcs; - const std::vector<MSVCRegistryEntry> ®istryEntries = installedMSVCsFromRegistry(); - for (const MSVCRegistryEntry ®istryEntry : registryEntries) { + std::vector<MSVCInstallInfo> installInfos = installedMSVCsFromVsWhere(); + if (installInfos.empty()) + installInfos = installedMSVCsFromRegistry(); + for (const MSVCInstallInfo &installInfo : installInfos) { MSVC msvc; - msvc.internalVsVersion = Version::fromString(registryEntry.version); + msvc.internalVsVersion = Version::fromString(installInfo.version); if (!msvc.internalVsVersion.isValid()) continue; - QDir vsInstallDir(registryEntry.installDir); + QDir vsInstallDir(installInfo.installDir); msvc.vsInstallPath = vsInstallDir.absolutePath(); if (vsInstallDir.dirName() != QStringLiteral("VC") && !vsInstallDir.cd(QStringLiteral("VC"))) { @@ -223,9 +307,9 @@ static std::vector<MSVC> installedMSVCs() } msvc.version = QString::number(Internal::VisualStudioVersionInfo( - Version::fromString(registryEntry.version)).marketingVersion()); + Version::fromString(installInfo.version)).marketingVersion()); if (msvc.version.isEmpty()) { - qbsWarning() << Tr::tr("Unknown MSVC version %1 found.").arg(registryEntry.version); + qbsWarning() << Tr::tr("Unknown MSVC version %1 found.").arg(installInfo.version); continue; } diff --git a/src/lib/corelib/language/astpropertiesitemhandler.cpp b/src/lib/corelib/language/astpropertiesitemhandler.cpp index 1b53f2f0b..1ea78bf79 100644 --- a/src/lib/corelib/language/astpropertiesitemhandler.cpp +++ b/src/lib/corelib/language/astpropertiesitemhandler.cpp @@ -135,7 +135,6 @@ private: void doApply(const QString &propertyName, Item *item, JSSourceValuePtr value, const JSSourceValuePtr &conditionalValue) { - QBS_ASSERT(!value || value->file() == conditionalValue->file(), return); if (!value) { value = JSSourceValue::create(true); value->setFile(conditionalValue->file()); diff --git a/src/lib/corelib/tools/persistence.h b/src/lib/corelib/tools/persistence.h index bd18bdf9d..e8d938ad3 100644 --- a/src/lib/corelib/tools/persistence.h +++ b/src/lib/corelib/tools/persistence.h @@ -52,7 +52,6 @@ #include <QtCore/qstring.h> #include <QtCore/qvariant.h> -#include <ctime> #include <memory> #include <type_traits> #include <unordered_map> @@ -371,19 +370,6 @@ template<> struct PPHelper<long> } }; -template<typename T> -struct PPHelper<T, std::enable_if_t<std::is_same<T, std::time_t>::value - && !std::is_same<T, long>::value>> -{ - static void store(std::time_t value, PersistentPool *pool) { pool->m_stream << qint64(value); } - static void load(std::time_t &value, PersistentPool *pool) - { - qint64 v; - pool->m_stream >> v; - value = static_cast<std::time_t>(v); - } -}; - template<typename T> struct PPHelper<T, std::enable_if_t<std::is_enum<T>::value>> { using U = std::underlying_type_t<T>; diff --git a/src/lib/corelib/tools/vsenvironmentdetector.cpp b/src/lib/corelib/tools/vsenvironmentdetector.cpp index 32e6d3497..21ce3406f 100644 --- a/src/lib/corelib/tools/vsenvironmentdetector.cpp +++ b/src/lib/corelib/tools/vsenvironmentdetector.cpp @@ -218,7 +218,7 @@ void VsEnvironmentDetector::writeBatchFile(QIODevice *device, const QString &vcv { const QStringList varnames = QStringList() << StringConstants::pathEnvVar() << QLatin1String("INCLUDE") << QLatin1String("LIB") << QLatin1String("WindowsSdkDir") - << QLatin1String("WindowsSDKVersion"); + << QLatin1String("WindowsSDKVersion") << QLatin1String("VSINSTALLDIR"); QTextStream s(device); s << "@echo off" << endl; for (const MSVC *msvc : msvcs) { diff --git a/src/lib/qtprofilesetup/qtmoduleinfo.cpp b/src/lib/qtprofilesetup/qtmoduleinfo.cpp index 95799632c..56827a458 100644 --- a/src/lib/qtprofilesetup/qtmoduleinfo.cpp +++ b/src/lib/qtprofilesetup/qtmoduleinfo.cpp @@ -280,6 +280,25 @@ static QStringList makeList(const QByteArray &s) return QString::fromLatin1(s).split(QLatin1Char(' '), QString::SkipEmptyParts); } +static QString guessLibraryFilePath(const QString &prlFilePath, const QString &libDir, + const QtEnvironment &qtEnv) +{ + const QString baseName = QFileInfo(prlFilePath).baseName(); + const QStringList prefixCandidates{QString(), QLatin1String("lib")}; + const QStringList suffixCandidates{QLatin1String("so.") + qtEnv.qtVersion, + QLatin1String("so"), QLatin1String("a"), QLatin1String("lib"), + QLatin1String("dll.a")}; + for (const QString &prefix : prefixCandidates) { + for (const QString &suffix : suffixCandidates) { + const QString candidate = libDir + QLatin1Char('/') + prefix + baseName + + QLatin1Char('.') + suffix; + if (QFile::exists(candidate)) + return candidate; + } + } + return QString(); +} + void QtModuleInfo::setupLibraries(const QtEnvironment &qtEnv, bool debugBuild, Internal::Set<QString> *nonExistingPrlFiles) { @@ -337,19 +356,17 @@ void QtModuleInfo::setupLibraries(const QtEnvironment &qtEnv, bool debugBuild, if (isNonStaticQt4OnWindows) prlFilePath.chop(1); // The prl file base name does *not* contain the version number... prlFilePath.append(QLatin1String(".prl")); - if (nonExistingPrlFiles->contains(prlFilePath)) - return; QFile prlFile(prlFilePath); if (!prlFile.open(QIODevice::ReadOnly)) { - // We can't error out here, as some modules in a self-built Qt don't have the expected - // file names. Real-life example: "libQt0Feedback.prl". This is just too stupid - // to work around, so let's ignore it. - if (mustExist) { - qDebug("Skipping prl file '%s', because it cannot be opened (%s).", - qPrintable(prlFilePath), - qPrintable(prlFile.errorString())); + libFilePath = guessLibraryFilePath(prlFilePath, libDir, qtEnv); + if (nonExistingPrlFiles->insert(prlFilePath).second) { + if (mustExist && libFilePath.isEmpty()) { + qDebug("Could not open prl file '%s' for module '%s' (%s), and failed to deduce " + "the library file path. This module will likely not be usable by qbs.", + qPrintable(prlFilePath), qPrintable(name), + qPrintable(prlFile.errorString())); + } } - nonExistingPrlFiles->insert(prlFilePath); return; } const QList<QByteArray> prlLines = prlFile.readAll().split('\n'); @@ -643,6 +660,34 @@ static QList<QByteArray> getPriFileContentsRecursively(const Profile &profile, return lines; } +static QStringList extractPaths(const QByteArray &rhs, const QString &filePath) +{ + QStringList paths; + int startIndex = 0; + for (;;) { + while (startIndex < rhs.size() && rhs.at(startIndex) == ' ') + ++startIndex; + if (startIndex >= rhs.size()) + break; + int endIndex; + if (rhs.at(startIndex) == '"') { + ++startIndex; + endIndex = rhs.indexOf('"', startIndex); + if (endIndex == -1) { + qDebug("Unmatched quote in file '%s'", qPrintable(filePath)); + break; + } + } else { + endIndex = rhs.indexOf(' ', startIndex + 1); + if (endIndex == -1) + endIndex = rhs.size(); + } + paths << QString::fromLocal8Bit(rhs.mid(startIndex, endIndex - startIndex)); + startIndex = endIndex + 1; + } + return paths; +} + QList<QtModuleInfo> allQt5Modules(const Profile &profile, const QtEnvironment &qtEnvironment) { Internal::Set<QString> nonExistingPrlFiles; @@ -705,7 +750,7 @@ QList<QtModuleInfo> allQt5Modules(const Profile &profile, const QtEnvironment &q hasV2 = true; } } else if (key.endsWith(".includes")) { - moduleInfo.includePaths = QString::fromLocal8Bit(value).split(QLatin1Char(' ')); + moduleInfo.includePaths = extractPaths(value, dit.filePath()); for (auto &includePath : moduleInfo.includePaths) { includePath .replace(QLatin1String("$$QT_MODULE_INCLUDE_BASE"), diff --git a/src/lib/qtprofilesetup/templates/core.qbs b/src/lib/qtprofilesetup/templates/core.qbs index fe961f219..7f7329501 100644 --- a/src/lib/qtprofilesetup/templates/core.qbs +++ b/src/lib/qtprofilesetup/templates/core.qbs @@ -115,6 +115,20 @@ Module { } return defines; } + cpp.driverFlags: { + var flags = []; + if (qbs.toolchain.contains("gcc")) { + if (config.contains("sanitize_address")) + flags.push("-fsanitize=address"); + if (config.contains("sanitize_undefined")) + flags.push("-fsanitize=undefined"); + if (config.contains("sanitize_thread")) + flags.push("-fsanitize=thread"); + if (config.contains("sanitize_memory")) + flags.push("-fsanitize=memory"); + } + return flags; + } cpp.includePaths: { var paths = @includes@; paths.push(mkspecPath, generatedHeadersDir); |