aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/qbs-setup-android/android-setup.cpp29
-rw-r--r--src/app/qbs-setup-toolchains/msvcprobe.cpp106
-rw-r--r--src/lib/corelib/language/astpropertiesitemhandler.cpp1
-rw-r--r--src/lib/corelib/tools/persistence.h14
-rw-r--r--src/lib/corelib/tools/vsenvironmentdetector.cpp2
-rw-r--r--src/lib/qtprofilesetup/qtmoduleinfo.cpp67
-rw-r--r--src/lib/qtprofilesetup/templates/core.qbs14
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> &registryEntries = installedMSVCsFromRegistry();
- for (const MSVCRegistryEntry &registryEntry : 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);