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);
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -276,6 +276,7 @@ public:
|
|||||||
virtual bool openOutput(QFile &, const QString &build) const;
|
virtual bool openOutput(QFile &, const QString &build) const;
|
||||||
bool isWindowsShell() const { return Option::dir_sep == QLatin1String("\\"); }
|
bool isWindowsShell() const { return Option::dir_sep == QLatin1String("\\"); }
|
||||||
QString shellQuote(const QString &str);
|
QString shellQuote(const QString &str);
|
||||||
|
virtual ProKey fullTargetVariable() const;
|
||||||
};
|
};
|
||||||
Q_DECLARE_TYPEINFO(MakefileGenerator::Compiler, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(MakefileGenerator::Compiler, Q_MOVABLE_TYPE);
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(MakefileGenerator::FileFixifyTypes)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(MakefileGenerator::FileFixifyTypes)
|
||||||
|
@ -33,6 +33,10 @@
|
|||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "cachekeys.h"
|
#include "cachekeys.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#define BUILDSMETATYPE 1
|
#define BUILDSMETATYPE 1
|
||||||
#define SUBDIRSMETATYPE 2
|
#define SUBDIRSMETATYPE 2
|
||||||
|
|
||||||
@ -58,6 +62,7 @@ private:
|
|||||||
void clearBuilds();
|
void clearBuilds();
|
||||||
MakefileGenerator *processBuild(const ProString &);
|
MakefileGenerator *processBuild(const ProString &);
|
||||||
void accumulateVariableFromBuilds(const ProKey &name, Build *build) const;
|
void accumulateVariableFromBuilds(const ProKey &name, Build *build) const;
|
||||||
|
void checkForConflictingTargets() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -186,6 +191,7 @@ BuildsMetaMakefileGenerator::write()
|
|||||||
if(!build->makefile) {
|
if(!build->makefile) {
|
||||||
ret = false;
|
ret = false;
|
||||||
} else if(build == glue) {
|
} else if(build == glue) {
|
||||||
|
checkForConflictingTargets();
|
||||||
accumulateVariableFromBuilds("QMAKE_INTERNAL_INCLUDED_FILES", build);
|
accumulateVariableFromBuilds("QMAKE_INTERNAL_INCLUDED_FILES", build);
|
||||||
ret = build->makefile->writeProjectMakefile();
|
ret = build->makefile->writeProjectMakefile();
|
||||||
} else {
|
} else {
|
||||||
@ -239,6 +245,39 @@ void BuildsMetaMakefileGenerator::accumulateVariableFromBuilds(const ProKey &nam
|
|||||||
values.removeDuplicates();
|
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
|
class SubdirsMetaMakefileGenerator : public MetaMakefileGenerator
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -815,4 +815,9 @@ QString Win32MakefileGenerator::getManifestFileForRcFile() const
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProKey Win32MakefileGenerator::fullTargetVariable() const
|
||||||
|
{
|
||||||
|
return "DEST_TARGET";
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -64,6 +64,9 @@ protected:
|
|||||||
void processRcFileVar();
|
void processRcFileVar();
|
||||||
static QString cQuoted(const QString &str);
|
static QString cQuoted(const QString &str);
|
||||||
virtual QString getManifestFileForRcFile() const;
|
virtual QString getManifestFileForRcFile() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProKey fullTargetVariable() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
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 <QDir>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QRegularExpression>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
@ -82,6 +83,7 @@ private slots:
|
|||||||
void project();
|
void project();
|
||||||
void proFileCache();
|
void proFileCache();
|
||||||
void resources();
|
void resources();
|
||||||
|
void conflictingTargets();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TestCompiler test_compiler;
|
TestCompiler test_compiler;
|
||||||
@ -621,5 +623,18 @@ void tst_qmake::resources()
|
|||||||
QVERIFY(test_compiler.make(workDir));
|
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)
|
QTEST_MAIN(tst_qmake)
|
||||||
#include "tst_qmake.moc"
|
#include "tst_qmake.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user