Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,27 @@ Please download __linuxdeployqt-x86_64.AppImage__ from the [Releases](https://gi
## Usage

```
Usage: linuxdeployqt app-binary [options]
Usage: linuxdeployqt <app-binary|desktop file> [options]

Options:
-verbose=<0-3> : 0 = no output, 1 = error/warning (default), 2 = normal, 3 = debug
-no-plugins : Skip plugin deployment
-appimage : Create an AppImage
-no-strip : Don't run 'strip' on the binaries
-bundle-non-qt-libs : Also bundle non-core, non-Qt libraries
-executable=<path> : Let the given executable use the deployed libraries too
-qmldir=<path> : Scan for QML imports to bundle from the given directory, determined by Qt's qmlimportscanner
-always-overwrite : Copy files even if the target file exists
-qmake=<path> : The qmake executable to use
-no-translations : Skip deployment of translations
-extra-plugins=<list> : List of extra plugins which should be deployed, separated by comma
-verbose=<0-3> : 0 = no output, 1 = error/warning (default),
2 = normal, 3 = debug
-no-plugins : Skip plugin deployment
-appimage : Create an AppImage (implies -bundle-non-qt-libs)
-no-strip : Don't run 'strip' on the binaries
-bundle-non-qt-libs : Also bundle non-core, non-Qt libraries
-executable=<path> : Let the given executable use the deployed libraries
too
-qmldir=<path> : Scan for QML imports in the given path
-always-overwrite : Copy files even if the target file exists
-qmake=<path> : The qmake executable to use
-no-translations : Skip deployment of translations.
-extra-plugins=<list> : List of extra plugins which should be deployed,
separated by comma.
-save-lib-path : Relative path from folder below bin to where to save the deployed libs,
defaults to /lib
-exclude-folder: : Excludes all libs in folder and subfolders.
-version : Print version statement and exit.

linuxdeployqt takes an application as input and makes it
self-contained by copying in the Qt libraries and plugins that
Expand Down
20 changes: 20 additions & 0 deletions tools/linuxdeployqt/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ int main(int argc, char **argv)
qInfo() << " -no-translations : Skip deployment of translations.";
qInfo() << " -extra-plugins=<list> : List of extra plugins which should be deployed,";
qInfo() << " separated by comma.";
qInfo() << " -save-lib-path : Relative path from folder below bin to where to save the deployed libs,";
qInfo() << " defaults to /lib, should not be used with -appimage";
qInfo() << " -exclude-folder: : Excludes all libs in folder and subfolders.";
qInfo() << " -version : Print version statement and exit.";
qInfo() << "";
qInfo() << "linuxdeployqt takes an application as input and makes it";
Expand Down Expand Up @@ -199,6 +202,8 @@ int main(int argc, char **argv)
extern bool fhsLikeMode;
extern QString fhsPrefix;
extern QStringList librarySearchPath;
extern QString librarySavePath;
extern QString blockedFolder;
extern bool alwaysOwerwriteEnabled;
QStringList additionalExecutables;
bool qmldirArgumentUsed = false;
Expand Down Expand Up @@ -367,6 +372,7 @@ int main(int argc, char **argv)
LogDebug() << "Argument found:" << argument;
appimage = true;
bundleAllButCoreLibs = true;
librarySavePath = "";
} else if (argument == QByteArray("-no-strip")) {
LogDebug() << "Argument found:" << argument;
runStripEnabled = false;
Expand Down Expand Up @@ -411,6 +417,20 @@ int main(int argc, char **argv)
LogDebug() << "Argument found:" << argument;
int index = argument.indexOf("=");
extraQtPlugins = QString(argument.mid(index + 1)).split(",");
} else if (argument.startsWith(QByteArray("-save-lib-path"))) {
LogDebug() << "Argument found:" << argument;
int index = argument.indexOf('=');
if (index == -1)
LogError() << "Missing library path";
else if (!appimage)
librarySavePath = argument.mid(index+1);
} else if (argument.startsWith(QByteArray("-exclude-folder"))) {
LogDebug() << "Argument found:" << argument;
int index = argument.indexOf('=');
if (index == -1)
LogError() << "Missing exclude folder path";
else
blockedFolder = argument.mid(index+1);
} else if (argument.startsWith("-")) {
LogError() << "Error: arguments must not start with --, only -" << "\n";
return 1;
Expand Down
48 changes: 29 additions & 19 deletions tools/linuxdeployqt/shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <QCoreApplication>
#include <QString>
#include <QStringList>
#include <QFileInfo>
#include <QDebug>
#include <iostream>
#include <QProcess>
Expand All @@ -52,6 +53,8 @@ bool fhsLikeMode = false;
QString fhsPrefix;
bool alwaysOwerwriteEnabled = false;
QStringList librarySearchPath;
QString librarySavePath;
QString blockedFolder;
bool appstoreCompliant = false;
int logLevel = 1;
int qtDetected = 0;
Expand Down Expand Up @@ -435,12 +438,7 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath,
{
(void)rpaths;

if(fhsLikeMode == false){
bundleLibraryDirectory= "lib"; // relative to bundle
} else {
QString relativePrefix = fhsPrefix.replace(appDirPath+"/", "");
bundleLibraryDirectory = relativePrefix + "/lib/";
}
handleFshLibPath(appDirPath);
LogDebug() << "bundleLibraryDirectory:" << bundleLibraryDirectory;

LibraryInfo info;
Expand All @@ -465,12 +463,11 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath,
echo -ne '"'$item'" << '
done
*/

QStringList excludelist;
excludelist << "libasound.so.2" << "libcom_err.so.2" << "libcrypt.so.1" << "libc.so.6" << "libdl.so.2" << "libdrm.so.2" << "libexpat.so.1" << "libfontconfig.so.1" << "libgcc_s.so.1" << "libgdk_pixbuf-2.0.so.0" << "libgio-2.0.so.0" << "libglib-2.0.so.0" << "libGL.so.1" << "libgobject-2.0.so.0" << "libgpg-error.so.0" << "libICE.so.6" << "libkeyutils.so.1" << "libm.so.6" << "libnsl.so.1" << "libnss3.so" << "libnssutil3.so" << "libp11-kit.so.0" << "libpangoft2-1.0.so.0" << "libpangocairo-1.0.so.0" << "libpango-1.0.so.0" << "libpthread.so.0" << "libresolv.so.2" << "librt.so.1" << "libSM.so.6" << "libstdc++.so.6" << "libusb-1.0.so.0" << "libuuid.so.1" << "libX11.so.6" << "libxcb.so.1" << "libz.so.1";
LogDebug() << "excludelist:" << excludelist;
if (! trimmed.contains("libicu")) {
if (containsHowOften(excludelist, QFileInfo(trimmed).completeBaseName())) {
if (containsHowOften(excludelist, QFileInfo(trimmed).completeBaseName()) || (!blockedFolder.isEmpty() && QFileInfo(trimmed).absolutePath().startsWith(blockedFolder))) {
LogDebug() << "Skipping blacklisted" << trimmed;
return info;
}
Expand Down Expand Up @@ -716,13 +713,7 @@ void recursiveCopyAndDeploy(const QString &appDirPath, const QSet<QString> &rpat
runStrip(fileDestinationPath);

// Find out the relative path to the lib/ directory and set it as the rpath
// FIXME: remove code duplication - the next few lines exist elsewhere already
if(fhsLikeMode == false){
bundleLibraryDirectory= "lib"; // relative to bundle
} else {
QString relativePrefix = fhsPrefix.replace(appDirPath+"/", "");
bundleLibraryDirectory = relativePrefix + "/lib/";
}
handleFshLibPath(appDirPath);

QDir dir(QFileInfo(fileDestinationPath).canonicalFilePath());
QString relativePath = dir.relativeFilePath(appDirPath + "/" + bundleLibraryDirectory);
Expand Down Expand Up @@ -846,6 +837,7 @@ void changeIdentification(const QString &id, const QString &binaryPath)
LogNormal() << "Checking rpath in" << binaryPath;
QString oldRpath = runPatchelf(QStringList() << "--print-rpath" << binaryPath);
LogDebug() << "oldRpath:" << oldRpath;
QString newRpath;
if (oldRpath.startsWith("/")){
LogDebug() << "Old rpath in" << binaryPath << "starts with /, hence adding it to LD_LIBRARY_PATH";
// FIXME: Split along ":" characters, check each one, only append to LD_LIBRARY_PATH if not already there
Expand All @@ -857,9 +849,13 @@ void changeIdentification(const QString &id, const QString &binaryPath)
LogDebug() << "Added to LD_LIBRARY_PATH:" << newPath;
setenv("LD_LIBRARY_PATH",newPath.toUtf8().constData(),1);
}
} else if(oldRpath.startsWith("$ORIGIN") && oldRpath != id) {
newRpath = oldRpath + ":" + id;
} else {
newRpath = id;
}
LogNormal() << "Changing rpath in" << binaryPath << "to" << id;
runPatchelf(QStringList() << "--set-rpath" << id << binaryPath);
LogNormal() << "Changing rpath in" << binaryPath << "to" << newRpath;
runPatchelf(QStringList() << "--set-rpath" << newRpath << binaryPath);

// qt_prfxpath:
if (binaryPath.contains("libQt5Core")) {
Expand Down Expand Up @@ -1151,10 +1147,11 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a
qtDetectionComplete = 1;

QString libraryPath;
QString prefix = librarySavePath.isEmpty() ? "lib/" : librarySavePath;
if(fhsLikeMode == false){
libraryPath = QFileInfo(applicationBundle.binaryPath).dir().filePath("lib/" + bundleLibraryDirectory);
libraryPath = QFileInfo(applicationBundle.binaryPath).dir().filePath(prefix + bundleLibraryDirectory);
} else {
libraryPath = QFileInfo(applicationBundle.binaryPath).dir().filePath("../lib/" + bundleLibraryDirectory);
libraryPath = QFileInfo(applicationBundle.binaryPath).dir().filePath("../" + prefix + bundleLibraryDirectory);
}

/* Make ldd detect pre-existing libraries in the AppDir.
Expand Down Expand Up @@ -1866,3 +1863,16 @@ bool deployTranslations(const QString &sourcePath, const QString &target, quint6
} // for prefixes.
return true;
}


void handleFshLibPath(const QString& appDirPath)
{
if(fhsLikeMode == false){
bundleLibraryDirectory = librarySavePath.isEmpty() ? "lib" : librarySavePath; // relative to bundle
} else {
QString relativePrefix = fhsPrefix.replace(appDirPath+"/", "");
QString tmp = librarySavePath.isEmpty() ? "/lib/" : librarySavePath;
bundleLibraryDirectory = relativePrefix + tmp;
}
}

1 change: 1 addition & 0 deletions tools/linuxdeployqt/shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,6 @@ bool checkAppImagePrerequisites(const QString &appBundlePath);
void findUsedModules(DeploymentInfo &info);
void deployTranslations(const QString &appDirPath, quint64 usedQtModules);
bool deployTranslations(const QString &sourcePath, const QString &target, quint64 usedQtModules);
void handleFshLibPath(const QString& appDirPath);

#endif