summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@theqtcompany.com>2016-01-26 17:16:02 +0100
committerAlexandru Croitor <alexandru.croitor@theqtcompany.com>2016-01-28 13:42:30 +0000
commit7d2b096815c139aab19886cc97ccee5c1d4eaa73 (patch)
tree15bbc0c528de20eca363b134bb8bb8a70b93a2a1
parentd2b9b4850a5e20b126171e4418fdf1782e244c6f (diff)
Fix macdeployqt to properly sign inner bundles.
QtWebEngine uses a framework called QtWebEngineCore which contains an inner bundle called QtWebEngineProcess.app. Because it was not signed in the proper order, the whole signing process failed. Fix consists in checking if there are any inner app bundles inside frameworks, and sign them before signing the rest of the main bundle. Change-Id: I48abe26d1e61cd1ce17cb185bcd8d1d72f6c9607 Task-number: QTBUG-50636 Reviewed-by: Morten Johan Sørvig <morten.sorvig@theqtcompany.com>
-rw-r--r--src/macdeployqt/shared/shared.cpp80
-rw-r--r--src/macdeployqt/shared/shared.h4
2 files changed, 77 insertions, 7 deletions
diff --git a/src/macdeployqt/shared/shared.cpp b/src/macdeployqt/shared/shared.cpp
index d20b2198e..9ea4c2261 100644
--- a/src/macdeployqt/shared/shared.cpp
+++ b/src/macdeployqt/shared/shared.cpp
@@ -350,6 +350,19 @@ QStringList findAppFrameworkNames(const QString &appBundlePath)
return frameworks;
}
+QStringList findAppFrameworkPaths(const QString &appBundlePath)
+{
+ QStringList frameworks;
+ QString searchPath = appBundlePath + "/Contents/Frameworks/";
+ QDirIterator iter(searchPath, QStringList() << QString::fromLatin1("*.framework"), QDir::Dirs);
+ while (iter.hasNext()) {
+ iter.next();
+ frameworks << iter.fileInfo().filePath();
+ }
+
+ return frameworks;
+}
+
QStringList findAppLibraries(const QString &appBundlePath)
{
QStringList result;
@@ -1247,7 +1260,7 @@ void codesignFile(const QString &identity, const QString &filePath)
}
}
-void codesign(const QString &identity, const QString &appBundlePath)
+QSet<QString> codesignBundle(const QString &identity, const QString &appBundlePath)
{
// Code sign all binaries in the app bundle. This needs to
// be done inside-out, e.g sign framework dependencies
@@ -1273,10 +1286,37 @@ void codesign(const QString &identity, const QString &appBundlePath)
foreach (const QString &binary, foundPluginBinaries)
pendingBinaries.push(binary);
- QStringList foundLibraries = findAppBundleFiles(appBundlePath + "/Contents/Frameworks/");
- foreach (const QString &binary, foundLibraries)
- pendingBinaries.push(binary);
+ // Add frameworks for processing.
+ QStringList frameworkPaths = findAppFrameworkPaths(appBundlePath);
+ foreach (const QString &frameworkPath, frameworkPaths) {
+
+ // Add all files for a framework as a catch all.
+ QStringList bundleFiles = findAppBundleFiles(frameworkPath);
+ foreach (const QString &binary, bundleFiles)
+ pendingBinaries.push(binary);
+ // Prioritise first to sign any additional inner bundles found in the Helpers folder (e.g
+ // used by QtWebEngine).
+ QDirIterator helpersIterator(frameworkPath, QStringList() << QString::fromLatin1("Helpers"), QDir::Dirs | QDir::NoSymLinks, QDirIterator::Subdirectories);
+ while (helpersIterator.hasNext()) {
+ helpersIterator.next();
+ QString helpersPath = helpersIterator.filePath();
+ QStringList innerBundleNames = QDir(helpersPath).entryList(QStringList() << "*.app", QDir::Dirs);
+ foreach (const QString &innerBundleName, innerBundleNames)
+ signedBinaries += codesignBundle(identity, helpersPath + "/" + innerBundleName);
+ }
+
+ // Also make sure to sign any libraries that will not be found by otool because they
+ // are not linked and won't be seen as a dependency.
+ QDirIterator librariesIterator(frameworkPath, QStringList() << QString::fromLatin1("Libraries"), QDir::Dirs | QDir::NoSymLinks, QDirIterator::Subdirectories);
+ while (librariesIterator.hasNext()) {
+ librariesIterator.next();
+ QString librariesPath = librariesIterator.filePath();
+ bundleFiles = findAppBundleFiles(librariesPath);
+ foreach (const QString &binary, bundleFiles)
+ pendingBinaries.push(binary);
+ }
+ }
// Sign all binares; use otool to find and sign dependencies first.
while (!pendingBinaries.isEmpty()) {
@@ -1286,17 +1326,39 @@ void codesign(const QString &identity, const QString &appBundlePath)
// Check if there are unsigned dependencies, sign these first
QStringList dependencies = getBinaryDependencies(rootBinariesPath, binary).toSet().subtract(signedBinaries).toList();
+
if (!dependencies.isEmpty()) {
pendingBinaries.push(binary);
- foreach (const QString &dependency, dependencies)
+ int dependenciesSkipped = 0;
+ foreach (const QString &dependency, dependencies) {
+ // Skip dependencies that are outside the current app bundle, because this might
+ // cause a codesign error if the current bundle is part of the dependency (e.g.
+ // a bundle is part of a framework helper, and depends on that framework).
+ // The dependencies will be taken care of after the current bundle is signed.
+ if (!dependency.startsWith(appBundlePath)) {
+ ++dependenciesSkipped;
+ LogNormal() << "Skipping outside dependency: " << dependency;
+ continue;
+ }
pendingBinaries.push(dependency);
- continue;
+ }
+
+ // If all dependencies were skipped, make sure the binary is actually signed, instead
+ // of going into an infinite loop.
+ if (dependenciesSkipped == dependencies.size()) {
+ pendingBinaries.pop();
+ } else {
+ continue;
+ }
}
+
// All dependencies are signed, now sign this binary
codesignFile(identity, binary);
signedBinaries.insert(binary);
}
+ LogNormal() << "Finished codesigning " << appBundlePath << "with identity" << identity;
+
// Verify code signature
QProcess codesign;
codesign.start("codesign", QStringList() << "--deep" << "-v" << appBundlePath);
@@ -1308,6 +1370,12 @@ void codesign(const QString &identity, const QString &appBundlePath)
} else if (!err.isEmpty()) {
LogDebug() << err;
}
+
+ return signedBinaries;
+}
+
+void codesign(const QString &identity, const QString &appBundlePath) {
+ codesignBundle(identity, appBundlePath);
}
void createDiskImage(const QString &appBundlePath)
diff --git a/src/macdeployqt/shared/shared.h b/src/macdeployqt/shared/shared.h
index ea678c226..a6d58607c 100644
--- a/src/macdeployqt/shared/shared.h
+++ b/src/macdeployqt/shared/shared.h
@@ -36,6 +36,7 @@
#include <QString>
#include <QStringList>
#include <QDebug>
+#include <QSet>
extern int logLevel;
#define LogError() if (logLevel < 0) {} else qDebug() << "ERROR:"
@@ -85,7 +86,6 @@ public:
bool useLoaderPath;
};
-
inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info);
void changeQtFrameworks(const QString appPath, const QString &qtPath, bool useDebugLibs);
@@ -107,7 +107,9 @@ void runStrip(const QString &binaryPath);
void stripAppBinary(const QString &bundlePath);
QString findAppBinary(const QString &appBundlePath);
QStringList findAppFrameworkNames(const QString &appBundlePath);
+QStringList findAppFrameworkPaths(const QString &appBundlePath);
void codesignFile(const QString &identity, const QString &filePath);
+QSet<QString> codesignBundle(const QString &identity, const QString &appBundlePath);
void codesign(const QString &identity, const QString &appBundlePath);
void createDiskImage(const QString &appBundlePath);