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 <qregularexpression.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
//#define DEBUG_SOLUTION_GEN
|
//#define DEBUG_SOLUTION_GEN
|
||||||
|
|
||||||
@ -806,38 +808,67 @@ void VcprojGenerator::init()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all input files for a custom compiler into a map for uniqueness,
|
// Helper function to create a fake file foo.cbt for the project view.
|
||||||
// unless the compiler is configure as a combined stage, then use the first one
|
//
|
||||||
|
// 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")) {
|
for (const ProString &quc : project->values("QMAKE_EXTRA_COMPILERS")) {
|
||||||
const ProStringList &invar = project->values(ProKey(quc + ".input"));
|
const ProStringList &invar = project->values(ProKey(quc + ".input"));
|
||||||
const QString compiler_out = project->first(ProKey(quc + ".output")).toQString();
|
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());
|
QStringList inputFiles;
|
||||||
if (!fileList.isEmpty()) {
|
for (auto it = invar.begin(); it != invar.end(); ++it)
|
||||||
if (project->values(ProKey(quc + ".CONFIG")).indexOf("combine") != -1)
|
inputFiles += project->values(it->toKey()).toQStringList();
|
||||||
fileList.erase(fileList.begin() + 1, fileList.end());
|
|
||||||
for (ProStringList::ConstIterator fit = fileList.constBegin(); fit != fileList.constEnd(); ++fit) {
|
if (project->values(ProKey(quc + ".CONFIG")).contains("combine")) {
|
||||||
QString file = (*fit).toQString();
|
// 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 (verifyExtraCompiler(quc, file)) {
|
||||||
if (!hasBuiltinCompiler(file)) {
|
if (!hasBuiltinCompiler(file)) {
|
||||||
extraCompilerSources[file] += quc.toQString();
|
extraCompilerSources[file] += quc.toQString();
|
||||||
} else {
|
} else {
|
||||||
// Create a fake file foo.moc.cbt for the project view.
|
QString out;
|
||||||
// This prevents VS from complaining about a circular
|
std::tie(std::ignore, out)
|
||||||
// dependency from foo.moc -> foo.moc.
|
= addExtraCompilerSourceWithCustomBuildToolFakeFile(compiler_out,
|
||||||
QString realOut = replaceExtraCompilerVariables(
|
quc,
|
||||||
compiler_out, file, QString(), NoShell);
|
QStringList(file));
|
||||||
QString out = realOut + customBuildToolFilterFileSuffix;
|
|
||||||
createCustomBuildToolFakeFile(out, realOut);
|
|
||||||
out = Option::fixPathToTargetOS(out, false);
|
|
||||||
extraCompilerSources[out] += quc.toQString();
|
|
||||||
extraCompilerOutputs[out] = file;
|
extraCompilerOutputs[out] = file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if 0 // Debugging
|
#if 0 // Debugging
|
||||||
for (auto it = extraCompilerSources.cbegin(), end = extraCompilerSources.cend(); it != end; ++it)
|
for (auto it = extraCompilerSources.cbegin(), end = extraCompilerSources.cend(); it != end; ++it)
|
||||||
@ -1545,9 +1576,10 @@ void VcprojGenerator::initExtraCompilerOutputs()
|
|||||||
if (!outputs.isEmpty())
|
if (!outputs.isEmpty())
|
||||||
tmp_out = outputs.first().toQString();
|
tmp_out = outputs.first().toQString();
|
||||||
if (project->values(ProKey(*it + ".CONFIG")).indexOf("combine") != -1) {
|
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(
|
extraCompile.addFile(Option::fixPathToTargetOS(
|
||||||
replaceExtraCompilerVariables(tmp_out, QString(), QString(), NoShell), false));
|
replaceExtraCompilerVariables(tmp_out + customBuildToolFilterFileSuffix,
|
||||||
|
QString(), QString(), NoShell), false));
|
||||||
} else if (!inputVars.isEmpty()) {
|
} else if (!inputVars.isEmpty()) {
|
||||||
// One output file per input
|
// One output file per input
|
||||||
const ProStringList &tmp_in = project->values(inputVars.first().toKey());
|
const ProStringList &tmp_in = project->values(inputVars.first().toKey());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user