Skip to content

Instantly share code, notes, and snippets.

@thomaslmiller
Created September 18, 2018 21:34
Show Gist options
  • Save thomaslmiller/4d2457918ef8eb86d800a5f864ee64e0 to your computer and use it in GitHub Desktop.
Save thomaslmiller/4d2457918ef8eb86d800a5f864ee64e0 to your computer and use it in GitHub Desktop.
diff --git a/src/shared/winutils/utils.cpp b/src/shared/winutils/utils.cpp
index 8f9cc198..c10ca61b 100644
--- a/src/shared/winutils/utils.cpp
+++ b/src/shared/winutils/utils.cpp
@@ -840,7 +840,7 @@ inline void determineDebugAndDependentLibs(const ImageNtHeader *nth, const void
// and debug flags.
bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage,
QStringList *dependentLibrariesIn, unsigned *wordSizeIn,
- bool *isDebugIn, bool isMinGW)
+ bool *isDebugIn, bool isMinGW, unsigned *machineArchIn)
{
bool result = false;
HANDLE hFile = NULL;
@@ -890,6 +890,9 @@ bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage
fileMemory, isMinGW, dependentLibrariesIn, isDebugIn, errorMessage);
}
+ if (machineArchIn)
+ *machineArchIn = (unsigned) ntHeaders->FileHeader.Machine;
+
result = true;
if (optVerboseLevel > 1) {
std::wcout << __FUNCTION__ << ": " << QDir::toNativeSeparators(peExecutableFileName)
@@ -1032,4 +1035,21 @@ bool patchQtCore(const QString &path, QString *errorMessage)
return true;
}
+QString getArchString (unsigned machineArch)
+{
+ switch (machineArch)
+ {
+ case IMAGE_FILE_MACHINE_I386:
+ return QStringLiteral("x86");
+ case IMAGE_FILE_MACHINE_ARM:
+ return QStringLiteral("arm");
+ case IMAGE_FILE_MACHINE_AMD64:
+ return QStringLiteral("x64");
+ case IMAGE_FILE_MACHINE_ARM64:
+ return QStringLiteral("arm64");
+ default:
+ return QStringLiteral("");
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/shared/winutils/utils.h b/src/shared/winutils/utils.h
index a5e6f01f..d201f733 100644
--- a/src/shared/winutils/utils.h
+++ b/src/shared/winutils/utils.h
@@ -185,21 +185,23 @@ bool runElevatedBackgroundProcess(const QString &binary, const QStringList &args
bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage,
QStringList *dependentLibraries = 0, unsigned *wordSize = 0,
- bool *isDebug = 0, bool isMinGW = false);
+ bool *isDebug = 0, bool isMinGW = false, unsigned *machineArch = 0);
bool readElfExecutable(const QString &elfExecutableFileName, QString *errorMessage,
QStringList *dependentLibraries = 0, unsigned *wordSize = 0,
bool *isDebug = 0);
inline bool readExecutable(const QString &executableFileName, Platform platform,
QString *errorMessage, QStringList *dependentLibraries = 0,
- unsigned *wordSize = 0, bool *isDebug = 0)
+ unsigned *wordSize = 0, bool *isDebug = 0, unsigned *machineArch = 0)
{
return platform == Unix ?
readElfExecutable(executableFileName, errorMessage, dependentLibraries, wordSize, isDebug) :
readPeExecutable(executableFileName, errorMessage, dependentLibraries, wordSize, isDebug,
- (platform == WindowsDesktopMinGW));
+ (platform == WindowsDesktopMinGW), machineArch);
}
+QString getArchString (unsigned machineArch);
+
// Return dependent modules of executable files.
inline QStringList findDependentLibraries(const QString &executableFileName, Platform platform, QString *errorMessage)
diff --git a/src/windeployqt/main.cpp b/src/windeployqt/main.cpp
index efffc5d0..1aa9fc72 100644
--- a/src/windeployqt/main.cpp
+++ b/src/windeployqt/main.cpp
@@ -40,6 +40,7 @@
#include <QtCore/QOperatingSystemVersion>
#include <QtCore/QSharedPointer>
#include <QtCore/QVector>
+#include <QtCore/qt_windows.h>
#include <algorithm>
#include <iostream>
@@ -680,13 +681,13 @@ static inline bool isQtModule(const QString &libName)
// Helper for recursively finding all dependent Qt libraries.
static bool findDependentQtLibraries(const QString &qtBinDir, const QString &binary, Platform platform,
QString *errorMessage, QStringList *result,
- unsigned *wordSize = 0, bool *isDebug = 0,
+ unsigned *wordSize = 0, bool *isDebug = 0, unsigned *machineArch = 0,
int *directDependencyCount = 0, int recursionDepth = 0)
{
QStringList dependentLibs;
if (directDependencyCount)
*directDependencyCount = 0;
- if (!readExecutable(binary, platform, errorMessage, &dependentLibs, wordSize, isDebug)) {
+ if (!readExecutable(binary, platform, errorMessage, &dependentLibs, wordSize, isDebug, machineArch)) {
errorMessage->prepend(QLatin1String("Unable to find dependent libraries of ") +
QDir::toNativeSeparators(binary) + QLatin1String(" :"));
return false;
@@ -706,7 +707,7 @@ static bool findDependentQtLibraries(const QString &qtBinDir, const QString &bin
*directDependencyCount = end - start;
// Recurse
for (int i = start; i < end; ++i)
- if (!findDependentQtLibraries(qtBinDir, result->at(i), platform, errorMessage, result, 0, 0, 0, recursionDepth + 1))
+ if (!findDependentQtLibraries(qtBinDir, result->at(i), platform, errorMessage, result, 0, 0, 0, 0, recursionDepth + 1))
return false;
return true;
}
@@ -1039,8 +1040,9 @@ static QString libraryPath(const QString &libraryLocation, const char *name,
}
static QString vcDebugRedistDir() { return QStringLiteral("Debug_NonRedist"); }
+static QString onecoreRedistDir() { return QStringLiteral("onecore"); }
-static QString vcRedistDir()
+static QString vcRedistDir(unsigned machineArch)
{
const char vcDirVar[] = "VCINSTALLDIR";
const QChar slash(QLatin1Char('/'));
@@ -1067,7 +1069,9 @@ static QString vcRedistDir()
const bool isWindows10 = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
for (const QFileInfo &f : subDirs) {
QString path = f.absoluteFilePath();
- if (QFileInfo(path + slash + vcDebugRedistDir()).isDir())
+ // Make sure we have the binaries for this architecture, since they may be missing for arm64.
+ // Fall back to the onecore directory if so.
+ if (QFileInfo(path + slash + vcDebugRedistDir() + slash + getArchString(machineArch)).isDir())
return path;
if (isWindows10) {
path += QStringLiteral("/onecore");
@@ -1080,7 +1084,7 @@ static QString vcRedistDir()
return QString();
}
-static QStringList compilerRunTimeLibs(Platform platform, bool isDebug, unsigned wordSize)
+static QStringList compilerRunTimeLibs(Platform platform, bool isDebug, unsigned machineArch)
{
QStringList result;
switch (platform) {
@@ -1103,15 +1107,15 @@ static QStringList compilerRunTimeLibs(Platform platform, bool isDebug, unsigned
}
break;
case WindowsDesktop: { // MSVC/Desktop: Add redistributable packages.
- QString vcRedistDirName = vcRedistDir();
+ QString vcRedistDirName = vcRedistDir(machineArch);
if (vcRedistDirName.isEmpty())
break;
QStringList redistFiles;
QDir vcRedistDir(vcRedistDirName);
- const QString wordSizeString(QLatin1String(wordSize > 32 ? "x64" : "x86"));
+ const QString machineArchString = getArchString(machineArch);
if (isDebug) {
// Append DLLs from Debug_NonRedist\x??\Microsoft.VC<version>.DebugCRT.
- if (vcRedistDir.cd(vcDebugRedistDir()) && vcRedistDir.cd(wordSizeString)) {
+ if (vcRedistDir.cd(vcDebugRedistDir()) && vcRedistDir.cd(machineArchString)) {
const QStringList names = vcRedistDir.entryList(QStringList(QStringLiteral("Microsoft.VC*.DebugCRT")), QDir::Dirs);
if (!names.isEmpty() && vcRedistDir.cd(names.first())) {
const QFileInfoList &dlls = vcRedistDir.entryInfoList(QStringList(QLatin1String("*.dll")));
@@ -1125,13 +1129,22 @@ static QStringList compilerRunTimeLibs(Platform platform, bool isDebug, unsigned
if (!countryCodes.isEmpty()) // Pre MSVC2017
releaseRedistDir += QLatin1Char('/') + countryCodes.constFirst();
QFileInfo fi(releaseRedistDir + QLatin1Char('/') + QStringLiteral("vc_redist.")
- + wordSizeString + QStringLiteral(".exe"));
+ + machineArchString + QStringLiteral(".exe"));
if (!fi.isFile()) { // Pre MSVC2017/15.5
fi.setFile(releaseRedistDir + QLatin1Char('/') + QStringLiteral("vcredist_")
- + wordSizeString + QStringLiteral(".exe"));
+ + machineArchString + QStringLiteral(".exe"));
}
if (fi.isFile())
redistFiles.append(fi.absoluteFilePath());
+ else if (machineArch == IMAGE_FILE_MACHINE_ARM64 && vcRedistDir.cd(machineArchString)) {
+ // Fallback to onecore binaries on arm64 until VS adds the MSI-based installer for arm64.
+ const QStringList names = vcRedistDir.entryList(QStringList(QStringLiteral("Microsoft.VC*.CRT")), QDir::Dirs);
+ if (!names.isEmpty() && vcRedistDir.cd(names.first())) {
+ const QFileInfoList &dlls = vcRedistDir.entryInfoList(QStringList(QLatin1String("*.dll")));
+ for (const QFileInfo &dll : dlls)
+ redistFiles.append(dll.absoluteFilePath());
+ }
+ }
}
if (redistFiles.isEmpty()) {
std::wcerr << "Warning: Cannot find Visual Studio " << (isDebug ? "debug" : "release")
@@ -1219,14 +1232,15 @@ static DeployResult deploy(const Options &options,
QStringList dependentQtLibs;
bool detectedDebug;
unsigned wordSize;
+ unsigned machineArch;
int directDependencyCount = 0;
if (!findDependentQtLibraries(libraryLocation, options.binaries.first(), options.platform, errorMessage, &dependentQtLibs, &wordSize,
- &detectedDebug, &directDependencyCount)) {
+ &detectedDebug, &machineArch, &directDependencyCount)) {
return result;
}
for (int b = 1; b < options.binaries.size(); ++b) {
if (!findDependentQtLibraries(libraryLocation, options.binaries.at(b), options.platform, errorMessage, &dependentQtLibs,
- nullptr, nullptr, nullptr)) {
+ Q_NULLPTR, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR)) {
return result;
}
}
@@ -1316,7 +1330,7 @@ static DeployResult deploy(const Options &options,
qmlScanResult.append(scanResult);
// Additional dependencies of QML plugins.
for (const QString &plugin : qAsConst(qmlScanResult.plugins)) {
- if (!findDependentQtLibraries(libraryLocation, plugin, options.platform, errorMessage, &dependentQtLibs, &wordSize, &detectedDebug))
+ if (!findDependentQtLibraries(libraryLocation, plugin, options.platform, errorMessage, &dependentQtLibs, &wordSize, &detectedDebug, &machineArch))
return result;
}
if (optVerboseLevel >= 1) {
@@ -1410,7 +1424,8 @@ static DeployResult deploy(const Options &options,
deployedQtLibraries.append(libEglFullPath);
}
// Find the system D3d Compiler matching the D3D library.
- if (options.systemD3dCompiler && !options.isWinRt()) {
+ // Any arm64 OS will be new enough to be shipped with the D3DCompiler inbox.
+ if (options.systemD3dCompiler && !options.isWinRt() && machineArch != IMAGE_FILE_MACHINE_ARM64) {
const QString d3dCompiler = findD3dCompiler(options.platform, qtBinDir, wordSize);
if (d3dCompiler.isEmpty()) {
std::wcerr << "Warning: Cannot find any version of the d3dcompiler DLL.\n";
@@ -1459,7 +1474,7 @@ static DeployResult deploy(const Options &options,
options.directory : options.libraryDirectory;
QStringList libraries = deployedQtLibraries;
if (options.compilerRunTime)
- libraries.append(compilerRunTimeLibs(options.platform, isDebug, wordSize));
+ libraries.append(compilerRunTimeLibs(options.platform, isDebug, machineArch));
for (const QString &qtLib : qAsConst(libraries)) {
if (!updateLibrary(qtLib, targetPath, options, errorMessage))
return result;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment