summaryrefslogtreecommitdiffstats
path: root/qmake
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-12-18 08:37:31 +0100
committerLiang Qi <liang.qi@theqtcompany.com>2015-12-18 08:37:31 +0100
commitbeb65dcd79f8c354dab7bb4a8d08157bd9d69329 (patch)
tree4632a0ff0df8462f8913f347042cf8378de03268 /qmake
parent3fc1002489d5861d4f7cc2e1e8800881d6593c9d (diff)
parente3288f246b44ba2b6d90b90eb99ab61f496d8d57 (diff)
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts: src/gui/painting/painting.pri src/plugins/platforms/xcb/qxcbconnection.cpp tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro tests/auto/corelib/tools/qlocale/test/test.pro tests/auto/gui/kernel/qwindow/tst_qwindow.cpp tools/configure/environment.cpp Change-Id: I9c40f458b89b2c206de2d2c24e90b5f679c93495
Diffstat (limited to 'qmake')
-rw-r--r--qmake/doc/src/qmake-manual.qdoc1
-rw-r--r--qmake/generators/makefiledeps.cpp441
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp22
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp19
4 files changed, 316 insertions, 167 deletions
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index ff7b7fe1da..89ce3b3504 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -2408,7 +2408,6 @@
\row \li .file \li Specify the subproject \c pro file explicitly. Cannot be
used in conjunction with \c .subdir modifier.
\row \li .depends \li This subproject depends on specified subproject.
- Available only on platforms that use makefiles.
\row \li .makefile \li The makefile of subproject.
Available only on platforms that use makefiles.
\row \li .target \li Base string used for makefile targets related to this
diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp
index 0f11745f4c..047d17f18a 100644
--- a/qmake/generators/makefiledeps.cpp
+++ b/qmake/generators/makefiledeps.cpp
@@ -388,6 +388,121 @@ QFileInfo QMakeSourceFileInfo::findFileInfo(const QMakeLocalFileName &dep)
return QFileInfo(dep.real());
}
+static int skipEscapedLineEnds(const char *buffer, int buffer_len, int offset, int *lines)
+{
+ // Join physical lines to make logical lines, as in the C preprocessor
+ while (offset + 1 < buffer_len
+ && buffer[offset] == '\\'
+ && qmake_endOfLine(buffer[offset + 1])) {
+ offset += 2;
+ ++*lines;
+ if (offset < buffer_len
+ && buffer[offset - 1] == '\r'
+ && buffer[offset] == '\n') // CRLF
+ offset++;
+ }
+ return offset;
+}
+
+static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start,
+ const char *needle, int needle_len,
+ int *matchlen, int *lines)
+{
+ int x = start;
+ for (int n = 0; n < needle_len && x < buffer_len;
+ n++, x = skipEscapedLineEnds(buffer, buffer_len, x + 1, lines)) {
+ if (buffer[x] != needle[n])
+ return false;
+ }
+ // That also skipped any remaining BSNLs immediately after the match.
+
+ // Tell caller how long the match was:
+ *matchlen = x - start;
+
+ return true;
+}
+
+/* Advance from an opening quote at buffer[offset] to the matching close quote. */
+static int scanPastString(char *buffer, int buffer_len, int offset, int *lines)
+{
+ // It might be a C++11 raw string.
+ bool israw = false;
+ if (buffer[offset] == '"' && offset > 0) {
+ int explore = offset - 1;
+ while (explore > 0 && buffer[explore] != 'R') {
+ if (buffer[explore] == '8' || buffer[explore] == 'u' || buffer[explore] == 'U') {
+ explore--;
+ } else if (explore > 1 && qmake_endOfLine(buffer[explore])
+ && buffer[explore - 1] == '\\') {
+ explore -= 2;
+ } else if (explore > 2 && buffer[explore] == '\n'
+ && buffer[explore - 1] == '\r'
+ && buffer[explore - 2] == '\\') {
+ explore -= 3;
+ } else {
+ break;
+ }
+ }
+ israw = (buffer[explore] == 'R');
+ }
+
+ if (israw) {
+#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), lines)
+
+ offset = SKIP_BSNL(offset + 1);
+ const char *const delim = buffer + offset;
+ int clean = offset;
+ while (offset < buffer_len && buffer[offset] != '(') {
+ if (clean < offset)
+ buffer[clean++] = buffer[offset];
+ else
+ clean++;
+
+ offset = SKIP_BSNL(offset + 1);
+ }
+ /*
+ Not checking correctness (trust real compiler to do that):
+ - no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim;
+ - at most 16 bytes in delim
+
+ Raw strings are surely defined after phase 2, when BSNLs are resolved;
+ so the delimiter's exclusion of '\\' and space (including newlines)
+ applies too late to save us the need to cope with BSNLs in it.
+ */
+
+ const int delimlen = buffer + clean - delim;
+ int matchlen = delimlen, extralines = 0;
+ while ((offset = SKIP_BSNL(offset + 1)) < buffer_len
+ && (buffer[offset] != ')'
+ || (delimlen > 0 &&
+ !matchWhileUnsplitting(buffer, buffer_len,
+ offset + 1, delim, delimlen,
+ &matchlen, &extralines))
+ || buffer[offset + 1 + matchlen] != '"')) {
+ // skip, but keep track of lines
+ if (qmake_endOfLine(buffer[offset]))
+ ++*lines;
+ extralines = 0;
+ }
+ *lines += extralines; // from the match
+ // buffer[offset] is ')'
+ offset += 1 + matchlen; // 1 for ')', then delim
+ // buffer[offset] is '"'
+
+#undef SKIP_BSNL
+ } else { // Traditional string or char literal:
+ const char term = buffer[offset];
+ while (++offset < buffer_len && buffer[offset] != term) {
+ if (buffer[offset] == '\\')
+ ++offset;
+ else if (qmake_endOfLine(buffer[offset]))
+ ++*lines;
+ }
+ }
+
+ return offset;
+}
+
bool QMakeSourceFileInfo::findDeps(SourceFile *file)
{
if(file->dep_checked || file->type == TYPE_UNKNOWN)
@@ -426,6 +541,18 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
file->deps = new SourceDependChildren;
int line_count = 1;
+ enum {
+ /*
+ States of C preprocessing (for TYPE_C only), after backslash-newline
+ elimination and skipping comments and spaces (i.e. in ANSI X3.159-1989
+ section 2.1.1.2's phase 4). We're about to study buffer[x] to decide
+ on which transition to do.
+ */
+ AtStart, // start of logical line; a # may start a preprocessor directive
+ HadHash, // saw a # at start, looking for preprocessor keyword
+ WantName, // saw #include or #import, waiting for name
+ InCode // after directive, parsing non-#include directive or in actual code
+ } cpp_state = AtStart;
for(int x = 0; x < buffer_len; ++x) {
bool try_local = true;
@@ -505,118 +632,164 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
++line_count;
} else if(file->type == QMakeSourceFileInfo::TYPE_QRC) {
} else if(file->type == QMakeSourceFileInfo::TYPE_C) {
- for(int beginning=1; x < buffer_len; ++x) {
+ // We've studied all buffer[i] for i < x
+ for (; x < buffer_len; ++x) {
+ // How to handle backslash-newline (BSNL) pairs:
+#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
+
// Seek code or directive, skipping comments and space:
for(; x < buffer_len; ++x) {
+ x = SKIP_BSNL(x);
if (buffer[x] == ' ' || buffer[x] == '\t') {
// keep going
- } else if (buffer[x] == '/' && x + 1 < buffer_len &&
- (buffer[x + 1] == '/' || buffer[x + 1] == '*')) {
- ++x;
- if (buffer[x] == '/') { // C++-style comment
- for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
- beginning = 1;
- } else { // C-style comment
+ } else if (buffer[x] == '/') {
+ int extralines = 0;
+ int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
+ if (buffer[y] == '/') { // C++-style comment
+ line_count += extralines;
+ x = SKIP_BSNL(y + 1);
+ while (x < buffer_len && !qmake_endOfLine(buffer[x]))
+ x = SKIP_BSNL(x + 1); // skip
+
+ cpp_state = AtStart;
+ ++line_count;
+ } else if (buffer[y] == '*') { // C-style comment
+ line_count += extralines;
+ x = y;
while (++x < buffer_len) {
+ x = SKIP_BSNL(x);
if (buffer[x] == '*') {
- if (x + 1 < buffer_len && buffer[x + 1] == '/') {
- ++x; // skip '*'; for loop skips '/'.
+ extralines = 0;
+ y = skipEscapedLineEnds(buffer, buffer_len,
+ x + 1, &extralines);
+ if (y < buffer_len && buffer[y] == '/') {
+ line_count += extralines;
+ x = y; // for loop shall step past this
break;
}
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
}
}
+ } else {
+ // buffer[x] is the division operator
+ break;
}
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
- beginning = 1;
+ cpp_state = AtStart;
} else {
+ /* Drop out of phases 1, 2, 3, into phase 4 */
break;
}
}
+ // Phase 4 study of buffer[x]:
if(x >= buffer_len)
break;
- // preprocessor directive
- if (beginning && buffer[x] == '#') {
- // Advance to start of preprocessing directive
- while (++x < buffer_len
- && (buffer[x] == ' ' || buffer[x] == '\t')) {} // skip
-
- if (qmake_endOfLine(buffer[x])) {
- ++line_count;
- beginning = 1;
- continue;
+ switch (cpp_state) {
+ case HadHash:
+ {
+ // Read keyword; buffer[x] starts first preprocessing token after #
+ const char *const keyword = buffer + x;
+ int clean = x;
+ while (x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z') {
+ // skip over keyword, consolidating it if it contains BSNLs
+ // (see WantName's similar code consolidating inc, below)
+ if (clean < x)
+ buffer[clean++] = buffer[x];
+ else
+ clean++;
+
+ x = SKIP_BSNL(x + 1);
}
+ const int keyword_len = buffer + clean - keyword;
+ x--; // Still need to study buffer[x] next time round for loop.
+
+ cpp_state =
+ ((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
+ || (keyword_len == 6 && !strncmp(keyword, "import", 6))) // Obj-C
+ ? WantName : InCode;
break;
}
- // quoted strings
- if (buffer[x] == '\'' || buffer[x] == '"') {
- const char term = buffer[x];
- while (++x < buffer_len) {
- if (buffer[x] == term) {
- ++x;
- break;
- } else if (buffer[x] == '\\') {
- ++x;
- } else if (qmake_endOfLine(buffer[x])) {
+ case WantName:
+ {
+ char term = buffer[x];
+ if (term == '<') {
+ try_local = false;
+ term = '>';
+ } else if (term != '"') {
+ /*
+ Possibly malformed, but this may be something like:
+ #include IDENTIFIER
+ which does work, if #define IDENTIFIER "filename" is
+ in effect. This is beyond this noddy preprocessor's
+ powers of tracking. So give up and resume searching
+ for a directive. We haven't made sense of buffer[x],
+ so back up to ensure we do study it (now as code) next
+ time round the loop.
+ */
+ x--;
+ cpp_state = InCode;
+ continue;
+ }
+
+ x = SKIP_BSNL(x + 1);
+ inc = buffer + x;
+ int clean = x; // offset if we need to clear \-newlines
+ for (; x < buffer_len && buffer[x] != term; x = SKIP_BSNL(x + 1)) {
+ if (qmake_endOfLine(buffer[x])) { // malformed
+ cpp_state = AtStart;
++line_count;
+ break;
}
+
+ /*
+ If we do skip any BSNLs, we need to consolidate the
+ surviving text by copying to lower indices. For that
+ to be possible, we also have to keep 'clean' advanced
+ in step with x even when we've yet to see any BSNLs.
+ */
+ if (clean < x)
+ buffer[clean++] = buffer[x];
+ else
+ clean++;
}
- }
- beginning = 0;
- }
- if(x >= buffer_len)
- break;
+ if (cpp_state == WantName)
+ buffer[clean] = '\0';
+ else // i.e. malformed
+ inc = 0;
- // Got a preprocessor directive
- const char *const keyword = buffer + x;
- for (;
- x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z';
- x++) {} // skip over identifier
- int keyword_len = buffer + x - keyword;
- for (;
- x < buffer_len && (buffer[x] == ' ' || buffer[x] == '\t');
- x++) {} // skip spaces after keyword
-
- /* Keyword with nothing after it, e.g. #endif: not interesting. */
- if (qmake_endOfLine(buffer[x]))
- keyword_len = 0;
-
- if((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
- || (keyword_len == 6 && !strncmp(keyword, "import", 6))) { // Obj-C
- char term = buffer[x];
- if(term == '<') {
- try_local = false;
- term = '>';
- } else if(term != '"') { //wtf?
- continue;
+ cpp_state = InCode; // hereafter
+ break;
}
- x++;
- inc = buffer + x;
- for (;
- buffer[x] != term && !qmake_endOfLine(buffer[x]);
- ++x) {} // skip until end of include name
- buffer[x] = '\0';
- } else if (buffer[x] == '\'' || buffer[x] == '"') {
- const char term = buffer[x++];
- while(x < buffer_len) {
- if (buffer[x] == term)
+
+ case AtStart:
+ // Preprocessor directive?
+ if (buffer[x] == '#') {
+ cpp_state = HadHash;
break;
- if (buffer[x] == '\\') {
- x+=2;
- } else {
- if (qmake_endOfLine(buffer[x]))
- ++line_count;
- ++x;
}
+ cpp_state = InCode;
+ // ... and fall through to handle buffer[x] as such.
+ case InCode:
+ // matching quotes (string literals and character literals)
+ if (buffer[x] == '\'' || buffer[x] == '"') {
+ x = scanPastString(buffer, buffer_len, x, &line_count);
+ // for loop's ++x shall step over the closing quote.
+ }
+ // else: buffer[x] is just some code; move on.
+ break;
}
- } else {
- --x;
+
+ if (inc) // We were in WantName and found a name.
+ break;
+#undef SKIP_BSNL
}
+ if(x >= buffer_len)
+ break;
}
if(inc) {
@@ -699,7 +872,7 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
files_changed = true;
file->moc_checked = true;
- int buffer_len;
+ int buffer_len = 0;
char *buffer = 0;
{
struct stat fst;
@@ -717,42 +890,56 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
return false; //shouldn't happen
}
buffer = getBuffer(fst.st_size);
- for(int have_read = buffer_len = 0;
- (have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len));
- buffer_len += have_read) ;
+ while (int have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len))
+ buffer_len += have_read;
+
QT_CLOSE(fd);
}
debug_msg(2, "findMocs: %s", file->file.local().toLatin1().constData());
int line_count = 1;
- bool ignore_qobject = false, ignore_qgadget = false;
+ bool ignore[2] = { false, false }; // [0] for Q_OBJECT, [1] for Q_GADGET
/* qmake ignore Q_GADGET */
/* qmake ignore Q_OBJECT */
for(int x = 0; x < buffer_len; x++) {
+#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
+ x = SKIP_BSNL(x);
if (buffer[x] == '/') {
- ++x;
- if(buffer_len >= x) {
- if (buffer[x] == '/') { // C++-style comment
- for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
- } else if (buffer[x] == '*') { // C-style comment
- for(++x; x < buffer_len; ++x) {
+ int extralines = 0;
+ int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
+ if (buffer_len > y) {
+ // If comment, advance to the character that ends it:
+ if (buffer[y] == '/') { // C++-style comment
+ line_count += extralines;
+ x = y;
+ do {
+ x = SKIP_BSNL(x + 1);
+ } while (x < buffer_len && !qmake_endOfLine(buffer[x]));
+
+ } else if (buffer[y] == '*') { // C-style comment
+ line_count += extralines;
+ x = SKIP_BSNL(y + 1);
+ for (; x < buffer_len; x = SKIP_BSNL(x + 1)) {
if (buffer[x] == 't' || buffer[x] == 'q') { // ignore
if(buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
file->file.real().toLatin1().constData(), line_count);
x += 20;
- ignore_qobject = true;
+ ignore[0] = true;
} else if(buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_GADGET", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_GADGET\"",
file->file.real().toLatin1().constData(), line_count);
x += 20;
- ignore_qgadget = true;
+ ignore[1] = true;
}
} else if (buffer[x] == '*') {
- if (buffer_len >= x + 1 && buffer[x + 1] == '/') {
- ++x;
+ extralines = 0;
+ y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
+ if (buffer_len > y && buffer[y] == '/') {
+ line_count += extralines;
+ x = y;
break;
}
} else if (Option::debug_level && qmake_endOfLine(buffer[x])) {
@@ -760,56 +947,44 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
}
}
}
+ // else: don't update x, buffer[x] is just the division operator.
}
} else if (buffer[x] == '\'' || buffer[x] == '"') {
- const char term = buffer[x++];
- while(x < buffer_len) {
- if (buffer[x] == term)
- break;
- if (buffer[x] == '\\') {
- x+=2;
- } else {
- if (qmake_endOfLine(buffer[x]))
- ++line_count;
- ++x;
- }
- }
+ x = scanPastString(buffer, buffer_len, x, &line_count);
+ // Leaves us on closing quote; for loop's x++ steps us past it.
}
- if (Option::debug_level && qmake_endOfLine(buffer[x]))
+
+ if (x < buffer_len && Option::debug_level && qmake_endOfLine(buffer[x]))
++line_count;
- if (buffer_len > x + 2 && buffer[x + 1] == 'Q' &&
- buffer[x + 2] == '_' && !isCWordChar(buffer[x])) {
- ++x;
- int match = 0;
- static const char *interesting[] = { "OBJECT", "GADGET" };
- for (int interest = 0, m1, m2; interest < 2; ++interest) {
- if(interest == 0 && ignore_qobject)
- continue;
- else if(interest == 1 && ignore_qgadget)
- continue;
- for (m1 = 0, m2 = 0; interesting[interest][m1]; ++m1) {
- if (interesting[interest][m1] != buffer[x + 2 + m1]) {
- m2 = -1;
- break;
+ if (buffer_len > x + 8 && !isCWordChar(buffer[x])) {
+ int morelines = 0;
+ int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &morelines);
+ if (buffer[y] == 'Q') {
+ static const char interesting[][9] = { "Q_OBJECT", "Q_GADGET" };
+ for (int interest = 0; interest < 2; ++interest) {
+ if (ignore[interest])
+ continue;
+
+ int matchlen = 0, extralines = 0;
+ if (matchWhileUnsplitting(buffer, buffer_len, y,
+ interesting[interest],
+ strlen(interesting[interest]),
+ &matchlen, &extralines)
+ && y + matchlen < buffer_len
+ && !isCWordChar(buffer[y + matchlen])) {
+ if (Option::debug_level) {
+ buffer[y + matchlen] = '\0';
+ debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
+ file->file.real().toLatin1().constData(),
+ line_count + morelines, buffer + y);
+ }
+ file->mocable = true;
+ return true;
}
- ++m2;
- }
- if(m1 == m2) {
- match = m2 + 2;
- break;
- }
- }
- if (match && !isCWordChar(buffer[x + match])) {
- if (Option::debug_level) {
- buffer[x + match] = '\0';
- debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
- file->file.real().toLatin1().constData(),
- line_count, buffer + x);
}
- file->mocable = true;
- return true;
}
}
+#undef SKIP_BSNL
}
return true;
}
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index a546e03b59..06c99b6e38 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -142,18 +142,8 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
const bool isPhone = project->isActiveConfig(QStringLiteral("winphone"));
#ifdef Q_OS_WIN
- QString regKeyPrefix;
-#if !defined(Q_OS_WIN64) && _WIN32_WINNT >= 0x0501
- BOOL isWow64;
- IsWow64Process(GetCurrentProcess(), &isWow64);
- if (!isWow64)
- regKeyPrefix = QStringLiteral("Software\\");
- else
-#endif
- regKeyPrefix = QStringLiteral("Software\\Wow6432Node\\");
-
- QString regKey = regKeyPrefix + QStringLiteral("Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
- const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey);
+ QString regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
+ const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
if (vcInstallDir.isEmpty()) {
fprintf(stderr, "Failed to find the Visual Studio installation directory.\n");
return false;
@@ -161,13 +151,13 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
QString windowsPath;
if (isPhone) {
- windowsPath = "Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v";
+ windowsPath = "Software\\Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v";
} else {
- windowsPath = "Microsoft\\Microsoft SDKs\\Windows\\v";
+ windowsPath = "Software\\Microsoft\\Microsoft SDKs\\Windows\\v";
}
- regKey = regKeyPrefix + windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder");
- const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey);
+ regKey = windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder");
+ const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
if (kitDir.isEmpty()) {
fprintf(stderr, "Failed to find the Windows Kit installation directory.\n");
return false;
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index d70480b028..1e187075c8 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -70,21 +70,6 @@ struct DotNetCombo {
const char *versionStr;
const char *regKey;
} dotNetCombo[] = {
-#ifdef Q_OS_WIN64
- {NET2015, "MSVC.NET 2015 (14.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
- {NET2013, "MSVC.NET 2013 (12.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
- {NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
- {NET2012, "MSVC.NET 2012 (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"},
- {NET2012, "MSVC.NET 2012 Express Edition (11.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\11.0\\Setup\\VC\\ProductDir"},
- {NET2010, "MSVC.NET 2010 (10.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"},
- {NET2010, "MSVC.NET 2010 Express Edition (10.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\10.0\\Setup\\VC\\ProductDir"},
- {NET2008, "MSVC.NET 2008 (9.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\9.0\\Setup\\VC\\ProductDir"},
- {NET2008, "MSVC.NET 2008 Express Edition (9.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\9.0\\Setup\\VC\\ProductDir"},
- {NET2005, "MSVC.NET 2005 (8.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"},
- {NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"},
- {NET2003, "MSVC.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
- {NET2002, "MSVC.NET 2002 (7.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
-#else
{NET2015, "MSVC.NET 2015 (14.0)", "Software\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 (12.0)", "Software\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
@@ -98,7 +83,6 @@ struct DotNetCombo {
{NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"},
{NET2003, "MSVC.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
{NET2002, "MSVC.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
-#endif
{NETUnknown, "", ""},
};
@@ -125,7 +109,8 @@ DotNET which_dotnet_version(const QByteArray &preferredVersion = QByteArray())
int installed = 0;
int i = 0;
for(; dotNetCombo[i].version; ++i) {
- QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey);
+ QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey,
+ KEY_WOW64_32KEY);
if (!path.isEmpty() && installPaths.value(dotNetCombo[i].version) != path) {
lowestInstalledVersion = &dotNetCombo[i];
installPaths.insert(lowestInstalledVersion->version, path);