summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2013-12-03 18:23:31 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-12-04 13:12:41 +0100
commitab3e8e80fbd81a38039c713189b0422972e0963e (patch)
tree3b9c6ae690ab9396f71c2f8dd9a43c67efa835d1
parent68a98516d01a93ca5e831a6ec2bdf6a7fc1b2254 (diff)
Completely bootstrap idc.
idc dynamically loads libraries depending on QtCore.dll whose static instances can then cause clashes. Task-number: QTBUG-35275 Change-Id: Icd219a2bb36b0a5c3927c3163e93dc07bb5317aa Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
-rw-r--r--src/tools/idc/idc.pro4
-rw-r--r--src/tools/idc/main.cpp99
2 files changed, 76 insertions, 27 deletions
diff --git a/src/tools/idc/idc.pro b/src/tools/idc/idc.pro
index b9d8dee..1898ed5 100644
--- a/src/tools/idc/idc.pro
+++ b/src/tools/idc/idc.pro
@@ -1,7 +1,5 @@
option(host_build)
-
-QT = core
-
+CONFIG += force_bootstrap
SOURCES = main.cpp
load(qt_tool)
diff --git a/src/tools/idc/main.cpp b/src/tools/idc/main.cpp
index a28d56c..987d829 100644
--- a/src/tools/idc/main.cpp
+++ b/src/tools/idc/main.cpp
@@ -41,8 +41,8 @@
#include <QDir>
#include <QFile>
-#include <QProcess>
-#include <QLibraryInfo>
+#include <QDir>
+#include <QScopedArrayPointer>
#include <qt_windows.h>
#include <io.h>
@@ -70,33 +70,84 @@ static bool hasDllExtension(const QString &filePath)
return hasFileExtension(filePath, QStringLiteral(".dll"));
}
+// Prepend the Qt binary directory to PATH.
+static bool prependPath()
+{
+ enum { maxEnvironmentSize = 32767 };
+ wchar_t buffer[maxEnvironmentSize];
+ if (!GetModuleFileName(NULL, buffer, maxEnvironmentSize))
+ return false;
+ wchar_t *ptr = wcsrchr(buffer, L'\\');
+ if (!ptr)
+ return false;
+ *ptr++ = L';';
+ const wchar_t pathVariable[] = L"PATH";
+ if (!GetEnvironmentVariable(pathVariable, ptr, maxEnvironmentSize - (ptr - buffer))
+ || !SetEnvironmentVariable(pathVariable, buffer)) {
+ return false;
+ }
+ return true;
+}
+
+static QString errorString(DWORD errorCode)
+{
+ wchar_t *resultW = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&resultW, 0, NULL);
+ const QString result = QString::fromWCharArray(resultW);
+ LocalFree((HLOCAL)resultW);
+ return result;
+}
+
static bool runWithQtInEnvironment(const QString &cmd)
{
- QProcess proc;
+ enum { timeOutMs = 30000 };
+ static const bool pathSet = prependPath();
+ if (!pathSet)
+ return false;
- // prepend the qt binary directory to the path
- QStringList env = QProcess::systemEnvironment();
- for (int i=0; i<env.count(); ++i) {
- QString var = env.at(i);
- int setidx = var.indexOf(QLatin1Char('='));
- if (setidx != -1) {
- QString varname = var.left(setidx).trimmed().toUpper();
- if (varname == QLatin1String("PATH")) {
- var = var.mid(setidx + 1);
- var = QLatin1String("PATH=") +
- QLibraryInfo::location(QLibraryInfo::BinariesPath) +
- QLatin1Char(';') + var;
- env[i] = var;
- break;
- }
- }
- }
+ STARTUPINFO si;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
- proc.setEnvironment(env);
- proc.start(cmd);
- proc.waitForFinished(-1);
+ STARTUPINFO myInfo;
+ GetStartupInfo(&myInfo);
+ si.hStdInput = myInfo.hStdInput;
+ si.hStdOutput = myInfo.hStdOutput;
+ si.hStdError = myInfo.hStdError;
- return (proc.exitCode() == 0);
+ PROCESS_INFORMATION pi;
+ ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+
+ QScopedArrayPointer<wchar_t> commandLineW(new wchar_t[cmd.size() + 1]);
+ cmd.toWCharArray(commandLineW.data());
+ commandLineW[cmd.size()] = 0;
+ if (!CreateProcessW(0, commandLineW.data(), 0, 0, /* InheritHandles */ TRUE, 0, 0, 0, &si, &pi)) {
+ fprintf(stderr, "Unable to execute \"%s\": %s\n", qPrintable(cmd),
+ qPrintable(errorString(GetLastError())));
+ return false;
+ }
+
+ DWORD exitCode = 1;
+ switch (WaitForSingleObject(pi.hProcess, timeOutMs)) {
+ case WAIT_OBJECT_0:
+ GetExitCodeProcess(pi.hProcess, &exitCode);
+ break;
+ case WAIT_TIMEOUT:
+ fprintf(stderr, "Timed out after %d ms out waiting for \"%s\".\n",
+ int(timeOutMs), qPrintable(cmd));
+ TerminateProcess(pi.hProcess, 1);
+ break;
+ default:
+ fprintf(stderr, "Error waiting for \"%s\": %s\n",
+ qPrintable(cmd), qPrintable(errorString(GetLastError())));
+ TerminateProcess(pi.hProcess, 1);
+ break;
+ }
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ return exitCode == 0;
}
static bool attachTypeLibrary(const QString &applicationName, int resource, const QByteArray &data, QString *errorMessage)