summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--installerfw.pri16
-rw-r--r--src/libs/installer/installer.pro2
-rw-r--r--src/sdk/translations/it.ts4
-rw-r--r--src/sdk/translations/ru.ts27
-rw-r--r--tools/binarycreator/binarycreator.cpp171
-rw-r--r--tools/devtool/devtool.pro5
6 files changed, 197 insertions, 28 deletions
diff --git a/installerfw.pri b/installerfw.pri
index 4aed182c1..2810e5144 100644
--- a/installerfw.pri
+++ b/installerfw.pri
@@ -126,13 +126,11 @@ DEFINES += NOMINMAX QT_NO_CAST_FROM_ASCII QT_STRICT_ITERATORS QT_USE_QSTRINGBUIL
IFW_VERSION_STR=$$IFW_VERSION_STR IFW_VERSION=$$IFW_VERSION
DEFINES += IFW_REPOSITORY_FORMAT_VERSION=$$IFW_REPOSITORY_FORMAT_VERSION
-static {
- LIBS += -l7z
- win32-g++*: LIBS += -lmpr -luuid
-
- equals(TEMPLATE, app) {
- msvc:POST_TARGETDEPS += $$IFW_LIB_PATH/installer.lib $$IFW_LIB_PATH/7z.lib
- win32-g++*:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
- unix:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
- }
+LIBS += -l7z
+win32-g++*: LIBS += -lmpr -luuid
+
+equals(TEMPLATE, app) {
+ msvc:POST_TARGETDEPS += $$IFW_LIB_PATH/installer.lib $$IFW_LIB_PATH/7z.lib
+ win32-g++*:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
+ unix:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
}
diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro
index d641ff1fc..f649a1ecb 100644
--- a/src/libs/installer/installer.pro
+++ b/src/libs/installer/installer.pro
@@ -2,6 +2,8 @@ TEMPLATE = lib
TARGET = installer
INCLUDEPATH += . ..
+CONFIG += staticlib
+
include(../7zip/7zip.pri)
include(../kdtools/kdtools.pri)
include(../../../installerfw.pri)
diff --git a/src/sdk/translations/it.ts b/src/sdk/translations/it.ts
index 91458b78e..514013f57 100644
--- a/src/sdk/translations/it.ts
+++ b/src/sdk/translations/it.ts
@@ -1439,11 +1439,11 @@ Errore durante lo scaricamento %2</translation>
</message>
<message>
<source>Click Done to exit the %1 Wizard.</source>
- <translation>Clicca Fatto per uscire dalla procedura guidatadi %1.</translation>
+ <translation>Clicca Fatto per uscire dalla procedura guidata di %1.</translation>
</message>
<message>
<source>Click Finish to exit the %1 Wizard.</source>
- <translation>Clicca Finito per uscire dalla procedura guidatadi %1.</translation>
+ <translation>Clicca Finito per uscire dalla procedura guidata di %1.</translation>
</message>
<message>
<source>Restart</source>
diff --git a/src/sdk/translations/ru.ts b/src/sdk/translations/ru.ts
index d23095583..2783f3eef 100644
--- a/src/sdk/translations/ru.ts
+++ b/src/sdk/translations/ru.ts
@@ -871,6 +871,10 @@
<translation>&amp;Снять отметки выбора со всех компонентов</translation>
</message>
<message>
+ <source>&amp;Browse QBSP files</source>
+ <translation>&amp;Обзор файлов QBSP</translation>
+ </message>
+ <message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
<translation>Этот компонент займёт приблизительно %1 на жестком диске.</translation>
</message>
@@ -891,16 +895,12 @@
<translation>Пожалуйста, выберите компоненты, которые вы хотите удалить.</translation>
</message>
<message>
- <source>Select the components to install. Deselect installed components to uninstall them.</source>
- <translation>Выберите компоненты для установки.Для удаления уже установленных компонентов снимите отметки выбора.</translation>
+ <source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
+ <translation>Выберите компоненты для установки. Для удаления уже установленных компонентов снимите отметки выбора. Уже установленные компоненты не будут обновлены.</translation>
</message>
<message>
<source>To install new compressed repository, browse the repositories from your computer</source>
- <translation type="unfinished">Для установки нового хранилища укажите путь к нему на вашем компьютере</translation>
- </message>
- <message>
- <source>&amp;Browse BSP or 7z files...</source>
- <translation>&amp;Обзор BSP или 7z файлов...</translation>
+ <translation>Для установки нового хранилища укажите путь к нему на вашем компьютере</translation>
</message>
<message>
<source>Open File</source>
@@ -1155,9 +1155,8 @@ Error while loading %2</source>
<translation>Обнаружено несовпадение контрольной суммы «%1».</translation>
</message>
<message>
- <source>Network error while downloading &quot;%1&quot;: %2</source>
- <extracomment>%2 is a sentence describing the error</extracomment>
- <translation>Возникла ошибка сети при загрузке «%1»: %2</translation>
+ <source>Network error while downloading &apos;%1&apos;: %2.</source>
+ <translation>Возникла ошибка сети при загрузке «%1»: %2.</translation>
</message>
<message>
<source>Unknown network error while downloading &quot;%1&quot;.</source>
@@ -1464,6 +1463,10 @@ Error while loading %2</source>
<translation>Подготовка к загрузке метаданных...</translation>
</message>
<message>
+ <source>Unpacking compressed repositories. This may take a while...</source>
+ <translation>Распаковка сжатых хранилищ. Это может занять некоторое время...</translation>
+ </message>
+ <message>
<source>Meta data download canceled.</source>
<translation>Загрузка метаданных отменена.</translation>
</message>
@@ -1496,10 +1499,6 @@ Error while loading %2</source>
<translation>Извлечение метаданных...</translation>
</message>
<message>
- <source>Unpacking compressed repositories...</source>
- <translation>Распаковка сжатых хранилищ...</translation>
- </message>
- <message>
<source>Error while extracting archive &quot;%1&quot;: %2</source>
<translation>Ошибка извлечения из архива «%1»: %2</translation>
</message>
diff --git a/tools/binarycreator/binarycreator.cpp b/tools/binarycreator/binarycreator.cpp
index 361dbd3fa..6492b59a1 100644
--- a/tools/binarycreator/binarycreator.cpp
+++ b/tools/binarycreator/binarycreator.cpp
@@ -50,6 +50,15 @@
#include <iostream>
+#ifdef Q_OS_MACOS
+#include <QtCore/QtEndian>
+#include <QtCore/QFile>
+#include <QtCore/QVersionNumber>
+
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#endif
+
using namespace QInstaller;
struct Input {
@@ -99,6 +108,159 @@ static void chmod755(const QString &absolutFilePath)
}
#endif
+#ifdef Q_OS_MACOS
+template <typename T = uint32_t> T readInt(QIODevice *ioDevice, bool *ok,
+ bool swap, bool peek = false) {
+ const auto bytes = peek
+ ? ioDevice->peek(sizeof(T))
+ : ioDevice->read(sizeof(T));
+ if (bytes.size() != sizeof(T)) {
+ if (ok)
+ *ok = false;
+ return T();
+ }
+ if (ok)
+ *ok = true;
+ T n = *reinterpret_cast<const T *>(bytes.constData());
+ return swap ? qbswap(n) : n;
+}
+
+static QVersionNumber readMachOMinimumSystemVersion(QIODevice *device)
+{
+ bool ok;
+ std::vector<qint64> machoOffsets;
+
+ qint64 pos = device->pos();
+ uint32_t magic = readInt(device, &ok, false);
+ if (magic == FAT_MAGIC || magic == FAT_CIGAM ||
+ magic == FAT_MAGIC_64 || magic == FAT_CIGAM_64) {
+ bool swap = magic == FAT_CIGAM || magic == FAT_CIGAM_64;
+ uint32_t nfat = readInt(device, &ok, swap);
+ if (!ok)
+ return QVersionNumber();
+
+ for (uint32_t n = 0; n < nfat; ++n) {
+ const bool is64bit = magic == FAT_MAGIC_64 || magic == FAT_CIGAM_64;
+ fat_arch_64 fat_arch;
+ fat_arch.cputype = static_cast<cpu_type_t>(readInt(device, &ok, swap));
+ if (!ok)
+ return QVersionNumber();
+
+ fat_arch.cpusubtype = static_cast<cpu_subtype_t>(readInt(device, &ok, swap));
+ if (!ok)
+ return QVersionNumber();
+
+ fat_arch.offset = is64bit
+ ? readInt<uint64_t>(device, &ok, swap) : readInt(device, &ok, swap);
+ if (!ok)
+ return QVersionNumber();
+
+ fat_arch.size = is64bit
+ ? readInt<uint64_t>(device, &ok, swap) : readInt(device, &ok, swap);
+ if (!ok)
+ return QVersionNumber();
+
+ fat_arch.align = readInt(device, &ok, swap);
+ if (!ok)
+ return QVersionNumber();
+
+ fat_arch.reserved = is64bit ? readInt(device, &ok, swap) : 0;
+ if (!ok)
+ return QVersionNumber();
+
+ machoOffsets.push_back(static_cast<qint64>(fat_arch.offset));
+ }
+ } else if (!ok) {
+ return QVersionNumber();
+ }
+
+ // Wasn't a fat file, so we just read a thin Mach-O from the original offset
+ if (machoOffsets.empty())
+ machoOffsets.push_back(pos);
+
+ std::vector<QVersionNumber> versions;
+
+ for (const auto &offset : machoOffsets) {
+ if (!device->seek(offset))
+ return QVersionNumber();
+
+ bool swap = false;
+ mach_header_64 header;
+ header.magic = readInt(device, nullptr, swap);
+ switch (header.magic) {
+ case MH_CIGAM:
+ case MH_CIGAM_64:
+ swap = true;
+ break;
+ case MH_MAGIC:
+ case MH_MAGIC_64:
+ break;
+ default:
+ return QVersionNumber();
+ }
+
+ header.cputype = static_cast<cpu_type_t>(readInt(device, &ok, swap));
+ if (!ok)
+ return QVersionNumber();
+
+ header.cpusubtype = static_cast<cpu_subtype_t>(readInt(device, &ok, swap));
+ if (!ok)
+ return QVersionNumber();
+
+ header.filetype = readInt(device, &ok, swap);
+ if (!ok)
+ return QVersionNumber();
+
+ header.ncmds = readInt(device, &ok, swap);
+ if (!ok)
+ return QVersionNumber();
+
+ header.sizeofcmds = readInt(device, &ok, swap);
+ if (!ok)
+ return QVersionNumber();
+
+ header.flags = readInt(device, &ok, swap);
+ if (!ok)
+ return QVersionNumber();
+
+ header.reserved = header.magic == MH_MAGIC_64 || header.magic == MH_CIGAM_64
+ ? readInt(device, &ok, swap) : 0;
+ if (!ok)
+ return QVersionNumber();
+
+ for (uint32_t i = 0; i < header.ncmds; ++i) {
+ const uint32_t cmd = readInt(device, nullptr, swap);
+ const uint32_t cmdsize = readInt(device, nullptr, swap);
+ if (cmd == 0 || cmdsize == 0)
+ return QVersionNumber();
+
+ switch (cmd) {
+ case LC_VERSION_MIN_MACOSX:
+ case LC_VERSION_MIN_IPHONEOS:
+ case LC_VERSION_MIN_TVOS:
+ case LC_VERSION_MIN_WATCHOS:
+ const uint32_t version = readInt(device, &ok, swap, true);
+ if (!ok)
+ return QVersionNumber();
+
+ versions.push_back(QVersionNumber(
+ static_cast<int>(version >> 16),
+ static_cast<int>((version >> 8) & 0xff),
+ static_cast<int>(version & 0xff)));
+ break;
+ }
+
+ const qint64 remaining = static_cast<qint64>(cmdsize - sizeof(cmd) - sizeof(cmdsize));
+ if (device->read(remaining).size() != remaining)
+ return QVersionNumber();
+ }
+ }
+
+ std::sort(versions.begin(), versions.end());
+ return !versions.empty() ? versions.front() : QVersionNumber();
+}
+#endif
+
static int assemble(Input input, const QInstaller::Settings &settings, const QString &signingIdentity)
{
#ifdef Q_OS_OSX
@@ -124,6 +286,11 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
// output should be a bundle
const QFileInfo fi(input.outputPath);
+ QString minimumSystemVersion;
+ QFile file(input.installerExePath);
+ if (file.open(QIODevice::ReadOnly))
+ minimumSystemVersion = readMachOMinimumSystemVersion(&file).normalized().toString();
+
const QString contentsResourcesPath = fi.filePath() + QLatin1String("/Contents/Resources/");
QInstaller::mkpath(fi.filePath() + QLatin1String("/Contents/MacOS"));
@@ -182,6 +349,10 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
<< endl;
plistStream << QLatin1String("\t<key>NSPrincipalClass</key>") << endl;
plistStream << QLatin1String("\t<string>NSApplication</string>") << endl;
+ if (!minimumSystemVersion.isEmpty()) {
+ plistStream << QLatin1String("\t<key>LSMinimumSystemVersion</key>") << endl;
+ plistStream << QLatin1String("\t<string>") << minimumSystemVersion << QLatin1String("</string>") << endl;
+ }
plistStream << QLatin1String("</dict>") << endl;
plistStream << QLatin1String("</plist>") << endl;
diff --git a/tools/devtool/devtool.pro b/tools/devtool/devtool.pro
index 0b52d7ca1..bb2d4417b 100644
--- a/tools/devtool/devtool.pro
+++ b/tools/devtool/devtool.pro
@@ -1,10 +1,9 @@
TEMPLATE = app
TARGET = devtool
-include(../../installerfw.pri)
+QT = core network qml xml
-QT -= gui
-QT += network xml
+include(../../installerfw.pri)
CONFIG += console
DESTDIR = $$IFW_APP_PATH