summaryrefslogtreecommitdiffstats
path: root/qmake/generators
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-02-01 21:00:55 +0100
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-02-01 21:00:55 +0100
commitdcd5cb973622d059818dba1a2c7b9a7b7601a14c (patch)
treefbda1c8c6d36cae42b084f7298cf5b1904e21e9f /qmake/generators
parentf299b565b5904e39a47b6133643448e46810f0ed (diff)
parentff68e5d667cc62141f177d01f747a62c95f08d3e (diff)
Merge remote-tracking branch 'gerrit/dev' into HEAD
Diffstat (limited to 'qmake/generators')
-rw-r--r--qmake/generators/makefile.cpp15
-rw-r--r--qmake/generators/makefile.h2
-rw-r--r--qmake/generators/unix/unixmake2.cpp14
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp22
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.h1
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp94
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp3
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp25
-rw-r--r--qmake/generators/win32/msvc_vcproj.h1
-rw-r--r--qmake/generators/win32/registry.cpp158
-rw-r--r--qmake/generators/win32/registry_p.h73
11 files changed, 370 insertions, 38 deletions
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 1ba2587bd0..2845888dde 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -2254,12 +2254,17 @@ MakefileGenerator::writeDefaultVariables(QTextStream &t)
t << "MOVE = " << var("QMAKE_MOVE") << endl;
}
-QString MakefileGenerator::buildArgs()
+QString MakefileGenerator::buildArgs(bool withExtra)
{
QString ret;
for (const QString &arg : qAsConst(Option::globals->qmake_args))
ret += " " + shellQuote(arg);
+ if (withExtra && !Option::globals->qmake_extra_args.isEmpty()) {
+ ret += " --";
+ for (const QString &arg : qAsConst(Option::globals->qmake_extra_args))
+ ret += " " + shellQuote(arg);
+ }
return ret;
}
@@ -2278,7 +2283,7 @@ QString MakefileGenerator::build_args()
ret += " " + escapeFilePath(fileFixify(project->projectFile()));
// general options and arguments
- ret += buildArgs();
+ ret += buildArgs(true);
return ret;
}
@@ -2442,7 +2447,7 @@ MakefileGenerator::writeSubTargetCall(QTextStream &t,
if (!in_directory.isEmpty())
t << "\n\t" << mkdir_p_asstring(out_directory);
pfx = "( " + chkexists.arg(out) +
- + " $(QMAKE) -o " + out + ' ' + in + buildArgs()
+ + " $(QMAKE) -o " + out + ' ' + in + buildArgs(false)
+ " ) && ";
}
writeSubMakeCall(t, out_directory_cdin + pfx, makefilein);
@@ -2513,7 +2518,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubT
t << mkdir_p_asstring(out_directory)
<< out_directory_cdin;
}
- t << "$(QMAKE) -o " << out << ' ' << in << buildArgs();
+ t << "$(QMAKE) -o " << out << ' ' << in << buildArgs(false);
if (!dont_recurse)
writeSubMakeCall(t, out_directory_cdin, makefilein + " qmake_all");
else
@@ -2710,7 +2715,7 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll)
if(project->isEmpty("QMAKE_FAILED_REQUIREMENTS") && !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) {
QStringList files = escapeFilePaths(fileFixify(Option::mkfile::project_files));
t << escapeDependencyPath(project->first("QMAKE_INTERNAL_PRL_FILE").toQString()) << ": \n\t"
- << "@$(QMAKE) -prl " << files.join(' ') << ' ' << buildArgs() << endl;
+ << "@$(QMAKE) -prl " << files.join(' ') << ' ' << buildArgs(true) << endl;
}
QString qmake = build_args();
diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h
index 86fec748eb..4ced3bd121 100644
--- a/qmake/generators/makefile.h
+++ b/qmake/generators/makefile.h
@@ -178,7 +178,7 @@ protected:
QString specdir();
//subclasses can use these to query information about how the generator was "run"
- QString buildArgs();
+ QString buildArgs(bool withExtra);
virtual QStringList &findDependencies(const QString &file);
virtual bool doDepends() const { return Option::mkfile::do_deps; }
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index 3d12ffd65c..5b56cac784 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -659,11 +659,15 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "$(TARGETA): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) $(OBJCOMP)";
if(do_incremental)
t << " $(INCREMENTAL_OBJECTS)";
- t << ' ' << depVar("POST_TARGETDEPS") << "\n\t"
- << "-$(DEL_FILE) $(TARGETA) \n\t"
+ t << ' ' << depVar("POST_TARGETDEPS") << "\n\t";
+ if (!project->isEmpty("QMAKE_PRE_LINK"))
+ t << var("QMAKE_PRE_LINK") << "\n\t";
+ t << "-$(DEL_FILE) $(TARGETA) \n\t"
<< var("QMAKE_AR_CMD");
if(do_incremental)
t << " $(INCREMENTAL_OBJECTS)";
+ if (!project->isEmpty("QMAKE_POST_LINK"))
+ t << "\n\t" << var("QMAKE_POST_LINK");
if(!project->isEmpty("QMAKE_RANLIB"))
t << "\n\t$(RANLIB) $(TARGETA)";
t << endl << endl;
@@ -680,6 +684,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
<< " $(OBJECTS) $(OBJCOMP) " << depVar("POST_TARGETDEPS") << "\n\t";
if(!destdir.isEmpty())
t << mkdir_p_asstring(destdir, false) << "\n\t";
+ if (!project->isEmpty("QMAKE_PRE_LINK"))
+ t << var("QMAKE_PRE_LINK") << "\n\t";
t << "-$(DEL_FILE) " << destdir << "$(TARGET)\n\t"
<< var("QMAKE_AR_CMD") << "\n";
if(!project->isEmpty("QMAKE_POST_LINK"))
@@ -710,6 +716,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
if(!destdir.isEmpty())
t << mkdir_p_asstring(destdir, false) << "\n\t";
+ if (!project->isEmpty("QMAKE_PRE_LINK"))
+ t << var("QMAKE_PRE_LINK") << "\n\t";
t << "-$(DEL_FILE) " << lib << "\n\t"
<< ar << "\n";
if(!project->isEmpty("QMAKE_POST_LINK"))
@@ -732,7 +740,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
if(!meta_files.isEmpty())
t << escapeDependencyPaths(meta_files).join(" ") << ": \n\t"
- << "@$(QMAKE) -prl " << escapeFilePath(project->projectFile()) << ' ' << buildArgs() << endl;
+ << "@$(QMAKE) -prl " << escapeFilePath(project->projectFile()) << ' ' << buildArgs(true) << endl;
}
if (!project->isEmpty("QMAKE_BUNDLE")) {
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index 3f789405b2..129fb28e01 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -176,7 +176,7 @@ const char _Optimization[] = "Optimization";
const char _OptimizeReferences[] = "OptimizeReferences";
const char _OutputDirectory[] = "OutputDirectory";
const char _OutputFile[] = "OutputFile";
-const char _PlatformToolSet[] = "PlatformToolSet";
+const char _PlatformToolSet[] = "PlatformToolset";
const char _PrecompiledHeader[] = "PrecompiledHeader";
const char _PrecompiledHeaderFile[] = "PrecompiledHeaderFile";
const char _PrecompiledHeaderOutputFile[] = "PrecompiledHeaderOutputFile";
@@ -406,7 +406,7 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool)
xml << decl("1.0", "utf-8")
<< tag("Project")
<< attrTag("DefaultTargets","Build")
- << attrTag("ToolsVersion", "4.0")
+ << attrTagToolsVersion(tool.Configuration)
<< attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")
<< tag("ItemGroup")
<< attrTag("Label", "ProjectConfigurations");
@@ -550,7 +550,7 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool)
xmlFilter << decl("1.0", "utf-8")
<< tag("Project")
- << attrTag("ToolsVersion", "4.0")
+ << attrTagToolsVersion(tool.Configuration)
<< attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
xmlFilter << tag("ItemGroup");
@@ -587,6 +587,8 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool)
outputFilter(tempProj, xml, xmlFilter, tempProj.ExtraCompilers.at(x));
}
+ outputFilter(tempProj, xml, xmlFilter, "Root Files");
+
xml << import("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
xml << tag("ImportGroup")
@@ -603,13 +605,10 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
xml.setIndentString(" ");
- const QString toolsVersion = (tool.SdkVersion == QLatin1String("10.0")) ? QStringLiteral("14.0")
- : QStringLiteral("4.0");
-
xml << decl("1.0", "utf-8")
<< tag("Project")
<< attrTag("DefaultTargets","Build")
- << attrTag("ToolsVersion", toolsVersion)
+ << attrTagToolsVersion(tool.SingleProjects.first().Configuration)
<< attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")
<< tag("ItemGroup")
<< attrTag("Label", "ProjectConfigurations");
@@ -794,7 +793,7 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool)
xmlFilter << decl("1.0", "utf-8")
<< tag("Project")
- << attrTag("ToolsVersion", "4.0")
+ << attrTagToolsVersion(tool.SingleProjects.first().Configuration)
<< attrTag("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
xmlFilter << tag("ItemGroup");
@@ -2054,4 +2053,11 @@ QString VCXProjectWriter::generateCondition(const VCConfiguration &config)
return QStringLiteral("'$(Configuration)|$(Platform)'=='") + config.Name + QLatin1Char('\'');
}
+XmlOutput::xml_output VCXProjectWriter::attrTagToolsVersion(const VCConfiguration &config)
+{
+ if (config.CompilerVersion >= NET2013)
+ return noxml();
+ return attrTag("ToolsVersion", "4.0");
+}
+
QT_END_NAMESPACE
diff --git a/qmake/generators/win32/msbuild_objectmodel.h b/qmake/generators/win32/msbuild_objectmodel.h
index fe46430e60..2e77537916 100644
--- a/qmake/generators/win32/msbuild_objectmodel.h
+++ b/qmake/generators/win32/msbuild_objectmodel.h
@@ -182,6 +182,7 @@ private:
bool fileAdded, bool hasCustomBuildStep);
static void outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter, const QString &fileName, const QString &filterName);
static QString generateCondition(const VCConfiguration &config);
+ static XmlOutput::xml_output attrTagToolsVersion(const VCConfiguration &config);
friend class XTreeNode;
friend class XFlatNode;
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index 380ce60c5b..c19c101d43 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -34,7 +34,7 @@
#include <qdiriterator.h>
#include <qset.h>
-#include <windows/registry_p.h>
+#include <registry_p.h>
#include <time.h>
@@ -75,25 +75,44 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
QString arch = project->first("VCPROJ_ARCH").toQString().toLower();
QString compiler;
QString compilerArch;
- if (arch == QLatin1String("arm")) {
- compiler = QStringLiteral("x86_arm");
- compilerArch = QStringLiteral("arm");
- } else if (arch == QLatin1String("x64")) {
+ const QString msvcVer = project->first("MSVC_VER").toQString();
+ if (msvcVer.isEmpty()) {
+ fprintf(stderr, "Mkspec does not specify MSVC_VER. Cannot continue.\n");
+ return false;
+ }
+
+ if (msvcVer == QStringLiteral("15.0")) {
const ProStringList hostArch = project->values("QMAKE_TARGET.arch");
if (hostArch.contains("x86_64"))
- compiler = QStringLiteral("amd64");
+ compiler = QStringLiteral("HostX64/");
else
- compiler = QStringLiteral("x86_amd64");
- compilerArch = QStringLiteral("amd64");
+ compiler = QStringLiteral("HostX86/");
+ if (arch == QLatin1String("arm")) {
+ compiler += QStringLiteral("arm");
+ compilerArch = QStringLiteral("arm");
+ } else if (arch == QLatin1String("x64")) {
+ compiler += QStringLiteral("x64");
+ compilerArch = QStringLiteral("amd64");
+ } else {
+ compiler += QStringLiteral("x86");
+ compilerArch = QStringLiteral("amd64");
+ }
} else {
- arch = QStringLiteral("x86");
+ if (arch == QLatin1String("arm")) {
+ compiler = QStringLiteral("x86_arm");
+ compilerArch = QStringLiteral("arm");
+ } else if (arch == QLatin1String("x64")) {
+ const ProStringList hostArch = project->values("QMAKE_TARGET.arch");
+ if (hostArch.contains("x86_64"))
+ compiler = QStringLiteral("amd64");
+ else
+ compiler = QStringLiteral("x86_amd64");
+ compilerArch = QStringLiteral("amd64");
+ } else {
+ arch = QStringLiteral("x86");
+ }
}
- const QString msvcVer = project->first("MSVC_VER").toQString();
- if (msvcVer.isEmpty()) {
- fprintf(stderr, "Mkspec does not specify MSVC_VER. Cannot continue.\n");
- return false;
- }
const QString winsdkVer = project->first("WINSDK_VER").toQString();
if (winsdkVer.isEmpty()) {
fprintf(stderr, "Mkspec does not specify WINSDK_VER. Cannot continue.\n");
@@ -106,7 +125,11 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
}
#ifdef Q_OS_WIN
- QString regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
+ QString regKey;
+ if (msvcVer == QStringLiteral("15.0"))
+ regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\SxS\\VS7\\") + msvcVer;
+ else
+ 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");
@@ -128,7 +151,46 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
QStringList incDirs;
QStringList libDirs;
QStringList binDirs;
- if (msvcVer == QStringLiteral("14.0")) {
+ if (msvcVer == QStringLiteral("15.0")) {
+ const QString toolsInstallDir = qgetenv("VCToolsInstallDir");
+ if (toolsInstallDir.isEmpty()) {
+ fprintf(stderr, "Failed to access tools installation dir.\n");
+ return false;
+ }
+
+ binDirs << toolsInstallDir + QStringLiteral("bin/") + compiler;
+ if (arch == QStringLiteral("x64"))
+ binDirs << toolsInstallDir + QStringLiteral("bin/HostX86/X86");
+ binDirs << kitDir + QStringLiteral("bin/x86");
+ binDirs << vcInstallDir + QStringLiteral("Common7/Tools");
+ binDirs << vcInstallDir + QStringLiteral("Common7/ide");
+ binDirs << vcInstallDir + QStringLiteral("MSBuild/15.0/bin");
+
+ incDirs << toolsInstallDir + QStringLiteral("include");
+ incDirs << vcInstallDir + QStringLiteral("VC/Auxiliary/VS/include");
+
+ const QString crtVersion = qgetenv("UCRTVersion");
+ if (crtVersion.isEmpty()) {
+ fprintf(stderr, "Failed to access CRT version.\n");
+ return false;
+ }
+ const QString crtInclude = kitDir + QStringLiteral("Include/") + crtVersion;
+ const QString crtLib = kitDir + QStringLiteral("Lib/") + crtVersion;
+ incDirs << crtInclude + QStringLiteral("/ucrt");
+ incDirs << crtInclude + QStringLiteral("/um");
+ incDirs << crtInclude + QStringLiteral("/shared");
+ incDirs << crtInclude + QStringLiteral("/winrt");
+
+ incDirs << kitDir + QStringLiteral("Extension SDKs/WindowsMobile/")
+ + crtVersion + QStringLiteral("/Include/WinRT");
+
+ libDirs << toolsInstallDir + QStringLiteral("lib/") + arch + QStringLiteral("/store");
+
+ libDirs << vcInstallDir + QStringLiteral("VC/Auxiliary/VS/lib/") + arch;
+
+ libDirs << crtLib + QStringLiteral("/ucrt/") + arch;
+ libDirs << crtLib + QStringLiteral("/um/") + arch;
+ } else if (msvcVer == QStringLiteral("14.0")) {
binDirs << vcInstallDir + QStringLiteral("bin/") + compiler;
binDirs << vcInstallDir + QStringLiteral("bin/"); // Maybe remove for x86 again?
binDirs << kitDir + QStringLiteral("bin/") + (arch == QStringLiteral("arm") ? QStringLiteral("x86") : arch);
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
index 33d96c146c..60734b4d1b 100644
--- a/qmake/generators/win32/msvc_objectmodel.cpp
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -54,7 +54,8 @@ static DotNET vsVersionFromString(const char *versionString)
"10.0", NET2010,
"11.0", NET2012,
"12.0", NET2013,
- "14.0", NET2015
+ "14.0", NET2015,
+ "15.0", NET2017
};
DotNET result = NETUnknown;
for (const auto entry : mapping) {
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index b3da4db4c5..3d5b80e06d 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -670,6 +670,21 @@ bool VcprojGenerator::hasBuiltinCompiler(const QString &file)
return false;
}
+void VcprojGenerator::createCustomBuildToolFakeFile(const QString &cbtFilePath,
+ const QString &realOutFilePath)
+{
+ QFile file(fileFixify(cbtFilePath, FileFixifyFromOutdir | FileFixifyAbsolute));
+ if (file.exists())
+ return;
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ warn_msg(WarnLogic, "Cannot create '%s'.", qPrintable(file.fileName()));
+ return;
+ }
+ file.write("This is a dummy file needed to create ");
+ file.write(qPrintable(realOutFilePath));
+ file.write("\n");
+}
+
void VcprojGenerator::init()
{
is64Bit = (project->first("QMAKE_TARGET.arch") == "x86_64");
@@ -797,12 +812,14 @@ void VcprojGenerator::init()
if (!hasBuiltinCompiler(file)) {
extraCompilerSources[file] += quc.toQString();
} else {
- // Use a fake file name foo.moc.cbt for the project view.
+ // Create a fake file foo.moc.cbt for the project view.
// This prevents VS from complaining about a circular
// dependency from foo.moc -> foo.moc.
- QString out = Option::fixPathToTargetOS(replaceExtraCompilerVariables(
- compiler_out, file, QString(), NoShell), false);
- out += customBuildToolFilterFileSuffix;
+ QString realOut = replaceExtraCompilerVariables(
+ compiler_out, file, QString(), NoShell);
+ QString out = realOut + customBuildToolFilterFileSuffix;
+ createCustomBuildToolFakeFile(out, realOut);
+ out = Option::fixPathToTargetOS(out, false);
extraCompilerSources[out] += quc.toQString();
extraCompilerOutputs[out] = file;
}
diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h
index e3e67d64b9..4882296b46 100644
--- a/qmake/generators/win32/msvc_vcproj.h
+++ b/qmake/generators/win32/msvc_vcproj.h
@@ -130,6 +130,7 @@ private:
bool isStandardSuffix(const QString &suffix) const;
ProString firstInputFileName(const ProString &extraCompilerName) const;
QString firstExpandedOutputFileName(const ProString &extraCompilerName);
+ void createCustomBuildToolFakeFile(const QString &cbtFilePath, const QString &realOutFilePath);
friend class VCFilter;
};
diff --git a/qmake/generators/win32/registry.cpp b/qmake/generators/win32/registry.cpp
new file mode 100644
index 0000000000..74c912ca43
--- /dev/null
+++ b/qmake/generators/win32/registry.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstringlist.h>
+#include "registry_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN32
+/*!
+ Returns the path part of a registry key.
+ e.g.
+ For a key
+ "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
+ it returns
+ "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\"
+*/
+static QString keyPath(const QString &rKey)
+{
+ int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+ if (idx == -1)
+ return QString();
+ return rKey.left(idx + 1);
+}
+
+/*!
+ Returns the name part of a registry key.
+ e.g.
+ For a key
+ "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
+ it returns
+ "ProductDir"
+*/
+static QString keyName(const QString &rKey)
+{
+ int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+ if (idx == -1)
+ return rKey;
+
+ QString res(rKey.mid(idx + 1));
+ if (res == QLatin1String("Default") || res == QLatin1String("."))
+ res = QString();
+ return res;
+}
+#endif
+
+QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned long options)
+{
+ QString result;
+
+#ifdef Q_OS_WIN32
+ QString rSubkeyName = keyName(rSubkey);
+ QString rSubkeyPath = keyPath(rSubkey);
+
+ HKEY handle = 0;
+ LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0,
+ KEY_READ | options, &handle);
+
+ if (res != ERROR_SUCCESS)
+ return QString();
+
+ // get the size and type of the value
+ DWORD dataType;
+ DWORD dataSize;
+ res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize);
+ if (res != ERROR_SUCCESS) {
+ RegCloseKey(handle);
+ return QString();
+ }
+
+ // get the value
+ QByteArray data(dataSize, 0);
+ res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, 0,
+ reinterpret_cast<unsigned char*>(data.data()), &dataSize);
+ if (res != ERROR_SUCCESS) {
+ RegCloseKey(handle);
+ return QString();
+ }
+
+ switch (dataType) {
+ case REG_EXPAND_SZ:
+ case REG_SZ: {
+ result = QString::fromWCharArray(((const wchar_t *)data.constData()));
+ break;
+ }
+
+ case REG_MULTI_SZ: {
+ QStringList l;
+ int i = 0;
+ for (;;) {
+ QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i);
+ i += s.length() + 1;
+
+ if (s.isEmpty())
+ break;
+ l.append(s);
+ }
+ result = l.join(QLatin1String(", "));
+ break;
+ }
+
+ case REG_NONE:
+ case REG_BINARY: {
+ result = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2);
+ break;
+ }
+
+ case REG_DWORD_BIG_ENDIAN:
+ case REG_DWORD: {
+ Q_ASSERT(data.size() == sizeof(int));
+ int i;
+ memcpy((char*)&i, data.constData(), sizeof(int));
+ result = QString::number(i);
+ break;
+ }
+
+ default:
+ qWarning("QSettings: unknown data %u type in windows registry", quint32(dataType));
+ break;
+ }
+
+ RegCloseKey(handle);
+#else
+ Q_UNUSED(parentHandle);
+ Q_UNUSED(rSubkey)
+ Q_UNUSED(options);
+#endif
+
+ return result;
+}
+
+QT_END_NAMESPACE
+
diff --git a/qmake/generators/win32/registry_p.h b/qmake/generators/win32/registry_p.h
new file mode 100644
index 0000000000..3526dffd45
--- /dev/null
+++ b/qmake/generators/win32/registry_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_WINDOWS_REGISTRY_H
+#define QT_WINDOWS_REGISTRY_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_WIN32
+ #include <QtCore/qt_windows.h>
+#else
+ typedef void* HKEY;
+#endif
+
+#include <QtCore/qstring.h>
+
+/**
+ * Read a value from the Windows registry.
+ *
+ * If the key is not found, or the registry cannot be accessed (for example
+ * if this code is compiled for a platform other than Windows), a null
+ * string is returned.
+ *
+ * 32-bit code reads from the registry's 32 bit view (Wow6432Node),
+ * 64 bit code reads from the 64 bit view.
+ * Pass KEY_WOW64_32KEY to access the 32 bit view regardless of the
+ * application's architecture, KEY_WOW64_64KEY respectively.
+ */
+QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey,
+ unsigned long options = 0);
+
+QT_END_NAMESPACE
+
+#endif // QT_WINDOWS_REGISTRY_H
+