diff options
author | Joerg Bornemann <joerg.bornemann@theqtcompany.com> | 2014-12-22 14:54:08 +0100 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@theqtcompany.com> | 2015-01-28 12:33:18 +0000 |
commit | 5582851c33a768cfe63a418da0bf0df69260f227 (patch) | |
tree | d477e777afb11922f97ad2aa7032620022448a09 /qmake | |
parent | ce9c4915d53c9dabfa3b5a28e62ecd2bb49337d4 (diff) |
turn off nmake inference rule generation on detected conflicts
When there are source files with the same file name in different
directories of the project, then nmake's inference rules might pick up
the wrong source file. Note that this even happens when only one of those
files is in SOURCES. The existence of conflicting file names is enough
to cause hard-to-find build failures.
The usual work-around for this situation is CONFIG+=no_batch.
This is now done automatically when a conflict situation is detected and
a warning message is printed.
Task-number: QTBUG-13496
Change-Id: Icd81027407d3d489dbc50231e5ed8bcb91f8d2bc
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'qmake')
-rw-r--r-- | qmake/generators/win32/msvc_nmake.cpp | 53 | ||||
-rw-r--r-- | qmake/generators/win32/msvc_nmake.h | 1 |
2 files changed, 48 insertions, 6 deletions
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 37e247c5cb..e6170e4825 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -37,6 +37,7 @@ #include <qregexp.h> #include <qdir.h> +#include <qdiriterator.h> #include <qset.h> #include <windows/registry_p.h> @@ -425,6 +426,17 @@ void NmakeMakefileGenerator::init() } } +QStringList NmakeMakefileGenerator::sourceFilesForImplicitRulesFilter() +{ + QStringList filter; + const QChar wildcard = QLatin1Char('*'); + foreach (const QString &ext, Option::c_ext) + filter << wildcard + ext; + foreach (const QString &ext, Option::cpp_ext) + filter << wildcard + ext; + return filter; +} + void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t) { t << ".SUFFIXES:"; @@ -434,12 +446,9 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t) t << " " << (*cppit); t << endl << endl; - if(!project->isActiveConfig("no_batch")) { - // Batchmode doesn't use the non implicit rules QMAKE_RUN_CXX & QMAKE_RUN_CC - project->variables().remove("QMAKE_RUN_CXX"); - project->variables().remove("QMAKE_RUN_CC"); - - QSet<QString> source_directories; + bool useInferenceRules = !project->isActiveConfig("no_batch"); + QSet<QString> source_directories; + if (useInferenceRules) { source_directories.insert("."); static const char * const directories[] = { "UI_SOURCES_DIR", "UI_DIR", 0 }; for (int y = 0; directories[y]; y++) { @@ -462,6 +471,38 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t) } } + // nmake's inference rules might pick up the wrong files when encountering source files with + // the same name in different directories. In this situation, turn inference rules off. + QHash<QString, QString> fileNames; + bool duplicatesFound = false; + const QStringList sourceFilesFilter = sourceFilesForImplicitRulesFilter(); + QStringList fixifiedSourceDirs = fileFixify(source_directories.toList(), FileFixifyAbsolute); + fixifiedSourceDirs.removeDuplicates(); + foreach (const QString &sourceDir, fixifiedSourceDirs) { + QDirIterator dit(sourceDir, sourceFilesFilter, QDir::Files | QDir::NoDotAndDotDot); + while (dit.hasNext()) { + dit.next(); + QString &duplicate = fileNames[dit.fileName()]; + if (duplicate.isNull()) { + duplicate = dit.filePath(); + } else { + warn_msg(WarnLogic, "%s conflicts with %s", qPrintable(duplicate), + qPrintable(dit.filePath())); + duplicatesFound = true; + } + } + } + if (duplicatesFound) { + useInferenceRules = false; + warn_msg(WarnLogic, "Automatically turning off nmake's inference rules. (CONFIG += no_batch)"); + } + } + + if (useInferenceRules) { + // Batchmode doesn't use the non implicit rules QMAKE_RUN_CXX & QMAKE_RUN_CC + project->variables().remove("QMAKE_RUN_CXX"); + project->variables().remove("QMAKE_RUN_CC"); + foreach (const QString &sourceDir, source_directories) { if (sourceDir.isEmpty()) continue; diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h index 753223b98e..c514fa4452 100644 --- a/qmake/generators/win32/msvc_nmake.h +++ b/qmake/generators/win32/msvc_nmake.h @@ -48,6 +48,7 @@ class NmakeMakefileGenerator : public Win32MakefileGenerator void writeLinkCommand(QTextStream &t, const QString &extraFlags = QString(), const QString &extraInlineFileContent = QString()); int msvcVersion() const; void init(); + static QStringList sourceFilesForImplicitRulesFilter(); protected: virtual void writeSubMakeCall(QTextStream &t, const QString &callPrefix, |