diff options
Diffstat (limited to 'qmake/generators')
-rw-r--r-- | qmake/generators/mac/pbuilder_pbx.cpp | 24 | ||||
-rw-r--r-- | qmake/generators/mac/pbuilder_pbx.h | 1 | ||||
-rw-r--r-- | qmake/generators/makefile.cpp | 77 | ||||
-rw-r--r-- | qmake/generators/makefile.h | 13 | ||||
-rw-r--r-- | qmake/generators/unix/unixmake2.cpp | 28 | ||||
-rw-r--r-- | qmake/generators/win32/msbuild_objectmodel.cpp | 6 | ||||
-rw-r--r-- | qmake/generators/win32/msvc_objectmodel.cpp | 161 | ||||
-rw-r--r-- | qmake/generators/win32/msvc_objectmodel.h | 9 | ||||
-rw-r--r-- | qmake/generators/win32/msvc_vcproj.cpp | 112 |
9 files changed, 320 insertions, 111 deletions
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index c2f6df7787..832794fc76 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -778,6 +778,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) { QString mkfile = pbx_dir + Option::dir_sep + "qt_preprocess.mak"; QFile mkf(mkfile); + ProStringList outputPaths; + ProStringList inputPaths; if(mkf.open(QIODevice::WriteOnly | QIODevice::Text)) { writingUnixMakefileGenerator = true; debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData()); @@ -827,8 +829,11 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) ++added; const QString file_name = fileFixify(fn, FileFixifyFromOutdir); const QString tmpOut = fileFixify(tmp_out.first().toQString(), FileFixifyFromOutdir); - mkt << ' ' << escapeDependencyPath(Option::fixPathToTargetOS( + QString path = escapeDependencyPath(Option::fixPathToTargetOS( replaceExtraCompilerVariables(tmpOut, file_name, QString(), NoShell))); + mkt << ' ' << path; + inputPaths << fn; + outputPaths << path; } } } @@ -839,6 +844,14 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) mkt.flush(); mkf.close(); } + // Remove duplicates from build steps with "combine" + outputPaths.removeDuplicates(); + + // Don't create cycles. We only have one qt_preprocess.mak which runs different compilers + // whose inputs may depend on the output of another. The "compilers" step will run all + // compilers anyway + inputPaths.removeEach(outputPaths); + mkfile = fileFixify(mkfile); QString phase_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET"); // project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); @@ -849,10 +862,13 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("name", "Qt Preprocessors") << ";\n" + << "\t\t\t" << writeSettings("inputPaths", inputPaths, SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("outputPaths", outputPaths, SettingsAsList, 4) << ";\n" << "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";\n" << "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(Option::output_dir) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n" << "\t\t\t" << writeSettings("showEnvVarsInLog", "0") << ";\n" + << "\t\t\t" << writeSettings("alwaysOutOfDate", "1") << ";\n" << "\t\t};\n"; } @@ -2046,4 +2062,10 @@ ProjectBuilderMakefileGenerator::writeSettings(const QString &var, const ProStri return ret; } +bool +ProjectBuilderMakefileGenerator::inhibitMakeDirOutPath(const ProKey &path) const +{ + return path == "OBJECTS_DIR"; +} + QT_END_NAMESPACE diff --git a/qmake/generators/mac/pbuilder_pbx.h b/qmake/generators/mac/pbuilder_pbx.h index 1b90a3bbeb..fcf6b0557a 100644 --- a/qmake/generators/mac/pbuilder_pbx.h +++ b/qmake/generators/mac/pbuilder_pbx.h @@ -68,6 +68,7 @@ public: protected: bool doPrecompiledHeaders() const override { return false; } bool doDepends() const override { return writingUnixMakefileGenerator && UnixMakefileGenerator::doDepends(); } + bool inhibitMakeDirOutPath(const ProKey &path) const override; }; QT_END_NAMESPACE diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 5c61a3c65c..7ff921549d 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -173,6 +173,9 @@ MakefileGenerator::initOutPaths() if (noIO() || (project->first("TEMPLATE") == "subdirs")) continue; + if (inhibitMakeDirOutPath(dkey)) + continue; + QString path = project->first(dkey).toQString(); //not to be changed any further path = fileFixify(path, FileFixifyBackwards); debug_msg(3, "Fixed output_dir %s (%s) into %s", dirs[x], @@ -216,6 +219,18 @@ MakefileGenerator::initOutPaths() } } +/* + * For the given directory path, return true if MakefileGenerator::initOutPaths() should inhibit the + * creation of the directory. Overload this in subclasses. + */ +bool +MakefileGenerator::inhibitMakeDirOutPath(const ProKey &path) const +{ + Q_UNUSED(path); + return false; +} + + QMakeProject *MakefileGenerator::projectFile() const { @@ -945,6 +960,15 @@ MakefileGenerator::filterIncludedFiles(const char *var) inputs.end()); } +void MakefileGenerator::processSources() +{ + if (project->isActiveConfig("compile_included_sources")) + return; + + filterIncludedFiles("SOURCES"); + filterIncludedFiles("GENERATED_SOURCES"); +} + static QString qv(const ProString &val) { @@ -1286,7 +1310,14 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild) else cmd = QLatin1String("$(QINSTALL)"); cmd += " " + escapeFilePath(wild) + " " + escapeFilePath(dst_file); - inst << cmd; + + QString sedArgs = createSedArgs(ProKey("QMAKE_INSTALL_REPLACE"), fi.fileName()); + if (!sedArgs.isEmpty()) + inst << "$(SED) " + sedArgs + ' ' + escapeFilePath(wild) + " > " + + escapeFilePath(dst_file); + else + inst << cmd; + if (!noStrip && !project->isActiveConfig("debug_info") && !project->isActiveConfig("nostrip") && !fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP")) inst << QString("-") + var("QMAKE_STRIP") + " " + @@ -3412,35 +3443,43 @@ static QString windowsifyPath(const QString &str) return QString(str).replace('/', QLatin1String("\\\\\\\\")); } -QString MakefileGenerator::installMetaFile(const ProKey &replace_rule, const QString &src, const QString &dst) +QString MakefileGenerator::createSedArgs(const ProKey &replace_rule, const QString &file_name) const { - QString ret; - if (project->isEmpty(replace_rule) - || project->isActiveConfig("no_sed_meta_install")) { - ret += "$(INSTALL_FILE) " + escapeFilePath(src) + ' ' + escapeFilePath(dst); - } else { - QString sedargs; + QString sedargs; + if (!project->isEmpty(replace_rule) && !project->isActiveConfig("no_sed_meta_install")) { const ProStringList &replace_rules = project->values(replace_rule); for (int r = 0; r < replace_rules.size(); ++r) { const ProString match = project->first(ProKey(replace_rules.at(r) + ".match")), - replace = project->first(ProKey(replace_rules.at(r) + ".replace")); - if (!match.isEmpty() /*&& match != replace*/) { + replace = project->first(ProKey(replace_rules.at(r) + ".replace")), + filename = project->first(ProKey(replace_rules.at(r) + ".filename")); + if (!match.isEmpty() /*&& match != replace*/ + && (filename.isEmpty() || filename == file_name)) { sedargs += " -e " + shellQuote("s," + match + "," + replace + ",g"); - if (isWindowsShell() && project->first(ProKey(replace_rules.at(r) + ".CONFIG")).contains("path")) - sedargs += " -e " + shellQuote("s," + windowsifyPath(match.toQString()) - + "," + windowsifyPath(replace.toQString()) + ",gi"); + if (isWindowsShell() + && project->first(ProKey(replace_rules.at(r) + ".CONFIG")).contains("path")) + sedargs += " -e " + + shellQuote("s," + windowsifyPath(match.toQString()) + "," + + windowsifyPath(replace.toQString()) + ",gi"); } } - if (sedargs.isEmpty()) { - ret += "$(INSTALL_FILE) " + escapeFilePath(src) + ' ' + escapeFilePath(dst); - } else { - ret += "$(SED) " + sedargs + ' ' + escapeFilePath(src) + " > " + escapeFilePath(dst); - } + } + return sedargs; +} + +QString MakefileGenerator::installMetaFile(const ProKey &replace_rule, const QString &src, + const QString &dst) const +{ + QString ret; + QString sedargs = createSedArgs(replace_rule); + if (sedargs.isEmpty()) { + ret = "$(INSTALL_FILE) " + escapeFilePath(src) + ' ' + escapeFilePath(dst); + } else { + ret = "$(SED) " + sedargs + ' ' + escapeFilePath(src) + " > " + escapeFilePath(dst); } return ret; } -QString MakefileGenerator::shellQuote(const QString &str) +QString MakefileGenerator::shellQuote(const QString &str) const { return isWindowsShell() ? IoUtils::shellQuoteWin(str) : IoUtils::shellQuoteUnix(str); } diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index a96b9c54da..106069c454 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -153,6 +153,7 @@ protected: void verifyCompilers(); virtual void init(); void initOutPaths(); + virtual bool inhibitMakeDirOutPath(const ProKey &path) const; struct Compiler { QString variable_in; @@ -194,10 +195,7 @@ protected: virtual bool doDepends() const { return Option::mkfile::do_deps; } void filterIncludedFiles(const char *); - void processSources() { - filterIncludedFiles("SOURCES"); - filterIncludedFiles("GENERATED_SOURCES"); - } + void processSources(); //for installs virtual QString defaultInstall(const QString &); @@ -251,8 +249,9 @@ public: protected: QString fileFixify(const QString &file, FileFixifyTypes fix = FileFixifyDefault, bool canon = true) const; QStringList fileFixify(const QStringList &files, FileFixifyTypes fix = FileFixifyDefault, bool canon = true) const; - - QString installMetaFile(const ProKey &replace_rule, const QString &src, const QString &dst); + QString createSedArgs(const ProKey &replace_rule, const QString &file_type = QString()) const; + QString installMetaFile(const ProKey &replace_rule, const QString &src, + const QString &dst) const; virtual bool processPrlFileBase(QString &origFile, const QStringRef &origName, const QStringRef &fixedBase, int slashOff); @@ -278,7 +277,7 @@ public: virtual bool mergeBuildProject(MakefileGenerator * /*other*/) { return false; } virtual bool openOutput(QFile &, const QString &build) const; bool isWindowsShell() const { return Option::dir_sep == QLatin1String("\\"); } - QString shellQuote(const QString &str); + QString shellQuote(const QString &str) const; virtual ProKey fullTargetVariable() const; }; Q_DECLARE_TYPEINFO(MakefileGenerator::Compiler, Q_MOVABLE_TYPE); diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index ad6a0e94f2..7cb55a57a1 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -37,6 +37,9 @@ #include <qdebug.h> #include <time.h> +#include <tuple> +#include <utility> + QT_BEGIN_NAMESPACE void @@ -1415,6 +1418,25 @@ UnixMakefileGenerator::libtoolFileName(bool fixify) return ret; } +static std::pair<ProStringList, ProStringList> +splitFrameworksAndLibs(const ProStringList &linkArgs) +{ + std::pair<ProStringList, ProStringList> result; + bool frameworkArg = false; + for (auto arg : linkArgs) { + if (frameworkArg) { + frameworkArg = false; + result.second += arg; + } else if (arg == "-framework") { + frameworkArg = true; + result.second += arg; + } else { + result.first += arg; + } + } + return result; +} + void UnixMakefileGenerator::writeLibtoolFile() { @@ -1489,7 +1511,13 @@ UnixMakefileGenerator::writeLibtoolFile() ProStringList libs; for (auto var : libVars) libs += fixLibFlags(var); + ProStringList frameworks; + std::tie(libs, frameworks) = splitFrameworksAndLibs(libs); t << "dependency_libs='" << fixDependencyLibs(libs).join(' ') << "'\n\n"; + if (!frameworks.isEmpty()) { + t << "# Frameworks that this library depends upon.\n"; + t << "inherited_linker_flags='" << frameworks.join(' ') << "'\n\n"; + } t << "# Version information for " << lname << "\n"; int maj = project->first("VER_MAJ").toInt(); 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()); |