summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qmake/generators/makefile.cpp9
-rw-r--r--qmake/generators/makefile.h1
-rw-r--r--qmake/generators/metamakefile.cpp39
-rw-r--r--qmake/generators/win32/winmakefile.cpp5
-rw-r--r--qmake/generators/win32/winmakefile.h3
-rw-r--r--tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro5
-rw-r--r--tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp4
-rw-r--r--tests/auto/tools/qmake/tst_qmake.cpp15
8 files changed, 81 insertions, 0 deletions
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 2082bd6dc3..59cae332d8 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -3456,4 +3456,13 @@ QString MakefileGenerator::shellQuote(const QString &str)
return isWindowsShell() ? IoUtils::shellQuoteWin(str) : IoUtils::shellQuoteUnix(str);
}
+/*
+ * Returns the name of the variable that contains the fully resolved target
+ * (including DESTDIR) of this generator.
+ */
+ProKey MakefileGenerator::fullTargetVariable() const
+{
+ return "TARGET";
+}
+
QT_END_NAMESPACE
diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h
index ac1d5abb11..45250a6aa2 100644
--- a/qmake/generators/makefile.h
+++ b/qmake/generators/makefile.h
@@ -276,6 +276,7 @@ public:
virtual bool openOutput(QFile &, const QString &build) const;
bool isWindowsShell() const { return Option::dir_sep == QLatin1String("\\"); }
QString shellQuote(const QString &str);
+ virtual ProKey fullTargetVariable() const;
};
Q_DECLARE_TYPEINFO(MakefileGenerator::Compiler, Q_MOVABLE_TYPE);
Q_DECLARE_OPERATORS_FOR_FLAGS(MakefileGenerator::FileFixifyTypes)
diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp
index 705ad7008a..22a72100f7 100644
--- a/qmake/generators/metamakefile.cpp
+++ b/qmake/generators/metamakefile.cpp
@@ -33,6 +33,10 @@
#include "project.h"
#include "cachekeys.h"
+#include <algorithm>
+#include <iterator>
+#include <utility>
+
#define BUILDSMETATYPE 1
#define SUBDIRSMETATYPE 2
@@ -58,6 +62,7 @@ private:
void clearBuilds();
MakefileGenerator *processBuild(const ProString &);
void accumulateVariableFromBuilds(const ProKey &name, Build *build) const;
+ void checkForConflictingTargets() const;
public:
@@ -186,6 +191,7 @@ BuildsMetaMakefileGenerator::write()
if(!build->makefile) {
ret = false;
} else if(build == glue) {
+ checkForConflictingTargets();
accumulateVariableFromBuilds("QMAKE_INTERNAL_INCLUDED_FILES", build);
ret = build->makefile->writeProjectMakefile();
} else {
@@ -239,6 +245,39 @@ void BuildsMetaMakefileGenerator::accumulateVariableFromBuilds(const ProKey &nam
values.removeDuplicates();
}
+void BuildsMetaMakefileGenerator::checkForConflictingTargets() const
+{
+ if (makefiles.count() < 3) {
+ // Checking for conflicts only makes sense if we have more than one BUILD,
+ // and the last entry in makefiles is the "glue" Build.
+ return;
+ }
+ using TargetInfo = std::pair<Build *, ProString>;
+ QVector<TargetInfo> targets;
+ const int last = makefiles.count() - 1;
+ targets.resize(last);
+ for (int i = 0; i < last; ++i) {
+ Build *b = makefiles.at(i);
+ auto mkf = b->makefile;
+ auto prj = mkf->projectFile();
+ targets[i] = std::make_pair(b, prj->first(mkf->fullTargetVariable()));
+ }
+ std::stable_sort(targets.begin(), targets.end(),
+ [](const TargetInfo &lhs, const TargetInfo &rhs)
+ {
+ return lhs.second < rhs.second;
+ });
+ for (auto prev = targets.begin(), it = std::next(prev); it != targets.end(); ++prev, ++it) {
+ if (prev->second == it->second) {
+ warn_msg(WarnLogic, "Targets of builds '%s' and '%s' conflict: %s.",
+ qPrintable(prev->first->build),
+ qPrintable(it->first->build),
+ qPrintable(prev->second.toQString()));
+ break;
+ }
+ }
+}
+
class SubdirsMetaMakefileGenerator : public MetaMakefileGenerator
{
protected:
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
index b79fd8f250..613a5a6a89 100644
--- a/qmake/generators/win32/winmakefile.cpp
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -815,4 +815,9 @@ QString Win32MakefileGenerator::getManifestFileForRcFile() const
return QString();
}
+ProKey Win32MakefileGenerator::fullTargetVariable() const
+{
+ return "DEST_TARGET";
+}
+
QT_END_NAMESPACE
diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h
index 8eb633fdfa..09984fe355 100644
--- a/qmake/generators/win32/winmakefile.h
+++ b/qmake/generators/win32/winmakefile.h
@@ -64,6 +64,9 @@ protected:
void processRcFileVar();
static QString cQuoted(const QString &str);
virtual QString getManifestFileForRcFile() const;
+
+public:
+ ProKey fullTargetVariable() const override;
};
QT_END_NAMESPACE
diff --git a/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro b/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro
new file mode 100644
index 0000000000..c3e8034e35
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro
@@ -0,0 +1,5 @@
+TEMPLATE = app
+CONFIG += debug_and_release
+TARGET = bah
+DESTDIR = shu
+SOURCES += main.cpp
diff --git a/tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp b/tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp
new file mode 100644
index 0000000000..39de28135a
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp
@@ -0,0 +1,4 @@
+int main(int, char **)
+{
+ return 0;
+}
diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp
index 1df31904d6..cda4c500e1 100644
--- a/tests/auto/tools/qmake/tst_qmake.cpp
+++ b/tests/auto/tools/qmake/tst_qmake.cpp
@@ -33,6 +33,7 @@
#include <QDir>
#include <QDirIterator>
#include <QObject>
+#include <QRegularExpression>
#include <QStandardPaths>
#include <QTemporaryDir>
@@ -82,6 +83,7 @@ private slots:
void project();
void proFileCache();
void resources();
+ void conflictingTargets();
private:
TestCompiler test_compiler;
@@ -621,5 +623,18 @@ void tst_qmake::resources()
QVERIFY(test_compiler.make(workDir));
}
+void tst_qmake::conflictingTargets()
+{
+ QString workDir = base_path + "/testdata/conflicting_targets";
+ QVERIFY(test_compiler.qmake(workDir, "conflicting_targets"));
+ const QRegularExpression rex("Targets of builds '([^']+)' and '([^']+)' conflict");
+ auto match = rex.match(test_compiler.commandOutput());
+ QVERIFY(match.hasMatch());
+ QStringList builds = { match.captured(1), match.captured(2) };
+ std::sort(builds.begin(), builds.end());
+ const QStringList expectedBuilds{"Debug", "Release"};
+ QCOMPARE(builds, expectedBuilds);
+}
+
QTEST_MAIN(tst_qmake)
#include "tst_qmake.moc"