QmakeProjectManager: Compare the right set of arguments

... when determining whether to re-run qmake.
We need to look at the effective arguments, not the user arguments.
Of course, the whole approach is still a shaky heuristic, but it should
be more correct now than it was before.

Fixes: QTCREATORBUG-24538
Change-Id: I763f8095becacde0f9549890161b8a47c6344b6b
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Christian Kandeler
2020-09-08 10:32:17 +02:00
parent d7229d4afc
commit 1e452f1ad3
4 changed files with 26 additions and 20 deletions

View File

@@ -126,13 +126,12 @@ void dumpQMakeAssignments(const QList<QMakeAssignment> &list)
} }
} }
void MakeFileParse::parseAssignments(QList<QMakeAssignment> *assignments) QList<QMakeAssignment> MakeFileParse::parseAssignments(const QList<QMakeAssignment> &assignments)
{ {
bool foundSeparateDebugInfo = false; bool foundSeparateDebugInfo = false;
bool foundForceDebugInfo = false; bool foundForceDebugInfo = false;
QList<QMakeAssignment> oldAssignments = *assignments; QList<QMakeAssignment> filteredAssignments;
assignments->clear(); foreach (const QMakeAssignment &qa, assignments) {
foreach (const QMakeAssignment &qa, oldAssignments) {
if (qa.variable == QLatin1String("CONFIG")) { if (qa.variable == QLatin1String("CONFIG")) {
QStringList values = qa.value.split(QLatin1Char(' ')); QStringList values = qa.value.split(QLatin1Char(' '));
QStringList newValues; QStringList newValues;
@@ -218,10 +217,10 @@ void MakeFileParse::parseAssignments(QList<QMakeAssignment> *assignments)
if (!newValues.isEmpty()) { if (!newValues.isEmpty()) {
QMakeAssignment newQA = qa; QMakeAssignment newQA = qa;
newQA.value = newValues.join(QLatin1Char(' ')); newQA.value = newValues.join(QLatin1Char(' '));
assignments->append(newQA); filteredAssignments.append(newQA);
} }
} else { } else {
assignments->append(qa); filteredAssignments.append(qa);
} }
} }
@@ -233,15 +232,16 @@ void MakeFileParse::parseAssignments(QList<QMakeAssignment> *assignments)
newQA.variable = QLatin1String("CONFIG"); newQA.variable = QLatin1String("CONFIG");
newQA.op = QLatin1String("+="); newQA.op = QLatin1String("+=");
newQA.value = QLatin1String("force_debug_info"); newQA.value = QLatin1String("force_debug_info");
assignments->append(newQA); filteredAssignments.append(newQA);
} else if (foundSeparateDebugInfo) { } else if (foundSeparateDebugInfo) {
// Found only separate_debug_info, so readd it // Found only separate_debug_info, so readd it
QMakeAssignment newQA; QMakeAssignment newQA;
newQA.variable = QLatin1String("CONFIG"); newQA.variable = QLatin1String("CONFIG");
newQA.op = QLatin1String("+="); newQA.op = QLatin1String("+=");
newQA.value = QLatin1String("separate_debug_info"); newQA.value = QLatin1String("separate_debug_info");
assignments->append(newQA); filteredAssignments.append(newQA);
} }
return filteredAssignments;
} }
static FilePath findQMakeBinaryFromMakefile(const QString &makefile) static FilePath findQMakeBinaryFromMakefile(const QString &makefile)
@@ -270,7 +270,7 @@ static FilePath findQMakeBinaryFromMakefile(const QString &makefile)
return FilePath(); return FilePath();
} }
MakeFileParse::MakeFileParse(const QString &makefile) MakeFileParse::MakeFileParse(const QString &makefile, Mode mode) : m_mode(mode)
{ {
qCDebug(logging()) << "Parsing makefile" << makefile; qCDebug(logging()) << "Parsing makefile" << makefile;
if (!QFileInfo::exists(makefile)) { if (!QFileInfo::exists(makefile)) {
@@ -367,9 +367,9 @@ void MakeFileParse::parseCommandLine(const QString &command, const QString &proj
dumpQMakeAssignments(assignments); dumpQMakeAssignments(assignments);
// Filter out CONFIG arguments we know into m_qmakeBuildConfig and m_config // Filter out CONFIG arguments we know into m_qmakeBuildConfig and m_config
parseAssignments(&assignments); const QList<QMakeAssignment> filteredAssignments = parseAssignments(assignments);
qCDebug(logging()) << " After parsing"; qCDebug(logging()) << " After parsing";
dumpQMakeAssignments(assignments); dumpQMakeAssignments(filteredAssignments);
qCDebug(logging()) << " Explicit Debug" << m_qmakeBuildConfig.explicitDebug; qCDebug(logging()) << " Explicit Debug" << m_qmakeBuildConfig.explicitDebug;
qCDebug(logging()) << " Explicit Release" << m_qmakeBuildConfig.explicitRelease; qCDebug(logging()) << " Explicit Release" << m_qmakeBuildConfig.explicitRelease;
@@ -385,7 +385,9 @@ void MakeFileParse::parseCommandLine(const QString &command, const QString &proj
<< (m_config.separateDebugInfo == TriState::Enabled); << (m_config.separateDebugInfo == TriState::Enabled);
// Create command line of all unfiltered arguments // Create command line of all unfiltered arguments
foreach (const QMakeAssignment &qa, assignments) const QList<QMakeAssignment> &assignmentsToUse = m_mode == Mode::FilterKnownConfigValues
? filteredAssignments : assignments;
foreach (const QMakeAssignment &qa, assignmentsToUse)
QtcProcess::addArg(&m_unparsedArguments, qa.variable + qa.op + qa.value); QtcProcess::addArg(&m_unparsedArguments, qa.variable + qa.op + qa.value);
if (!afterAssignments.isEmpty()) { if (!afterAssignments.isEmpty()) {
QtcProcess::addArg(&m_unparsedArguments, QLatin1String("-after")); QtcProcess::addArg(&m_unparsedArguments, QLatin1String("-after"));
@@ -517,7 +519,7 @@ void QmakeProjectManagerPlugin::testMakefileParser()
QFETCH(bool, separateDebugInfo); QFETCH(bool, separateDebugInfo);
QFETCH(int, effectiveBuildConfig); QFETCH(int, effectiveBuildConfig);
MakeFileParse parser("/tmp/something"); MakeFileParse parser("/tmp/something", MakeFileParse::Mode::FilterKnownConfigValues);
parser.parseCommandLine(command, project); parser.parseCommandLine(command, project);
QCOMPARE(Utils::QtcProcess::splitArgs(parser.unparsedArguments()), QCOMPARE(Utils::QtcProcess::splitArgs(parser.unparsedArguments()),

View File

@@ -42,7 +42,8 @@ struct QMakeAssignment
class MakeFileParse class MakeFileParse
{ {
public: public:
MakeFileParse(const QString &makefile); enum class Mode { FilterKnownConfigValues, DoNotFilterKnownConfigValues };
MakeFileParse(const QString &makefile, Mode mode);
enum MakefileState { MakefileMissing, CouldNotParse, Okay }; enum MakefileState { MakefileMissing, CouldNotParse, Okay };
@@ -63,7 +64,7 @@ public:
private: private:
void parseArgs(const QString &args, const QString &project, void parseArgs(const QString &args, const QString &project,
QList<QMakeAssignment> *assignments, QList<QMakeAssignment> *afterAssignments); QList<QMakeAssignment> *assignments, QList<QMakeAssignment> *afterAssignments);
void parseAssignments(QList<QMakeAssignment> *assignments); QList<QMakeAssignment> parseAssignments(const QList<QMakeAssignment> &assignments);
class QmakeBuildConfig class QmakeBuildConfig
{ {
@@ -74,6 +75,7 @@ private:
bool explicitNoBuildAll = false; bool explicitNoBuildAll = false;
}; };
const Mode m_mode;
MakefileState m_state; MakefileState m_state;
Utils::FilePath m_qmakePath; Utils::FilePath m_qmakePath;
QString m_srcProFile; QString m_srcProFile;

View File

@@ -490,7 +490,7 @@ QmakeBuildConfiguration::MakefileState QmakeBuildConfiguration::compareToImportF
qCDebug(logs) << "QMakeBuildConfiguration::compareToImport"; qCDebug(logs) << "QMakeBuildConfiguration::compareToImport";
QMakeStep *qs = qmakeStep(); QMakeStep *qs = qmakeStep();
MakeFileParse parse(makefile); MakeFileParse parse(makefile, MakeFileParse::Mode::DoNotFilterKnownConfigValues);
if (parse.makeFileState() == MakeFileParse::MakefileMissing) { if (parse.makeFileState() == MakeFileParse::MakefileMissing) {
qCDebug(logs) << "**Makefile missing"; qCDebug(logs) << "**Makefile missing";
@@ -546,10 +546,12 @@ QmakeBuildConfiguration::MakefileState QmakeBuildConfiguration::compareToImportF
// and compare that on its own // and compare that on its own
QString workingDirectory = QFileInfo(makefile).absolutePath(); QString workingDirectory = QFileInfo(makefile).absolutePath();
QStringList actualArgs; QStringList actualArgs;
QString userArgs = macroExpander()->expandProcessArgs(qs->userArguments()); QString allArgs = macroExpander()->expandProcessArgs(qs->allArguments(
// This copies the settings from userArgs to actualArgs (minus some we QtKitAspect::qtVersion(target()->kit()), QMakeStep::ArgumentFlag::Expand));
// This copies the settings from allArgs to actualArgs (minus some we
// are not interested in), splitting them up into individual strings: // are not interested in), splitting them up into individual strings:
extractSpecFromArguments(&userArgs, workingDirectory, version, &actualArgs); extractSpecFromArguments(&allArgs, workingDirectory, version, &actualArgs);
actualArgs.removeFirst(); // Project file.
const QString actualSpec = qs->mkspec(); const QString actualSpec = qs->mkspec();
QString qmakeArgs = parse.unparsedArguments(); QString qmakeArgs = parse.unparsedArguments();

View File

@@ -126,7 +126,7 @@ QList<void *> QmakeProjectImporter::examineDirectory(const FilePath &importPath)
qCDebug(logs) << " Parsing makefile" << file; qCDebug(logs) << " Parsing makefile" << file;
// find interesting makefiles // find interesting makefiles
QString makefile = importPath.toString() + QLatin1Char('/') + file; QString makefile = importPath.toString() + QLatin1Char('/') + file;
MakeFileParse parse(makefile); MakeFileParse parse(makefile, MakeFileParse::Mode::FilterKnownConfigValues);
if (parse.makeFileState() != MakeFileParse::Okay) { if (parse.makeFileState() != MakeFileParse::Okay) {
qCDebug(logs) << " Parsing the makefile failed" << makefile; qCDebug(logs) << " Parsing the makefile failed" << makefile;
continue; continue;