Created
August 16, 2018 22:46
-
-
Save thomaslmiller/69c74e9e02c17224a347a314231bbb46 to your computer and use it in GitHub Desktop.
QtTools diff for WindeployQt Arm64 Support
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/shared/winutils/utils.cpp b/src/shared/winutils/utils.cpp | |
index 8f9cc198..a03984b4 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; | |
@@ -889,6 +889,9 @@ bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage | |
determineDebugAndDependentLibs(reinterpret_cast<const IMAGE_NT_HEADERS64 *>(ntHeaders), | |
fileMemory, isMinGW, dependentLibrariesIn, isDebugIn, errorMessage); | |
} | |
+ | |
+ if (machineArchIn) | |
+ *machineArchIn = (unsigned) ntHeaders->FileHeader.Machine; | |
result = true; | |
if (optVerboseLevel > 1) { | |
@@ -958,7 +961,7 @@ QString findD3dCompiler(Platform platform, const QString &qtBinDir, unsigned wor | |
for (const QString &candidate : qAsConst(candidateVersions)) { | |
const QString dll = findInPath(candidate); | |
if (!dll.isEmpty() | |
- && readPeExecutable(dll, &errorMessage, 0, &detectedWordSize, 0) | |
+ && readPeExecutable(dll, &errorMessage, 0, 0, 0, &detectedWordSize, 0) | |
&& detectedWordSize == wordSize) { | |
return dll; | |
} | |
@@ -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..5bfa755d 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