qmake/vcxproj: Fix "CONFIG += combine" extra compilers
Extra compilers with "CONFIG += combine" were broken for qmake's vcxproj generator since forever. Usually, extra compilers are handled by attaching the Custom Build Tool to the input file. This is not possible for combine extra compilers, because they map multiple inputs to one output. We cannot attach the Custom Build Tool to the output either, because this would result in circular dependency errors (output trying to create output itself). To fix this, we create a custom build tool fake file (.cbt) for the output and attach the Custom Build Tool there. This is the same trick we do for regular extra compilers that have C++ sources as input (e.g. the one that generates moc_predefs.h). Pick-to: 6.2 5.15 Fixes: QTBUG-94806 Change-Id: Ib808a43fead737df91b89a1ac5e180aeae37efae Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
parent
3681369120
commit
e022ff0a8e
@ -40,6 +40,8 @@
|
||||
#include <qregularexpression.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
//#define DEBUG_SOLUTION_GEN
|
||||
|
||||
@ -806,33 +808,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1545,9 +1576,10 @@ void VcprojGenerator::initExtraCompilerOutputs()
|
||||
if (!outputs.isEmpty())
|
||||
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());
|
||||
|
Loading…
Reference in New Issue
Block a user