From 2f52ffe4c8f22d3054a088f18e4a20737927c38e Mon Sep 17 00:00:00 2001 From: probonopd Date: Wed, 7 Jun 2017 22:23:25 +0200 Subject: [PATCH 01/23] Clarify make install for .pro files [ci skip] --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 637402d..853dcbc 100644 --- a/README.md +++ b/README.md @@ -94,8 +94,14 @@ When you save your change, then Travis CI should build and upload an AppImage fo For this to work, you need to enable Travis CI for your repository as [described here](https://travis-ci.org/getting_started) __prior to merging this__, if you haven't already done so. +By default, qmake `.pro` files generated by Qt Creator unfortunately don't support `make install` out of the box. In this case you will get -Note that if `qmake` does not allow for `make install` or does not install the desktop file and icon, then change it similar to https://github.com/probonopd/FeedTheMonkey/blob/master/FeedTheMonkey.pro. +``` +make: Nothing to be done for `install'. +find: `appdir/': No such file or directory +``` + +If `qmake` does not allow for `make install` or does not install the desktop file and icon, then you need to change your `.pro` file it similar to https://github.com/probonopd/FeedTheMonkey/blob/master/FeedTheMonkey.pro. ``` - make INSTALL_ROOT=appdir install ; find appdir/ From 2bbb0844b56c0064b43d56244b2c360dad3ecb16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Fri, 9 Jun 2017 09:34:05 +0200 Subject: [PATCH 02/23] Try to find version specific qmake first Improve logging --- shared/shared.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/shared/shared.cpp b/shared/shared.cpp index a1cbe25..4415e03 100644 --- a/shared/shared.cpp +++ b/shared/shared.cpp @@ -1031,19 +1031,22 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a QString qmakePath = ""; - // The upstream name of the binary is "qmake", for Qt 4 and Qt 5 - qmakePath = QStandardPaths::findExecutable("qmake"); - // But openSUSE has qmake for Qt 4 and qmake-qt5 for Qt 5 + // Try to find a version specific qmake first + // openSUSE has qmake for Qt 4 and qmake-qt5 for Qt 5 // Qt 4 on Fedora comes with suffix -qt4 // http://www.geopsy.org/wiki/index.php/Installing_Qt_binary_packages + if(qtDetected == 5){ + qmakePath = QStandardPaths::findExecutable("qmake-qt5"); + LogDebug() << "qmake 5"; + } else if(qtDetected == 4){ + qmakePath = QStandardPaths::findExecutable("qmake-qt4"); + LogDebug() << "qmake 4"; + } + if(qmakePath == ""){ - if(qtDetected == 5){ - qmakePath = QStandardPaths::findExecutable("qmake-qt5"); - } - if(qtDetected == 4){ - qmakePath = QStandardPaths::findExecutable("qmake-qt4"); - } + // The upstream name of the binary is "qmake", for Qt 4 and Qt 5 + qmakePath = QStandardPaths::findExecutable("qmake"); } if(qmakePath == ""){ @@ -1051,6 +1054,7 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a exit(1); } + LogNormal() << "Using qmake: " << qmakePath; QString output = captureOutput(qmakePath + " -query"); LogDebug() << "-query output from qmake:" << output; From 11e35ce7afe28139a923114c5cae8db54713c659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Fri, 9 Jun 2017 09:34:55 +0200 Subject: [PATCH 03/23] Fix Qt version detection, qtDetected must not be a bool --- shared/shared.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/shared.cpp b/shared/shared.cpp index 4415e03..be56d3a 100644 --- a/shared/shared.cpp +++ b/shared/shared.cpp @@ -54,7 +54,7 @@ bool alwaysOwerwriteEnabled = false; QStringList librarySearchPath; bool appstoreCompliant = false; int logLevel = 1; -bool qtDetected = 0; +int qtDetected = 0; bool qtDetectionComplete = 0; // As long as Qt is not detected yet, ldd may encounter "not found" messages, continue anyway bool deployLibrary = false; From c8aac7154e1f10bf5aab448740abc431642264ea Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 10 Jun 2017 12:59:31 +0200 Subject: [PATCH 04/23] Codacy Badge [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 853dcbc..d113dda 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# linuxdeployqt [![Build Status](https://travis-ci.org/probonopd/linuxdeployqt.svg?branch=master)](https://travis-ci.org/probonopd/linuxdeployqt) [![discourse](https://img.shields.io/badge/forum-discourse-orange.svg)](http://discourse.appimage.org/t/linuxdeployqt-new-linux-deployment-tool-for-qt/57) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/probonopd/AppImageKit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![irc](https://img.shields.io/badge/IRC-%23AppImage%20on%20freenode-blue.svg)](https://webchat.freenode.net/?channels=AppImage) +# linuxdeployqt [![Build Status](https://travis-ci.org/probonopd/linuxdeployqt.svg?branch=master)](https://travis-ci.org/probonopd/linuxdeployqt) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/93b4a359057e412b8a7673b4b61d7cb7)](https://www.codacy.com/app/probonopd/linuxdeployqt?utm_source=github.com&utm_medium=referral&utm_content=probonopd/linuxdeployqt&utm_campaign=Badge_Grade) [![discourse](https://img.shields.io/badge/forum-discourse-orange.svg)](http://discourse.appimage.org/t/linuxdeployqt-new-linux-deployment-tool-for-qt/57) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/probonopd/AppImageKit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![irc](https://img.shields.io/badge/IRC-%23AppImage%20on%20freenode-blue.svg)](https://webchat.freenode.net/?channels=AppImage) This Linux Deployment Tool for Qt, `linuxdeployqt`, takes an application as input and makes it self-contained by copying in the Qt libraries and plugins that the application uses into a bundle. This can optionally be put into an [AppImage](http://appimage.org/), and, using [fpm](https://github.com/probonopd/linuxdeployqt/issues/9), into cross-distro deb and rpm packages. From b661b394fafd0fb5c611d03379d5ec0521512426 Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 10 Jun 2017 13:08:43 +0200 Subject: [PATCH 05/23] Closes #138, the function 'getBinaryDependencies' was never used --- shared/shared.cpp | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) diff --git a/shared/shared.cpp b/shared/shared.cpp index be56d3a..87cfe42 100644 --- a/shared/shared.cpp +++ b/shared/shared.cpp @@ -577,53 +577,6 @@ QList getQtLibrariesForPaths(const QStringList &paths, const QStrin return result; } -QStringList getBinaryDependencies(const QString executablePath, - const QString &path, - const QList &additionalBinariesContainingRpaths) -{ - QStringList binaries; - - const QList dependencies = findDependencyInfo(path).dependencies; - - bool rpathsLoaded = false; - QSet rpaths; - - // return bundle-local dependencies. (those starting with @executable_path) - foreach (const DylibInfo &info, dependencies) { - QString trimmedLine = info.binaryPath; - if (trimmedLine.startsWith("@executable_path/")) { - QString binary = QDir::cleanPath(executablePath + trimmedLine.mid(QStringLiteral("@executable_path/").length())); - if (binary != path) - binaries.append(binary); - } else if (trimmedLine.startsWith("@rpath/")) { - if (!rpathsLoaded) { - rpaths = getBinaryRPaths(path, true, executablePath); - foreach (const QString &binaryPath, additionalBinariesContainingRpaths) { - QSet binaryRpaths = getBinaryRPaths(binaryPath, true); - rpaths += binaryRpaths; - } - rpathsLoaded = true; - } - bool resolved = false; - foreach (const QString &rpath, rpaths) { - QString binary = QDir::cleanPath(rpath + "/" + trimmedLine.mid(QStringLiteral("@rpath/").length())); - LogDebug() << "Checking for" << binary; - if (QFile::exists(binary)) { - binaries.append(binary); - resolved = true; - break; - } - } - if (!resolved && !rpaths.isEmpty()) { - LogError() << "Cannot resolve rpath" << trimmedLine; - LogError() << " using" << rpaths; - } - } - } - - return binaries; -} - // copies everything _inside_ sourcePath to destinationPath bool recursiveCopy(const QString &sourcePath, const QString &destinationPath) { From fd8bd3053487ab4d1ed61755b076a423283949dc Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 10 Jun 2017 15:35:01 +0200 Subject: [PATCH 06/23] Create shared.cpp --- shared/shared.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/shared/shared.cpp b/shared/shared.cpp index 87cfe42..97bd933 100644 --- a/shared/shared.cpp +++ b/shared/shared.cpp @@ -670,7 +670,7 @@ QString copyDylib(const LibraryInfo &library, const QString path) return dylibDestinationBinaryPath; } -void runPatchelf(QStringList options) +QString runPatchelf(QStringList options) { QProcess patchelftool; patchelftool.start("patchelf", options); @@ -690,6 +690,7 @@ void runPatchelf(QStringList options) LogError() << "runPatchelf:" << patchelftool.readAllStandardOutput(); // exit(1); // Do not exit because this could be a script that patchelf can't work on } + return(patchelftool.readAllStandardOutput().trimmed()); } bool patchQtCore(const QString &path, const QString &variable, const QString &value) @@ -742,6 +743,17 @@ bool patchQtCore(const QString &path, const QString &variable, const QString &va void changeIdentification(const QString &id, const QString &binaryPath) { + LogNormal() << "Checking rpath in" << binaryPath; + QString oldRpath = runPatchelf(QStringList() << "--get-rpath" << id << binaryPath); + 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 + QString oldPath = env.value("LD_LIBRARY_PATH"); + QString newPath = oldRpath + ":" + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path + // FIXME: Directory layout might be different for system Qt; cannot assume lib/ to always be inside the Qt directory + LogDebug() << "Changed LD_LIBRARY_PATH:" << newPath; + setenv("LD_LIBRARY_PATH",newPath.toUtf8().constData(),1); + } LogNormal() << "Changing rpath in" << binaryPath << "to" << id; runPatchelf(QStringList() << "--set-rpath" << id << binaryPath); From 646201dcab94038581d28633ffc89ffda8748ee6 Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 10 Jun 2017 15:43:07 +0200 Subject: [PATCH 07/23] Revert "Create shared.cpp" This reverts commit fd8bd3053487ab4d1ed61755b076a423283949dc. --- shared/shared.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/shared/shared.cpp b/shared/shared.cpp index 97bd933..87cfe42 100644 --- a/shared/shared.cpp +++ b/shared/shared.cpp @@ -670,7 +670,7 @@ QString copyDylib(const LibraryInfo &library, const QString path) return dylibDestinationBinaryPath; } -QString runPatchelf(QStringList options) +void runPatchelf(QStringList options) { QProcess patchelftool; patchelftool.start("patchelf", options); @@ -690,7 +690,6 @@ QString runPatchelf(QStringList options) LogError() << "runPatchelf:" << patchelftool.readAllStandardOutput(); // exit(1); // Do not exit because this could be a script that patchelf can't work on } - return(patchelftool.readAllStandardOutput().trimmed()); } bool patchQtCore(const QString &path, const QString &variable, const QString &value) @@ -743,17 +742,6 @@ bool patchQtCore(const QString &path, const QString &variable, const QString &va void changeIdentification(const QString &id, const QString &binaryPath) { - LogNormal() << "Checking rpath in" << binaryPath; - QString oldRpath = runPatchelf(QStringList() << "--get-rpath" << id << binaryPath); - 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 - QString oldPath = env.value("LD_LIBRARY_PATH"); - QString newPath = oldRpath + ":" + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path - // FIXME: Directory layout might be different for system Qt; cannot assume lib/ to always be inside the Qt directory - LogDebug() << "Changed LD_LIBRARY_PATH:" << newPath; - setenv("LD_LIBRARY_PATH",newPath.toUtf8().constData(),1); - } LogNormal() << "Changing rpath in" << binaryPath << "to" << id; runPatchelf(QStringList() << "--set-rpath" << id << binaryPath); From 6d4c1d966b010fd732e2d4ad11327926e4860b92 Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 10 Jun 2017 22:01:00 +0000 Subject: [PATCH 08/23] Attempt to obey pre-existing RPATHs, #52 --- shared/shared.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/shared/shared.cpp b/shared/shared.cpp index 87cfe42..70c58dd 100644 --- a/shared/shared.cpp +++ b/shared/shared.cpp @@ -670,26 +670,28 @@ QString copyDylib(const LibraryInfo &library, const QString path) return dylibDestinationBinaryPath; } -void runPatchelf(QStringList options) +QString runPatchelf(QStringList options) { QProcess patchelftool; + LogDebug() << "options:" << options; patchelftool.start("patchelf", options); if (!patchelftool.waitForStarted()) { - if(patchelftool.errorString().contains("execvp: No such file or directory")){ + if(patchelftool.errorString().contains("No such file or directory")){ LogError() << "Could not start patchelf."; LogError() << "Make sure it is installed on your $PATH, e.g., in /usr/local/bin."; LogError() << "You can get it from https://nixos.org/patchelf.html."; } else { - LogError() << "Could not start patchelftool. Process error is" << patchelftool.errorString(); + LogError() << "Could not start patchelf tool. Process error is" << patchelftool.errorString(); } exit(1); } patchelftool.waitForFinished(); if (patchelftool.exitCode() != 0) { LogError() << "runPatchelf:" << patchelftool.readAllStandardError(); - LogError() << "runPatchelf:" << patchelftool.readAllStandardOutput(); + // LogError() << "runPatchelf:" << patchelftool.readAllStandardOutput(); // exit(1); // Do not exit because this could be a script that patchelf can't work on } + return(patchelftool.readAllStandardOutput().trimmed()); } bool patchQtCore(const QString &path, const QString &variable, const QString &value) @@ -742,6 +744,19 @@ bool patchQtCore(const QString &path, const QString &variable, const QString &va void changeIdentification(const QString &id, const QString &binaryPath) { + LogNormal() << "Checking rpath in" << binaryPath; + QString oldRpath = runPatchelf(QStringList() << "--print-rpath" << binaryPath); + LogDebug() << "oldRpath:" << oldRpath; + 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 + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + QString oldPath = env.value("LD_LIBRARY_PATH"); + QString newPath = oldRpath + ":" + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path + // FIXME: Directory layout might be different for system Qt; cannot assume lib/ to always be inside the Qt directory + LogDebug() << "Added to LD_LIBRARY_PATH:" << newPath; + setenv("LD_LIBRARY_PATH",newPath.toUtf8().constData(),1); + } LogNormal() << "Changing rpath in" << binaryPath << "to" << id; runPatchelf(QStringList() << "--set-rpath" << id << binaryPath); From 9a93e030cff2cb10e9e672ebb3360d30b3099c6d Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 10 Jun 2017 22:05:26 +0000 Subject: [PATCH 09/23] Attempt to obey pre-existing RPATHs, #52 --- shared/shared.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/shared/shared.cpp b/shared/shared.cpp index 70c58dd..38fec81 100644 --- a/shared/shared.cpp +++ b/shared/shared.cpp @@ -752,10 +752,12 @@ void changeIdentification(const QString &id, const QString &binaryPath) // FIXME: Split along ":" characters, check each one, only append to LD_LIBRARY_PATH if not already there QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QString oldPath = env.value("LD_LIBRARY_PATH"); - QString newPath = oldRpath + ":" + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path - // FIXME: Directory layout might be different for system Qt; cannot assume lib/ to always be inside the Qt directory - LogDebug() << "Added to LD_LIBRARY_PATH:" << newPath; - setenv("LD_LIBRARY_PATH",newPath.toUtf8().constData(),1); + if (not oldPath.contains(oldRpath)){ + QString newPath = oldRpath + ":" + oldPath; // FIXME: If we use a ldd replacement, we still need to observe this path + // FIXME: Directory layout might be different for system Qt; cannot assume lib/ to always be inside the Qt directory + LogDebug() << "Added to LD_LIBRARY_PATH:" << newPath; + setenv("LD_LIBRARY_PATH",newPath.toUtf8().constData(),1); + } } LogNormal() << "Changing rpath in" << binaryPath << "to" << id; runPatchelf(QStringList() << "--set-rpath" << id << binaryPath); From bd459f786968d92bcf3be24e9aa9c7aed2e6cdea Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 10 Jun 2017 22:07:42 +0000 Subject: [PATCH 10/23] Do not error when there are no translations --- shared/shared.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/shared.cpp b/shared/shared.cpp index 38fec81..a59411a 100644 --- a/shared/shared.cpp +++ b/shared/shared.cpp @@ -1599,7 +1599,7 @@ void deployTranslations(const QString &appDirPath, quint64 usedQtModules) LogDebug() << "Deploying translations..."; QString qtTranslationsPath = qtToBeBundledInfo.value("QT_INSTALL_TRANSLATIONS"); if (qtTranslationsPath.isEmpty() || !QFile::exists(qtTranslationsPath)) { - LogError() << "Qt translations path could not be determined"; + LogDebug() << "Qt translations path could not be determined, maybe there are no translations?"; return; } From 63404085185a4110fa05657a8a150f7c1e44e13c Mon Sep 17 00:00:00 2001 From: Jakob Gahde Date: Tue, 6 Jun 2017 01:00:34 +0200 Subject: [PATCH 11/23] Also set rpath for -executable=, resolves #83 --- shared/shared.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/shared/shared.cpp b/shared/shared.cpp index a59411a..363a71a 100644 --- a/shared/shared.cpp +++ b/shared/shared.cpp @@ -1059,10 +1059,14 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a /* From now on let ldd exit if it doesn't find something */ qtDetectionComplete = 1; + QString libraryPath; if(fhsLikeMode == false){ - changeIdentification("$ORIGIN/lib/" + bundleLibraryDirectory, QFileInfo(applicationBundle.binaryPath).canonicalFilePath()); + libraryPath = QFileInfo(applicationBundle.binaryPath).dir().filePath("lib/" + bundleLibraryDirectory); } else { - changeIdentification("$ORIGIN/../lib/" + bundleLibraryDirectory, QFileInfo(applicationBundle.binaryPath).canonicalFilePath()); + libraryPath = QFileInfo(applicationBundle.binaryPath).dir().filePath("../lib/" + bundleLibraryDirectory); + } + foreach (const QString &executable, QStringList() << applicationBundle.binaryPath << additionalExecutables) { + changeIdentification("$ORIGIN/" + QFileInfo(executable).dir().relativeFilePath(libraryPath) + "/" + bundleLibraryDirectory, QFileInfo(executable).canonicalFilePath()); } applicationBundle.libraryPaths = findAppLibraries(appDirPath); LogDebug() << "applicationBundle.libraryPaths:" << applicationBundle.libraryPaths; From 93ba2f186e7c5ddc21559c69db51b60d49ddda8f Mon Sep 17 00:00:00 2001 From: Felix Barz Date: Mon, 19 Jun 2017 18:32:53 +0200 Subject: [PATCH 12/23] Qt module project structure (#124) Refactor the project structure to make it build as a "Qt module". It's a first step to get this tool closer to Qt. The main advantage here is: Simply running: ``` qmake make make install ``` will compile and install the tool into your Qt installation, and make it a part of your Qt just like any other tool (qmake, etc.) --- .qmake.conf | 5 +++++ BUILDING.md | 8 +++++++- linuxdeployqt.pro | 3 +-- linuxdeployqt/linuxdeployqt.pro | 2 -- src/src.pro | 1 + sync.profile | 5 +++++ tests/tests-ci.sh | 4 ++-- tests/tests.pro | 11 +++++++++++ tools/linuxdeployqt/linuxdeployqt.pro | 17 +++++++++++++++++ {linuxdeployqt => tools/linuxdeployqt}/main.cpp | 6 +++--- {shared => tools/linuxdeployqt}/shared.cpp | 0 {shared => tools/linuxdeployqt}/shared.h | 0 tools/tools.pro | 4 ++++ 13 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 .qmake.conf delete mode 100644 linuxdeployqt/linuxdeployqt.pro create mode 100644 src/src.pro create mode 100644 sync.profile create mode 100644 tests/tests.pro create mode 100644 tools/linuxdeployqt/linuxdeployqt.pro rename {linuxdeployqt => tools/linuxdeployqt}/main.cpp (99%) rename {shared => tools/linuxdeployqt}/shared.cpp (100%) rename {shared => tools/linuxdeployqt}/shared.h (100%) create mode 100644 tools/tools.pro diff --git a/.qmake.conf b/.qmake.conf new file mode 100644 index 0000000..ae52f0b --- /dev/null +++ b/.qmake.conf @@ -0,0 +1,5 @@ +load(qt_build_config) + +CONFIG += warning_clean exceptions + +MODULE_VERSION = 0.5.0 diff --git a/BUILDING.md b/BUILDING.md index b66838c..23e2a1c 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -12,10 +12,16 @@ git clone https://github.com/probonopd/linuxdeployqt.git # Then build in Qt Creator, or use export PATH=$(readlink -f /tmp/.mount_QtCreator-*-x86_64/*/gcc_64/bin/):$PATH cd linuxdeployqt -qmake linuxdeployqt.pro +qmake make ``` +* Optional if you want to install `linuxdeployqt` into your Qt installation, and make it a part of your Qt just like any other tool (qmake, etc.) + +``` +sudo make install +``` + * Build and install [patchelf](https://nixos.org/patchelf.html) (a small utility to modify the dynamic linker and RPATH of ELF executables; similar to `install_name_tool` on macOS). To learn more about this, see http://blog.qt.io/blog/2011/10/28/rpath-and-runpath/ ``` diff --git a/linuxdeployqt.pro b/linuxdeployqt.pro index 1e2f2d5..58c33f2 100644 --- a/linuxdeployqt.pro +++ b/linuxdeployqt.pro @@ -1,2 +1 @@ -TEMPLATE = subdirs -SUBDIRS = linuxdeployqt +load(qt_parts) diff --git a/linuxdeployqt/linuxdeployqt.pro b/linuxdeployqt/linuxdeployqt.pro deleted file mode 100644 index b9e628a..0000000 --- a/linuxdeployqt/linuxdeployqt.pro +++ /dev/null @@ -1,2 +0,0 @@ -QT = core -SOURCES += main.cpp ../shared/shared.cpp diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..86290fc --- /dev/null +++ b/src/src.pro @@ -0,0 +1 @@ +TEMPLATE = aux diff --git a/sync.profile b/sync.profile new file mode 100644 index 0000000..58dbecb --- /dev/null +++ b/sync.profile @@ -0,0 +1,5 @@ +%modules = ( +); + +%moduleheaders = ( +); diff --git a/tests/tests-ci.sh b/tests/tests-ci.sh index 901ac43..a704606 100755 --- a/tests/tests-ci.sh +++ b/tests/tests-ci.sh @@ -10,8 +10,8 @@ mkdir -p linuxdeployqt.AppDir/usr/bin/ cp /usr/bin/patchelf /usr/local/bin/{appimagetool,mksquashfs,zsyncmake} linuxdeployqt.AppDir/usr/bin/ find linuxdeployqt.AppDir/ export VERSION=continuous -cp ./linuxdeployqt/linuxdeployqt linuxdeployqt.AppDir/usr/bin/ -./linuxdeployqt/linuxdeployqt linuxdeployqt.AppDir/linuxdeployqt.desktop -verbose=3 -appimage +cp ./bin/linuxdeployqt linuxdeployqt.AppDir/usr/bin/ +./bin/linuxdeployqt linuxdeployqt.AppDir/linuxdeployqt.desktop -verbose=3 -appimage ls -lh find *.AppDir xpra start :99 diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 0000000..089e590 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,11 @@ +TEMPLATE = subdirs + +SUBDIRS += \ + QtQuickControls2Application \ + QtWebEngineApplication \ + QtWidgetsApplication + +DISTFILES += \ + tests-ci.sh \ + tests-environment.sh \ + tests.sh diff --git a/tools/linuxdeployqt/linuxdeployqt.pro b/tools/linuxdeployqt/linuxdeployqt.pro new file mode 100644 index 0000000..26f115e --- /dev/null +++ b/tools/linuxdeployqt/linuxdeployqt.pro @@ -0,0 +1,17 @@ +option(host_build) + +QT = core +CONFIG += console + +TARGET = linuxdeployqt +VERSION = $$MODULE_VERSION + +DEFINES += BUILD_LINUXDEPLOYQT + +load(qt_tool) + +HEADERS += shared.h +SOURCES += main.cpp \ + shared.cpp + +DEFINES -= QT_USE_QSTRINGBUILDER #leads to compile errors if not disabled diff --git a/linuxdeployqt/main.cpp b/tools/linuxdeployqt/main.cpp similarity index 99% rename from linuxdeployqt/main.cpp rename to tools/linuxdeployqt/main.cpp index 0bde0c2..67baecc 100644 --- a/linuxdeployqt/main.cpp +++ b/tools/linuxdeployqt/main.cpp @@ -28,7 +28,7 @@ #include #include #include -#include "../shared/shared.h" +#include "shared.h" #include #include #include @@ -146,7 +146,7 @@ int main(int argc, char **argv) // Allow binaries next to linuxdeployqt to be found; this is useful for bundling // this application itself together with helper binaries such as patchelf QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - QString oldPath = env.value("PATH"); + QString oldPath = env.value("PATH"); QString newPath = QCoreApplication::applicationDirPath() + ":" + oldPath; LogDebug() << newPath; setenv("PATH",newPath.toUtf8().constData(),1); @@ -306,7 +306,7 @@ int main(int argc, char **argv) qDebug() << "preExistingToplevelIcon:" << preExistingToplevelIcon; } else { qDebug() << "iconToBeUsed:" << iconToBeUsed; - QString targetIconPath = appDirPath + "/" + QFileInfo(iconToBeUsed).fileName(); + QString targetIconPath = appDirPath + "/" + QFileInfo(iconToBeUsed).fileName(); if (QFile::copy(iconToBeUsed, targetIconPath)){ qDebug() << "Copied" << iconToBeUsed << "to" << targetIconPath; QFile::copy(targetIconPath, appDirPath + "/.DirIcon"); diff --git a/shared/shared.cpp b/tools/linuxdeployqt/shared.cpp similarity index 100% rename from shared/shared.cpp rename to tools/linuxdeployqt/shared.cpp diff --git a/shared/shared.h b/tools/linuxdeployqt/shared.h similarity index 100% rename from shared/shared.h rename to tools/linuxdeployqt/shared.h diff --git a/tools/tools.pro b/tools/tools.pro new file mode 100644 index 0000000..91ee914 --- /dev/null +++ b/tools/tools.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS += linuxdeployqt From f399119ab6718f7943d00d35a87d8580cc60ac7d Mon Sep 17 00:00:00 2001 From: orbifx Date: Mon, 19 Jun 2017 17:34:38 +0100 Subject: [PATCH 13/23] Show example usage and restructures usage section (#139) --- README.md | 53 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index d113dda..8b8e3a7 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,40 @@ Please download __linuxdeployqt-x86_64.AppImage__ from the [Releases](https://gi ## Usage +``` +Usage: linuxdeployqt app-binary [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= : Let the given executable use the deployed libraries too + -qmldir= : Scan for QML imports in the given path + -always-overwrite : Copy files even if the target file exists + -no-translations : Skip deployment of translations + +linuxdeployqt takes an application as input and makes it +self-contained by copying in the Qt libraries and plugins that +the application uses. +``` + +#### Simplest example + +Given that a desktop file should be provided with an AppImage, `linuxdeployqt` can use that to determine the parameters of the build. + +`linuxdeployqt ./path/to/appdir/usr/share/application_name.desktop` + +Where the _desktop_ file specifies the executable to be run (with `EXEC=`), the name of the applications and an icon. +See [desktop file specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html). + +#### Checking library inclusion + Open in Qt Creator and build your application. Run it from the command line and inspect it with `ldd` to make sure the correct libraries from the correct locations are getting loaded, as `linuxdeployqt` will use `ldd` internally to determine from where to copy libraries into the bundle. +#### QMake configuration + __Important:__ `linuxdeployqt` deploys the Qt instance that qmake on the $PATH points to, so make sure that it is the correct one. Verify that qmake finds the correct Qt instance like this before running the `linuxdeployqt` tool: ``` @@ -30,6 +62,8 @@ Using Qt version 5.7.0 in /tmp/.mount_QtCreator-5.7.0-x86_64/5.7/gcc_64/lib ``` If this does not show the correct path to your Qt instance that you want to be bundled, then adjust your `$PATH` to find the correct `qmake`. +#### Remove unecessary files + Before running linuxdeployqt it may be wise to delete unneeded files that you do not wish to distribute from the build directory. These may be autogenerated during the build. You can delete them like so: ``` @@ -38,25 +72,6 @@ find $HOME/build-*-*_Qt_* \( -name "moc_*" -or -name "*.o" -or -name "qrc_*" -or Alternatively, you could use `$DESTDIR`. -``` -Usage: linuxdeployqt app-binary [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= : Let the given executable use the deployed libraries too - -qmldir= : Scan for QML imports in the given path - -always-overwrite : Copy files even if the target file exists - -no-translations : Skip deployment of translations - -linuxdeployqt takes an application as input and makes it -self-contained by copying in the Qt libraries and plugins that -the application uses. -``` - ## Using linuxdeployqt with Travis CI A common use case for `linuxdeployqt` is to use it on Travis CI after the `make` command. The following example illustrates how to use `linuxdeployqt` with Travis CI. Create a `.travis.yml` file similar to this one (be sure to customize it, e.g., change `APPNAME` to the name of your application as it is spelled in the `Name=` entry of the `.desktop` file): From c662e56e2f956d4caa71a96fa6495bd5c816a4b7 Mon Sep 17 00:00:00 2001 From: orbifx Date: Tue, 20 Jun 2017 16:43:36 +0100 Subject: [PATCH 14/23] Elaborates on -qmldir --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b8e3a7..973ac1a 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Options: -no-strip : Don't run 'strip' on the binaries -bundle-non-qt-libs : Also bundle non-core, non-Qt libraries -executable= : Let the given executable use the deployed libraries too - -qmldir= : Scan for QML imports in the given path + -qmldir= : 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 -no-translations : Skip deployment of translations From 4e3a8bfe834368a9168dc77859062aa15d2022ba Mon Sep 17 00:00:00 2001 From: probonopd Date: Wed, 28 Jun 2017 22:35:31 +0200 Subject: [PATCH 15/23] Cannot assume libkrb5* to be there, it is missing on openSUSE LEAP 42.0 --- tools/linuxdeployqt/shared.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/linuxdeployqt/shared.cpp b/tools/linuxdeployqt/shared.cpp index 363a71a..44dde98 100644 --- a/tools/linuxdeployqt/shared.cpp +++ b/tools/linuxdeployqt/shared.cpp @@ -374,7 +374,7 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, */ 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" << "libgdk-x11-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" << "libgssapi_krb5.so.2" << "libgtk-x11-2.0.so.0" << "libhcrypto.so.4" << "libhx509.so.5" << "libICE.so.6" << "libidn.so.11" << "libk5crypto.so.3" << "libkeyutils.so.1" << "libkrb5.so.26" << "libkrb5.so.3" << "libkrb5support.so.0" << "libm.so.6" << "libnss3.so" << "libnssutil3.so" << "libp11-kit.so.0" << "libpangoft2-1.0.so.0" << "libpangocairo-1.0.so.0" << "libpango-1.0.so.0" << "libpcre.so.3" << "libpthread.so.0" << "libresolv.so.2" << "libroken.so.18" << "librt.so.1" << "libselinux.so.1" << "libSM.so.6" << "libstdc++.so.6" << "libusb-1.0.so.0" << "libuuid.so.1" << "libwind.so.0" << "libX11.so.6" << "libxcb.so.1" << "libz.so.1"; + 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" << "libgdk-x11-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" << "libgssapi_krb5.so.2" << "libgtk-x11-2.0.so.0" << "libhcrypto.so.4" << "libhx509.so.5" << "libICE.so.6" << "libidn.so.11" << "libk5crypto.so.3" << "libkeyutils.so.1" << "libm.so.6" << "libnss3.so" << "libnssutil3.so" << "libp11-kit.so.0" << "libpangoft2-1.0.so.0" << "libpangocairo-1.0.so.0" << "libpango-1.0.so.0" << "libpcre.so.3" << "libpthread.so.0" << "libresolv.so.2" << "libroken.so.18" << "librt.so.1" << "libselinux.so.1" << "libSM.so.6" << "libstdc++.so.6" << "libusb-1.0.so.0" << "libuuid.so.1" << "libwind.so.0" << "libX11.so.6" << "libxcb.so.1" << "libz.so.1"; LogDebug() << "excludelist:" << excludelist; if (! trimmed.contains("libicu")) { if (containsHowOften(excludelist, QFileInfo(trimmed).completeBaseName())) { From 18fd602a2224fa7e085511072319d94e5ad45115 Mon Sep 17 00:00:00 2001 From: probonopd Date: Wed, 28 Jun 2017 23:11:04 +0200 Subject: [PATCH 16/23] libhcrypto.so.4 missing on openSUSE LEAP 42.0 --- tools/linuxdeployqt/shared.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/linuxdeployqt/shared.cpp b/tools/linuxdeployqt/shared.cpp index 44dde98..e6d3a0b 100644 --- a/tools/linuxdeployqt/shared.cpp +++ b/tools/linuxdeployqt/shared.cpp @@ -374,7 +374,7 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, */ 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" << "libgdk-x11-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" << "libgssapi_krb5.so.2" << "libgtk-x11-2.0.so.0" << "libhcrypto.so.4" << "libhx509.so.5" << "libICE.so.6" << "libidn.so.11" << "libk5crypto.so.3" << "libkeyutils.so.1" << "libm.so.6" << "libnss3.so" << "libnssutil3.so" << "libp11-kit.so.0" << "libpangoft2-1.0.so.0" << "libpangocairo-1.0.so.0" << "libpango-1.0.so.0" << "libpcre.so.3" << "libpthread.so.0" << "libresolv.so.2" << "libroken.so.18" << "librt.so.1" << "libselinux.so.1" << "libSM.so.6" << "libstdc++.so.6" << "libusb-1.0.so.0" << "libuuid.so.1" << "libwind.so.0" << "libX11.so.6" << "libxcb.so.1" << "libz.so.1"; + 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" << "libgdk-x11-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" << "libgssapi_krb5.so.2" << "libgtk-x11-2.0.so.0" << "libhx509.so.5" << "libICE.so.6" << "libidn.so.11" << "libk5crypto.so.3" << "libkeyutils.so.1" << "libm.so.6" << "libnss3.so" << "libnssutil3.so" << "libp11-kit.so.0" << "libpangoft2-1.0.so.0" << "libpangocairo-1.0.so.0" << "libpango-1.0.so.0" << "libpcre.so.3" << "libpthread.so.0" << "libresolv.so.2" << "libroken.so.18" << "librt.so.1" << "libselinux.so.1" << "libSM.so.6" << "libstdc++.so.6" << "libusb-1.0.so.0" << "libuuid.so.1" << "libwind.so.0" << "libX11.so.6" << "libxcb.so.1" << "libz.so.1"; LogDebug() << "excludelist:" << excludelist; if (! trimmed.contains("libicu")) { if (containsHowOften(excludelist, QFileInfo(trimmed).completeBaseName())) { From c96f01bc4a7eaa3e16df29d5e275d90ef6946a1e Mon Sep 17 00:00:00 2001 From: probonopd Date: Wed, 28 Jun 2017 23:43:32 +0200 Subject: [PATCH 17/23] Libraries missing on openSUSE 42.0 --- tools/linuxdeployqt/shared.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/linuxdeployqt/shared.cpp b/tools/linuxdeployqt/shared.cpp index e6d3a0b..3f17245 100644 --- a/tools/linuxdeployqt/shared.cpp +++ b/tools/linuxdeployqt/shared.cpp @@ -374,7 +374,7 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, */ 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" << "libgdk-x11-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" << "libgssapi_krb5.so.2" << "libgtk-x11-2.0.so.0" << "libhx509.so.5" << "libICE.so.6" << "libidn.so.11" << "libk5crypto.so.3" << "libkeyutils.so.1" << "libm.so.6" << "libnss3.so" << "libnssutil3.so" << "libp11-kit.so.0" << "libpangoft2-1.0.so.0" << "libpangocairo-1.0.so.0" << "libpango-1.0.so.0" << "libpcre.so.3" << "libpthread.so.0" << "libresolv.so.2" << "libroken.so.18" << "librt.so.1" << "libselinux.so.1" << "libSM.so.6" << "libstdc++.so.6" << "libusb-1.0.so.0" << "libuuid.so.1" << "libwind.so.0" << "libX11.so.6" << "libxcb.so.1" << "libz.so.1"; + 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" << "libgdk-x11-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" << "libgssapi_krb5.so.2" << "libgtk-x11-2.0.so.0" << "libICE.so.6" << "libidn.so.11" << "libk5crypto.so.3" << "libkeyutils.so.1" << "libm.so.6" << "libnss3.so" << "libnssutil3.so" << "libp11-kit.so.0" << "libpangoft2-1.0.so.0" << "libpangocairo-1.0.so.0" << "libpango-1.0.so.0" << "libpcre.so.3" << "libpthread.so.0" << "libresolv.so.2" << "librt.so.1" << "libselinux.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())) { From 4685e33a6efa8ad7f25b9138606b7bf1e1abbcf2 Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 1 Jul 2017 22:46:38 +0200 Subject: [PATCH 18/23] Do not blacklist libpcre.so.* https://github.com/OpenOrienteering/mapper/pull/898#issuecomment-312454680 --- tools/linuxdeployqt/shared.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/linuxdeployqt/shared.cpp b/tools/linuxdeployqt/shared.cpp index 3f17245..5d8436f 100644 --- a/tools/linuxdeployqt/shared.cpp +++ b/tools/linuxdeployqt/shared.cpp @@ -374,7 +374,7 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath, */ 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" << "libgdk-x11-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" << "libgssapi_krb5.so.2" << "libgtk-x11-2.0.so.0" << "libICE.so.6" << "libidn.so.11" << "libk5crypto.so.3" << "libkeyutils.so.1" << "libm.so.6" << "libnss3.so" << "libnssutil3.so" << "libp11-kit.so.0" << "libpangoft2-1.0.so.0" << "libpangocairo-1.0.so.0" << "libpango-1.0.so.0" << "libpcre.so.3" << "libpthread.so.0" << "libresolv.so.2" << "librt.so.1" << "libselinux.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"; + 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" << "libgdk-x11-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" << "libgssapi_krb5.so.2" << "libgtk-x11-2.0.so.0" << "libICE.so.6" << "libidn.so.11" << "libk5crypto.so.3" << "libkeyutils.so.1" << "libm.so.6" << "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" << "libselinux.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())) { From 892964978c4a75287ccdc2a062524890e5708efe Mon Sep 17 00:00:00 2001 From: probonopd Date: Fri, 7 Jul 2017 20:36:48 +0200 Subject: [PATCH 19/23] Exit if appDirPath == "/", closes #144 --- tools/linuxdeployqt/main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/linuxdeployqt/main.cpp b/tools/linuxdeployqt/main.cpp index 67baecc..78a1355 100644 --- a/tools/linuxdeployqt/main.cpp +++ b/tools/linuxdeployqt/main.cpp @@ -185,7 +185,7 @@ int main(int argc, char **argv) if (QDir().exists(appBinaryPath)) { qDebug() << "app-binary:" << appBinaryPath; } else { - qDebug() << "Error: Could not find app-binary" << appBinaryPath; + LogError() << "Error: Could not find app-binary" << appBinaryPath; return 1; } @@ -199,6 +199,11 @@ int main(int argc, char **argv) QString relativePrefix = fhsPrefix.replace(appDirPath+"/", ""); relativeBinPath = relativePrefix + "/bin/" + appName; } + if(appDirPath == "/"){ + LogError() << "'/' is not a valid AppDir. Please refer to the documentation."; + LogError() << "Consider adding INSTALL_ROOT or DESTDIR to your install steps."; + return 1; + } qDebug() << "appDirPath:" << appDirPath; qDebug() << "relativeBinPath:" << relativeBinPath; From b65b349b55e77bd71b72cf61315551399f5b379b Mon Sep 17 00:00:00 2001 From: probonopd Date: Sun, 9 Jul 2017 10:12:29 +0200 Subject: [PATCH 20/23] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 973ac1a..bc43496 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ Given that a desktop file should be provided with an AppImage, `linuxdeployqt` c Where the _desktop_ file specifies the executable to be run (with `EXEC=`), the name of the applications and an icon. See [desktop file specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html). +For a more detailed example, see "Using linuxdeployqt with Travis CI" below. + #### Checking library inclusion Open in Qt Creator and build your application. Run it from the command line and inspect it with `ldd` to make sure the correct libraries from the correct locations are getting loaded, as `linuxdeployqt` will use `ldd` internally to determine from where to copy libraries into the bundle. From d0e3617f6b604692abcc6d70467be261a972635f Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Sun, 9 Jul 2017 22:47:17 -0400 Subject: [PATCH 21/23] Update BUILDING.md Explicitly state that `linuxdeployqt` releases are x86_64 only. This notice should be reworded if/when more platforms are added to the releases area. --- BUILDING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 23e2a1c..dc025b2 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1,8 +1,8 @@ # Building from source -If you just would like to bundle your application, it is normally not necessary that you build `linuxdeployqt` yourself. Instead, download __linuxdeployqt-x86_64.AppImage__ from the [Releases](https://github.com/probonopd/linuxdeployqt/releases) page and `chmod a+x` it. This bundle, by the way, has been generated using `linuxdeployqt` itself as part of our Travis CI continuous build pipeline. +If you just would like to bundle your application for x86_64 platforms, it is normally not necessary that you build `linuxdeployqt` yourself. Instead, download __linuxdeployqt-x86_64.AppImage__ from the [Releases](https://github.com/probonopd/linuxdeployqt/releases) page and `chmod a+x` it. This bundle, by the way, has been generated using `linuxdeployqt` itself as part of our Travis CI continuous build pipeline. -So, if you still think you would like to compile from source, here are the steps: +So, if you are on another platform (e.g. i686, ARM) or would like to compile from source, here are the steps: * Get and build linuxdeployqt e.g., using Qt 5.7.0 (you could use this [Qt Creator AppImage](https://bintray.com/probono/AppImages/QtCreator#files) for this) From 50f650bd4d76a6854a8222f4b329a67e13143c34 Mon Sep 17 00:00:00 2001 From: probonopd Date: Mon, 10 Jul 2017 19:47:36 +0200 Subject: [PATCH 22/23] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bc43496..fbd7a62 100644 --- a/README.md +++ b/README.md @@ -85,24 +85,24 @@ sudo: require dist: trusty before_install: - - sudo add-apt-repository ppa:beineri/opt-qt58-trusty -y + - sudo add-apt-repository ppa:beineri/opt-qt59-trusty -y - sudo apt-get update -qq install: - - sudo apt-get -y install qt58base + - sudo apt-get -y install qt59base - source /opt/qt*/bin/qt*-env.sh script: - qmake PREFIX=/usr - make -j$(nproc) - make INSTALL_ROOT=appdir install ; find appdir/ - -after_success: - wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" - chmod a+x linuxdeployqt*.AppImage - unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH - ./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -bundle-non-qt-libs - ./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -appimage + +after_success: - find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq - curl --upload-file ./APPNAME*.AppImage https://transfer.sh/APPNAME-git.$(git rev-parse --short HEAD)-x86_64.AppImage ``` From 9d9192f31b31f3046997711e268bf32a6e9bd28d Mon Sep 17 00:00:00 2001 From: probonopd Date: Sat, 22 Jul 2017 12:54:03 +0000 Subject: [PATCH 23/23] Attempt to fix "not found" error --- tools/linuxdeployqt/shared.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tools/linuxdeployqt/shared.cpp b/tools/linuxdeployqt/shared.cpp index 5d8436f..3ef0ce4 100644 --- a/tools/linuxdeployqt/shared.cpp +++ b/tools/linuxdeployqt/shared.cpp @@ -298,6 +298,14 @@ LddInfo findDependencyInfo(const QString &binaryPath) } foreach (QString outputLine, outputLines) { + + if(outputLine.contains("libQt5")){ + qtDetected = 5; + } + if(outputLine.contains("libQtCore.so.4")){ + qtDetected = 4; + } + // LogDebug() << "ldd outputLine:" << outputLine; if ((outputLine.contains("not found")) && (qtDetectionComplete == 1)){ LogError() << "ldd outputLine:" << outputLine.replace("\t", ""); @@ -984,15 +992,6 @@ DeploymentInfo deployQtLibraries(const QString &appDirPath, const QStringList &a // Find out whether Qt is a dependency of the application to be bundled LddInfo lddInfo = findDependencyInfo(appBinaryPath); - foreach (const DylibInfo dep, lddInfo.dependencies) { - LogDebug() << "dep.binaryPath" << dep.binaryPath; - if(dep.binaryPath.contains("libQt5")){ - qtDetected = 5; - } - if(dep.binaryPath.contains("libQtCore.so.4")){ - qtDetected = 4; - } - } if(qtDetected != 0){