Be able to create a response file for other generators too
When building an application for Android on Windows it is possible that the command line will be too long when doing the link step. So the code for generating a response file is moved to MakefileGenerator so it can be used by the other generators easily. The same variables used by MinGW can be used elsewhere then. Fixes: QTBUG-71940 Change-Id: I6c331d12e9541a90a4a95e0154d0ea1c056489bc Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
parent
4ada4f283e
commit
b274f656b8
@ -70,6 +70,11 @@ QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined
|
||||
QMAKE_LFLAGS_RPATH = -Wl,-rpath=
|
||||
QMAKE_LFLAGS_RPATHLINK = -Wl,-rpath-link=
|
||||
|
||||
equals(QMAKE_HOST.os, Windows) {
|
||||
QMAKE_LINK_OBJECT_MAX = 10
|
||||
QMAKE_LINK_OBJECT_SCRIPT = object_script
|
||||
}
|
||||
|
||||
QMAKE_LIBS_X11 =
|
||||
QMAKE_LIBS_THREAD =
|
||||
QMAKE_LIBS_OPENGL =
|
||||
|
@ -3455,4 +3455,28 @@ ProKey MakefileGenerator::fullTargetVariable() const
|
||||
return "TARGET";
|
||||
}
|
||||
|
||||
void MakefileGenerator::createResponseFile(const QString &fileName, const ProStringList &objList)
|
||||
{
|
||||
QString filePath = Option::output_dir + QDir::separator() + fileName;
|
||||
QFile file(filePath);
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QTextStream t(&file);
|
||||
for (ProStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) {
|
||||
QString path = (*it).toQString();
|
||||
// In response files, whitespace and special characters are
|
||||
// escaped with a backslash; backslashes themselves can either
|
||||
// be escaped into double backslashes, or, as this is a list of
|
||||
// path names, converted to forward slashes.
|
||||
path.replace(QLatin1Char('\\'), QLatin1String("/"))
|
||||
.replace(QLatin1Char(' '), QLatin1String("\\ "))
|
||||
.replace(QLatin1Char('\t'), QLatin1String("\\\t"))
|
||||
.replace(QLatin1Char('"'), QLatin1String("\\\""))
|
||||
.replace(QLatin1Char('\''), QLatin1String("\\'"));
|
||||
t << path << Qt::endl;
|
||||
}
|
||||
t.flush();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -257,6 +257,7 @@ protected:
|
||||
const QStringRef &fixedBase, int slashOff);
|
||||
bool processPrlFileCore(QString &origFile, const QStringRef &origName,
|
||||
const QString &fixedFile);
|
||||
void createResponseFile(const QString &fileName, const ProStringList &objList);
|
||||
|
||||
public:
|
||||
QMakeProject *projectFile() const;
|
||||
|
@ -58,7 +58,7 @@ protected:
|
||||
void writeSubTargets(QTextStream &t, QList<SubTarget*> subtargets, int flags) override;
|
||||
void writeMakeParts(QTextStream &);
|
||||
bool writeMakefile(QTextStream &) override;
|
||||
|
||||
std::pair<bool, QString> writeObjectsPart(QTextStream &, bool do_incremental);
|
||||
private:
|
||||
void init2();
|
||||
ProStringList libdirToFlags(const ProKey &key);
|
||||
|
@ -246,38 +246,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
|
||||
t << "####### Files\n\n";
|
||||
// This is used by the dist target.
|
||||
t << "SOURCES = " << fileVarList("SOURCES") << ' ' << fileVarList("GENERATED_SOURCES") << Qt::endl;
|
||||
if(do_incremental) {
|
||||
const ProStringList &objs = project->values("OBJECTS");
|
||||
const ProStringList &incrs = project->values("QMAKE_INCREMENTAL");
|
||||
ProStringList incrs_out;
|
||||
t << "OBJECTS = ";
|
||||
for (ProStringList::ConstIterator objit = objs.begin(); objit != objs.end(); ++objit) {
|
||||
bool increment = false;
|
||||
for (ProStringList::ConstIterator incrit = incrs.begin(); incrit != incrs.end(); ++incrit) {
|
||||
if ((*objit).toQString().indexOf(QRegExp((*incrit).toQString(), Qt::CaseSensitive,
|
||||
QRegExp::Wildcard)) != -1) {
|
||||
increment = true;
|
||||
incrs_out.append((*objit));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!increment)
|
||||
t << "\\\n\t\t" << (*objit);
|
||||
}
|
||||
if(incrs_out.count() == objs.count()) { //we just switched places, no real incrementals to be done!
|
||||
t << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << Qt::endl;
|
||||
} else if(!incrs_out.count()) {
|
||||
t << Qt::endl;
|
||||
} else {
|
||||
src_incremental = true;
|
||||
t << Qt::endl;
|
||||
t << "INCREMENTAL_OBJECTS = "
|
||||
<< escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << Qt::endl;
|
||||
}
|
||||
} else {
|
||||
// Used all over the place in both deps and commands.
|
||||
t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << Qt::endl;
|
||||
}
|
||||
auto objectParts = writeObjectsPart(t, do_incremental);
|
||||
src_incremental = objectParts.first;
|
||||
if(do_incremental && !src_incremental)
|
||||
do_incremental = false;
|
||||
t << "DIST = " << valList(fileFixify(project->values("DISTFILES").toQStringList())) << " "
|
||||
@ -513,7 +483,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
|
||||
t << mkdir_p_asstring(destdir) << "\n\t";
|
||||
if (!project->isEmpty("QMAKE_PRE_LINK"))
|
||||
t << var("QMAKE_PRE_LINK") << "\n\t";
|
||||
t << "$(LINK) $(LFLAGS) " << var("QMAKE_LINK_O_FLAG") << "$(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)";
|
||||
t << "$(LINK) $(LFLAGS) " << var("QMAKE_LINK_O_FLAG") << "$(TARGET) "
|
||||
<< objectParts.second << " $(OBJCOMP) $(LIBS)";
|
||||
if (!project->isEmpty("QMAKE_POST_LINK"))
|
||||
t << "\n\t" << var("QMAKE_POST_LINK");
|
||||
}
|
||||
@ -1545,4 +1516,56 @@ UnixMakefileGenerator::writeLibtoolFile()
|
||||
"libdir='" << Option::fixPathToTargetOS(install_dir.toQString(), false) << "'\n";
|
||||
}
|
||||
|
||||
std::pair<bool, QString> UnixMakefileGenerator::writeObjectsPart(QTextStream &t, bool do_incremental)
|
||||
{
|
||||
bool src_incremental = false;
|
||||
QString objectsLinkLine;
|
||||
const ProStringList &objs = project->values("OBJECTS");
|
||||
if (do_incremental) {
|
||||
const ProStringList &incrs = project->values("QMAKE_INCREMENTAL");
|
||||
ProStringList incrs_out;
|
||||
t << "OBJECTS = ";
|
||||
for (ProStringList::ConstIterator objit = objs.begin(); objit != objs.end(); ++objit) {
|
||||
bool increment = false;
|
||||
for (ProStringList::ConstIterator incrit = incrs.begin(); incrit != incrs.end(); ++incrit) {
|
||||
if ((*objit).toQString().indexOf(QRegExp((*incrit).toQString(), Qt::CaseSensitive,
|
||||
QRegExp::Wildcard)) != -1) {
|
||||
increment = true;
|
||||
incrs_out.append((*objit));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!increment)
|
||||
t << "\\\n\t\t" << (*objit);
|
||||
}
|
||||
if (incrs_out.count() == objs.count()) { //we just switched places, no real incrementals to be done!
|
||||
t << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << endl;
|
||||
} else if (!incrs_out.count()) {
|
||||
t << endl;
|
||||
} else {
|
||||
src_incremental = true;
|
||||
t << endl;
|
||||
t << "INCREMENTAL_OBJECTS = "
|
||||
<< escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << endl;
|
||||
}
|
||||
} else {
|
||||
const ProString &objMax = project->first("QMAKE_LINK_OBJECT_MAX");
|
||||
// Used all over the place in both deps and commands.
|
||||
if (objMax.isEmpty() || project->values("OBJECTS").count() < objMax.toInt()) {
|
||||
objectsLinkLine = "$(OBJECTS)";
|
||||
} else {
|
||||
QString ld_response_file = fileVar("OBJECTS_DIR");
|
||||
ld_response_file += var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET");
|
||||
if (!var("BUILD_NAME").isEmpty())
|
||||
ld_response_file += "." + var("BUILD_NAME");
|
||||
if (!var("MAKEFILE").isEmpty())
|
||||
ld_response_file += "." + var("MAKEFILE");
|
||||
createResponseFile(ld_response_file, objs);
|
||||
objectsLinkLine = "@" + escapeFilePath(ld_response_file);
|
||||
}
|
||||
t << "OBJECTS = " << valList(escapeDependencyPaths(objs)) << endl;
|
||||
}
|
||||
return std::make_pair(src_incremental, objectsLinkLine);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -115,30 +115,6 @@ QString MingwMakefileGenerator::installRoot() const
|
||||
return QStringLiteral("$(INSTALL_ROOT:@msyshack@%=%)");
|
||||
}
|
||||
|
||||
static void createResponseFile(const QString &fileName, const ProStringList &objList)
|
||||
{
|
||||
QString filePath = Option::output_dir + QDir::separator() + fileName;
|
||||
QFile file(filePath);
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QTextStream t(&file);
|
||||
for (ProStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) {
|
||||
QString path = (*it).toQString();
|
||||
// In response files, whitespace and special characters are
|
||||
// escaped with a backslash; backslashes themselves can either
|
||||
// be escaped into double backslashes, or, as this is a list of
|
||||
// path names, converted to forward slashes.
|
||||
path.replace(QLatin1Char('\\'), QLatin1String("/"))
|
||||
.replace(QLatin1Char(' '), QLatin1String("\\ "))
|
||||
.replace(QLatin1Char('\t'), QLatin1String("\\\t"))
|
||||
.replace(QLatin1Char('"'), QLatin1String("\\\""))
|
||||
.replace(QLatin1Char('\''), QLatin1String("\\'"));
|
||||
t << path << Qt::endl;
|
||||
}
|
||||
t.flush();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
void MingwMakefileGenerator::writeMingwParts(QTextStream &t)
|
||||
{
|
||||
writeStandardParts(t);
|
||||
|
Loading…
Reference in New Issue
Block a user