Merge branch 'master' into master
This commit is contained in:
-18
@@ -25,21 +25,3 @@ branches:
|
|||||||
except:
|
except:
|
||||||
- # Do not build tags that we create when we upload to GitHub Releases
|
- # Do not build tags that we create when we upload to GitHub Releases
|
||||||
- /^(?i:continuous)$/
|
- /^(?i:continuous)$/
|
||||||
|
|
||||||
notifications:
|
|
||||||
irc:
|
|
||||||
channels:
|
|
||||||
- "chat.freenode.net#AppImage"
|
|
||||||
on_success: always # options: [always|never|change] default: always
|
|
||||||
on_failure: always # options: [always|never|change] default: always
|
|
||||||
on_start: always # options: [always|never|change] default: always
|
|
||||||
template:
|
|
||||||
- "%{repository} build %{build_number}: %{result} %{build_url}"
|
|
||||||
use_notice: true
|
|
||||||
# skip_join: true
|
|
||||||
webhooks:
|
|
||||||
urls:
|
|
||||||
- https://webhooks.gitter.im/e/4bf20518805a55998cc2
|
|
||||||
on_success: always # options: [always|never|change] default: always
|
|
||||||
on_failure: always # options: [always|never|change] default: always
|
|
||||||
on_start: always # options: [always|never|change] default: always
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ Options:
|
|||||||
-executable=<path> : Let the given executable use the deployed libraries 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
|
||||||
|
-no-translations : Skip deployment of translations
|
||||||
|
|
||||||
linuxdeployqt takes an application as input and makes it
|
linuxdeployqt takes an application as input and makes it
|
||||||
self-contained by copying in the Qt libraries and plugins that
|
self-contained by copying in the Qt libraries and plugins that
|
||||||
@@ -77,7 +78,7 @@ install:
|
|||||||
|
|
||||||
script:
|
script:
|
||||||
- qmake PREFIX=/usr
|
- qmake PREFIX=/usr
|
||||||
- make -j4
|
- make -j$(nproc)
|
||||||
- make INSTALL_ROOT=appdir install ; find appdir/
|
- make INSTALL_ROOT=appdir install ; find appdir/
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
@@ -105,6 +106,7 @@ __CMake__ wants `DESTDIR` instead:
|
|||||||
|
|
||||||
```
|
```
|
||||||
- cmake . -DCMAKE_INSTALL_PREFIX=/usr
|
- cmake . -DCMAKE_INSTALL_PREFIX=/usr
|
||||||
|
- make -j$(nproc)
|
||||||
- make DESTDIR=appdir install ; find appdir/
|
- make DESTDIR=appdir install ; find appdir/
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -112,7 +114,7 @@ __autotools__ (the dinosaur that spends precious minutes "checking...") wants `D
|
|||||||
|
|
||||||
```
|
```
|
||||||
- ./configure --prefix=/usr
|
- ./configure --prefix=/usr
|
||||||
- make -j4
|
- make -j$(nproc)
|
||||||
- make install DESTDIR=$(readlink -f appdir) ; find appdir/
|
- make install DESTDIR=$(readlink -f appdir) ; find appdir/
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -136,7 +138,7 @@ This PR, when merged, will compile this application on [Travis CI](https://travi
|
|||||||
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.
|
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.
|
||||||
|
|
||||||
Providing an [AppImage](http://appimage.org/) would have, among others, these advantages:
|
Providing an [AppImage](http://appimage.org/) would have, among others, these advantages:
|
||||||
- Works for most Linux distributions (including Ubuntu, Fedora, openSUSE, CentOS, elementaryOS, Linux Mint, and others)
|
- Applications packaged as an AppImage can run on many distributions (including Ubuntu, Fedora, openSUSE, CentOS, elementaryOS, Linux Mint, and others)
|
||||||
- One app = one file = super simple for users: just download one AppImage file, [make it executable](http://discourse.appimage.org/t/how-to-make-an-appimage-executable/80), and run
|
- One app = one file = super simple for users: just download one AppImage file, [make it executable](http://discourse.appimage.org/t/how-to-make-an-appimage-executable/80), and run
|
||||||
- No unpacking or installation necessary
|
- No unpacking or installation necessary
|
||||||
- No root needed
|
- No root needed
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ int main(int argc, char **argv)
|
|||||||
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() << " -qmake=<path> : The qmake executable to use";
|
qDebug() << " -qmake=<path> : The qmake executable to use";
|
||||||
|
qDebug() << " -no-translations : Skip deployment of translations.";
|
||||||
qDebug() << "";
|
qDebug() << "";
|
||||||
qDebug() << "linuxdeployqt takes an application as input and makes it";
|
qDebug() << "linuxdeployqt takes an application as input and makes it";
|
||||||
qDebug() << "self-contained by copying in the Qt libraries and plugins that";
|
qDebug() << "self-contained by copying in the Qt libraries and plugins that";
|
||||||
@@ -170,6 +171,7 @@ int main(int argc, char **argv)
|
|||||||
extern QStringList librarySearchPath;
|
extern QStringList librarySearchPath;
|
||||||
QStringList additionalExecutables;
|
QStringList additionalExecutables;
|
||||||
bool qmldirArgumentUsed = false;
|
bool qmldirArgumentUsed = false;
|
||||||
|
bool skipTranslations = false;
|
||||||
QStringList qmlDirs;
|
QStringList qmlDirs;
|
||||||
QString qmakeExecutable;
|
QString qmakeExecutable;
|
||||||
|
|
||||||
@@ -365,6 +367,9 @@ int main(int argc, char **argv)
|
|||||||
LogDebug() << "Argument found:" << argument;
|
LogDebug() << "Argument found:" << argument;
|
||||||
int index = argument.indexOf("=");
|
int index = argument.indexOf("=");
|
||||||
qmakeExecutable = argument.mid(index+1);
|
qmakeExecutable = argument.mid(index+1);
|
||||||
|
} else if (argument == QByteArray("-no-translations")) {
|
||||||
|
LogDebug() << "Argument found:" << argument;
|
||||||
|
skipTranslations = true;
|
||||||
} else if (argument.startsWith("-")) {
|
} else if (argument.startsWith("-")) {
|
||||||
LogError() << "Unknown argument" << argument << "\n";
|
LogError() << "Unknown argument" << argument << "\n";
|
||||||
return 1;
|
return 1;
|
||||||
@@ -399,6 +404,9 @@ int main(int argc, char **argv)
|
|||||||
deploymentInfo.deployedLibraries = deploymentInfo.deployedLibraries.toSet().toList();
|
deploymentInfo.deployedLibraries = deploymentInfo.deployedLibraries.toSet().toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deploymentInfo.usedModulesMask = 0;
|
||||||
|
findUsedModules(deploymentInfo);
|
||||||
|
|
||||||
if (plugins && !deploymentInfo.qtPath.isEmpty()) {
|
if (plugins && !deploymentInfo.qtPath.isEmpty()) {
|
||||||
if (deploymentInfo.pluginPath.isEmpty())
|
if (deploymentInfo.pluginPath.isEmpty())
|
||||||
deploymentInfo.pluginPath = QDir::cleanPath(deploymentInfo.qtPath + "/../plugins");
|
deploymentInfo.pluginPath = QDir::cleanPath(deploymentInfo.qtPath + "/../plugins");
|
||||||
@@ -409,6 +417,10 @@ int main(int argc, char **argv)
|
|||||||
if (runStripEnabled)
|
if (runStripEnabled)
|
||||||
stripAppBinary(appDirPath);
|
stripAppBinary(appDirPath);
|
||||||
|
|
||||||
|
if (!skipTranslations) {
|
||||||
|
deployTranslations(appDirPath, deploymentInfo.usedModulesMask);
|
||||||
|
}
|
||||||
|
|
||||||
if (appimage) {
|
if (appimage) {
|
||||||
int result = createAppImage(appDirPath);
|
int result = createAppImage(appDirPath);
|
||||||
LogDebug() << "result:" << result;
|
LogDebug() << "result:" << result;
|
||||||
|
|||||||
+257
-2
@@ -62,6 +62,122 @@ using std::endl;
|
|||||||
|
|
||||||
QMap<QString,QString> qtToBeBundledInfo;
|
QMap<QString,QString> qtToBeBundledInfo;
|
||||||
|
|
||||||
|
enum QtModule
|
||||||
|
#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC)
|
||||||
|
: quint64
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
QtBluetoothModule = 0x0000000000000001,
|
||||||
|
QtCLuceneModule = 0x0000000000000002,
|
||||||
|
QtConcurrentModule = 0x0000000000000004,
|
||||||
|
QtCoreModule = 0x0000000000000008,
|
||||||
|
QtDeclarativeModule = 0x0000000000000010,
|
||||||
|
QtDesignerComponents = 0x0000000000000020,
|
||||||
|
QtDesignerModule = 0x0000000000000040,
|
||||||
|
QtGuiModule = 0x0000000000000080,
|
||||||
|
QtCluceneModule = 0x0000000000000100,
|
||||||
|
QtHelpModule = 0x0000000000000200,
|
||||||
|
QtMultimediaModule = 0x0000000000000400,
|
||||||
|
QtMultimediaWidgetsModule = 0x0000000000000800,
|
||||||
|
QtMultimediaQuickModule = 0x0000000000001000,
|
||||||
|
QtNetworkModule = 0x0000000000002000,
|
||||||
|
QtNfcModule = 0x0000000000004000,
|
||||||
|
QtOpenGLModule = 0x0000000000008000,
|
||||||
|
QtPositioningModule = 0x0000000000010000,
|
||||||
|
QtPrintSupportModule = 0x0000000000020000,
|
||||||
|
QtQmlModule = 0x0000000000040000,
|
||||||
|
QtQuickModule = 0x0000000000080000,
|
||||||
|
QtQuickParticlesModule = 0x0000000000100000,
|
||||||
|
QtScriptModule = 0x0000000000200000,
|
||||||
|
QtScriptToolsModule = 0x0000000000400000,
|
||||||
|
QtSensorsModule = 0x0000000000800000,
|
||||||
|
QtSerialPortModule = 0x0000000001000000,
|
||||||
|
QtSqlModule = 0x0000000002000000,
|
||||||
|
QtSvgModule = 0x0000000004000000,
|
||||||
|
QtTestModule = 0x0000000008000000,
|
||||||
|
QtWidgetsModule = 0x0000000010000000,
|
||||||
|
QtWinExtrasModule = 0x0000000020000000,
|
||||||
|
QtXmlModule = 0x0000000040000000,
|
||||||
|
QtXmlPatternsModule = 0x0000000080000000,
|
||||||
|
QtWebKitModule = 0x0000000100000000,
|
||||||
|
QtWebKitWidgetsModule = 0x0000000200000000,
|
||||||
|
QtQuickWidgetsModule = 0x0000000400000000,
|
||||||
|
QtWebSocketsModule = 0x0000000800000000,
|
||||||
|
QtEnginioModule = 0x0000001000000000,
|
||||||
|
QtWebEngineCoreModule = 0x0000002000000000,
|
||||||
|
QtWebEngineModule = 0x0000004000000000,
|
||||||
|
QtWebEngineWidgetsModule = 0x0000008000000000,
|
||||||
|
QtQmlToolingModule = 0x0000010000000000,
|
||||||
|
Qt3DCoreModule = 0x0000020000000000,
|
||||||
|
Qt3DRendererModule = 0x0000040000000000,
|
||||||
|
Qt3DQuickModule = 0x0000080000000000,
|
||||||
|
Qt3DQuickRendererModule = 0x0000100000000000,
|
||||||
|
Qt3DInputModule = 0x0000200000000000,
|
||||||
|
QtLocationModule = 0x0000400000000000,
|
||||||
|
QtWebChannelModule = 0x0000800000000000,
|
||||||
|
QtTextToSpeechModule = 0x0001000000000000,
|
||||||
|
QtSerialBusModule = 0x0002000000000000
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QtModuleEntry {
|
||||||
|
quint64 module;
|
||||||
|
const char *option;
|
||||||
|
const char *libraryName;
|
||||||
|
const char *translation;
|
||||||
|
};
|
||||||
|
|
||||||
|
static QtModuleEntry qtModuleEntries[] = {
|
||||||
|
{ QtBluetoothModule, "bluetooth", "Qt5Bluetooth", 0 },
|
||||||
|
{ QtCLuceneModule, "clucene", "Qt5CLucene", "qt_help" },
|
||||||
|
{ QtConcurrentModule, "concurrent", "Qt5Concurrent", "qtbase" },
|
||||||
|
{ QtCoreModule, "core", "Qt5Core", "qtbase" },
|
||||||
|
{ QtDeclarativeModule, "declarative", "Qt5Declarative", "qtquick1" },
|
||||||
|
{ QtDesignerModule, "designer", "Qt5Designer", 0 },
|
||||||
|
{ QtDesignerComponents, "designercomponents", "Qt5DesignerComponents", 0 },
|
||||||
|
{ QtEnginioModule, "enginio", "Enginio", 0 },
|
||||||
|
{ QtGuiModule, "gui", "Qt5Gui", "qtbase" },
|
||||||
|
{ QtHelpModule, "qthelp", "Qt5Help", "qt_help" },
|
||||||
|
{ QtMultimediaModule, "multimedia", "Qt5Multimedia", "qtmultimedia" },
|
||||||
|
{ QtMultimediaWidgetsModule, "multimediawidgets", "Qt5MultimediaWidgets", "qtmultimedia" },
|
||||||
|
{ QtMultimediaQuickModule, "multimediaquick", "Qt5MultimediaQuick_p", "qtmultimedia" },
|
||||||
|
{ QtNetworkModule, "network", "Qt5Network", "qtbase" },
|
||||||
|
{ QtNfcModule, "nfc", "Qt5Nfc", 0 },
|
||||||
|
{ QtOpenGLModule, "opengl", "Qt5OpenGL", 0 },
|
||||||
|
{ QtPositioningModule, "positioning", "Qt5Positioning", 0 },
|
||||||
|
{ QtPrintSupportModule, "printsupport", "Qt5PrintSupport", 0 },
|
||||||
|
{ QtQmlModule, "qml", "Qt5Qml", "qtdeclarative" },
|
||||||
|
{ QtQmlToolingModule, "qmltooling", "qmltooling", 0 },
|
||||||
|
{ QtQuickModule, "quick", "Qt5Quick", "qtdeclarative" },
|
||||||
|
{ QtQuickParticlesModule, "quickparticles", "Qt5QuickParticles", 0 },
|
||||||
|
{ QtQuickWidgetsModule, "quickwidgets", "Qt5QuickWidgets", 0 },
|
||||||
|
{ QtScriptModule, "script", "Qt5Script", "qtscript" },
|
||||||
|
{ QtScriptToolsModule, "scripttools", "Qt5ScriptTools", "qtscript" },
|
||||||
|
{ QtSensorsModule, "sensors", "Qt5Sensors", 0 },
|
||||||
|
{ QtSerialPortModule, "serialport", "Qt5SerialPort", "qtserialport" },
|
||||||
|
{ QtSqlModule, "sql", "Qt5Sql", "qtbase" },
|
||||||
|
{ QtSvgModule, "svg", "Qt5Svg", 0 },
|
||||||
|
{ QtTestModule, "test", "Qt5Test", "qtbase" },
|
||||||
|
{ QtWebKitModule, "webkit", "Qt5WebKit", 0 },
|
||||||
|
{ QtWebKitWidgetsModule, "webkitwidgets", "Qt5WebKitWidgets", 0 },
|
||||||
|
{ QtWebSocketsModule, "websockets", "Qt5WebSockets", "qtwebsockets" },
|
||||||
|
{ QtWidgetsModule, "widgets", "Qt5Widgets", "qtbase" },
|
||||||
|
{ QtWinExtrasModule, "winextras", "Qt5WinExtras", 0 },
|
||||||
|
{ QtXmlModule, "xml", "Qt5Xml", "qtbase" },
|
||||||
|
{ QtXmlPatternsModule, "xmlpatterns", "Qt5XmlPatterns", "qtxmlpatterns" },
|
||||||
|
{ QtWebEngineCoreModule, "webenginecore", "Qt5WebEngineCore", 0 },
|
||||||
|
{ QtWebEngineModule, "webengine", "Qt5WebEngine", "qtwebengine" },
|
||||||
|
{ QtWebEngineWidgetsModule, "webenginewidgets", "Qt5WebEngineWidgets", 0 },
|
||||||
|
{ Qt3DCoreModule, "3dcore", "Qt53DCore", 0 },
|
||||||
|
{ Qt3DRendererModule, "3drenderer", "Qt53DRenderer", 0 },
|
||||||
|
{ Qt3DQuickModule, "3dquick", "Qt53DQuick", 0 },
|
||||||
|
{ Qt3DQuickRendererModule, "3dquickrenderer", "Qt53DQuickRenderer", 0 },
|
||||||
|
{ Qt3DInputModule, "3dinput", "Qt53DInput", 0 },
|
||||||
|
{ QtLocationModule, "geoservices", "Qt5Location", 0 },
|
||||||
|
{ QtWebChannelModule, "webchannel", "Qt5WebChannel", 0 },
|
||||||
|
{ QtTextToSpeechModule, "texttospeech", "Qt5TextToSpeech", 0 },
|
||||||
|
{ QtSerialBusModule, "serialbus", "Qt5SerialBus", 0 }
|
||||||
|
};
|
||||||
|
|
||||||
bool operator==(const LibraryInfo &a, const LibraryInfo &b)
|
bool operator==(const LibraryInfo &a, const LibraryInfo &b)
|
||||||
{
|
{
|
||||||
return ((a.libraryPath == b.libraryPath) && (a.binaryPath == b.binaryPath));
|
return ((a.libraryPath == b.libraryPath) && (a.binaryPath == b.binaryPath));
|
||||||
@@ -257,7 +373,7 @@ LibraryInfo parseLddLibraryLine(const QString &line, const QString &appDirPath,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
QStringList excludelist;
|
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" << "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" << "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";
|
||||||
LogDebug() << "excludelist:" << excludelist;
|
LogDebug() << "excludelist:" << excludelist;
|
||||||
if (! trimmed.contains("libicu")) {
|
if (! trimmed.contains("libicu")) {
|
||||||
if (containsHowOften(excludelist, QFileInfo(trimmed).completeBaseName())) {
|
if (containsHowOften(excludelist, QFileInfo(trimmed).completeBaseName())) {
|
||||||
@@ -624,6 +740,7 @@ void runPatchelf(QStringList options)
|
|||||||
|
|
||||||
bool patchQtCore(const QString &path, const QString &variable, const QString &value)
|
bool patchQtCore(const QString &path, const QString &variable, const QString &value)
|
||||||
{
|
{
|
||||||
|
return true; // ################################### Disabling for now since using qt.conf
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
if (!file.open(QIODevice::ReadWrite)) {
|
if (!file.open(QIODevice::ReadWrite)) {
|
||||||
LogWarning() << QString::fromLatin1("Unable to patch %1: %2").arg(
|
LogWarning() << QString::fromLatin1("Unable to patch %1: %2").arg(
|
||||||
@@ -810,6 +927,7 @@ DeploymentInfo deployQtLibraries(QList<LibraryInfo> libraries,
|
|||||||
LogNormal() << "Deploying the following libraries:" << binaryPaths;
|
LogNormal() << "Deploying the following libraries:" << binaryPaths;
|
||||||
QStringList copiedLibraries;
|
QStringList copiedLibraries;
|
||||||
DeploymentInfo deploymentInfo;
|
DeploymentInfo deploymentInfo;
|
||||||
|
deploymentInfo.requiresQtWidgetsLibrary = false;
|
||||||
deploymentInfo.useLoaderPath = useLoaderPath;
|
deploymentInfo.useLoaderPath = useLoaderPath;
|
||||||
deploymentInfo.pluginPath = qtToBeBundledInfo.value("QT_INSTALL_PLUGINS");
|
deploymentInfo.pluginPath = qtToBeBundledInfo.value("QT_INSTALL_PLUGINS");
|
||||||
QSet<QString> rpathsUsed;
|
QSet<QString> rpathsUsed;
|
||||||
@@ -822,6 +940,10 @@ DeploymentInfo deployQtLibraries(QList<LibraryInfo> libraries,
|
|||||||
LogNormal() << "Setting deploymentInfo.qtPath to:" << library.libraryDirectory;
|
LogNormal() << "Setting deploymentInfo.qtPath to:" << library.libraryDirectory;
|
||||||
deploymentInfo.qtPath = library.libraryDirectory;
|
deploymentInfo.qtPath = library.libraryDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(library.libraryName.contains("libQt") and library.libraryName.contains("Widgets.so")) {
|
||||||
|
deploymentInfo.requiresQtWidgetsLibrary = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (library.libraryDirectory.startsWith(bundlePath)) {
|
if (library.libraryDirectory.startsWith(bundlePath)) {
|
||||||
LogNormal() << library.libraryName << "already deployed, skipping.";
|
LogNormal() << library.libraryName << "already deployed, skipping.";
|
||||||
@@ -1385,7 +1507,7 @@ bool deployQmlImports(const QString &appDirPath, DeploymentInfo deploymentInfo,
|
|||||||
// 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.deployedLibraries.contains("QtWidgets") && qtQuickContolsInUse) {
|
if (deploymentInfo.requiresQtWidgetsLibrary && qtQuickContolsInUse) {
|
||||||
LogNormal() << "Deploying QML import QtQuick/PrivateWidgets";
|
LogNormal() << "Deploying QML import QtQuick/PrivateWidgets";
|
||||||
QString name = "QtQuick/PrivateWidgets";
|
QString name = "QtQuick/PrivateWidgets";
|
||||||
QString path = qtToBeBundledInfo.value("QT_INSTALL_QML") + QLatin1Char('/') + name;
|
QString path = qtToBeBundledInfo.value("QT_INSTALL_QML") + QLatin1Char('/') + name;
|
||||||
@@ -1471,3 +1593,136 @@ int createAppImage(const QString &appDirPath)
|
|||||||
LogNormal() << "WEXITSTATUS(ret)" << WEXITSTATUS(ret);
|
LogNormal() << "WEXITSTATUS(ret)" << WEXITSTATUS(ret);
|
||||||
return WEXITSTATUS(ret);
|
return WEXITSTATUS(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void findUsedModules(DeploymentInfo &info)
|
||||||
|
{
|
||||||
|
LogDebug() << "Creating mask of used modules";
|
||||||
|
|
||||||
|
const QStringList &libraries = info.deployedLibraries;
|
||||||
|
|
||||||
|
const size_t qtModulesCount = sizeof(qtModuleEntries)/sizeof(QtModuleEntry);
|
||||||
|
for (size_t i = 0; i < qtModulesCount; ++i) {
|
||||||
|
QtModuleEntry &entry = qtModuleEntries[i];
|
||||||
|
const QString name = QLatin1String(qtModuleEntries[i].libraryName);
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
foreach (const QString &library, libraries) {
|
||||||
|
if (library.contains(name, Qt::CaseInsensitive)) {
|
||||||
|
LogDebug() << "Found dependency:" << name;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
info.usedModulesMask |= entry.module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString translationsDirPath = appDirPath + QStringLiteral("/translations");
|
||||||
|
LogDebug() << "Using" << translationsDirPath << "as translations directory for App";
|
||||||
|
LogDebug() << "Using" << qtTranslationsPath << " to search for Qt translations";
|
||||||
|
|
||||||
|
QFileInfo fi(translationsDirPath);
|
||||||
|
if (!fi.isDir()) {
|
||||||
|
if (!QDir().mkpath(translationsDirPath)) {
|
||||||
|
LogError() << "Failed to create translations directory";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LogDebug() << "Translations directory already exists";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deployTranslations(qtTranslationsPath, translationsDirPath, usedQtModules)) {
|
||||||
|
LogError() << "Failed to copy translations";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList translationNameFilters(quint64 modules, const QString &prefix)
|
||||||
|
{
|
||||||
|
QStringList result;
|
||||||
|
const size_t qtModulesCount = sizeof(qtModuleEntries)/sizeof(QtModuleEntry);
|
||||||
|
for (size_t i = 0; i < qtModulesCount; ++i) {
|
||||||
|
if ((qtModuleEntries[i].module & modules) && qtModuleEntries[i].translation) {
|
||||||
|
const QString name = QLatin1String(qtModuleEntries[i].translation) +
|
||||||
|
QLatin1Char('_') + prefix + QStringLiteral(".qm");
|
||||||
|
if (!result.contains(name))
|
||||||
|
result.push_back(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LogDebug() << "Translation name filters:" << result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deployTranslations(const QString &sourcePath, const QString &target, quint64 usedQtModules)
|
||||||
|
{
|
||||||
|
LogDebug() << "Translations target is" << target;
|
||||||
|
|
||||||
|
// Find available languages prefixes by checking on qtbase.
|
||||||
|
QStringList prefixes;
|
||||||
|
QDir sourceDir(sourcePath);
|
||||||
|
const QStringList qmFilter = QStringList(QStringLiteral("qtbase_*.qm"));
|
||||||
|
foreach (QString qmFile, sourceDir.entryList(qmFilter)) {
|
||||||
|
qmFile.chop(3);
|
||||||
|
qmFile.remove(0, 7);
|
||||||
|
prefixes.push_back(qmFile);
|
||||||
|
}
|
||||||
|
if (prefixes.isEmpty()) {
|
||||||
|
LogError() << "Could not find any translations in "
|
||||||
|
<< sourcePath << " (developer build?)";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Run lconvert to concatenate all files into a single named "qt_<prefix>.qm" in the application folder
|
||||||
|
// Use QT_INSTALL_TRANSLATIONS as working directory to keep the command line short.
|
||||||
|
const QString absoluteTarget = QFileInfo(target).absoluteFilePath();
|
||||||
|
|
||||||
|
QString lconvertPath = QDir::cleanPath(qtToBeBundledInfo.value("QT_INSTALL_BINS")) + "/lconvert";
|
||||||
|
LogDebug() << "Looking for lconvert at" << lconvertPath;
|
||||||
|
|
||||||
|
// Fallback: Look relative to the linuxdeployqt binary
|
||||||
|
if (!QFile(lconvertPath).exists()){
|
||||||
|
lconvertPath = QCoreApplication::applicationDirPath() + "/lconvert";
|
||||||
|
LogDebug() << "Fallback, looking for lconvert at" << lconvertPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that we found a lconvert binary
|
||||||
|
if (!QFile(lconvertPath).exists()) {
|
||||||
|
LogError() << "lconvert not found at" << lconvertPath;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogNormal() << "Found lconvert at" << lconvertPath;
|
||||||
|
|
||||||
|
QStringList arguments;
|
||||||
|
foreach (const QString &prefix, prefixes) {
|
||||||
|
arguments.clear();
|
||||||
|
const QString targetFile = QStringLiteral("qt_") + prefix + QStringLiteral(".qm");
|
||||||
|
arguments.append(QStringLiteral("-o"));
|
||||||
|
const QString currentTargetFile = absoluteTarget + QLatin1Char('/') + targetFile;
|
||||||
|
arguments.append(currentTargetFile);
|
||||||
|
|
||||||
|
foreach (const QFileInfo &qmFileInfo, sourceDir.entryInfoList(translationNameFilters(usedQtModules, prefix)))
|
||||||
|
arguments.append(qmFileInfo.absoluteFilePath());
|
||||||
|
|
||||||
|
LogNormal() << "Creating " << currentTargetFile << "...";
|
||||||
|
LogDebug() << "lconvert arguments:" << arguments;
|
||||||
|
|
||||||
|
QProcess lconvert;
|
||||||
|
lconvert.start(lconvertPath, arguments);
|
||||||
|
lconvert.waitForFinished();
|
||||||
|
|
||||||
|
if (lconvert.exitStatus() != QProcess::NormalExit) {
|
||||||
|
LogError() << "Fail in lconvert on file" << currentTargetFile;
|
||||||
|
}
|
||||||
|
} // for prefixes.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -96,9 +96,11 @@ public:
|
|||||||
QString qtPath;
|
QString qtPath;
|
||||||
QString pluginPath;
|
QString pluginPath;
|
||||||
QStringList deployedLibraries;
|
QStringList deployedLibraries;
|
||||||
|
quint64 usedModulesMask;
|
||||||
QSet<QString> rpathsUsed;
|
QSet<QString> rpathsUsed;
|
||||||
bool useLoaderPath;
|
bool useLoaderPath;
|
||||||
bool isLibrary;
|
bool isLibrary;
|
||||||
|
bool requiresQtWidgetsLibrary;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QDebug operator<<(QDebug debug, const AppDirInfo &info);
|
inline QDebug operator<<(QDebug debug, const AppDirInfo &info);
|
||||||
@@ -129,5 +131,8 @@ QStringList findAppLibraries(const QString &appDirPath);
|
|||||||
bool patchQtCore(const QString &path, const QString &variable, const QString &value);
|
bool patchQtCore(const QString &path, const QString &variable, const QString &value);
|
||||||
int createAppImage(const QString &appBundlePath);
|
int createAppImage(const QString &appBundlePath);
|
||||||
bool checkAppImagePrerequisites(const QString &appBundlePath);
|
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);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+19
-3
@@ -3,11 +3,11 @@
|
|||||||
set -x
|
set -x
|
||||||
|
|
||||||
source /opt/qt*/bin/qt*-env.sh
|
source /opt/qt*/bin/qt*-env.sh
|
||||||
/opt/qt*/bin/qmake linuxdeployqt.pro
|
/opt/qt*/bin/qmake CONFIG+=release CONFIG+=force_debug_info linuxdeployqt.pro
|
||||||
make -j2
|
make -j
|
||||||
|
|
||||||
mkdir -p linuxdeployqt.AppDir/usr/bin/
|
mkdir -p linuxdeployqt.AppDir/usr/bin/
|
||||||
cp /usr/local/bin/{appimagetool,mksquashfs,patchelf,zsyncmake} linuxdeployqt.AppDir/usr/bin/
|
cp /usr/bin/patchelf /usr/local/bin/{appimagetool,mksquashfs,zsyncmake} linuxdeployqt.AppDir/usr/bin/
|
||||||
find linuxdeployqt.AppDir/
|
find linuxdeployqt.AppDir/
|
||||||
export VERSION=continuous
|
export VERSION=continuous
|
||||||
cp ./linuxdeployqt/linuxdeployqt linuxdeployqt.AppDir/usr/bin/
|
cp ./linuxdeployqt/linuxdeployqt linuxdeployqt.AppDir/usr/bin/
|
||||||
@@ -24,4 +24,20 @@ do
|
|||||||
sleep 1;
|
sleep 1;
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# enable core dumps
|
||||||
|
echo "/tmp/coredump" | sudo tee /proc/sys/kernel/core_pattern
|
||||||
|
|
||||||
|
ulimit -c unlimited
|
||||||
|
ulimit -a -S
|
||||||
|
ulimit -a -H
|
||||||
|
|
||||||
bash -e tests/tests.sh
|
bash -e tests/tests.sh
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "FAILURE: linuxdeployqt CRASHED -- uploading files for debugging to transfer.sh"
|
||||||
|
set -v
|
||||||
|
[ -e /tmp/coredump ] && curl --upload-file /tmp/coredump https://transfer.sh/coredump
|
||||||
|
curl --upload-file linuxdeployqt-*-x86_64.AppImage https://transfer.sh/linuxdeployqt-x86_64.AppImage
|
||||||
|
find -type f -iname 'libQt5Core.so*' -exec curl --upload {} https://transfer.sh/libQt5Core.so \; || true
|
||||||
|
exit $RESULT
|
||||||
|
fi
|
||||||
|
|||||||
@@ -5,14 +5,8 @@ set -e
|
|||||||
sudo add-apt-repository --yes ppa:beineri/opt-qt58-trusty
|
sudo add-apt-repository --yes ppa:beineri/opt-qt58-trusty
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
|
|
||||||
git clone -o 44b7f95 https://github.com/NixOS/patchelf.git
|
wget http://ftp.de.debian.org/debian/pool/main/p/patchelf/patchelf_0.8-2_amd64.deb
|
||||||
cd patchelf
|
sudo dpkg -i patchelf_0.8-2_amd64.deb
|
||||||
bash ./bootstrap.sh
|
|
||||||
./configure
|
|
||||||
make -j2
|
|
||||||
sudo make install
|
|
||||||
|
|
||||||
cd -
|
|
||||||
|
|
||||||
cd /tmp/
|
cd /tmp/
|
||||||
wget -c "https://github.com/probonopd/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
|
wget -c "https://github.com/probonopd/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||||
|
|||||||
Reference in New Issue
Block a user