diff options
Diffstat (limited to 'qmake/generators/win32/msvc_objectmodel.cpp')
-rw-r--r-- | qmake/generators/win32/msvc_objectmodel.cpp | 257 |
1 files changed, 144 insertions, 113 deletions
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index eacf9a0e5e..6517e5c451 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "msvc_objectmodel.h" #include "msvc_vcproj.h" @@ -40,36 +15,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 --------------------------------------------------------- @@ -330,14 +311,12 @@ static QString vcCommandSeparator() // of the custom commands into it, and putting an "if errorlevel goto" statement behind it. // As we want every sub-command to be error-checked (as is done by makefile-based // backends), we insert the checks ourselves, using the undocumented jump target. - static QString cmdSep = - QLatin1String("
if errorlevel 1 goto VCReportError
"); - return cmdSep; + return QStringLiteral("
if errorlevel 1 goto VCReportError
"); } static void unknownOptionWarning(const char *tool, const char *option) { - static bool firstCall = true; + Q_CONSTINIT static bool firstCall = true; warn_msg(WarnLogic, "Could not parse %s option '%s'; added to AdditionalOptions.", tool, option); if (firstCall) { firstCall = false; @@ -404,7 +383,7 @@ VCCLCompilerTool::VCCLCompilerTool() CompileForArchitecture(archUnknown), InterworkCalls(unset), EnablePREfast(unset), - DisplayFullPaths(unset), + DisplayFullPaths(_False), MultiProcessorCompilation(unset), GenerateXMLDocumentationFiles(unset), CreateHotpatchableImage(unset) @@ -883,7 +862,7 @@ bool VCCLCompilerTool::parseOption(const char* option) } break; } - // Fallthrough + [[fallthrough]]; default: found = false; break; } @@ -1147,12 +1126,40 @@ 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 QRegularExpression rex("(c(?:\\+\\+)?)(.+)"); + auto m = rex.match(option + 5); + if (m.hasMatch()) { + QString *var = nullptr; + const QStringList *knownVersions = nullptr; + QString valuePrefix; + auto lang = m.capturedView(1); + auto version = m.capturedView(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 +1477,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; @@ -1520,7 +1540,7 @@ bool VCLinkerTool::parseOption(const char* option) { QStringList both = QString(option+6).split(","); HeapReserveSize = both[0].toLongLong(); - if(both.count() == 2) + if(both.size() == 2) HeapCommitSize = both[1].toLongLong(); } break; @@ -1560,24 +1580,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} @@ -1625,7 +1649,13 @@ bool VCLinkerTool::parseOption(const char* option) MapLines = _True; break; case 0x341a6b5: // /MERGE:from=to - MergeSections = option+7; + if (MergeSections.isEmpty()) { + MergeSections = option+7; + } else { + // vcxproj files / the VS property editor do not support multiple MergeSections entries. + // Add them as additional options. + AdditionalOptions += option; + } break; case 0x0341d8c: // /MIDL:@file MidlCommandFile = option+7; @@ -1699,7 +1729,7 @@ bool VCLinkerTool::parseOption(const char* option) { QStringList both = QString(option+7).split(","); StackReserveSize = both[0].toLongLong(); - if(both.count() == 2) + if(both.size() == 2) StackCommitSize = both[1].toLongLong(); } break; @@ -2202,13 +2232,13 @@ void VCFilter::addFile(const VCFilterFile& fileInfo) void VCFilter::addFiles(const QStringList& fileList) { - for (int i = 0; i < fileList.count(); ++i) + for (int i = 0; i < fileList.size(); ++i) addFile(fileList.at(i)); } void VCFilter::addFiles(const ProStringList& fileList) { - for (int i = 0; i < fileList.count(); ++i) + for (int i = 0; i < fileList.size(); ++i) addFile(fileList.at(i).toQString()); } @@ -2242,7 +2272,7 @@ void VCFilter::modifyPCHstage(QString str) lines << "* WARNING: All changes made in this file will be lost."; lines << "--------------------------------------------------------------------*/"; lines << "#include \"" + Project->precompHFilename + "\""; - for (const QString &line : qAsConst(lines)) + for (const QString &line : std::as_const(lines)) CustomBuildTool.CommandLine += "echo " + line + ">>" + toFile; return; } @@ -2275,7 +2305,7 @@ void VCFilter::modifyPCHstage(QString str) VCFilterFile VCFilter::findFile(const QString &filePath, bool *found) const { - for (int i = 0; i < Files.count(); ++i) { + for (int i = 0; i < Files.size(); ++i) { const VCFilterFile &f = Files.at(i); if (f.file == filePath) { *found = true; @@ -2301,7 +2331,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile); // Remove the fake file suffix we've added initially to generate correct command lines. - inFile.chop(Project->customBuildToolFilterFileSuffix.length()); + inFile.chop(Project->customBuildToolFilterFileSuffix.size()); // qDebug("*** Extra compiler file has object mapped file '%s' => '%s'", qPrintable(inFile), qPrintable(objectMappedFile.join(' '))); } @@ -2313,7 +2343,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) CustomBuildTool.ToolPath.clear(); CustomBuildTool.ToolName = QLatin1String(_VCCustomBuildTool); - for (int x = 0; x < extraCompilers.count(); ++x) { + for (int x = 0; x < extraCompilers.size(); ++x) { const QString &extraCompilerName = extraCompilers.at(x); if (!Project->verifyExtraCompiler(extraCompilerName, inFile) && !hasBuiltIn) @@ -2358,7 +2388,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) configs.contains("dep_existing_only"), true /* checkCommandAvailability */); } - for (int i = 0; i < deps.count(); ++i) + for (int i = 0; i < deps.size(); ++i) deps[i] = Option::fixPathToTargetOS( Project->replaceExtraCompilerVariables( deps.at(i), inFile, out, MakefileGenerator::NoShell), @@ -2367,9 +2397,9 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) if (combined) { // Add dependencies for each file const ProStringList &tmp_in = Project->project->values(ProKey(extraCompilerName + ".input")); - for (int a = 0; a < tmp_in.count(); ++a) { + for (int a = 0; a < tmp_in.size(); ++a) { const ProStringList &files = Project->project->values(tmp_in.at(a).toKey()); - for (int b = 0; b < files.count(); ++b) { + for (int b = 0; b < files.size(); ++b) { QString file = files.at(b).toQString(); deps += Project->findDependencies(file); inputs += Option::fixPathToTargetOS(file, false); @@ -2399,10 +2429,11 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) cmd_name = cmd.left(space); else cmd_name = cmd; + cmd_name = cmd_name.trimmed(); } // Fixify paths - for (int i = 0; i < deps.count(); ++i) + for (int i = 0; i < deps.size(); ++i) deps[i] = Option::fixPathToTargetOS(deps[i], false); @@ -2420,7 +2451,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) deps += CustomBuildTool.AdditionalDependencies; // Make sure that all deps are only once QStringList uniqDeps; - for (int c = 0; c < deps.count(); ++c) { + for (int c = 0; c < deps.size(); ++c) { QString aDep = deps.at(c); if (!aDep.isEmpty()) uniqDeps << aDep; @@ -2431,7 +2462,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) // Ensure that none of the output files are also dependencies. Or else, the custom buildstep // will be rebuild every time, even if nothing has changed. - for (const QString &output : qAsConst(CustomBuildTool.Outputs)) + for (const QString &output : std::as_const(CustomBuildTool.Outputs)) CustomBuildTool.AdditionalDependencies.removeAll(output); useCustomBuildTool = !CustomBuildTool.CommandLine.isEmpty(); @@ -2466,7 +2497,7 @@ const VCFilter &VCProjectSingleConfig::filterByName(const QString &name) const const VCFilter &VCProjectSingleConfig::filterForExtraCompiler(const QString &compilerName) const { - for (int i = 0; i < ExtraCompilersFiles.count(); ++i) + for (int i = 0; i < ExtraCompilersFiles.size(); ++i) if (ExtraCompilersFiles.at(i).Name == compilerName) return ExtraCompilersFiles.at(i); @@ -2546,7 +2577,7 @@ void VCProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool) outputFilter(tempProj, xml, "Distribution Files"); QSet<QString> extraCompilersInProject; - for (int i = 0; i < tool.ExtraCompilersFiles.count(); ++i) { + for (int i = 0; i < tool.ExtraCompilersFiles.size(); ++i) { const QString &compilerName = tool.ExtraCompilersFiles.at(i).Name; if (!extraCompilersInProject.contains(compilerName)) { extraCompilersInProject += compilerName; @@ -2554,7 +2585,7 @@ void VCProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool) } } - for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) { + for (int x = 0; x < tempProj.ExtraCompilers.size(); ++x) { outputFilter(tempProj, xml, tempProj.ExtraCompilers.at(x)); } outputFilter(tempProj, xml, "Root Files"); @@ -2565,7 +2596,7 @@ void VCProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool) void VCProjectWriter::write(XmlOutput &xml, VCProject &tool) { - if (tool.SingleProjects.count() == 0) { + if (tool.SingleProjects.size() == 0) { warn_msg(WarnLogic, "Generator: .NET: no single project in merge project, no output"); return; } @@ -2585,7 +2616,7 @@ void VCProjectWriter::write(XmlOutput &xml, VCProject &tool) << closetag(_Platforms) << tag(_Configurations); // Output each configuration - for (int i = 0; i < tool.SingleProjects.count(); ++i) + for (int i = 0; i < tool.SingleProjects.size(); ++i) write(xml, tool.SingleProjects.at(i).Configuration); xml << closetag(_Configurations) << tag(q_Files); @@ -2598,7 +2629,7 @@ void VCProjectWriter::write(XmlOutput &xml, VCProject &tool) outputFilter(tool, xml, "Resource Files"); outputFilter(tool, xml, "Deployment Files"); outputFilter(tool, xml, "Distribution Files"); - for (int x = 0; x < tool.ExtraCompilers.count(); ++x) { + for (int x = 0; x < tool.ExtraCompilers.size(); ++x) { outputFilter(tool, xml, tool.ExtraCompilers.at(x)); } outputFilter(tool, xml, "Root Files"); @@ -2900,7 +2931,7 @@ void VCProjectWriter::write(XmlOutput &xml, const VCConfiguration &tool) void VCProjectWriter::write(XmlOutput &xml, VCFilter &tool) { - if(!tool.Files.count()) + if(!tool.Files.size()) return; if (!tool.Name.isEmpty()) { @@ -2910,7 +2941,7 @@ void VCProjectWriter::write(XmlOutput &xml, VCFilter &tool) << attrS(_UniqueIdentifier, tool.Guid) << attrT(_ParseFiles, tool.ParseFiles); } - for (int i = 0; i < tool.Files.count(); ++i) { + for (int i = 0; i < tool.Files.size(); ++i) { const VCFilterFile &info = tool.Files.at(i); xml << tag(q_File) << attrS(_RelativePath, Option::fixPathToTargetOS(info.file)) @@ -2934,11 +2965,11 @@ void VCProjectWriter::outputFilter(VCProject &project, XmlOutput &xml, const QSt QString name, extfilter, guid; triState parse = unset; - for (int i = 0; i < project.SingleProjects.count(); ++i) { + for (int i = 0; i < project.SingleProjects.size(); ++i) { const VCFilter filter = project.SingleProjects.at(i).filterByName(filtername); // Merge all files in this filter to root tree - for (int x = 0; x < filter.Files.count(); ++x) + for (int x = 0; x < filter.Files.size(); ++x) root->addElement(filter.Files.at(x)); // Save filter setting from first filter. Next filters @@ -2973,7 +3004,7 @@ void VCProjectWriter::outputFileConfigs(VCProject &project, XmlOutput &xml, cons { xml << tag(q_File) << attrS(_RelativePath, Option::fixPathToTargetOS(info.file)); - for (int i = 0; i < project.SingleProjects.count(); ++i) { + for (int i = 0; i < project.SingleProjects.size(); ++i) { VCFilter filter = project.SingleProjects.at(i).filterByName(filtername); if (filter.Config) // only if the filter is not empty outputFileConfig(filter, xml, info.file); |