Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to create installation package for Ubuntu 18+ ?



  • Hi,

    I created installation package for Windows and Ubuntu16. But I didn't create package for Ubuntu 18.
    Create installation package for ubuntu 16:

    1. Compiler project.
    2. Run linuxdeployqt.exe (https://github.com/probonopd/linuxdeployqt). This option, not for Ubuntu18+. So I didn't deploy project

    What is the solution ?



  • @bknhatice
    Although I have not used it myself, linuxdeployqt is the tool to use for all Linuxes. Why do you say it's for Ubuntu 16 but not for 18+?



  • @JonB said in How to create installation package for Ubuntu 18+ ?:

    Although I have not used it myself, linuxdeployqt is the tool to use for all Linuxes. Why do you say it's for Ubuntu 16 but not for 18+?

    linuxdeployqt.AppImage source code:
    if (strverscmp (glcv, "2.27") >= 0) {
    qInfo() << "ERROR: The host system is too new.";
    qInfo() << "Please run on a system with a glibc version no newer than what comes with the oldest";
    qInfo() << "currently still-supported mainstream distribution (xenial), which is glibc 2.23.";
    qInfo() << "This is so that the resulting bundle will work on most still-supported Linux distributions.";
    qInfo() << "For more information, please see";
    qInfo() << "https://github.com/probonopd/linuxdeployqt/issues/340";
    return 1;
    }
    That is, when the glibc version is 2.27 and larger, it gives an error. Glibc version 2.27 for ubuntu 18. So, linuxdeployqt.AppImage cannot use for Ubuntu 18.

    Also, https://github.com/probonopd/linuxdeployqt/issues/340 : There is no solution to this problem.



  • @bknhatice
    If you have found and read that long bug report and there is no solution to it, then there is no solution to it.

    I note this seems to have been asked here before at https://forum.qt.io/topic/100364/qt-linux-deployment/8.

    And @SGaist said there:

    It also talks about the -unsupported-allow-new-glibc option.

    Did you read & act on that?



  • @JonB Yes, I tried. But problem not solved.



  • @bknhatice
    Maybe @SGaist will see this later on today and comment further....



  • I don't need to deploy in Linux, so I just briefly read that issue, seems that -unsupported-allow-new-glibc is just an idea, the author said he would welcome PR...

    For the rare exception cases, I would be willing to incorporate -unsupported-bundle-everything and -unsupported-allow-new-glibc options as mentioned above, if someone cares enough to send a PR.

    Please do not use this as it is entirely unsupported (as in: I will not work on issues that arise from the user using that option).

    Please follow this setup: https://github.com/probonopd/linuxdeployqt#using-linuxdeployqt-with-travis-ci

    And I saw someone downgraded to release build(5) to solve the problem.

    Use linuxdeployqt 5 instead of continuous due to probonopd/linuxdeployqt#340

    Also, the author offered a new tool and then close that issue:

    I am working on a new tool which may be suitable for those of you who don't want to or can't build on the oldest still-supported LTS distributions. It will allow one to make AppImages that bundle (almost) everything, and by that binaries compiled on newer systems will be able to run on older systems:

    https://github.com/probonopd/go-appimage/tree/master/src/appimagetool (name and repository are still subject to change)

    The -s deploy option causes the tool to bundle many more libraries than linuxdeployqt, down to (and including) glibc. This is still worse than building on the oldest still-supported LTS distribution (because it will increase the size of the AppImage and may have other unintended side effects), but at least it will result in applications running on older systems.





  • @JonB said in How to create installation package for Ubuntu 18+ ?:

    linuxdeployqt

    I am using linuxdeployqt on Ubuntu 18.

    They did end up providing an option you can pass at the command line, and it will lead to success.

    Here is the complete script that I use: https://github.com/219-design/qt-qml-project-template-with-ci/blob/master/install_linux.sh

    It even runs totally unattended in CI. You can open up the full CI log of any of the runs for details: https://github.com/219-design/qt-qml-project-template-with-ci/actions?query=workflow%3ACI



  • In case I ever rename the script (changing how it would be found on 'master'), here is a github link that is "frozen in time" and should remain valid indefinitely (as long as github is operating): https://github.com/219-design/qt-qml-project-template-with-ci/blob/0a696e808621/install_linux.sh



  • @KH-219Design
    So -unsupported-allow-new-glibc is a working option.
    Then someone must have sent a PR and the author accepted that but just won't provide any support on it.



  • @KH-219Design I'll try. I'll review the link you shared. Thank you very much.

    As far as I understand, I need to create the linuxdeployqt.Appimage file. Then I can use the deploy feature for Ubuntu 18.



  • @bknhatice
    Note sure what you mean by "I need to create the linuxdeployqt.Appimage file".

    The link @KH-219Design gave you is a script which will download a shell script. When that runs it will fetch an AppImage file from github. And use the -unsupported-allow-new-glibc option to produce a linuxdeployqt which you can run under Ubuntu 18. Then you use that to make/create/produce the deployment package for your executable to distribute to end users.

    That's my understanding (unless I'm wrong!), I don't know if it was yours.



  • @JonB Yes, I need to create the linuxdeployqt.AppImage file for Ubuntu 18. I'll add it here after I get it.



  • Forgive my absence. I haven't been able to check the forum in a few hectic days.

    I'll try to explain my approach to scripting linuxdeployqt in a bit more finer-grained, step-by-step level of detail.

    There are 3 main parts to the script:

    The first part creates a staging directory with an internal structure that is prescribed by linuxdeployqt. At the end of that first part, you have a directory that looks like this:

    AppImage_staging/
    └── usr
        ├── bin
        │   ├── app
        │   ├── event_filter.o
        │   ├── gui_tests.o
        │   ├── libapp.so
        │   ├── libapp.so.1
        │   ├── libapp.so.1.0
        │   ├── libapp.so.1.0.0
        │   ├── liblibstylesplugin.so
        │   ├── libminutil.so
        │   ├── libminutil.so.1
        │   ├── libminutil.so.1.0
        │   ├── libminutil.so.1.0.0
        │   ├── libtestmain.so
        │   ├── libtestmain.so.1
        │   ├── libtestmain.so.1.0
        │   ├── libtestmain.so.1.0.0
        │   ├── lib_tests
        │   ├── libutil.so
        │   ├── libutil.so.1
        │   ├── libutil.so.1.0
        │   ├── libutil.so.1.0.0
        │   ├── main.o
        │   ├── Makefile
        │   ├── moc_event_filter.cpp
        │   ├── moc_event_filter.o
        │   ├── moc_gui_tests.cpp
        │   ├── moc_gui_tests.o
        │   ├── moc_predefs.h
        │   └── view_model_collection.o
        ├── lib
        └── share
            ├── applications
            │   └── app.desktop
            └── icons
                └── hicolor
                    └── 256x256
                        └── apps
                            └── app.png
    

    All the contents that were copied into AppImage_staging/usr/bin/ were produced during my build. This means that I first build (compile and link) my Qt application, and then (subsequently) run the script that makes my app image.

    The contents of AppImage_staging/usr/share/, in contrast, are not artifacts of the build, but are rather supporting icons and supporting files that are committed in the git repository and rarely change.

    Note that the above steps have been performed with simple bash commands. We have not yet invoked anything provided by linuxdeployqt. We were merely preparing things.

    The second part of the script (see line 37) uses wget to download an app image of linuxdeployqt itself. (In an admirable case of "dogfooding", the linuxdeployqt folks deploy their own software in app image format.)

    It isn't until the last command of the script that the 3rd and final task takes place.

    Finally on line 51 we invoke linuxdeployqt.

    After running linuxdeployqt, the staging folder is now "fully baked". It now contains a heck of a lot more libraries and other supporting files (in particular, QML files).

    That folder can then be zipped or tarred (or just copied to an external USB drive), and you will be able to take that folder to any other Ubuntu 18 system and run the app regardless of whether "apt-get" versions of Qt have been installed on that system or not.

    I have only needed to go so far as creating this "full baked" folder. However, if you want to produce a single-file app image, then just add the -appimage option when invoking linuxdeployqt. (My script does not add the -appimage option.)



  • The following shows how much content the folder (or AppImage) will ultimately contain (for comparison with the above first step of staging).

    In fact, I even had to abbreviate the listing below because the Qt forum disallows more than ~32K characters per post :)

    AppImage_staging/
    ├── app.desktop
    ├── app.png
    ├── AppRun -> usr/bin/app
    └── usr
        ├── bin
        │   ├── app
        │   ├── event_filter.o
        │   ├── gui_tests.o
        │   ├── libapp.so
        │   ├── libapp.so.1
        │   ├── libapp.so.1.0
        │   ├── libapp.so.1.0.0
        │   ├── liblibstylesplugin.so
        │   ├── libminutil.so
        │   ├── libminutil.so.1
        │   ├── libminutil.so.1.0
        │   ├── libminutil.so.1.0.0
        │   ├── libtestmain.so
        │   ├── libtestmain.so.1
        │   ├── libtestmain.so.1.0
        │   ├── libtestmain.so.1.0.0
        │   ├── lib_tests
        │   ├── libutil.so
        │   ├── libutil.so.1
        │   ├── libutil.so.1.0
        │   ├── libutil.so.1.0.0
        │   ├── main.o
        │   ├── Makefile
        │   ├── moc_event_filter.cpp
        │   ├── moc_event_filter.o
        │   ├── moc_gui_tests.cpp
        │   ├── moc_gui_tests.o
        │   ├── moc_predefs.h
        │   ├── provision.sh
        │   ├── qt.conf
        │   └── view_model_collection.o
        ├── lib
        │   ├── libicudata.so.56
        │   ├── libicui18n.so.56
        │   ├── libicuuc.so.56
        │   ├── libQt5Core.so.5
        │   ├── libQt5DBus.so.5
        │   ├── libQt5Gui.so.5
        │   ├── libQt5Network.so.5
        │   ├── libQt5QmlModels.so.5
        │   ├── libQt5Qml.so.5
        │   ├── libQt5QmlWorkerScript.so.5
        │   ├── libQt5QuickControls2.so.5
        │   ├── libQt5Quick.so.5
        │   ├── libQt5QuickTemplates2.so.5
        │   ├── libQt5Svg.so.5
        │   ├── libQt5Widgets.so.5
        │   └── libQt5XcbQpa.so.5
        ├── plugins
        │   ├── bearer
        │   │   ├── libqconnmanbearer.so
        │   │   ├── libqgenericbearer.so
        │   │   └── libqnmbearer.so
        │   ├── imageformats
        │   │   ├── libqgif.so
        │   │   ├── libqicns.so
        │   │   ├── libqico.so
        │   │   ├── libqjpeg.so
        │   │   ├── libqsvg.so
        │   │   ├── libqtga.so
        │   │   ├── libqtiff.so
        │   │   ├── libqwbmp.so
        │   │   └── libqwebp.so
        │   ├── platforminputcontexts
        │   │   ├── libcomposeplatforminputcontextplugin.so
        │   │   └── libibusplatforminputcontextplugin.so
        │   ├── platforms
        │   │   └── libqxcb.so
        │   ├── platformthemes
        │   │   └── libqgtk3.so
        │   └── xcbglintegrations
        │       ├── libqxcb-egl-integration.so
        │       └── libqxcb-glx-integration.so
        ├── qml
        │   ├── Qt
        │   │   └── labs
        │   │       ├── folderlistmodel
        │   │       │   ├── libqmlfolderlistmodelplugin.so
        │   │       │   ├── plugins.qmltypes
        │   │       │   └── qmldir
        │   │       └── settings
        │   │           ├── libqmlsettingsplugin.so
        │   │           ├── plugins.qmltypes
        │   │           └── qmldir
        │   ├── QtGraphicalEffects
        │   │   ├── Blend.qml
        │   │   ├── BrightnessContrast.qml
        │   │   ├── Colorize.qml
        │   │   ├── ColorOverlay.qml
        │   │   ├── ConicalGradient.qml
        │   │   ├── Desaturate.qml
        │   │   ├── DirectionalBlur.qml
        │   │   ├── Displace.qml
        │   │   ├── DropShadow.qml
        │   │   ├── FastBlur.qml
        │   │   ├── GammaAdjust.qml
        │   │   ├── GaussianBlur.qml
        │   │   ├── Glow.qml
        │   │   ├── HueSaturation.qml
        │   │   ├── InnerShadow.qml
    
    ... truncated ...
    
        │   │   │   │   ├── PictureSpecifics.qml
        │   │   │   │   ├── PictureSpecifics.qmlc
        │   │   │   │   ├── PieMenuSpecifics.qml
        │   │   │   │   ├── PieMenuSpecifics.qmlc
        │   │   │   │   ├── qtquickextras.metainfo
        │   │   │   │   ├── StatusIndicatorSpecifics.qml
        │   │   │   │   ├── StatusIndicatorSpecifics.qmlc
        │   │   │   │   ├── ToggleButtonSpecifics.qml
        │   │   │   │   └── ToggleButtonSpecifics.qmlc
        │   │   │   ├── Dial.qml
        │   │   │   ├── Dial.qmlc
        │   │   │   ├── Gauge.qml
        │   │   │   ├── Gauge.qmlc
        │   │   │   ├── libqtquickextrasplugin.so
        │   │   │   ├── PieMenu.qml
        │   │   │   ├── PieMenu.qmlc
        │   │   │   ├── plugins.qmltypes
        │   │   │   ├── Private
        │   │   │   │   ├── CircularButton.qml
        │   │   │   │   ├── CircularButton.qmlc
        │   │   │   │   ├── CircularButtonStyleHelper.qml
        │   │   │   │   ├── CircularButtonStyleHelper.qmlc
        │   │   │   │   ├── CircularTickmarkLabel.qml
        │   │   │   │   ├── CircularTickmarkLabel.qmlc
        │   │   │   │   ├── Handle.qml
        │   │   │   │   ├── Handle.qmlc
        │   │   │   │   ├── PieMenuIcon.qml
        │   │   │   │   ├── PieMenuIcon.qmlc
        │   │   │   │   ├── qmldir
        │   │   │   │   ├── TextSingleton.qml
        │   │   │   │   └── TextSingleton.qmlc
        │   │   │   ├── qmldir
        │   │   │   ├── StatusIndicator.qml
        │   │   │   ├── StatusIndicator.qmlc
        │   │   │   ├── ToggleButton.qml
        │   │   │   ├── ToggleButton.qmlc
        │   │   │   ├── TumblerColumn.qml
        │   │   │   ├── TumblerColumn.qmlc
        │   │   │   ├── Tumbler.qml
        │   │   │   └── Tumbler.qmlc
        │   │   ├── Layouts
        │   │   │   ├── libqquicklayoutsplugin.so
        │   │   │   ├── plugins.qmltypes
        │   │   │   └── qmldir
        │   │   ├── PrivateWidgets
        │   │   │   ├── libwidgetsplugin.so
        │   │   │   ├── plugins.qmltypes
        │   │   │   └── qmldir
        │   │   ├── Templates.2
        │   │   │   ├── libqtquicktemplates2plugin.so
        │   │   │   ├── plugins.qmltypes
        │   │   │   └── qmldir
        │   │   └── Window.2
        │   │       ├── libwindowplugin.so
        │   │       ├── plugins.qmltypes
        │   │       └── qmldir
        │   └── QtQuick.2
        │       ├── libqtquick2plugin.so
        │       ├── plugins.qmltypes
        │       └── qmldir
        └── share
            ├── applications
            │   └── app.desktop
            └── icons
                └── hicolor
                    └── 256x256
                        └── apps
                            └── app.png