Warn about conflicting DESTDIR/TARGET combination in debug_and_release
If a project has DESTDIR and TARGET set to fixed values, then the target paths conflict when doing debug_and_release builds. With this change we're detecting this situation and yield a warning. Fixes: QTBUG-2736 Change-Id: Ib163db3463322792ab9fa5b997285ac9fc9819ab Reviewed-by: Kai Koehne <kai.koehne@qt.io>
This commit is contained in:
parent
38cfd3a8cb
commit
e75aed1a96
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -815,4 +815,9 @@ QString Win32MakefileGenerator::getManifestFileForRcFile() const
|
||||
return QString();
|
||||
}
|
||||
|
||||
ProKey Win32MakefileGenerator::fullTargetVariable() const
|
||||
{
|
||||
return "DEST_TARGET";
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -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
|
||||
|
5
tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro
vendored
Normal file
5
tests/auto/tools/qmake/testdata/conflicting_targets/conflicting_targets.pro
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += debug_and_release
|
||||
TARGET = bah
|
||||
DESTDIR = shu
|
||||
SOURCES += main.cpp
|
4
tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp
vendored
Normal file
4
tests/auto/tools/qmake/testdata/conflicting_targets/main.cpp
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
int main(int, char **)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user