Browse Source

Attempt at closing #3, reopen if this causes issues

master
probonopd 8 years ago
parent
commit
66ac27099d
  1. 4
      README.md
  2. 16
      linuxdeployqt/main.cpp
  3. 198
      shared/shared.cpp
  4. 34
      shared/shared.h

4
README.md

@ -22,8 +22,8 @@ Options:
-no-plugins : Skip plugin deployment -no-plugins : Skip plugin deployment
-appimage : Create an AppImage -appimage : Create an AppImage
-no-strip : Don't run 'strip' on the binaries -no-strip : Don't run 'strip' on the binaries
-use-debug-libs : Deploy with debug versions of frameworks and plugins (implies -no-strip) -use-debug-libs : Deploy with debug versions of libraries and plugins (implies -no-strip)
-executable=<path> : Let the given executable use the deployed frameworks too -executable=<path> : Let the given executable use the deployed libraries too
-qmldir=<path> : Scan for QML imports in the given path -qmldir=<path> : Scan for QML imports in the given path
-always-overwrite : Copy files even if the target file exists -always-overwrite : Copy files even if the target file exists
-libpath=<path> : Add the given path to the library search path -libpath=<path> : Add the given path to the library search path

16
linuxdeployqt/main.cpp

@ -48,8 +48,8 @@ int main(int argc, char **argv)
qDebug() << " -no-plugins : Skip plugin deployment"; qDebug() << " -no-plugins : Skip plugin deployment";
qDebug() << " -appimage : Create an AppImage"; qDebug() << " -appimage : Create an AppImage";
qDebug() << " -no-strip : Don't run 'strip' on the binaries"; qDebug() << " -no-strip : Don't run 'strip' on the binaries";
qDebug() << " -use-debug-libs : Deploy with debug versions of frameworks and plugins (implies -no-strip)"; qDebug() << " -use-debug-libs : Deploy with debug versions of libraries and plugins (implies -no-strip)";
qDebug() << " -executable=<path> : Let the given executable use the deployed frameworks too"; qDebug() << " -executable=<path> : Let the given executable use the deployed libraries too";
qDebug() << " -qmldir=<path> : Scan for QML imports in the given path"; qDebug() << " -qmldir=<path> : Scan for QML imports in the given path";
qDebug() << " -always-overwrite : Copy files even if the target file exists"; qDebug() << " -always-overwrite : Copy files even if the target file exists";
qDebug() << " -libpath=<path> : Add the given path to the library search path"; qDebug() << " -libpath=<path> : Add the given path to the library search path";
@ -160,7 +160,7 @@ int main(int argc, char **argv)
} }
} }
DeploymentInfo deploymentInfo = deployQtFrameworks(appBundlePath, additionalExecutables, useDebugLibs); DeploymentInfo deploymentInfo = deployQtLibraries(appBundlePath, additionalExecutables, useDebugLibs);
// Convenience: Look for .qml files in the current directoty if no -qmldir specified. // Convenience: Look for .qml files in the current directoty if no -qmldir specified.
if (qmlDirs.isEmpty()) { if (qmlDirs.isEmpty()) {
@ -175,11 +175,11 @@ int main(int argc, char **argv)
if (!ok && qmldirArgumentUsed) if (!ok && qmldirArgumentUsed)
return 1; // exit if the user explicitly asked for qml import deployment return 1; // exit if the user explicitly asked for qml import deployment
// Update deploymentInfo.deployedFrameworks - the QML imports // Update deploymentInfo.deployedLibraries - the QML imports
// may have brought in extra frameworks as dependencies. // may have brought in extra libraries as dependencies.
// deploymentInfo.deployedFrameworks += findAppFrameworkNames(appBundlePath); // deploymentInfo.deployedLibraries += findAppLibraryNames(appBundlePath);
deploymentInfo.deployedFrameworks += findAppLibraries(appBundlePath); deploymentInfo.deployedLibraries += findAppLibraries(appBundlePath);
deploymentInfo.deployedFrameworks = deploymentInfo.deployedFrameworks.toSet().toList(); deploymentInfo.deployedLibraries = deploymentInfo.deployedLibraries.toSet().toList();
} }
if (plugins && !deploymentInfo.qtPath.isEmpty()) { if (plugins && !deploymentInfo.qtPath.isEmpty()) {

198
shared/shared.cpp

@ -50,21 +50,21 @@ bool alwaysOwerwriteEnabled = false;
QStringList librarySearchPath; QStringList librarySearchPath;
bool appstoreCompliant = false; bool appstoreCompliant = false;
int logLevel = 1; int logLevel = 1;
bool deployFramework = false; bool deployLibrary = false;
using std::cout; using std::cout;
using std::endl; using std::endl;
bool operator==(const FrameworkInfo &a, const FrameworkInfo &b) bool operator==(const LibraryInfo &a, const LibraryInfo &b)
{ {
return ((a.frameworkPath == b.frameworkPath) && (a.binaryPath == b.binaryPath)); return ((a.libraryPath == b.libraryPath) && (a.binaryPath == b.binaryPath));
} }
QDebug operator<<(QDebug debug, const FrameworkInfo &info) QDebug operator<<(QDebug debug, const LibraryInfo &info)
{ {
debug << "Framework name" << info.frameworkName << "\n"; debug << "Library name" << info.libraryName << "\n";
debug << "Framework directory" << info.frameworkDirectory << "\n"; debug << "Library directory" << info.libraryDirectory << "\n";
debug << "Framework path" << info.frameworkPath << "\n"; debug << "Library path" << info.libraryPath << "\n";
debug << "Binary directory" << info.binaryDirectory << "\n"; debug << "Binary directory" << info.binaryDirectory << "\n";
debug << "Binary name" << info.binaryName << "\n"; debug << "Binary name" << info.binaryName << "\n";
debug << "Binary path" << info.binaryPath << "\n"; debug << "Binary path" << info.binaryPath << "\n";
@ -72,13 +72,13 @@ QDebug operator<<(QDebug debug, const FrameworkInfo &info)
debug << "Install name" << info.installName << "\n"; debug << "Install name" << info.installName << "\n";
debug << "Deployed install name" << info.deployedInstallName << "\n"; debug << "Deployed install name" << info.deployedInstallName << "\n";
debug << "Source file Path" << info.sourceFilePath << "\n"; debug << "Source file Path" << info.sourceFilePath << "\n";
debug << "Framework Destination Directory (relative to bundle)" << info.frameworkDestinationDirectory << "\n"; debug << "Library Destination Directory (relative to bundle)" << info.libraryDestinationDirectory << "\n";
debug << "Binary Destination Directory (relative to bundle)" << info.binaryDestinationDirectory << "\n"; debug << "Binary Destination Directory (relative to bundle)" << info.binaryDestinationDirectory << "\n";
return debug; return debug;
} }
const QString bundleFrameworkDirectory = "lib"; // the same directory as the main executable; could define a relative subdirectory here const QString bundleLibraryDirectory = "lib"; // the same directory as the main executable; could define a relative subdirectory here
inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info) inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info)
{ {
@ -209,9 +209,9 @@ OtoolInfo findDependencyInfo(const QString &binaryPath)
return info; return info;
} }
FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs) LibraryInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs)
{ {
FrameworkInfo info; LibraryInfo info;
QString trimmed = line.trimmed(); QString trimmed = line.trimmed();
LogDebug() << "parsing" << trimmed; LogDebug() << "parsing" << trimmed;
@ -225,14 +225,14 @@ FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundl
if (trimmed.startsWith("/lib")) if (trimmed.startsWith("/lib"))
return info; return info;
enum State {QtPath, FrameworkName, LibraryName, Version, End}; enum State {QtPath, LibraryName, Version, End};
State state = QtPath; State state = QtPath;
int part = 0; int part = 0;
QString name; QString name;
QString qtPath; QString qtPath;
QString suffix = useDebugLibs ? "_debug" : ""; QString suffix = useDebugLibs ? "_debug" : "";
// Split the line into [Qt-path]/lib/qt[Module].framework/Versions/[Version]/ // Split the line into [Qt-path]/lib/qt[Module].library/Versions/[Version]/
QStringList parts = trimmed.split("/"); QStringList parts = trimmed.split("/");
while (part < parts.count()) { while (part < parts.count()) {
const QString currentPart = parts.at(part).simplified() ; const QString currentPart = parts.at(part).simplified() ;
@ -243,8 +243,8 @@ FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundl
if (state == QtPath) { if (state == QtPath) {
// Check for library name part // Check for library name part
if (part < parts.count() && parts.at(part).contains(".so")) { if (part < parts.count() && parts.at(part).contains(".so")) {
info.frameworkDirectory += "/" + (qtPath + currentPart + "/").simplified(); info.libraryDirectory += "/" + (qtPath + currentPart + "/").simplified();
LogDebug() << "info.frameworkDirectory:" << info.frameworkDirectory; LogDebug() << "info.libraryDirectory:" << info.libraryDirectory;
state = LibraryName; state = LibraryName;
continue; continue;
} else if (trimmed.startsWith("/") == false) { // If the line does not contain a full path, the app is using a binary Qt package. } else if (trimmed.startsWith("/") == false) { // If the line does not contain a full path, the app is using a binary Qt package.
@ -255,14 +255,14 @@ FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundl
path += '/'; path += '/';
QString nameInPath = path + parts.join("/"); QString nameInPath = path + parts.join("/");
if (QFile::exists(nameInPath)) { if (QFile::exists(nameInPath)) {
info.frameworkDirectory = path + partsCopy.join("/"); info.libraryDirectory = path + partsCopy.join("/");
break; break;
} }
} }
if (info.frameworkDirectory.isEmpty()) if (info.libraryDirectory.isEmpty())
info.frameworkDirectory = "/usr/lib/" + partsCopy.join("/"); info.libraryDirectory = "/usr/lib/" + partsCopy.join("/");
if (!info.frameworkDirectory.endsWith("/")) if (!info.libraryDirectory.endsWith("/"))
info.frameworkDirectory += "/"; info.libraryDirectory += "/";
state = LibraryName; state = LibraryName;
--part; --part;
continue; continue;
@ -272,15 +272,15 @@ FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundl
} if (state == LibraryName) { } if (state == LibraryName) {
name = currentPart; name = currentPart;
info.isDylib = true; info.isDylib = true;
info.frameworkName = name; info.libraryName = name;
info.binaryName = name.left(name.indexOf('.')) + suffix + name.mid(name.indexOf('.')); info.binaryName = name.left(name.indexOf('.')) + suffix + name.mid(name.indexOf('.'));
info.deployedInstallName = "$ORIGIN"; // + info.binaryName; info.deployedInstallName = "$ORIGIN"; // + info.binaryName;
info.frameworkPath = info.frameworkDirectory + info.binaryName; info.libraryPath = info.libraryDirectory + info.binaryName;
info.sourceFilePath = info.frameworkPath; info.sourceFilePath = info.libraryPath;
info.frameworkDestinationDirectory = bundleFrameworkDirectory + "/"; info.libraryDestinationDirectory = bundleLibraryDirectory + "/";
info.binaryDestinationDirectory = info.frameworkDestinationDirectory; info.binaryDestinationDirectory = info.libraryDestinationDirectory;
info.binaryDirectory = info.frameworkDirectory; info.binaryDirectory = info.libraryDirectory;
info.binaryPath = info.frameworkPath; info.binaryPath = info.libraryPath;
state = End; state = End;
++part; ++part;
continue; continue;
@ -354,13 +354,13 @@ QStringList findAppBundleFiles(const QString &appBundlePath, bool absolutePath =
return result; return result;
} }
QList<FrameworkInfo> getQtFrameworks(const QList<DylibInfo> &dependencies, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs) QList<LibraryInfo> getQtLibraries(const QList<DylibInfo> &dependencies, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs)
{ {
QList<FrameworkInfo> libraries; QList<LibraryInfo> libraries;
for (const DylibInfo &dylibInfo : dependencies) { for (const DylibInfo &dylibInfo : dependencies) {
FrameworkInfo info = parseOtoolLibraryLine(dylibInfo.binaryPath, appBundlePath, rpaths, useDebugLibs); LibraryInfo info = parseOtoolLibraryLine(dylibInfo.binaryPath, appBundlePath, rpaths, useDebugLibs);
if (info.frameworkName.isEmpty() == false) { if (info.libraryName.isEmpty() == false) {
LogDebug() << "Adding framework:"; LogDebug() << "Adding library:";
LogDebug() << info; LogDebug() << info;
libraries.append(info); libraries.append(info);
} }
@ -405,21 +405,21 @@ QSet<QString> getBinaryRPaths(const QString &path, bool resolve = true, QString
return rpaths; return rpaths;
} }
QList<FrameworkInfo> getQtFrameworks(const QString &path, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs) QList<LibraryInfo> getQtLibraries(const QString &path, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs)
{ {
const OtoolInfo info = findDependencyInfo(path); const OtoolInfo info = findDependencyInfo(path);
return getQtFrameworks(info.dependencies, appBundlePath, rpaths + getBinaryRPaths(path), useDebugLibs); return getQtLibraries(info.dependencies, appBundlePath, rpaths + getBinaryRPaths(path), useDebugLibs);
} }
QList<FrameworkInfo> getQtFrameworksForPaths(const QStringList &paths, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs) QList<LibraryInfo> getQtLibrariesForPaths(const QStringList &paths, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs)
{ {
QList<FrameworkInfo> result; QList<LibraryInfo> result;
QSet<QString> existing; QSet<QString> existing;
foreach (const QString &path, paths) { foreach (const QString &path, paths) {
foreach (const FrameworkInfo &info, getQtFrameworks(path, appBundlePath, rpaths, useDebugLibs)) { foreach (const LibraryInfo &info, getQtLibraries(path, appBundlePath, rpaths, useDebugLibs)) {
if (!existing.contains(info.frameworkPath)) { // avoid duplicates if (!existing.contains(info.libraryPath)) { // avoid duplicates
existing.insert(info.frameworkPath); existing.insert(info.libraryPath);
result << info; result << info;
} }
} }
@ -521,17 +521,17 @@ void recursiveCopyAndDeploy(const QString &appBundlePath, const QSet<QString> &r
} }
} }
QString copyDylib(const FrameworkInfo &framework, const QString path) QString copyDylib(const LibraryInfo &library, const QString path)
{ {
if (!QFile::exists(framework.sourceFilePath)) { if (!QFile::exists(library.sourceFilePath)) {
LogError() << "no file at" << framework.sourceFilePath; LogError() << "no file at" << library.sourceFilePath;
return QString(); return QString();
} }
// Construct destination paths. The full path typically looks like // Construct destination paths. The full path typically looks like
// MyApp.app/Contents/Frameworks/libfoo.dylib // MyApp.app/Contents/Libraries/libfoo.dylib
QString dylibDestinationDirectory = path + QLatin1Char('/') + framework.frameworkDestinationDirectory; QString dylibDestinationDirectory = path + QLatin1Char('/') + library.libraryDestinationDirectory;
QString dylibDestinationBinaryPath = dylibDestinationDirectory + QLatin1Char('/') + framework.binaryName; QString dylibDestinationBinaryPath = dylibDestinationDirectory + QLatin1Char('/') + library.binaryName;
// Create destination directory // Create destination directory
if (!QDir().mkpath(dylibDestinationDirectory)) { if (!QDir().mkpath(dylibDestinationDirectory)) {
@ -544,7 +544,7 @@ QString copyDylib(const FrameworkInfo &framework, const QString path)
return dylibDestinationBinaryPath; return dylibDestinationBinaryPath;
// Copy dylib binary // Copy dylib binary
copyFilePrintStatus(framework.sourceFilePath, dylibDestinationBinaryPath); copyFilePrintStatus(library.sourceFilePath, dylibDestinationBinaryPath);
return dylibDestinationBinaryPath; return dylibDestinationBinaryPath;
} }
@ -602,83 +602,83 @@ void stripAppBinary(const QString &bundlePath)
} }
/* /*
Deploys the the listed frameworks listed into an app bundle. Deploys the the libraries listed into an app bundle.
The frameworks are searched for dependencies, which are also deployed. The libraries are searched for dependencies, which are also deployed.
(deploying Qt3Support will also deploy QtNetwork and QtSql for example.) (deploying Qt3Support will also deploy QtNetwork and QtSql for example.)
Returns a DeploymentInfo structure containing the Qt path used and a Returns a DeploymentInfo structure containing the Qt path used and a
a list of actually deployed frameworks. a list of actually deployed libraries.
*/ */
DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, DeploymentInfo deployQtLibraries(QList<LibraryInfo> libraries,
const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs, const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs,
bool useLoaderPath) bool useLoaderPath)
{ {
LogNormal(); LogNormal();
LogNormal() << "Deploying libraries found inside:" << binaryPaths; LogNormal() << "Deploying libraries found inside:" << binaryPaths;
QStringList copiedFrameworks; QStringList copiedLibraries;
DeploymentInfo deploymentInfo; DeploymentInfo deploymentInfo;
deploymentInfo.useLoaderPath = useLoaderPath; deploymentInfo.useLoaderPath = useLoaderPath;
QSet<QString> rpathsUsed; QSet<QString> rpathsUsed;
while (frameworks.isEmpty() == false) { while (libraries.isEmpty() == false) {
const FrameworkInfo framework = frameworks.takeFirst(); const LibraryInfo library = libraries.takeFirst();
copiedFrameworks.append(framework.frameworkName); copiedLibraries.append(library.libraryName);
if(framework.frameworkName.contains("libQt") and framework.frameworkName.contains("Core.so")) { if(library.libraryName.contains("libQt") and library.libraryName.contains("Core.so")) {
LogNormal() << "Setting deploymentInfo.qtPath to:" << framework.frameworkDirectory; LogNormal() << "Setting deploymentInfo.qtPath to:" << library.libraryDirectory;
deploymentInfo.qtPath = framework.frameworkDirectory; deploymentInfo.qtPath = library.libraryDirectory;
} }
if (framework.frameworkDirectory.startsWith(bundlePath)) { if (library.libraryDirectory.startsWith(bundlePath)) {
qDebug() << framework.frameworkName << "already deployed, skipping."; qDebug() << library.libraryName << "already deployed, skipping.";
continue; continue;
} }
if (framework.rpathUsed.isEmpty() != true) { if (library.rpathUsed.isEmpty() != true) {
rpathsUsed << framework.rpathUsed; rpathsUsed << library.rpathUsed;
} }
// Copy the framework/dylib to the app bundle. // Copy the library/dylib to the app bundle.
const QString deployedBinaryPath = copyDylib(framework, bundlePath); const QString deployedBinaryPath = copyDylib(library, bundlePath);
// Skip the rest if already was deployed. // Skip the rest if already was deployed.
if (deployedBinaryPath.isNull()) if (deployedBinaryPath.isNull())
continue; continue;
runStrip(deployedBinaryPath); runStrip(deployedBinaryPath);
if (!framework.rpathUsed.length()) { if (!library.rpathUsed.length()) {
changeIdentification(framework.deployedInstallName, deployedBinaryPath); changeIdentification(library.deployedInstallName, deployedBinaryPath);
} }
// Check for framework dependencies // Check for library dependencies
QList<FrameworkInfo> dependencies = getQtFrameworks(deployedBinaryPath, bundlePath, rpathsUsed, useDebugLibs); QList<LibraryInfo> dependencies = getQtLibraries(deployedBinaryPath, bundlePath, rpathsUsed, useDebugLibs);
foreach (FrameworkInfo dependency, dependencies) { foreach (LibraryInfo dependency, dependencies) {
if (dependency.rpathUsed.isEmpty() != true) { if (dependency.rpathUsed.isEmpty() != true) {
rpathsUsed << dependency.rpathUsed; rpathsUsed << dependency.rpathUsed;
} }
// Deploy framework if necessary. // Deploy library if necessary.
if (copiedFrameworks.contains(dependency.frameworkName) == false && frameworks.contains(dependency) == false) { if (copiedLibraries.contains(dependency.libraryName) == false && libraries.contains(dependency) == false) {
frameworks.append(dependency); libraries.append(dependency);
} }
} }
} }
deploymentInfo.deployedFrameworks = copiedFrameworks; deploymentInfo.deployedLibraries = copiedLibraries;
deploymentInfo.rpathsUsed += rpathsUsed; deploymentInfo.rpathsUsed += rpathsUsed;
return deploymentInfo; return deploymentInfo;
} }
DeploymentInfo deployQtFrameworks(const QString &appBundlePath, const QStringList &additionalExecutables, bool useDebugLibs) DeploymentInfo deployQtLibraries(const QString &appBundlePath, const QStringList &additionalExecutables, bool useDebugLibs)
{ {
ApplicationBundleInfo applicationBundle; ApplicationBundleInfo applicationBundle;
applicationBundle.path = appBundlePath; applicationBundle.path = appBundlePath;
LogDebug() << "applicationBundle.path:" << applicationBundle.path; LogDebug() << "applicationBundle.path:" << applicationBundle.path;
applicationBundle.binaryPath = findAppBinary(appBundlePath); applicationBundle.binaryPath = findAppBinary(appBundlePath);
LogDebug() << "applicationBundle.binaryPath:" << applicationBundle.binaryPath; LogDebug() << "applicationBundle.binaryPath:" << applicationBundle.binaryPath;
changeIdentification("$ORIGIN/" + bundleFrameworkDirectory, applicationBundle.binaryPath); changeIdentification("$ORIGIN/" + bundleLibraryDirectory, applicationBundle.binaryPath);
applicationBundle.libraryPaths = findAppLibraries(appBundlePath); applicationBundle.libraryPaths = findAppLibraries(appBundlePath);
LogDebug() << "applicationBundle.libraryPaths:" << applicationBundle.libraryPaths; LogDebug() << "applicationBundle.libraryPaths:" << applicationBundle.libraryPaths;
@ -693,15 +693,15 @@ DeploymentInfo deployQtFrameworks(const QString &appBundlePath, const QStringLis
LogDebug() << "allLibraryPaths:" << allLibraryPaths; LogDebug() << "allLibraryPaths:" << allLibraryPaths;
QList<FrameworkInfo> frameworks = getQtFrameworksForPaths(allBinaryPaths, appBundlePath, allLibraryPaths, useDebugLibs); QList<LibraryInfo> libraries = getQtLibrariesForPaths(allBinaryPaths, appBundlePath, allLibraryPaths, useDebugLibs);
if (frameworks.isEmpty() && !alwaysOwerwriteEnabled) { if (libraries.isEmpty() && !alwaysOwerwriteEnabled) {
LogWarning(); LogWarning();
LogWarning() << "Could not find any external Qt frameworks to deploy in" << appBundlePath; LogWarning() << "Could not find any external Qt libraries to deploy in" << appBundlePath;
LogWarning() << "Perhaps linuxdeployqt was already used on" << appBundlePath << "?"; LogWarning() << "Perhaps linuxdeployqt was already used on" << appBundlePath << "?";
LogWarning() << "If so, you will need to rebuild" << appBundlePath << "before trying again."; LogWarning() << "If so, you will need to rebuild" << appBundlePath << "before trying again.";
return DeploymentInfo(); return DeploymentInfo();
} else { } else {
return deployQtFrameworks(frameworks, applicationBundle.path, allBinaryPaths, useDebugLibs, !additionalExecutables.isEmpty()); return deployQtLibraries(libraries, applicationBundle.path, allBinaryPaths, useDebugLibs, !additionalExecutables.isEmpty());
} }
} }
@ -724,33 +724,33 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
pluginList.append("printsupport/libcupsprintersupport.so"); pluginList.append("printsupport/libcupsprintersupport.so");
// Network // Network
if (deploymentInfo.deployedFrameworks.contains(QStringLiteral("QtNetwork"))) { if (deploymentInfo.deployedLibraries.contains(QStringLiteral("QtNetwork"))) {
QStringList bearerPlugins = QDir(pluginSourcePath + QStringLiteral("/bearer")).entryList(QStringList() << QStringLiteral("*.so")); QStringList bearerPlugins = QDir(pluginSourcePath + QStringLiteral("/bearer")).entryList(QStringList() << QStringLiteral("*.so"));
foreach (const QString &plugin, bearerPlugins) { foreach (const QString &plugin, bearerPlugins) {
pluginList.append(QStringLiteral("bearer/") + plugin); pluginList.append(QStringLiteral("bearer/") + plugin);
} }
} }
// All image formats (svg if QtSvg.framework is used) // All image formats (svg if QtSvg.library is used)
QStringList imagePlugins = QDir(pluginSourcePath + QStringLiteral("/imageformats")).entryList(QStringList() << QStringLiteral("*.so")); QStringList imagePlugins = QDir(pluginSourcePath + QStringLiteral("/imageformats")).entryList(QStringList() << QStringLiteral("*.so"));
foreach (const QString &plugin, imagePlugins) { foreach (const QString &plugin, imagePlugins) {
if (plugin.contains(QStringLiteral("qsvg"))) { if (plugin.contains(QStringLiteral("qsvg"))) {
if (deploymentInfo.deployedFrameworks.contains(QStringLiteral("QtSvg"))) if (deploymentInfo.deployedLibraries.contains(QStringLiteral("QtSvg")))
pluginList.append(QStringLiteral("imageformats/") + plugin); pluginList.append(QStringLiteral("imageformats/") + plugin);
pluginList.append(QStringLiteral("imageformats/") + plugin); pluginList.append(QStringLiteral("imageformats/") + plugin);
} }
} }
// Sql plugins if QtSql.framework is in use // Sql plugins if QtSql.library is in use
if (deploymentInfo.deployedFrameworks.contains(QStringLiteral("QtSql"))) { if (deploymentInfo.deployedLibraries.contains(QStringLiteral("QtSql"))) {
QStringList sqlPlugins = QDir(pluginSourcePath + QStringLiteral("/sqldrivers")).entryList(QStringList() << QStringLiteral("*.so")); QStringList sqlPlugins = QDir(pluginSourcePath + QStringLiteral("/sqldrivers")).entryList(QStringList() << QStringLiteral("*.so"));
foreach (const QString &plugin, sqlPlugins) { foreach (const QString &plugin, sqlPlugins) {
pluginList.append(QStringLiteral("sqldrivers/") + plugin); pluginList.append(QStringLiteral("sqldrivers/") + plugin);
} }
} }
// multimedia plugins if QtMultimedia.framework is in use // multimedia plugins if QtMultimedia.library is in use
if (deploymentInfo.deployedFrameworks.contains(QStringLiteral("QtMultimedia"))) { if (deploymentInfo.deployedLibraries.contains(QStringLiteral("QtMultimedia"))) {
QStringList plugins = QDir(pluginSourcePath + QStringLiteral("/mediaservice")).entryList(QStringList() << QStringLiteral("*.so")); QStringList plugins = QDir(pluginSourcePath + QStringLiteral("/mediaservice")).entryList(QStringList() << QStringLiteral("*.so"));
foreach (const QString &plugin, plugins) { foreach (const QString &plugin, plugins) {
pluginList.append(QStringLiteral("mediaservice/") + plugin); pluginList.append(QStringLiteral("mediaservice/") + plugin);
@ -770,8 +770,8 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
if (copyFilePrintStatus(sourcePath, destinationPath)) { if (copyFilePrintStatus(sourcePath, destinationPath)) {
runStrip(destinationPath); runStrip(destinationPath);
QList<FrameworkInfo> frameworks = getQtFrameworks(destinationPath, appBundleInfo.path, deploymentInfo.rpathsUsed, useDebugLibs); QList<LibraryInfo> libraries = getQtLibraries(destinationPath, appBundleInfo.path, deploymentInfo.rpathsUsed, useDebugLibs);
deployQtFrameworks(frameworks, appBundleInfo.path, QStringList() << destinationPath, useDebugLibs, deploymentInfo.useLoaderPath); deployQtLibraries(libraries, appBundleInfo.path, QStringList() << destinationPath, useDebugLibs, deploymentInfo.useLoaderPath);
} }
} }
} }
@ -936,11 +936,11 @@ bool deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInf
// Special case: // Special case:
// Use of QtQuick.PrivateWidgets is not discoverable at deploy-time. // Use of QtQuick.PrivateWidgets is not discoverable at deploy-time.
// Recreate the run-time logic here as best as we can - deploy it iff // Recreate the run-time logic here as best as we can - deploy it iff
// 1) QtWidgets.framework is used // 1) QtWidgets.library is used
// 2) QtQuick.Controls is used // 2) QtQuick.Controls is used
// The intended failure mode is that libwidgetsplugin.dylib will be present // The intended failure mode is that libwidgetsplugin.dylib will be present
// in the app bundle but not used at run-time. // in the app bundle but not used at run-time.
if (deploymentInfo.deployedFrameworks.contains("QtWidgets.framework") && qtQuickContolsInUse) { if (deploymentInfo.deployedLibraries.contains("QtWidgets.library") && qtQuickContolsInUse) {
LogNormal() << "Deploying QML import QtQuick.PrivateWidgets"; LogNormal() << "Deploying QML import QtQuick.PrivateWidgets";
QString name = "QtQuick/PrivateWidgets"; QString name = "QtQuick/PrivateWidgets";
QString path = qmlImportsPath + QLatin1Char('/') + name; QString path = qmlImportsPath + QLatin1Char('/') + name;
@ -950,33 +950,33 @@ bool deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInf
return true; return true;
} }
void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QStringList &binaryPaths, const QString &absoluteQtPath) void changeQtLibraries(const QList<LibraryInfo> libraries, const QStringList &binaryPaths, const QString &absoluteQtPath)
{ {
LogNormal() << "Changing" << binaryPaths << "to link against"; LogNormal() << "Changing" << binaryPaths << "to link against";
LogNormal() << "Qt in" << absoluteQtPath; LogNormal() << "Qt in" << absoluteQtPath;
QString finalQtPath = absoluteQtPath; QString finalQtPath = absoluteQtPath;
if (!absoluteQtPath.startsWith("/Library/Frameworks")) if (!absoluteQtPath.startsWith("/Library/Libraries"))
finalQtPath += "/lib/"; finalQtPath += "/lib/";
foreach (FrameworkInfo framework, frameworks) { foreach (LibraryInfo library, libraries) {
const QString oldBinaryId = framework.installName; const QString oldBinaryId = library.installName;
const QString newBinaryId = finalQtPath + framework.frameworkName + framework.binaryPath; const QString newBinaryId = finalQtPath + library.libraryName + library.binaryPath;
} }
} }
void changeQtFrameworks(const QString appPath, const QString &qtPath, bool useDebugLibs) void changeQtLibraries(const QString appPath, const QString &qtPath, bool useDebugLibs)
{ {
const QString appBinaryPath = findAppBinary(appPath); const QString appBinaryPath = findAppBinary(appPath);
const QStringList libraryPaths = findAppLibraries(appPath); const QStringList libraryPaths = findAppLibraries(appPath);
const QList<FrameworkInfo> frameworks = getQtFrameworksForPaths(QStringList() << appBinaryPath << libraryPaths, appPath, getBinaryRPaths(appBinaryPath, true), useDebugLibs); const QList<LibraryInfo> libraries = getQtLibrariesForPaths(QStringList() << appBinaryPath << libraryPaths, appPath, getBinaryRPaths(appBinaryPath, true), useDebugLibs);
if (frameworks.isEmpty()) { if (libraries.isEmpty()) {
LogWarning(); LogWarning();
LogWarning() << "Could not find any _external_ Qt frameworks to change in" << appPath; LogWarning() << "Could not find any _external_ Qt libraries to change in" << appPath;
return; return;
} else { } else {
const QString absoluteQtPath = QDir(qtPath).absolutePath(); const QString absoluteQtPath = QDir(qtPath).absolutePath();
changeQtFrameworks(frameworks, QStringList() << appBinaryPath << libraryPaths, absoluteQtPath); changeQtLibraries(libraries, QStringList() << appBinaryPath << libraryPaths, absoluteQtPath);
} }
} }

34
shared/shared.h

@ -43,13 +43,13 @@ extern int logLevel;
extern bool runStripEnabled; extern bool runStripEnabled;
class FrameworkInfo class LibraryInfo
{ {
public: public:
bool isDylib; bool isDylib;
QString frameworkDirectory; QString libraryDirectory;
QString frameworkName; QString libraryName;
QString frameworkPath; QString libraryPath;
QString binaryDirectory; QString binaryDirectory;
QString binaryName; QString binaryName;
QString binaryPath; QString binaryPath;
@ -58,7 +58,7 @@ public:
QString installName; QString installName;
QString deployedInstallName; QString deployedInstallName;
QString sourceFilePath; QString sourceFilePath;
QString frameworkDestinationDirectory; QString libraryDestinationDirectory;
QString binaryDestinationDirectory; QString binaryDestinationDirectory;
}; };
@ -80,8 +80,8 @@ public:
QList<DylibInfo> dependencies; QList<DylibInfo> dependencies;
}; };
bool operator==(const FrameworkInfo &a, const FrameworkInfo &b); bool operator==(const LibraryInfo &a, const LibraryInfo &b);
QDebug operator<<(QDebug debug, const FrameworkInfo &info); QDebug operator<<(QDebug debug, const LibraryInfo &info);
class ApplicationBundleInfo class ApplicationBundleInfo
{ {
@ -96,25 +96,25 @@ class DeploymentInfo
public: public:
QString qtPath; QString qtPath;
QString pluginPath; QString pluginPath;
QStringList deployedFrameworks; QStringList deployedLibraries;
QSet<QString> rpathsUsed; QSet<QString> rpathsUsed;
bool useLoaderPath; bool useLoaderPath;
bool isFramework; bool isLibrary;
}; };
inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info); inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info);
void changeQtFrameworks(const QString appPath, const QString &qtPath, bool useDebugLibs); void changeQtLibraries(const QString appPath, const QString &qtPath, bool useDebugLibs);
void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QStringList &binaryPaths, const QString &qtPath); void changeQtLibraries(const QList<LibraryInfo> libraries, const QStringList &binaryPaths, const QString &qtPath);
OtoolInfo findDependencyInfo(const QString &binaryPath); OtoolInfo findDependencyInfo(const QString &binaryPath);
FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs); LibraryInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs);
QString findAppBinary(const QString &appBundlePath); QString findAppBinary(const QString &appBundlePath);
QList<FrameworkInfo> getQtFrameworks(const QString &path, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs); QList<LibraryInfo> getQtLibraries(const QString &path, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs);
QList<FrameworkInfo> getQtFrameworks(const QStringList &otoolLines, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs); QList<LibraryInfo> getQtLibraries(const QStringList &otoolLines, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs);
QString copyFramework(const FrameworkInfo &framework, const QString path); QString copyLibrary(const LibraryInfo &library, const QString path);
DeploymentInfo deployQtFrameworks(const QString &appBundlePath, const QStringList &additionalExecutables, bool useDebugLibs); DeploymentInfo deployQtLibraries(const QString &appBundlePath, const QStringList &additionalExecutables, bool useDebugLibs);
DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks,const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs, bool useLoaderPath); DeploymentInfo deployQtLibraries(QList<LibraryInfo> libraries,const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs, bool useLoaderPath);
void createQtConf(const QString &appBundlePath); void createQtConf(const QString &appBundlePath);
void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo, bool useDebugLibs); void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo, bool useDebugLibs);
bool deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInfo, QStringList &qmlDirs); bool deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInfo, QStringList &qmlDirs);

Loading…
Cancel
Save