summaryrefslogtreecommitdiffstats
path: root/src/tools/windeployqt/utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/windeployqt/utils.cpp')
-rw-r--r--src/tools/windeployqt/utils.cpp269
1 files changed, 20 insertions, 249 deletions
diff --git a/src/tools/windeployqt/utils.cpp b/src/tools/windeployqt/utils.cpp
index 51411192549..25b4a9788b2 100644
--- a/src/tools/windeployqt/utils.cpp
+++ b/src/tools/windeployqt/utils.cpp
@@ -8,6 +8,7 @@
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
+#include <QtCore/QProcess>
#include <QtCore/QTemporaryFile>
#include <QtCore/QScopedPointer>
#include <QtCore/QScopedArrayPointer>
@@ -17,16 +18,7 @@
# include <QtCore/private/qsystemerror_p.h>
# include <shlwapi.h>
# include <delayimp.h>
-#else // Q_OS_WIN
-# include <sys/wait.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <unistd.h>
-# include <stdlib.h>
-# include <string.h>
-# include <errno.h>
-# include <fcntl.h>
-#endif // !Q_OS_WIN
+#endif // Q_OS_WIN
QT_BEGIN_NAMESPACE
@@ -117,8 +109,6 @@ QStringList findSharedLibraries(const QDir &directory, Platform platform,
return result;
}
-#ifdef Q_OS_WIN
-
// Case-Normalize file name via GetShortPathNameW()/GetLongPathNameW()
QString normalizeFileName(const QString &name)
{
@@ -132,47 +122,6 @@ QString normalizeFileName(const QString &name)
return QDir::fromNativeSeparators(QString::fromWCharArray(result));
}
-// Find a tool binary in the Windows SDK 8
-QString findSdkTool(const QString &tool)
-{
- QStringList paths = QString::fromLocal8Bit(qgetenv("PATH")).split(u';');
- const QByteArray sdkDir = qgetenv("WindowsSdkDir");
- if (!sdkDir.isEmpty())
- paths.prepend(QDir::cleanPath(QString::fromLocal8Bit(sdkDir)) + "/Tools/x64"_L1);
- return QStandardPaths::findExecutable(tool, paths);
-}
-
-// runProcess helper: Create a temporary file for stdout/stderr redirection.
-static HANDLE createInheritableTemporaryFile()
-{
- wchar_t path[MAX_PATH];
- if (!GetTempPath(MAX_PATH, path))
- return INVALID_HANDLE_VALUE;
- wchar_t name[MAX_PATH];
- if (!GetTempFileName(path, L"temp", 0, name)) // Creates file.
- return INVALID_HANDLE_VALUE;
- SECURITY_ATTRIBUTES securityAttributes;
- ZeroMemory(&securityAttributes, sizeof(securityAttributes));
- securityAttributes.nLength = sizeof(securityAttributes);
- securityAttributes.bInheritHandle = TRUE;
- return CreateFile(name, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, &securityAttributes,
- TRUNCATE_EXISTING,
- FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL);
-}
-
-// runProcess helper: Rewind and read out a temporary file for stdout/stderr.
-static inline void readTemporaryProcessFile(HANDLE handle, QByteArray *result)
-{
- if (SetFilePointer(handle, 0, 0, FILE_BEGIN) == 0xFFFFFFFF)
- return;
- char buf[1024];
- DWORD bytesRead;
- while (ReadFile(handle, buf, sizeof(buf), &bytesRead, NULL) && bytesRead)
- result->append(buf, int(bytesRead));
- CloseHandle(handle);
-}
-
static inline void appendToCommandLine(const QString &argument, QString *commandLine)
{
const bool needsQuote = argument.contains(u' ');
@@ -185,8 +134,6 @@ static inline void appendToCommandLine(const QString &argument, QString *command
commandLine->append(u'"');
}
-// runProcess: Run a command line process (replacement for QProcess which
-// does not exist in the bootstrap library).
bool runProcess(const QString &binary, const QStringList &args,
const QString &workingDirectory,
unsigned long *exitCode, QByteArray *stdOut, QByteArray *stdErr,
@@ -195,211 +142,35 @@ bool runProcess(const QString &binary, const QStringList &args,
if (exitCode)
*exitCode = 0;
- STARTUPINFO si;
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
-
- STARTUPINFO myInfo;
- GetStartupInfo(&myInfo);
- si.hStdInput = myInfo.hStdInput;
- si.hStdOutput = myInfo.hStdOutput;
- si.hStdError = myInfo.hStdError;
-
- PROCESS_INFORMATION pi;
- ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
- const QChar backSlash = u'\\';
- QString nativeWorkingDir = QDir::toNativeSeparators(workingDirectory.isEmpty() ? QDir::currentPath() : workingDirectory);
- if (!nativeWorkingDir.endsWith(backSlash))
- nativeWorkingDir += backSlash;
-
- if (stdOut) {
- si.hStdOutput = createInheritableTemporaryFile();
- if (si.hStdOutput == INVALID_HANDLE_VALUE) {
- if (errorMessage)
- *errorMessage = QStringLiteral("Error creating stdout temporary file");
- return false;
- }
- si.dwFlags |= STARTF_USESTDHANDLES;
- }
-
- if (stdErr) {
- si.hStdError = createInheritableTemporaryFile();
- if (si.hStdError == INVALID_HANDLE_VALUE) {
- if (errorMessage)
- *errorMessage = QStringLiteral("Error creating stderr temporary file");
- return false;
- }
- si.dwFlags |= STARTF_USESTDHANDLES;
- }
-
- // Create a copy of the command line which CreateProcessW can modify.
- QString commandLine;
- appendToCommandLine(binary, &commandLine);
- for (const QString &a : args)
- appendToCommandLine(a, &commandLine);
- if (optVerboseLevel > 1)
+ QProcess process;
+ process.setProgram(binary);
+ process.setArguments(args);
+ process.setWorkingDirectory(workingDirectory);
+
+ // Output the command if requested.
+ if (optVerboseLevel > 1) {
+ QString commandLine;
+ appendToCommandLine(binary, &commandLine);
+ for (const QString &a : args)
+ appendToCommandLine(a, &commandLine);
std::wcout << "Running: " << commandLine << '\n';
+ }
- QScopedArrayPointer<wchar_t> commandLineW(new wchar_t[commandLine.size() + 1]);
- commandLine.toWCharArray(commandLineW.data());
- commandLineW[commandLine.size()] = 0;
- if (!CreateProcessW(0, commandLineW.data(), 0, 0, /* InheritHandles */ TRUE, 0, 0,
- reinterpret_cast<LPCWSTR>(nativeWorkingDir.utf16()), &si, &pi)) {
- if (stdOut)
- CloseHandle(si.hStdOutput);
- if (stdErr)
- CloseHandle(si.hStdError);
- if (errorMessage) {
- *errorMessage = QStringLiteral("CreateProcessW failed: ")
- + QSystemError::windowsString();
- }
+ process.start();
+ if (!process.waitForStarted() || !process.waitForFinished()) {
+ if (errorMessage)
+ *errorMessage = process.errorString();
return false;
}
- WaitForSingleObject(pi.hProcess, INFINITE);
- CloseHandle(pi.hThread);
- if (exitCode)
- GetExitCodeProcess(pi.hProcess, exitCode);
- CloseHandle(pi.hProcess);
-
if (stdOut)
- readTemporaryProcessFile(si.hStdOutput, stdOut);
+ *stdOut = process.readAllStandardOutput();
if (stdErr)
- readTemporaryProcessFile(si.hStdError, stdErr);
- return true;
-}
+ *stdErr = process.readAllStandardError();
-#else // Q_OS_WIN
-
-static inline char *encodeFileName(const QString &f)
-{
- const QByteArray encoded = QFile::encodeName(f);
- char *result = new char[encoded.size() + 1];
- strcpy(result, encoded.constData());
- return result;
-}
-
-static inline char *tempFilePattern()
-{
- QString path = QDir::tempPath();
- if (!path.endsWith(u'/'))
- path += u'/';
- path += QStringLiteral("tmpXXXXXX");
- return encodeFileName(path);
-}
-
-static inline QByteArray readOutRedirectFile(int fd)
-{
- enum { bufSize = 256 };
-
- QByteArray result;
- if (!lseek(fd, 0, 0)) {
- char buf[bufSize];
- while (true) {
- const ssize_t rs = read(fd, buf, bufSize);
- if (rs <= 0)
- break;
- result.append(buf, int(rs));
- }
- }
- close(fd);
- return result;
-}
-
-// runProcess: Run a command line process (replacement for QProcess which
-// does not exist in the bootstrap library).
-bool runProcess(const QString &binary, const QStringList &args,
- const QString &workingDirectory,
- unsigned long *exitCode, QByteArray *stdOut, QByteArray *stdErr,
- QString *errorMessage)
-{
- QScopedArrayPointer<char> stdOutFileName;
- QScopedArrayPointer<char> stdErrFileName;
-
- int stdOutFile = 0;
- if (stdOut) {
- stdOutFileName.reset(tempFilePattern());
- stdOutFile = mkstemp(stdOutFileName.data());
- if (stdOutFile < 0) {
- *errorMessage = QStringLiteral("mkstemp() failed: ") + QString::fromLocal8Bit(strerror(errno));
- return false;
- }
- }
-
- int stdErrFile = 0;
- if (stdErr) {
- stdErrFileName.reset(tempFilePattern());
- stdErrFile = mkstemp(stdErrFileName.data());
- if (stdErrFile < 0) {
- *errorMessage = QStringLiteral("mkstemp() failed: ") + QString::fromLocal8Bit(strerror(errno));
- return false;
- }
- }
-
- const pid_t pID = fork();
-
- if (pID < 0) {
- *errorMessage = QStringLiteral("Fork failed: ") + QString::fromLocal8Bit(strerror(errno));
- return false;
- }
-
- if (!pID) { // Child
- if (stdOut) {
- dup2(stdOutFile, STDOUT_FILENO);
- close(stdOutFile);
- }
- if (stdErr) {
- dup2(stdErrFile, STDERR_FILENO);
- close(stdErrFile);
- }
-
- if (!workingDirectory.isEmpty() && !QDir::setCurrent(workingDirectory)) {
- std::wcerr << "Failed to change working directory to " << workingDirectory << ".\n";
- ::_exit(-1);
- }
-
- char **argv = new char *[args.size() + 2]; // Create argv.
- char **ap = argv;
- *ap++ = encodeFileName(binary);
- for (const QString &a : std::as_const(args))
- *ap++ = encodeFileName(a);
- *ap = 0;
-
- execvp(argv[0], argv);
- ::_exit(-1);
- }
-
- int status;
- pid_t waitResult;
-
- do {
- waitResult = waitpid(pID, &status, 0);
- } while (waitResult == -1 && errno == EINTR);
-
- if (stdOut) {
- *stdOut = readOutRedirectFile(stdOutFile);
- unlink(stdOutFileName.data());
- }
- if (stdErr) {
- *stdErr = readOutRedirectFile(stdErrFile);
- unlink(stdErrFileName.data());
- }
-
- if (waitResult < 0) {
- *errorMessage = QStringLiteral("Wait failed: ") + QString::fromLocal8Bit(strerror(errno));
- return false;
- }
- if (!WIFEXITED(status)) {
- *errorMessage = binary + QStringLiteral(" did not exit cleanly.");
- return false;
- }
- if (exitCode)
- *exitCode = WEXITSTATUS(status);
return true;
}
-#endif // !Q_OS_WIN
-
// Find a file in the path using ShellAPI. This can be used to locate DLLs which
// QStandardPaths cannot do.
QString findInPath(const QString &file)