summaryrefslogtreecommitdiffstats
path: root/src/libs/ifwtools/binarycreator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/ifwtools/binarycreator.cpp')
-rw-r--r--src/libs/ifwtools/binarycreator.cpp176
1 files changed, 103 insertions, 73 deletions
diff --git a/src/libs/ifwtools/binarycreator.cpp b/src/libs/ifwtools/binarycreator.cpp
index a813c7f50..341052650 100644
--- a/src/libs/ifwtools/binarycreator.cpp
+++ b/src/libs/ifwtools/binarycreator.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -43,7 +43,7 @@
#include <QDirIterator>
#include <QDomDocument>
#include <QProcess>
-#include <QRegExp>
+#include <QRegularExpression>
#include <QSettings>
#include <QTemporaryFile>
#include <QTemporaryDir>
@@ -223,7 +223,7 @@ static QVersionNumber readMachOMinimumSystemVersion(QIODevice *device)
}
#endif
-static int assemble(Input input, const QInstaller::Settings &settings, const QString &signingIdentity)
+static int assemble(Input input, const QInstaller::Settings &settings, const BinaryCreatorArgs &args)
{
#ifdef Q_OS_MACOS
if (QInstaller::isInBundle(input.installerExePath)) {
@@ -262,7 +262,7 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QFile pkgInfo(fi.filePath() + QLatin1String("/Contents/PkgInfo"));
pkgInfo.open(QIODevice::WriteOnly);
QTextStream pkgInfoStream(&pkgInfo);
- pkgInfoStream << QLatin1String("APPL????") << endl;
+ pkgInfoStream << QLatin1String("APPL????") << Qt::endl;
}
QString iconFile;
@@ -282,44 +282,44 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QFile infoPList(fi.filePath() + QLatin1String("/Contents/Info.plist"));
infoPList.open(QIODevice::WriteOnly);
QTextStream plistStream(&infoPList);
- plistStream << QLatin1String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") << endl;
+ plistStream << QLatin1String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") << Qt::endl;
plistStream << QLatin1String("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
- "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">") << endl;
- plistStream << QLatin1String("<plist version=\"1.0\">") << endl;
- plistStream << QLatin1String("<dict>") << endl;
- plistStream << QLatin1String("\t<key>CFBundleIconFile</key>") << endl;
+ "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">") << Qt::endl;
+ plistStream << QLatin1String("<plist version=\"1.0\">") << Qt::endl;
+ plistStream << QLatin1String("<dict>") << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundleIconFile</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>") << iconTargetFile << QLatin1String("</string>")
- << endl;
- plistStream << QLatin1String("\t<key>CFBundlePackageType</key>") << endl;
- plistStream << QLatin1String("\t<string>APPL</string>") << endl;
+ << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundlePackageType</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>APPL</string>") << Qt::endl;
#define QUOTE_(x) #x
#define QUOTE(x) QUOTE_(x)
- plistStream << QLatin1String("\t<key>CFBundleShortVersionString</key>") << endl;
+ plistStream << QLatin1String("\t<key>CFBundleShortVersionString</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>") << QLatin1String(QUOTE(IFW_VERSION_STR)) << ("</string>")
- << endl;
- plistStream << QLatin1String("\t<key>CFBundleVersion</key>") << endl;
+ << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundleVersion</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>") << QLatin1String(QUOTE(IFW_VERSION_STR)) << ("</string>")
- << endl;
+ << Qt::endl;
#undef QUOTE
#undef QUOTE_
- plistStream << QLatin1String("\t<key>CFBundleSignature</key>") << endl;
- plistStream << QLatin1String("\t<string>\?\?\?\?</string>") << endl;
- plistStream << QLatin1String("\t<key>CFBundleExecutable</key>") << endl;
+ plistStream << QLatin1String("\t<key>CFBundleSignature</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>\?\?\?\?</string>") << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundleExecutable</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>") << fi.completeBaseName() << QLatin1String("</string>")
- << endl;
- plistStream << QLatin1String("\t<key>CFBundleIdentifier</key>") << endl;
- plistStream << QLatin1String("\t<string>com.yourcompany.installerbase</string>") << endl;
- plistStream << QLatin1String("\t<key>NOTE</key>") << endl;
+ << Qt::endl;
+ plistStream << QLatin1String("\t<key>CFBundleIdentifier</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>com.yourcompany.installerbase</string>") << Qt::endl;
+ plistStream << QLatin1String("\t<key>NOTE</key>") << Qt::endl;
plistStream << QLatin1String("\t<string>This file was generated by Qt Installer Framework.</string>")
- << endl;
- plistStream << QLatin1String("\t<key>NSPrincipalClass</key>") << endl;
- plistStream << QLatin1String("\t<string>NSApplication</string>") << endl;
+ << Qt::endl;
+ plistStream << QLatin1String("\t<key>NSPrincipalClass</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>NSApplication</string>") << Qt::endl;
if (!minimumSystemVersion.isEmpty()) {
- plistStream << QLatin1String("\t<key>LSMinimumSystemVersion</key>") << endl;
- plistStream << QLatin1String("\t<string>") << minimumSystemVersion << QLatin1String("</string>") << endl;
+ plistStream << QLatin1String("\t<key>LSMinimumSystemVersion</key>") << Qt::endl;
+ plistStream << QLatin1String("\t<string>") << minimumSystemVersion << QLatin1String("</string>") << Qt::endl;
}
- plistStream << QLatin1String("</dict>") << endl;
- plistStream << QLatin1String("</plist>") << endl;
+ plistStream << QLatin1String("</dict>") << Qt::endl;
+ plistStream << QLatin1String("</plist>") << Qt::endl;
input.outputPath = QString::fromLatin1("%1/Contents/MacOS/%2").arg(input.outputPath)
.arg(fi.completeBaseName());
@@ -405,22 +405,26 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QInstaller::appendData(&out, &exe, exe.size());
#endif
- foreach (const QInstallerTools::PackageInfo &info, input.packages) {
- QInstaller::ResourceCollection collection;
- collection.setName(info.name.toUtf8());
-
- qDebug() << "Creating resource archive for" << info.name;
- foreach (const QString &copiedFile, info.copiedFiles) {
- const QSharedPointer<Resource> resource(new Resource(copiedFile));
- qDebug().nospace() << "Appending " << copiedFile << " (" << humanReadableSize(resource->size()) << ")";
- collection.appendResource(resource);
+ if (!args.createMaintenanceTool) {
+ foreach (const QInstallerTools::PackageInfo &info, input.packages) {
+ QInstaller::ResourceCollection collection;
+ collection.setName(info.name.toUtf8());
+ qDebug() << "Creating resource archive for" << info.name;
+ foreach (const QString &copiedFile, info.copiedFiles) {
+ const QSharedPointer<Resource> resource(new Resource(copiedFile));
+ qDebug().nospace() << "Appending " << copiedFile << " (" << humanReadableSize(resource->size()) << ")";
+ collection.appendResource(resource);
+ }
+ input.manager.insertCollection(collection);
}
- input.manager.insertCollection(collection);
+
+ const QList<QInstaller::OperationBlob> operations;
+ BinaryContent::writeBinaryContent(&out, operations, input.manager,
+ BinaryContent::MagicInstallerMarker, BinaryContent::MagicCookie);
+ } else {
+ createMTDatFile(out);
}
- const QList<QInstaller::OperationBlob> operations;
- BinaryContent::writeBinaryContent(&out, operations, input.manager,
- BinaryContent::MagicInstallerMarker, BinaryContent::MagicCookie);
} catch (const Error &e) {
qCritical("Error occurred while assembling the installer: %s", qPrintable(e.message()));
QFile::remove(tempFile);
@@ -445,14 +449,14 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QFile::remove(tempFile);
#ifdef Q_OS_MACOS
- if (isBundle && !signingIdentity.isEmpty()) {
+ if (isBundle && !args.signingIdentity.isEmpty()) {
qDebug() << "Signing .app bundle...";
QProcess p;
p.start(QLatin1String("codesign"),
QStringList() << QLatin1String("--force")
<< QLatin1String("--deep")
- << QLatin1String("--sign") << signingIdentity
+ << QLatin1String("--sign") << args.signingIdentity
<< bundle);
if (!p.waitForFinished(-1)) {
@@ -503,8 +507,6 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
QDir(bundle).removeRecursively();
qDebug() << "done.";
}
-#else
- Q_UNUSED(signingIdentity)
#endif
return EXIT_SUCCESS;
}
@@ -609,27 +611,38 @@ void QInstallerTools::copyConfigData(const QString &configFile, const QString &t
qDebug().noquote() << QString::fromLatin1("Read dom element: <%1>%2</%1>.").arg(tagName, elementText);
if (tagName == QLatin1String("ProductImages")) {
- const QDomNodeList childNodes = domElement.childNodes();
- for (int index = 0; index < childNodes.count(); ++index) {
- const QDomElement childElement = childNodes.at(index).toElement();
- const QString childName = childElement.tagName();
- if (childName != QLatin1String("Image"))
+ const QDomNodeList productImageNode = domElement.childNodes();
+ for (int j = 0; j < productImageNode.count(); ++j) {
+ QDomElement productImagesElement = productImageNode.at(j).toElement();
+ if (productImagesElement.isNull())
continue;
+ const QString childName = productImagesElement.tagName();
+ if (childName != QLatin1String("ProductImage"))
+ continue;
+ const QDomNodeList imageNode = productImagesElement.childNodes();
+ for (int k = 0; k < imageNode.count(); ++k) {
+ QDomElement productImageElement = imageNode.at(k).toElement();
+ if (productImageElement.isNull())
+ continue;
+ const QString imageChildName = productImageElement.tagName();
+ if (imageChildName != QLatin1String("Image"))
+ continue;
+ const QString targetFile = targetDir + QLatin1Char('/') + productImageElement.text();
+ const QFileInfo childFileInfo = QFileInfo(sourceConfigFilePath, productImageElement.text());
+ QInstallerTools::copyWithException(childFileInfo.absoluteFilePath(), targetFile, imageChildName);
+ copyHighDPIImage(childFileInfo, imageChildName, targetFile);
+ }
- const QString targetFile = targetDir + QLatin1Char('/') + childElement.text();
- const QFileInfo childFileInfo = QFileInfo(sourceConfigFilePath, childElement.text());
- QInstallerTools::copyWithException(childFileInfo.absoluteFilePath(), targetFile, childName);
- copyHighDPIImage(childFileInfo, childName, targetFile);
}
continue;
}
- QString newName = domElement.text().replace(QRegExp(QLatin1String("\\\\|/|\\.|:")),
- QLatin1String("_"));
+ static const QRegularExpression regex(QLatin1String("\\\\|/|\\.|:"));
+ QString newName = domElement.text().replace(regex, QLatin1String("_"));
QString targetFile;
QFileInfo elementFileInfo;
- if (tagName == QLatin1String("Icon") || tagName == QLatin1String("InstallerApplicationIcon")) {
+ if (tagName == QLatin1String("InstallerApplicationIcon")) {
#if defined(Q_OS_MACOS)
const QString suffix = QLatin1String(".icns");
#elif defined(Q_OS_WIN)
@@ -691,13 +704,13 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
// Begin check arguments
foreach (const QString &packageDir, args.packagesDirectories) {
- if (!QFileInfo(packageDir).exists()) {
+ if (!QFileInfo::exists(packageDir)) {
argumentError = QString::fromLatin1("Error: Package directory not found at the specified location.");
return EXIT_FAILURE;
}
}
foreach (const QString &repositoryDir, args.repositoryDirectories) {
- if (!QFileInfo(repositoryDir).exists()) {
+ if (!QFileInfo::exists(repositoryDir)) {
argumentError = QString::fromLatin1("Error: Only local filesystem repositories now supported.");
return EXIT_FAILURE;
}
@@ -708,12 +721,12 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
"contain any components apart from the root component.");
return EXIT_FAILURE;
}
- if (!QFileInfo(args.templateBinary).exists()) {
+ if (!QFileInfo::exists(args.templateBinary)) {
#ifdef Q_OS_WIN
if (!args.templateBinary.endsWith(suffix))
args.templateBinary = args.templateBinary + suffix;
// Try again with added executable suffix
- if (!QFileInfo(args.templateBinary).exists()) {
+ if (!QFileInfo::exists(args.templateBinary)) {
argumentError = QString::fromLatin1("Error: Template base binary not found at the specified location.");
return EXIT_FAILURE;
}
@@ -743,7 +756,7 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
"--offline-only at the same time.");
return EXIT_FAILURE;
}
- if (args.target.isEmpty() && !args.compileResource) {
+ if (args.target.isEmpty() && !args.compileResource && !args.createMaintenanceTool) {
argumentError = QString::fromLatin1("Error: Target parameter missing.");
return EXIT_FAILURE;
}
@@ -751,7 +764,9 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
argumentError = QString::fromLatin1("Error: No configuration file selected.");
return EXIT_FAILURE;
}
- if (args.packagesDirectories.isEmpty() && args.repositoryDirectories.isEmpty()) {
+ if (args.packagesDirectories.isEmpty() && args.repositoryDirectories.isEmpty()
+ && !args.compileResource
+ && !args.createMaintenanceTool) {
argumentError = QString::fromLatin1("Error: Both Package directory and Repository parameters missing.");
return EXIT_FAILURE;
}
@@ -804,7 +819,8 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
// 2.2; copy the packages data and setup the packages vector with the files we copied,
// must happen before copying meta data because files will be compressed if
// needed and meta data generation relies on this
- copyComponentData(args.packagesDirectories, tmpRepoDir, &preparedPackages);
+ copyComponentData(args.packagesDirectories, tmpRepoDir, &preparedPackages,
+ args.archiveSuffix, args.compression);
// 2.3; add to common vector
packages.append(preparedPackages);
}
@@ -826,11 +842,6 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
confInternal.setValue(QLatin1String("offlineOnly"), args.offlineOnly);
}
-#ifdef Q_OS_MACOS
- // on mac, we enforce building a bundle
- if (!args.target.endsWith(QLatin1String(".app")) && !args.target.endsWith(QLatin1String(".dmg")))
- args.target += QLatin1String(".app");
-#endif
if (!args.compileResource) {
// 5; put the copied resources into a resource file
ResourceCollection metaCollection("QResources");
@@ -840,11 +851,20 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
input.manager.insertCollection(metaCollection);
input.packages = packages;
- input.outputPath = args.target;
+ if (args.createMaintenanceTool)
+ input.outputPath = settings.maintenanceToolName();
+ else
+ input.outputPath = args.target;
input.installerExePath = args.templateBinary;
+#ifdef Q_OS_MACOS
+ // on mac, we enforce building a bundle
+ if (!input.outputPath.endsWith(QLatin1String(".app")) && !input.outputPath.endsWith(QLatin1String(".dmg")))
+ input.outputPath += QLatin1String(".app");
+#endif
+
qDebug() << "Creating the binary";
- exitCode = assemble(input, settings, args.signingIdentity);
+ exitCode = assemble(input, settings, args);
} else {
createDefaultResourceFile(tmpMetaDir, QDir::currentPath() + QLatin1String("/update.rcc"));
exitCode = EXIT_SUCCESS;
@@ -866,3 +886,13 @@ int QInstallerTools::createBinary(BinaryCreatorArgs args, QString &argumentError
return exitCode;
}
+
+void QInstallerTools::createMTDatFile(QFile &datFile)
+{
+ QInstaller::appendInt64(&datFile, 0); // operations start
+ QInstaller::appendInt64(&datFile, 0); // operations end
+ QInstaller::appendInt64(&datFile, 0); // resource count
+ QInstaller::appendInt64(&datFile, 4 * sizeof(qint64)); // data block size
+ QInstaller::appendInt64(&datFile, BinaryContent::MagicUninstallerMarker);
+ QInstaller::appendInt64(&datFile, BinaryContent::MagicCookie);
+}