summaryrefslogtreecommitdiffstats
path: root/qmake/generators/win32
diff options
context:
space:
mode:
Diffstat (limited to 'qmake/generators/win32')
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp6
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp161
-rw-r--r--qmake/generators/win32/msvc_objectmodel.h9
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp112
4 files changed, 204 insertions, 84 deletions
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index 355260c974..f7ae426c91 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -144,6 +144,7 @@ const char _IntermediateDirectory[] = "IntermediateDirectory";
const char _KeyContainer[] = "KeyContainer";
const char _KeyFile[] = "KeyFile";
const char _LanguageStandard[] = "LanguageStandard";
+const char _LanguageStandard_C[] = "LanguageStandard_C";
const char _LargeAddressAware[] = "LargeAddressAware";
const char _LinkDLL[] = "LinkDLL";
const char _LinkErrorReporting[] = "LinkErrorReporting";
@@ -1130,6 +1131,8 @@ static inline QString toString(optLinkTimeCodeGenType option)
break;
case optLTCGEnabled:
return "UseLinkTimeCodeGeneration";
+ case optLTCGIncremental:
+ return "UseFastLinkTimeCodeGeneration";
case optLTCGInstrument:
return "PGInstrument";
case optLTCGOptimize:
@@ -1163,6 +1166,8 @@ static inline QString toString(triState genDebugInfo, linkerDebugOption option)
case _True:
if (option == linkerDebugOptionFastLink)
return "DebugFastLink";
+ else if (option == linkerDebugOptionFull)
+ return "DebugFull";
return "true";
}
return QString();
@@ -1483,6 +1488,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool)
<< attrTagT(_MinimalRebuild, tool.MinimalRebuild)
<< attrTagT(_MultiProcessorCompilation, tool.MultiProcessorCompilation)
<< attrTagS(_LanguageStandard, tool.LanguageStandard)
+ << attrTagS(_LanguageStandard_C, tool.LanguageStandard_C)
<< attrTagS(_ObjectFileName, tool.ObjectFile)
<< attrTagT(_OmitDefaultLibName, tool.OmitDefaultLibName)
<< attrTagT(_OmitFramePointers, tool.OmitFramePointers)
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
index 1b36feb67e..ee2ace981e 100644
--- a/qmake/generators/win32/msvc_objectmodel.cpp
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -40,36 +40,42 @@ using namespace QMakeInternal;
QT_BEGIN_NAMESPACE
-static DotNET vsVersionFromString(const char *versionString)
+DotNET vsVersionFromString(const ProString &versionString)
{
- struct VSVersionMapping
- {
- const char *str;
- DotNET version;
- };
- static VSVersionMapping mapping[] = {
- { "7.0", NET2002 },
- { "7.1", NET2003 },
- { "8.0", NET2005 },
- { "9.0", NET2008 },
- { "10.0", NET2010 },
- { "11.0", NET2012 },
- { "12.0", NET2013 },
- { "14.0", NET2015 },
- { "15.0", NET2017 },
- { "16.0", NET2019 }
- };
- DotNET result = NETUnknown;
- for (const auto entry : mapping) {
- if (strcmp(entry.str, versionString) == 0)
- return entry.version;
+ int idx = versionString.indexOf(QLatin1Char('.'));
+ if (idx == -1)
+ return NETUnknown;
+
+ QStringView versionView = versionString.toQStringView();
+ int versionMajor = versionView.left(idx).toInt();
+ int versionMinor = versionView.mid(idx + 1).toInt();
+
+ if (versionMajor == 17)
+ return NET2022;
+ if (versionMajor == 16)
+ return NET2019;
+ if (versionMajor == 15)
+ return NET2017;
+ if (versionMajor == 14)
+ return NET2015;
+ if (versionMajor == 12)
+ return NET2013;
+ if (versionMajor == 11)
+ return NET2012;
+ if (versionMajor == 10)
+ return NET2010;
+ if (versionMajor == 9)
+ return NET2008;
+ if (versionMajor == 8)
+ return NET2005;
+ if (versionMajor == 7) {
+ if (versionMinor == 0)
+ return NET2002;
+ if (versionMinor == 1)
+ return NET2003;
}
- return result;
-}
-DotNET vsVersionFromString(const ProString &versionString)
-{
- return vsVersionFromString(versionString.toLatin1().constData());
+ return NETUnknown;
}
// XML Tags ---------------------------------------------------------
@@ -404,7 +410,7 @@ VCCLCompilerTool::VCCLCompilerTool()
CompileForArchitecture(archUnknown),
InterworkCalls(unset),
EnablePREfast(unset),
- DisplayFullPaths(unset),
+ DisplayFullPaths(_False),
MultiProcessorCompilation(unset),
GenerateXMLDocumentationFiles(unset),
CreateHotpatchableImage(unset)
@@ -1147,12 +1153,39 @@ bool VCCLCompilerTool::parseOption(const char* option)
ShowIncludes = _True;
break;
}
- if (strlen(option) > 8 && second == 't' && third == 'd') {
- const QString version = option + 8;
- static const QStringList knownVersions = { "14", "17", "latest" };
- if (knownVersions.contains(version)) {
- LanguageStandard = "stdcpp" + version;
- break;
+ if (strlen(option) > 7 && second == 't' && third == 'd' && fourth == ':') {
+ static const QRegExp rex("(c(?:\\+\\+)?)(.+)");
+ if (rex.exactMatch(option + 5)) {
+ QString *var = nullptr;
+ const QStringList *knownVersions = nullptr;
+ QString valuePrefix;
+ auto lang = rex.cap(1);
+ auto version = rex.cap(2);
+ if (lang == QStringLiteral("c++")) {
+ // Turn /std:c++17 into <LanguageStandard>stdcpp17</LanguageStandard>
+ static const QStringList knownCxxVersions = {
+ "14",
+ "17",
+ "20",
+ "latest"
+ };
+ var = &LanguageStandard;
+ knownVersions = &knownCxxVersions;
+ valuePrefix = "stdcpp";
+ } else if (lang == QStringLiteral("c")) {
+ // Turn /std:c17 into <LanguageStandard_C>stdc17</LanguageStandard_C>
+ static const QStringList knownCVersions = {
+ "11",
+ "17"
+ };
+ var = &LanguageStandard_C;
+ knownVersions = &knownCVersions;
+ valuePrefix = "stdc";
+ }
+ if (var && knownVersions->contains(version)) {
+ *var = valuePrefix + version;
+ break;
+ }
}
}
found = false; break;
@@ -1470,10 +1503,23 @@ bool VCLinkerTool::parseOption(const char* option)
}else
EnableUAC = _True;
break;
- case 0x3389797: // /DEBUG[:FASTLINK]
- GenerateDebugInformation = _True;
- if (config->CompilerVersion >= NET2015 && strcmp(option + 7, "FASTLINK") == 0)
- DebugInfoOption = linkerDebugOptionFastLink;
+ case 0x3389797: // /DEBUG[:{FASTLINK|FULL|NONE}]
+ DebugInfoOption = linkerDebugOptionEnabled;
+ if (config->CompilerVersion >= NET2015 && *(option + 6) == ':') {
+ const char *str = option + 7;
+ if (qstricmp(str, "fastlink") == 0)
+ DebugInfoOption = linkerDebugOptionFastLink;
+ else if (qstricmp(str, "full") == 0)
+ DebugInfoOption = linkerDebugOptionFull;
+ else if (qstricmp(str, "none") == 0)
+ DebugInfoOption = linkerDebugOptionNone;
+ else
+ AdditionalOptions += option;
+ }
+ if (DebugInfoOption == linkerDebugOptionNone)
+ GenerateDebugInformation = _False;
+ else
+ GenerateDebugInformation = _True;
break;
case 0x0033896: // /DEF:filename
ModuleDefinitionFile = option+5;
@@ -1560,24 +1606,28 @@ bool VCLinkerTool::parseOption(const char* option)
case 0x0d745c8: // /LIBPATH:dir
AdditionalLibraryDirectories += option+9;
break;
- case 0x0341877: // /LTCG[:NOSTATUS|:STATUS]
- config->WholeProgramOptimization = _True;
- if (config->CompilerVersion >= NET2005) {
- LinkTimeCodeGeneration = optLTCGEnabled;
- if(*(option+5) == ':') {
- const char* str = option+6;
- if (*str == 'S')
- ShowProgress = linkProgressAll;
- else if (qstricmp(str, "pginstrument") == 0)
- LinkTimeCodeGeneration = optLTCGInstrument;
- else if (qstricmp(str, "pgoptimize") == 0)
- LinkTimeCodeGeneration = optLTCGOptimize;
- else if (qstricmp(str, "pgupdate") == 0)
- LinkTimeCodeGeneration = optLTCGUpdate;
- }
- } else {
- AdditionalOptions.append(option);
+ case 0x0341877: // /LTCG[:{INCREMENTAL|NOSTATUS|STATUS|OFF}]
+ // /LTCG:{PGINSTRUMENT|PGOPTIMIZE|PGUPDATE}
+ LinkTimeCodeGeneration = optLTCGEnabled;
+ if (*(option + 5) == ':') {
+ const char* str = option + 6;
+ if (qstricmp(str, "status") == 0)
+ ShowProgress = linkProgressAll;
+ else if (qstricmp(str, "off") == 0)
+ LinkTimeCodeGeneration = optLTCGDefault;
+ else if (qstricmp(str, "incremental") == 0)
+ LinkTimeCodeGeneration = optLTCGIncremental;
+ else if (qstricmp(str, "pginstrument") == 0)
+ LinkTimeCodeGeneration = optLTCGInstrument;
+ else if (qstricmp(str, "pgoptimize") == 0)
+ LinkTimeCodeGeneration = optLTCGOptimize;
+ else if (qstricmp(str, "pgupdate") == 0)
+ LinkTimeCodeGeneration = optLTCGUpdate;
+ else
+ AdditionalOptions.append(option);
}
+ if (LinkTimeCodeGeneration != optLTCGDefault)
+ config->WholeProgramOptimization = _True;
break;
case 0x379ED25:
case 0x157cf65: // /MACHINE:{AM33|ARM|CEE|IA64|X86|M32R|MIPS|MIPS16|MIPSFPU|MIPSFPU16|MIPSR41XX|PPC|SH3|SH4|SH5|THUMB|TRICORE}
@@ -2405,6 +2455,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info)
cmd_name = cmd.left(space);
else
cmd_name = cmd;
+ cmd_name = cmd_name.trimmed();
}
// Fixify paths
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
index 33eff0d914..c1e70b3b51 100644
--- a/qmake/generators/win32/msvc_objectmodel.h
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -53,7 +53,8 @@ enum DotNET {
NET2013 = 0xc0,
NET2015 = 0xd0,
NET2017 = 0xe0,
- NET2019
+ NET2019,
+ NET2022
};
DotNET vsVersionFromString(const ProString &versionString);
@@ -282,7 +283,9 @@ enum inlineExpansionOption {
};
enum linkerDebugOption {
linkerDebugOptionNone,
- linkerDebugOptionFastLink
+ linkerDebugOptionEnabled, // represents /DEBUG without further options
+ linkerDebugOptionFastLink,
+ linkerDebugOptionFull
};
enum linkIncrementalType {
linkIncrementalDefault,
@@ -355,6 +358,7 @@ enum optWin98Type {
enum optLinkTimeCodeGenType {
optLTCGDefault,
optLTCGEnabled,
+ optLTCGIncremental,
optLTCGInstrument,
optLTCGOptimize,
optLTCGUpdate
@@ -527,6 +531,7 @@ public:
inlineExpansionOption InlineFunctionExpansion;
triState KeepComments;
QString LanguageStandard;
+ QString LanguageStandard_C;
triState MinimalRebuild;
QString ObjectFile;
triState OmitDefaultLibName;
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index e117f472e0..d6a825af55 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -37,8 +37,11 @@
#include <qcryptographichash.h>
#include <qhash.h>
#include <quuid.h>
+#include <qregexp.h>
#include <stdlib.h>
+#include <tuple>
+#include <utility>
//#define DEBUG_SOLUTION_GEN
@@ -76,6 +79,8 @@ const char _slnHeader141[] = "Microsoft Visual Studio Solution File, Format
"\n# Visual Studio 15";
const char _slnHeader142[] = "Microsoft Visual Studio Solution File, Format Version 12.00"
"\n# Visual Studio Version 16";
+const char _slnHeader143[] = "Microsoft Visual Studio Solution File, Format Version 12.00"
+ "\n# Visual Studio Version 17";
// The following UUID _may_ change for later servicepacks...
// If so we need to search through the registry at
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\Projects
@@ -311,6 +316,8 @@ QString VcprojGenerator::retrievePlatformToolSet() const
return QStringLiteral("v141");
case NET2019:
return QStringLiteral("v142");
+ case NET2022:
+ return QStringLiteral("v143");
default:
return QString();
}
@@ -538,6 +545,9 @@ void VcprojGenerator::writeSubDirs(QTextStream &t)
}
switch (vcProject.Configuration.CompilerVersion) {
+ case NET2022:
+ t << _slnHeader143;
+ break;
case NET2019:
t << _slnHeader142;
break;
@@ -813,33 +823,62 @@ void VcprojGenerator::init()
}
}
- // Add all input files for a custom compiler into a map for uniqueness,
- // unless the compiler is configure as a combined stage, then use the first one
+ // Helper function to create a fake file foo.cbt for the project view.
+ //
+ // This prevents VS from complaining about a circular dependency from "foo -> foo".
+ //
+ // The .cbt file is added as "source" of the Custom Build Tool. This means, in the project
+ // view, this is the file the Custom Build Tool property page is attached to.
+ //
+ // This function returns a pair with
+ // - the fully resolved output file path
+ // - the file path of the .cbt file
+ auto addExtraCompilerSourceWithCustomBuildToolFakeFile
+ = [this](const QString &compilerOutput, const ProString &extraCompiler,
+ const QStringList &inputs) -> std::pair<QString, QString>
+ {
+ QString realOut = replaceExtraCompilerVariables(compilerOutput, inputs, {}, NoShell);
+ QString out = realOut + customBuildToolFilterFileSuffix;
+ createCustomBuildToolFakeFile(out, realOut);
+ out = Option::fixPathToTargetOS(out, false);
+ extraCompilerSources[out] += extraCompiler.toQString();
+ return { realOut, out };
+ };
+
+ // Add all input files for a custom compiler into a map for uniqueness.
+ //
+ // Use .cbt files for the following cases:
+ // - CONFIG += combine
+ // - the input has a built-in compiler (e.g. C++ source file)
for (const ProString &quc : project->values("QMAKE_EXTRA_COMPILERS")) {
const ProStringList &invar = project->values(ProKey(quc + ".input"));
const QString compiler_out = project->first(ProKey(quc + ".output")).toQString();
- for (ProStringList::ConstIterator iit = invar.constBegin(); iit != invar.constEnd(); ++iit) {
- ProStringList fileList = project->values((*iit).toKey());
- if (!fileList.isEmpty()) {
- if (project->values(ProKey(quc + ".CONFIG")).indexOf("combine") != -1)
- fileList.erase(fileList.begin() + 1, fileList.end());
- for (ProStringList::ConstIterator fit = fileList.constBegin(); fit != fileList.constEnd(); ++fit) {
- QString file = (*fit).toQString();
- if (verifyExtraCompiler(quc, file)) {
- if (!hasBuiltinCompiler(file)) {
- extraCompilerSources[file] += quc.toQString();
- } else {
- // 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 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;
- }
+
+ QStringList inputFiles;
+ for (auto it = invar.begin(); it != invar.end(); ++it)
+ inputFiles += project->values(it->toKey()).toQStringList();
+
+ if (project->values(ProKey(quc + ".CONFIG")).contains("combine")) {
+ // Handle "CONFIG += combine" extra compilers.
+ QString realOut;
+ QString out;
+ std::tie(realOut, out)
+ = addExtraCompilerSourceWithCustomBuildToolFakeFile(compiler_out, quc, inputFiles);
+ if (hasBuiltinCompiler(realOut))
+ extraCompilerOutputs[out] = realOut;
+ } else {
+ // Handle regular 1-to-1 extra compilers.
+ for (const QString &file : inputFiles) {
+ if (verifyExtraCompiler(quc, file)) {
+ if (!hasBuiltinCompiler(file)) {
+ extraCompilerSources[file] += quc.toQString();
+ } else {
+ QString out;
+ std::tie(std::ignore, out)
+ = addExtraCompilerSourceWithCustomBuildToolFakeFile(compiler_out,
+ quc,
+ QStringList(file));
+ extraCompilerOutputs[out] = file;
}
}
}
@@ -891,6 +930,9 @@ void VcprojGenerator::initProject()
// Own elements -----------------------------
vcProject.Name = project->first("QMAKE_ORIG_TARGET").toQString();
switch (vcProject.Configuration.CompilerVersion) {
+ case NET2022:
+ vcProject.Version = "17.00";
+ break;
case NET2019:
vcProject.Version = "16.00";
break;
@@ -1052,6 +1094,20 @@ void VcprojGenerator::initConfiguration()
initPreLinkEventTools();
}
+// Filter from the given QMAKE_CFLAGS the options that are relevant
+// for the vcxproj-global VCCLCompilerTool.
+static ProStringList relevantCFlags(const ProStringList &flags)
+{
+ ProStringList result;
+ static const QRegExp rex("^[/-]std:.*");
+ for (const ProString &flag : flags) {
+ if (rex.exactMatch(flag.toQString())) {
+ result.append(flag);
+ }
+ }
+ return result;
+}
+
void VcprojGenerator::initCompilerTool()
{
QString placement = project->first("OBJECTS_DIR").toQString();
@@ -1074,6 +1130,7 @@ void VcprojGenerator::initCompilerTool()
conf.compiler.ForcedIncludeFiles = project->values("PRECOMPILED_HEADER").toQStringList();
}
+ conf.compiler.parseOptions(relevantCFlags(project->values("QMAKE_CFLAGS")));
conf.compiler.parseOptions(project->values("QMAKE_CXXFLAGS"));
if (project->isActiveConfig("windows"))
@@ -1568,11 +1625,12 @@ void VcprojGenerator::initExtraCompilerOutputs()
QString tmp_out;
if (!outputs.isEmpty())
- tmp_out = project->first(outputs.first().toKey()).toQString();
+ tmp_out = outputs.first().toQString();
if (project->values(ProKey(*it + ".CONFIG")).indexOf("combine") != -1) {
- // Combined output, only one file result
+ // Combined output, only one file result. Use .cbt file.
extraCompile.addFile(Option::fixPathToTargetOS(
- replaceExtraCompilerVariables(tmp_out, QString(), QString(), NoShell), false));
+ replaceExtraCompilerVariables(tmp_out + customBuildToolFilterFileSuffix,
+ QString(), QString(), NoShell), false));
} else if (!inputVars.isEmpty()) {
// One output file per input
const ProStringList &tmp_in = project->values(inputVars.first().toKey());