diff options
author | Andy Shaw <andy.shaw@qt.io> | 2019-11-04 15:54:24 +0100 |
---|---|---|
committer | Andy Shaw <andy.shaw@qt.io> | 2019-11-06 18:14:17 +0100 |
commit | b274f656b82e06fad492e241dae6ae65cb377ad1 (patch) | |
tree | b77a35cf15c94b6e89f7485a3eac89ca155130f3 /qmake | |
parent | 4ada4f283efe4b2adcde29c2139dfc502c120399 (diff) |
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>
Diffstat (limited to 'qmake')
-rw-r--r-- | qmake/generators/makefile.cpp | 24 | ||||
-rw-r--r-- | qmake/generators/makefile.h | 1 | ||||
-rw-r--r-- | qmake/generators/unix/unixmake.h | 2 | ||||
-rw-r--r-- | qmake/generators/unix/unixmake2.cpp | 89 | ||||
-rw-r--r-- | qmake/generators/win32/mingw_make.cpp | 24 |
5 files changed, 82 insertions, 58 deletions
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index c5868adf27..ed7d057a88 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -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 diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index 18c27a4385..47e4c7531c 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -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; diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h index 79b161f6da..28302b4f15 100644 --- a/qmake/generators/unix/unixmake.h +++ b/qmake/generators/unix/unixmake.h @@ -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); diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index a87fbe0fc3..20f2c88444 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -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 diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 878291fae9..096b041056 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -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); |