CQtDeployer/Deploy/windependenciesscanner.cpp

189 lines
5.9 KiB
C++
Raw Normal View History

2019-01-26 07:54:56 +03:00
/*
* Copyright (C) 2018-2019 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
2018-11-15 18:00:23 +03:00
#include "windependenciesscanner.h"
2018-12-09 17:35:07 +03:00
#include "deployutils.h"
2018-11-15 18:00:23 +03:00
#include <QList>
2018-11-18 17:22:05 +03:00
#include <QDir>
2018-11-26 16:17:46 +03:00
#include <QDebug>
2018-11-15 18:00:23 +03:00
2018-12-09 17:35:07 +03:00
struct Options {
enum DebugDetection {
DebugDetectionAuto,
DebugDetectionForceDebug,
DebugDetectionForceRelease
};
enum AngleDetection {
AngleDetectionAuto,
AngleDetectionForceOn,
AngleDetectionForceOff
};
bool plugins = true;
bool libraries = true;
bool quickImports = true;
bool translations = true;
bool systemD3dCompiler = true;
bool compilerRunTime = false;
AngleDetection angleDetection = AngleDetectionAuto;
bool softwareRasterizer = true;
Platform platform = Windows;
quint64 additionalLibraries = 0;
quint64 disabledLibraries = 0;
unsigned updateFileFlags = 0;
QStringList qmlDirectories; // Project's QML files.
QString directory;
QString translationsDirectory; // Translations target directory
QString libraryDirectory;
QString pluginDirectory;
QStringList binaries;
JsonOutput *json = nullptr;
ListOption list = ListNone;
DebugDetection debugDetection = DebugDetectionAuto;
bool deployPdb = false;
bool dryRun = false;
bool patchQt = true;
inline bool isWinRt() const {
return platform == WinRtArm || platform == WinRtIntel;
}
};
2018-11-15 18:00:23 +03:00
WinDependenciesScanner::WinDependenciesScanner() {}
2018-12-09 17:35:07 +03:00
QMap<QString, QString> WinDependenciesScanner::qMakeAll(QString *errorMessage, const QString& binary)
{
QByteArray stdOut;
QByteArray stdErr;
unsigned long exitCode = 0;
if (!runProcess(binary, QStringList(QStringLiteral("-query")), QString(), &exitCode, &stdOut, &stdErr, errorMessage))
return QMap<QString, QString>();
if (exitCode) {
*errorMessage = binary + QStringLiteral(" returns ") + QString::number(exitCode)
+ QStringLiteral(": ") + QString::fromLocal8Bit(stdErr);
return QMap<QString, QString>();
}
const QString output = QString::fromLocal8Bit(stdOut).trimmed().remove(QLatin1Char('\r'));
QMap<QString, QString> result;
const int size = output.size();
for (int pos = 0; pos < size; ) {
const int colonPos = output.indexOf(QLatin1Char(':'), pos);
if (colonPos < 0)
break;
int endPos = output.indexOf(QLatin1Char('\n'), colonPos + 1);
if (endPos < 0)
endPos = size;
const QString key = output.mid(pos, colonPos - pos);
const QString value = output.mid(colonPos + 1, endPos - colonPos - 1);
result.insert(key, value);
pos = endPos + 1;
}
QFile qconfigPriFile(result.value(QStringLiteral("QT_HOST_DATA")) + QStringLiteral("/mkspecs/qconfig.pri"));
if (qconfigPriFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
while (true) {
const QByteArray line = qconfigPriFile.readLine();
if (line.isEmpty())
break;
if (line.startsWith("QT_LIBINFIX")) {
const int pos = line.indexOf('=');
if (pos >= 0) {
const QString infix = QString::fromUtf8(line.right(line.size() - pos - 1).trimmed());
if (!infix.isEmpty())
result.insert(QLatin1String(qmakeInfixKey), infix);
}
break;
}
}
} else {
std::wcerr << "Warning: Unable to read " << QDir::toNativeSeparators(qconfigPriFile.fileName())
<< ": " << qconfigPriFile.errorString()<< '\n';
}
return result;
}
2018-11-23 14:56:55 +03:00
void WinDependenciesScanner::setEnvironment(const QStringList &env) {
2018-11-18 17:22:05 +03:00
QDir dir;
2018-11-23 14:56:55 +03:00
for (auto i : env) {
2018-12-09 17:35:07 +03:00
2018-11-18 17:22:05 +03:00
dir.setPath(i);
if (!dir.exists()) {
continue;
}
2018-11-23 14:56:55 +03:00
auto list = dir.entryInfoList(QStringList() << "*.dll",
2018-11-18 17:22:05 +03:00
QDir::Files| QDir::NoDotAndDotDot);
2018-11-23 14:56:55 +03:00
for (auto i : list) {
2018-12-09 17:35:07 +03:00
auto newPriority = DeployUtils::getLibPriority(i.absoluteFilePath());
auto oldPriority = DeployUtils::getLibPriority(_EnvLibs.value(i.fileName(), ""));
if (newPriority > oldPriority)
_EnvLibs.insert(i.fileName(), i.absoluteFilePath());
2018-11-23 14:56:55 +03:00
}
2018-11-18 17:22:05 +03:00
}
}
2018-11-26 16:17:46 +03:00
Platform WinDependenciesScanner::platformFromMkSpec(const QString &xSpec)
{
if (xSpec == QLatin1String("linux-g++"))
return Unix;
if (xSpec.startsWith(QLatin1String("win32-")))
return xSpec.contains(QLatin1String("g++")) ? WindowsMinGW : Windows;
if (xSpec.startsWith(QLatin1String("winrt-x")))
return WinRtIntel;
if (xSpec.startsWith(QLatin1String("winrt-arm")))
return WinRtArm;
if (xSpec.startsWith(QLatin1String("wince"))) {
if (xSpec.contains(QLatin1String("-x86-")))
return WinCEIntel;
if (xSpec.contains(QLatin1String("-arm")))
return WinCEArm;
}
return UnknownPlatform;
}
2018-12-09 17:35:07 +03:00
QStringList WinDependenciesScanner::scan(const QString &path, Platform platfr,
const QString& qmake) {
2018-11-18 17:22:05 +03:00
QStringList result;
2018-11-26 16:17:46 +03:00
QString errorMessage;
if (platfr == Platform::UnknownPlatform) {
2018-12-09 17:35:07 +03:00
const auto qmakeVariables = qMakeAll(&errorMessage, qmake);
const QString xSpec = qmakeVariables.value(QStringLiteral("QMAKE_XSPEC"));
platfr = platformFromMkSpec(xSpec);
}
2018-11-26 16:17:46 +03:00
QStringList dep;
2018-11-26 21:53:44 +03:00
readExecutable(path, platfr, &errorMessage, &dep);
2018-11-26 16:17:46 +03:00
if (!errorMessage.isEmpty()) {
qCritical() << errorMessage;
return result;
}
2018-11-18 17:22:05 +03:00
2018-11-23 14:56:55 +03:00
for (auto i : dep) {
QString lib(i);
if (_EnvLibs.count(lib)) {
result.push_back(_EnvLibs.value(lib));
}
}
2018-11-18 17:22:05 +03:00
return result;
2018-11-15 18:00:23 +03:00
}
2018-11-23 14:56:55 +03:00
WinDependenciesScanner::~WinDependenciesScanner() {
}