diff --git a/.gitignore b/.gitignore index 30c4f8a..e202c3d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,4 @@ build/ .venv*/ venv*/ virtualenv*/ -venv*/ .idea/ diff --git a/.woodpecker/docs.yml b/.woodpecker/docs.yml index 7cdffd1..b7030a1 100644 --- a/.woodpecker/docs.yml +++ b/.woodpecker/docs.yml @@ -13,7 +13,7 @@ pipeline: - epub_filename=AppImage-documentation-git"$(date +%Y%m%d)"."$(git rev-parse --short HEAD)".epub - mkdir -p build/html/download - cp build/epub/AppImage.epub build/html/download/"$epub_filename" - - bash -xe ci/embed-epub-link.sh "$epub_filename" + - bash -xe .woodpecker/embed-epub-link.sh "$epub_filename" deploy: image: drillster/drone-rsync diff --git a/ci/embed-epub-link.sh b/.woodpecker/embed-epub-link.sh similarity index 89% rename from ci/embed-epub-link.sh rename to .woodpecker/embed-epub-link.sh index 21118bc..248469a 100644 --- a/ci/embed-epub-link.sh +++ b/.woodpecker/embed-epub-link.sh @@ -17,7 +17,7 @@ cat >> source/index.rst <<\EOF Download this document ---------------------- -`Download as ePub `_ +`Download as ePub `__ EOF sed -i "s|epub_filename|$epub_filename|" source/index.rst diff --git a/README.rst b/README.rst index 334c421..2685b66 100644 --- a/README.rst +++ b/README.rst @@ -1,29 +1,63 @@ AppImage docs ============= -|ci_status| |cd_status| - -.. |cd_status| image:: https://drone.assassinate-you.net/api/badges/AppImage/docs.appimage.org/status.svg - :alt: CD status - :target: https://drone.assassinate-you.net/AppImage/docs.appimage.org - -.. |ci_status| image:: https://github.com/AppImage/docs.appimage.org/workflows/CI/badge.svg +.. image:: https://github.com/AppImage/docs.appimage.org/workflows/CI/badge.svg :alt: CI status :target: https://github.com/AppImage/docs.appimage.org/actions -This repository is the home of the AppImage project's documentation. -It is the central source of information for users of AppImage (both -users and developers). +This repository is the home of the AppImage project documentation. This documentation is the central source of information for both AppImage developers and users. -View it at https://docs.appimage.org/. +You can view it at https://docs.appimage.org/. Build ----- -This is a `Sphinx `_ project, and can be built like -any other Sphinx project (e.g., using :code:`make html`) +This is a `Sphinx `__ project, and can be built like any other Sphinx project. If you have never used Sphinx before, this section explains how it can be set up and built. + +Convenience script +++++++++++++++++++ + +The easiest way to set up this project and build the documentation is to use the included convenience script ``make.sh``: + +.. code-block:: shell + + # Clone the project + > git clone https://github.com/AppImage/docs.appimage.org.git + > cd docs.appimage.org + + # Set up and build the documentation + > make.sh html + +Calling make.sh will build the documentation after setting up the project and everything required to build the documentation (such as creating a Python virtual environment and installing the dependencies in it). It will only perform the preparation steps that haven't been done before, so you can simply call it each time you want to re-build the documentation. + +**Live reloading:** You can use ``make.sh watch`` instead of ``make.sh html`` |live_reloading| + +Manually +++++++++ + +If you want to set up the project and build the documentation manually, you can use the following commands. (The ``make.sh`` script does essentially the same, just with additional tests whether these preparation steps have already been done before.) + +.. code-block:: shell + + # Clone the project + > git clone https://github.com/AppImage/docs.appimage.org.git + > cd docs.appimage.org + + # Create and activate a Python virtual environment + > mkdir venv + > python3 -m venv venv + > source venv/bin/activate + + # Install the required dependencies into the venv + > pip3 install -r requirements.txt + + # Build the documentation + > make html + +After that, you can rebuild the documentation simply with ``make html`` (although you have to execute ``source venv/bin/activate`` before that in every new terminal session). + +**Live reloading:** You can use ``make watch`` instead of ``make html`` |live_reloading| -For less experienced users of Sphinx/Python/virtualenv etc., a convenience script that sets up a local isolated Sphinx environment is included. It's a transparent wrapper for the :code:`Makefile`, and can be used as a drop-in replacement :code:`./make.sh html`. -For development (i.e., writing documentation), `sphinx-autobuild `_ has been integrated into the build system, which sets up a live-reloading webserver that rebuilds the site on changes and reloads the page in the browser automatically. You can use it by running :code:`./make.sh watch`. +.. |live_reloading| replace:: to set up a live-reloading webserver that automatically rebuilds the documentation and reloads the page in the browser on any change. (This is powered by `sphinx-autobuild `__.) diff --git a/source/_static/css/custom.css b/source/_static/css/custom.css index d823809..e8cb651 100644 --- a/source/_static/css/custom.css +++ b/source/_static/css/custom.css @@ -11,3 +11,107 @@ hyphenate-limit-last: always; hyphenate-limit-zone: 8%; } + + +/* Fix to display tables properly */ + +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: normal; +} + + +/* For the formatted table in the AppImage creation tools page */ + +.formatted-table tr:nth-child(1) td { + background-color: #006400 !important; + color: #000000 !important; +} +.formatted-table tr:nth-child(2) td { + background-color: #006400 !important; + color: #000000 !important; +} +.formatted-table tr:nth-child(3) td { + background-color: #FFFF00 !important; + color: #000000 !important; +} +.formatted-table tr:nth-child(4) td { + background-color: #FFFF00 !important; + color: #000000 !important; +} +.formatted-table tr:nth-child(5) td { + background-color: #FF8000 !important; + color: #000000 !important; +} +.formatted-table tr:nth-child(6) td { + background-color: #FF8000 !important; + color: #000000 !important; +} +.formatted-table tr:nth-child(7) td { + background-color: #FF0000 !important; + color: #000000 !important; +} + + +/* To allow bold hyperlinks and substitutions */ + +.bold-link a { + font-weight: bold; +} + +.bold { + font-weight: bold; +} + + +/* For additional information in the AppStream generator */ + +.tooltip { + position: relative; + display: inline-block; + cursor: pointer; + vertical-align: super; + font-size: smaller; + text-decoration: underline; + color: #007bff; +} + +.tooltip .tooltip-text { + visibility: hidden; + width: 200px; + background-color: #555; + color: #fff; + text-align: center; + border-radius: 5px; + padding: 5px; + position: absolute; + z-index: 1; + bottom: 125%; /* Position above the element */ + left: 50%; + transform: translateX(-50%); + opacity: 0; + transition: opacity 0.3s; + box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); +} + +.tooltip:hover .tooltip-text { + visibility: visible; + opacity: 1; +} + +.tooltip .tooltip-text::after { + content: ''; + position: absolute; + top: 100%; /* Arrow points downward */ + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: #555 transparent transparent transparent; +} + + +/* For the AppStream generator */ + +.full-width { + width: 100%; +} diff --git a/source/_static/img/packaging-guide/updates-realworld-example.png b/source/_static/img/packaging-guide/updates-realworld-example.png deleted file mode 100644 index 6b1b1e8..0000000 Binary files a/source/_static/img/packaging-guide/updates-realworld-example.png and /dev/null differ diff --git a/source/conf.py b/source/conf.py index 8916153..9ac26cd 100644 --- a/source/conf.py +++ b/source/conf.py @@ -53,9 +53,8 @@ templates_path = ['_templates'] # The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -source_suffix = ['.rst'] +# You can specify multiple suffixes: +source_suffix = {'.rst': 'restructuredtext'} # The master toctree document. master_doc = 'index' @@ -65,7 +64,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -124,6 +123,7 @@ # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] +html_css_files = ["css/custom.css"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -201,15 +201,10 @@ # -- Options for intersphinx extension --------------------------------------- -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +# Intersphinx stub configuration +intersphinx_mapping = {} # -- Options for todo extension ---------------------------------------------- # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True - - -# apply some subtle changes to the selected theme via custom CSS file -def setup(app): - app.add_css_file("css/custom.css") diff --git a/source/contact.rst b/source/contact.rst index 9cce234..7c333ec 100644 --- a/source/contact.rst +++ b/source/contact.rst @@ -1,32 +1,25 @@ -.. _ref-contact: +.. _contact: Contact ======= -The AppImage project documentation is brought to you by `the AppImage team `__. The source code is available `on GitHub `__. +The AppImage project documentation is brought to you by `the AppImage team `__ and other `contributors `__. The source code is available `on GitHub `__. -This page outlines how you can contact the team behind AppImage, e.g., to get additional support or have questions answered. +If you have further questions or need additional support, please feel free to contact the AppImage team: -IRC ---- +GitHub discussions +------------------ -If you have further questions, please feel free to contact the AppImage team. The easiest and fastest way is to join our `IRC channel #appimage `__ on `Libera.Chat `__ (`webchat `__). +An easy way to contact us is to ask questions on the `AppImage GitHub discussions page `__. Questions are usually answered in one to two days, and you'll get notified as soon as someone answered you. Posts stay, so you can always keep track of the conversation. You can also browse through other posts to see if someone else had the same question or problem. -You can join the channel from Matrix, too: ``#appimage:libera.chat``. -.. note:: +IRC +--- - Please beware that it might take a few minutes/hours until someone will check the chat and might be able to help you, so don't give up too quickly, and leave e.g., the tab open in the background if you can. You can also try at other times again. Please read `this article `__ before joining the IRC chat if you are new to IRC. +An alternative way to contact is us to join our `IRC channel #appimage `__ on `Libera.Chat `__ (`webchat `__). While this may be faster, you have to stay online for some hours until someone checks the chat and can help you, so don't give up too quickly, and e.g. leave the tab open in the background if you can. Please read `this article `__ before joining the IRC chat if you are new to IRC. .. seealso:: - - The :code:`#appimage` channel on freenode has been abandoned and is not maintained by the AppImage project. The channel :code:`##appimage` (which was created after :code:`#appimage` was forcefully removed because it mentioned our move) has never been official and has never been maintained by us. + The ``#appimage`` channel on freenode has been abandoned and is not maintained by the AppImage project. The channel ``##appimage`` (which was created after ``#appimage`` was forcefully removed because it mentioned our move) has never been official and has never been maintained by us. Please see `this article `__ for more information on what happened to our channel and why we planned to transition to a new network. - - -Forum ------ - -A slower but more sustainable way is to use the `Discourse forum `__. You can log in using your existing Google or GitHub account, or alternatively register a local account with your email address. diff --git a/source/error-pages/404.rst b/source/error-pages/404.rst index b8fbdf8..3fb1f87 100644 --- a/source/error-pages/404.rst +++ b/source/error-pages/404.rst @@ -1,17 +1,20 @@ :orphan: -.. custom 404 error page -- must be set up to be shown for all 404 errors in the webserver's configuration +.. + Custom 404 error page + This must be set up to be shown for all 404 errors in the webserver's configuration .. image:: /_static/img/appimage-grayscale.svg :align: center :width: 200px + 404: Not found ============== The resource you requested could not be found. .. note:: - As this documentation is still work in progress, the content might have been moved. Please use the search function or the table of contents to find its new location. + As this documentation is continuously being changed, the content might have been moved. Please use the search function or the table of contents to find its new location. -:ref:`Back to home page ` +:ref:`Back to the home page ` diff --git a/source/index.rst b/source/index.rst index 968d726..4ba8153 100644 --- a/source/index.rst +++ b/source/index.rst @@ -1,9 +1,4 @@ -.. image:: /_static/img/appimage.svg - :align: center - :width: 300px - ------------------- - +.. include:: substitutions.rst .. _home: @@ -14,19 +9,31 @@ Welcome to the AppImage documentation ------------------ -.. seealso:: +Welcome to the AppImage documentation. + +.. cssclass:: bold-link + +**If you are a first time user and just want to know how to run an AppImage (on your system or in a docker container) or have issues with an AppImage, see the** :ref:`Quickstart page `\ **!** + +| If you are a user and want to know how to integrate AppImages into your desktop, update them, use them portably or inspect their content, read the :ref:`user guide `. It covers all these topics and more. +| Its :ref:`Quickstart page ` covers all frequently asked questions and the most common problems. + +.. cssclass:: bold-link + +| **If you are a first time developer and want to know how to easily create an AppImage, look at the** :ref:`packaging guide `\ **:** +| It covers all requirements like desktop entry files, shows how to create an AppImage using modern AppImage creation tools |packaging_optional| - .. centered:: **First-time users, heads up!** Check out our :ref:`ref-quickstart` chapter! +If you want to know about |introduction_content|, read the :ref:`introduction chapter `. -In this documentation, all aspects of the AppImage project shall be explained, to have a single unified source of information. +If you want to know about |reference_content|, see the :ref:`reference chapter `. + +------------------ + +As you can see, this documentation explains all aspects of the AppImage project and serves as a single unified up-to-date source of information. .. note:: .. centered:: - **This documentation contains a lot of valuable information, but there's always something to add.** `Contributions welcome! `_ - -If you are new to AppImage, please read the introduction. It describes the ideas behind AppImage, shows the motivation, explains why you as a user and/or developer should be interested in AppImages. Also, it explains the core concepts of AppImage's design. - -To learn more about *using* AppImages, please read the User Guide. If you are interested in building and distributing AppImages or building software that works with AppImages, please check the Packaging Guide. + **This documentation contains a lot of valuable information, but there's always something to add.** `Contributions welcome! `__ .. toctree:: introduction/index @@ -36,3 +43,9 @@ To learn more about *using* AppImages, please read the User Guide. If you are in contact :maxdepth: 2 :caption: Contents: + +------------------ + +.. image:: /_static/img/appimage.svg + :align: center + :width: 300px diff --git a/source/introduction/advantages.rst b/source/introduction/advantages.rst deleted file mode 100644 index 595f1a8..0000000 --- a/source/introduction/advantages.rst +++ /dev/null @@ -1,55 +0,0 @@ -AppImage advantages -=================== - -This chapter compares AppImage with traditional application packaging formats on Linux and explains the advantages of the AppImage format. You can skip this chapter if you already know why AppImages are useful. - -Traditionally, applications have been installed on Linux systems by using the package manager that comes with the Linux distribution. However, this model does not scale well for long-tail applications, applications that are only used by a few users, or in cases where users want to use the very latest applications immediately after they are published by their developers. It also is very cumbersome for application developers that want to reach a large audience quickly. - - -.. contents:: Contents - :local: - :depth: 1 - - -Advantages for users --------------------- - -On the desktop, users are used to installing an operating system, using that operating systems for many years, and running the most recent applications whenever they feel like it. However, many Linux distributions restrict the availability of applications to those that were already published at the point in time when the Linux distribution was published. This effectively means that if the user wants to use a stable operating system, then the user is locked into a set of applications that was recent at the point when the operating system was released. While this may be reasonable for enterprise-critical applications or server side processes, it is not the model users expect from a desktop operating system. - -So-called "rolling release" distributions exist that provide latest versions of software. However, they make no distinction between the core operating system and applications. So, with a "rolling release" distribution users don’t only get the latest applications, but also an ever-changing base system. While this may be suitable for hobbyists and technology enthusiasts, it is hardly suitable for productive use where the base system has to be supportable. - -The combination of a long-term stable base operating system with the latest applications delivered in AppImage format can provide an elegant solution to this dilemma. While the base operating system can stay stable and only change every few years, users can download and run the very latest applications whenever they appear. - -AppImage also makes it easy to try out new versions of applications. Since versions can exist alongside each other, the user can simply download a new version of an application and try it out. If the new version proves to be superior, the user can then delete the old version and work with the new one. However, should the new version have bugs or be otherwise unusable, the user can simply delete the new version and continue using the old version. This is also very useful for testing nightly or continuous builds and for giving feedback to the application development team. - - -Advantages for system administrators ------------------------------------- - -System administrators in corporate, educational or institutional settings usually need to support a large number of desktop systems, where they either need to lock down the system so that users cannot make changes such as application installations, or need to find a way to leave the base system supportable while users can run applications on top. - -AppImages provide an elegant solution here: Since the core operating system is not changed through the installation of applications, the system stays pristine and supportable no matter what kind of applications end users run on the system. Users are happy because they can run their favorite applications without having to ask a system administrator to install them. System administrators are happy because they have less work. - - -Advantages for application authors ----------------------------------- - -Application authors may want to reach as many users as possible, regardless of the operating system and version users are running. With the traditional model, application authors either need to get their application into Linux distributions by creating packages according to the rules of distributions, which can be a lengthy and time-consuming process, or need to find someone who creates the application package for them. It does not help that different Linux distributions have very different rules for packaging applications. This means that if an author is successful to package an application according to the rules of one distribution, it may well not be suitable for inclusion in another distribution. In any case, it is not a quick and easy operation to get a new application into every Linux distribution. And even if an author gets an application into a Linux distribution, it will only appear in the soon-to-be-released version of that Linux distribution, which means that all the currently existing users using older versions of the Linux distribution are left out in the cold. - -If a third party (the distribution's "maintainer") packages the application for inclusion in the distribution, the third party may make unintended changes to the application not authorized by the original author. This has led to some application authors to ask Linux distributions to no longer distribute their software because they did not like the changes. - -Some developers do not want their applications to be distributed randomly, but be in full control over who downloads what and when. For example an application author may want users to fill in a survey before downloading the application. Also, the author may want to count the number of downloads. In other cases still, the application author may want to ask for a donation or even a required payment before the user can download the application through services such as Gumroad, PayPal, or Patreon. In the traditional Linux distribution model, this is not possible. - -Providing an AppImage solves these kinds of issues, since the application author is in full control over the application distribution and the user experience connected to it. - -Some applications require certain versions of dependencies in order to function properly. For example, an application may run only on a certain version of the Qt framework and may run into unexpected issues if another version is used. In the traditional Linux distribution model, an application has to use whatever version of a library the Linux distribution happens to provide, whereas with AppImage, the application author can exactly decide which version of a dependency should be used by the application. - - -Advantages for software testers -------------------------------- - -Successful application projects run a lot of tests. Whereas some tests may be automated, manual tests are always important to ensure both functionality and usability. In regression testing, different versions of an application are compared to each other concerning features and bugs. AppImage makes it easy to conduct application tests on local machines, since it allows to run various different versions of applications alongside each other. With portable mode, it is also possible to isolate the settings of each version of the application from each other, allowing for clean testing environments. - -The LibreOffice_ project, for example, uses AppImages to test new application versions. - -.. _LibreOffice: https://www.libreoffice.org/download/appimage/ diff --git a/source/introduction/concepts.rst b/source/introduction/concepts.rst index 4781d86..307d17d 100644 --- a/source/introduction/concepts.rst +++ b/source/introduction/concepts.rst @@ -1,3 +1,5 @@ +.. include:: ../substitutions.rst + Concepts ======== @@ -14,62 +16,62 @@ The AppImage development follows a few easy-to-understand core principles and co One app = one file ------------------ -AppImages are simple to understand. Every AppImage is a regular file, and every AppImage contains exactly one app with all its dependencies. Once the AppImage is :ref:`made executable `, a user can just run it, either by double clicking it in their desktop environment's file manager, by running it from the console etc. +AppImages are simple to understand. Every AppImage is a regular file, and every AppImage contains exactly one app with all its dependencies. Once the AppImage is :ref:`made executable `, a user can just run it, e.g. by double clicking it in their desktop environment's file manager or by running it from the console. -.. _ref-opinion-reusable-frameworks: .. note:: - - On a regular basis, `users ask `__ about implementing support for some sort of "reusable/shared frameworks". These frameworks are supposed to contain bundles of libraries which are needed by more than one AppImage, and hence could save some disk space. For management, they suggest complex automagic systems that will automatically fetch the "frameworks" from the Internet if they're not available, or some complicated, mostly manual methods how to users could bundle frameworks together with the AppImages on portable disks like USB sticks. + On a regular basis, `users ask `__ about implementing support for some sort of "reusable/shared frameworks". These frameworks are supposed to contain bundles of libraries which are needed by more than one AppImage, and hence could save some disk space. For management, they suggest complex automagic systems that will automatically fetch the "frameworks" from the Internet if they're not available, or some complicated, mostly manual methods how users could bundle frameworks together with the AppImages on portable disks like USB drives. These may be good ideas for some people, and even if they worked perfectly fine, they'd break with our most important concept: :ref:`one app = one file `. AppImages are so simple to understand *because* every application is a single file. There's no complexity in this approach, even grandma could understand it. And after all, disk space is cheap nowadays, right? - If you prefer this approach or absolutely need it, please check out alternative approaches. AppImage will never implement such a feature. + If you prefer this approach or absolutely need it, please check out alternative approaches like Flatpak or Snap. AppImage will never implement such a feature. .. _no-external-dependencies: -Do not depend on system-provided resources ------------------------------------------- +Bundle all required dependencies +-------------------------------- + +To be able to run on any Linux distribution, an AppImage has to bundle all resources it needs at runtime that cannot reasonably be expected to come with every still-supported target system (Linux distribution) in its default installation in a recent enough version. The most common resources that have to be bundled are the actual binaries, shared library dependencies, icons and other graphics and of course a :ref:`desktop file ` for desktop integration. -The author of an AppImage needs to decide for which target systems (Linux distributions) they want to offer the AppImage. Then, the author needs to bundle any dependencies that cannot reasonably be assumed to come with every target system (Linux distributions) in its default installation in a recent enough version. +This doesn't mean an AppImage must not use resources provided by the system, like for example basic libraries that can be assumed to be part of every target system (e.g., the C standard library or graphics libraries), user interface themes or the like. See the `excludelist `__ for a list of the libraries we consider to currently be part of every still-supported target system. -To be able to run on any Linux distribution, an AppImage should bundle all the resources it needs at runtime that cannot be reasonably expected to be "there" in the default installation of all still-supported target systems (Linux distributions). The most common resources are the actual binaries, shared library dependencies, icons and other graphics and of course one or more desktop files for desktop integration. -This doesn't mean an AppImage must not use resources provided by the system, like for example basic libraries that can be assumed to be part of every target system (e.g., the C standard library or graphics libraries), user interface themes or the like. See the `excludelist `__ for a list of the libraries we consider to currently be part of each still-supported target system (distribution). +.. _exclude-expected-libraries: +Exclude expected core libraries (Recommended, but optional) +----------------------------------------------------------- -.. _build-on-old-systems: +AppImages should usually exclude certain "core libraries", which can be expected to be present on all major desktop Linux distributions, reducing the overhead of :ref:`one app = one file `. These dependencies are mostly shared libraries and involve low level libraries like ``libc.so.6`` (the GNU C library, the C language standard library the majority of all Linux distributions use), but also common libraries like `zlib `__ that are normally present. -Build on old systems, run on newer systems ------------------------------------------- +It may seem contradictory to :ref:`the previous section ` to rely on distribution provided resources. This is a trade-off between trying to reduce redundancies while at the same time being as self-contained as possible. -It is considered best practice to develop and compile the application on the oldest still-supported Linux distribution that we can assume users to still use. For example, the oldest still-supported LTS release of Ubuntu is a good choice to develop applications against and build applications on. +In some cases, including the libraries might even break the AppImage on the target system. Those libraries involve, among others, hardware dependent libraries such as graphics card drivers provided libraries (e.g., ``libGL.so.1``, (`source `__)), or libraries that are built and linked differently on different distributions (e.g., ``libharfbuzz.so.0`` and ``libfreetype.so.6`` (`source `__)). -Applications should be built on the oldest possible system, allowing them to run on newer system. This allows the exclusion of certain "base libraries", which can be expected to be present on all major desktop Linux distributions, reducing the overhead of :ref:`one app = one file `. These dependencies are mostly shared libraries and involve low level libraries like :code:`libc.so.6` (the GNU C library, the C language standard library the majority of all Linux distributions use), but also common libraries like zlib_ or the GLib_ libraries are normally present. +The list of libraries that should be excluded, the so-called `excludelist `__, is carefully curated by the AppImage team, and is regularly updated. -It may seem contradictory to :ref:`the previous section ` to rely on distribution provided resources. This is a trade-off between trying to reduce redundancies while at the same time being as self-contained as possible. +**However, excluding these core libraries requires you to compile the application on the oldest still-supported Linux distribution version that we can assume users to still use.** For example, the oldest still-supported LTS release of Ubuntu is a good choice to build applications on. |old_compile_version_reason| -In some cases, including the libraries might even break the AppImage on the target system. Those libraries involve, among others, hardware dependent libraries such as graphics card drivers provided libraries (e.g., :code:`libGL.so.1`, (`source `__)), or libraries that are build and linked differently on different distributions (e.g., :code:`libharfbuzz.so.0` and :code:`libfreetype.so.6` (`source `__). +.. note:: + If you don't use any dynamic linking, and your application does not reference any of these core libraries, you don't have to build the application on an old system. -The list of libraries that can resp. have to be excluded, the so-called `excludelist `__, is carefully curated by the AppImage team, and is regularly updated. + However, even when using a programming language that usually links everything statically like Rust or Go, some libraries might still be dynamically linked, e.g. by including C code or dependencies that do so. You should test whether your application references any shared libraries with ``ldd`` before building and packaging on a newer system, and it's usually still better to build the application on an old system (to be safe in case of future changes). -.. _zlib: https://zlib.net/ -.. _GLib: https://developer.gnome.org/glib/ +Some :ref:`appimage-creation-tools` can also include these expected core libraries. |increased_appimage_size|, but removes the limitation of requiring the oldest supported LTS distribution version to compile the binaries (since all referenced libraries are included, the used distribution version is irrelevant). This should only be done if there are issues with the exclusion of the core libraries, e.g. if the AppImage can't be built on the oldest supported LTS distribution version, as the inclusion of some core libraries can also lead to other issues. If a considerable base of your users uses a system configuration without some of these core libraries (e.g. a custom Gentoo configuration), it's also an option to provide both AppImage versions. +There are also **experimental** tools that try to use an old version of ``glibc`` when compiling on a new system (`1 `__, `2 `__, `3 `__), but they don't always work and as they only adapt ``glibc`` and not other expected core libraries, the application might still crash when referencing a different core library. -.. _appimage-specification: AppImage specification ---------------------- -The term *AppImage* does not refer to some software project, but is actually a standard specified in the :ref:`AppImage specification `. Its reference implementation is called :ref:`ref-appimagekit`. +The term *AppImage* does not refer to some software project, but is actually a standard specified in the :ref:`AppImage specification `. There also is a :ref:`reference implementation ` that confirms to the specification. -Being designed as a standard with a reference implementation allows users to implement their own tools to build AppImages, and helps maintaining compatibility between different tools and components. +|specification_advantage| AppDirs ------- -The term *AppDir* refers to an application directory. These directories are the "source" of AppImages. When :ref:`ref-appimagetool` builds an AppImage, it creates a read-only image of such a directory, prepends the :ref:`ref-runtime`, and marks the file executable. +The term *AppDir* refers to an application directory. These directories are the "source" of AppImages. When :ref:`appimagetool` (the reference implementation) builds an AppImage, it creates a read-only image of such a directory, prepends the :ref:`runtime`, and marks the file executable. -The AppDir format is described in the :ref:`ref-appdir-specification`. +The AppDir format is described in the :ref:`appdir-specification`. diff --git a/source/introduction/index.rst b/source/introduction/index.rst index 8c4fe9b..2714770 100644 --- a/source/introduction/index.rst +++ b/source/introduction/index.rst @@ -1,20 +1,17 @@ +.. include:: ../substitutions.rst + +.. _introduction: + Introduction ============ -AppImage provides a way for upstream developers to provide "native" binaries for Linux users just the same way they could do for other operating systems. It allow packaging applications for any common Linux based operating system, e.g., Ubuntu, Debian, openSUSE, RHEL, CentOS, Fedora etc. AppImages come with all dependencies that cannot be assumed to be part of each target system in a recent enough version and will run on most Linux distributions without further modifications. +AppImage provides a way for upstream developers to provide "native" binaries for Linux users just the same way they could do for other operating systems. It allow packaging applications into one binary that runs on any common Linux based operating system, e.g., Ubuntu, Debian, Fedora, RHEL, openSUSE or Arch. AppImages come with all dependencies that cannot be assumed to be part of each target system in a recent enough version and will run on most Linux distributions without further modifications. -AppImage is the format, and AppImageKit_ provides a reference implementation. - -The following section provides an overview of the AppImage idea, the motives behind AppImage, and explains the basic concepts. Furthermore, there's an overview over the currently existing software, and some words on upstream packaging. +This chapter provides an overview on |introduction_content|. .. toctree:: - quickstart - motivation - advantages + motivation-advantages concepts - software-overview upstream :caption: Contents: :maxdepth: 2 - -.. _AppImageKit: https://github.com/AppImage/AppImageKit diff --git a/source/introduction/motivation-advantages.rst b/source/introduction/motivation-advantages.rst new file mode 100644 index 0000000..8553cbb --- /dev/null +++ b/source/introduction/motivation-advantages.rst @@ -0,0 +1,95 @@ +Motivation & Advantages +======================= + +Traditionally, applications have been installed on Linux systems by using the package manager that comes with the Linux distributions. However, this model has numerous disadvantages for users, developers, software testers and system administrators. + +This chapter explains the advantages of the AppImage format and compares it with traditional packet managers out of the perspective of all these groups of people. + +.. contents:: Contents + :local: + :depth: 1 + + +Advantages for users +-------------------- + +Consider the following user stories: + + "I, as a user, want to run the latest version of my favorite app on my stable distribution, which ships only with an old outdated version." + + "I, as a user, need to use multiple versions of an application in parallel." + + "I, as a user, want to take my favorite applications with me on a portable disk together with my data, allowing me to use any Linux computer to work with my files." + + "I am in a corporate or university environment and want to simply run some specific software, but lack permissions to 'install' applications." + +All these use cases can be accomplished by using AppImages: + +| While the traditional way of using the distribution's package manager often locks the user into a set of applications that was recent at the point when the operating system was released, using AppImages allows the user to always download and run the latest applications whenever they appear. +| And since AppImages are independent from each other and package all dependencies, the user can also try out several versions of an application in parallel, or use one in :ref:`portable mode ` on a USB drive. +| Additionally, AppImages are designed from the ground to run without super user permissions. Almost all major distributions are compatible with AppImages, without requiring the user to make any modifications to the base system. AppImages ship with their own runtime, and don't require external resources if packaged properly. + +Therefore, AppImages provide a simple user experience which guarantees that even less tech-savvy people can get started without any major issues. AppImage is primarily a user-focused way of bundling software. + +And as AppImage has been around for a while, a lot of useful, optional features have been developed, ranging from :ref:`efficient updates ` over so-called :ref:`desktop integration ` to :ref:`software catalogs `. None of these are required for the basic experience, though. AppImages are designed to :ref:`be run in three steps at most `. + + +Advantages for developers & application authors +----------------------------------------------- + +Consider the following problems a developer might face when trying to distribute their project with the distribution package managers: + + .. raw:: html + + To reach all Linux users, the developer has to package the application for each distribution individually accordingly to their rules, which is a lengthy and time-consuming process. +
+ Why is the packaging for every distribution different? + + .. note:: + Linux is just the kernel, but the operating systems users run are separate projects with different goals and concerns. They all ship with different versions and combinations of certain libraries, and most of them require software to be linked to the binaries in the distribution. Therefore, in order to be able to run a certain binary, that binary must be compiled *against* the distribution's set of libraries. As soon as another distribution's collection of libraries is not the same as the one the binary was built on, it might crash or even refuse to run. + + Additionally, different distributions have very different rules for packaging applications. This means that if an author successfully packaged an application according to the rules of one distribution, it may well not be suitable for inclusion in another distribution. + + .. raw:: html + +

+ + After the developer gets the application into a Linux distribution, it will only appear in the soon-to-be-released version of that Linux distribution, which means that all the currently existing users using older versions of the Linux distribution are left out in the cold. + + If a third party (the distribution's "maintainer") packages the application for inclusion in the distribution, the third party may make unintended changes to the application not authorized by the developer. + + | Some developers want to be in control over who downloads what and when. For example, the developer may require a payment, ask for a donation, or want users to fill out a survey before downloading the application. The developer may also want to count the number of downloads. + | This is not possible in the traditional Linux distribution model. + + Some applications require certain versions of dependencies in order to function properly. In the traditional Linux distribution model, an application has to use whatever version of a library the distribution happens to provide, which can lead to unexpected issues. + + +All these issues are solved when using AppImages to package the application: + +| The AppImage is independent from the distribution and has to be packaged just once, not for every distribution individually like for their packet managers. It can then be downloaded and run by every user and not only after their distribution has been updated. +| And as AppImages follow the philosophy of :ref:`upstream packaging `, no third party can make any changes to the applications that aren't intended by the original developer. Instead, the developer can exactly control who can download it under which condition. +| As the AppImage contains exactly the versions of dependencies that are required, no version mismatch issues occur when using it either. + +.. note:: + These issues can all be accomplished using tarballs that contain all libraries (except :ref:`lowest-level ones that usually shouldn't be shipped `), and maybe some sort of "run script" that makes sure only those libraries are used. + However, this is not user-friendly as the user has to know how to actually run the software and manage it as a folder of dependencies on their hard-drive. + + AppImages pursue the same idea (bundling the application, their dependencies and runtime resources), but improves the user-experience as they're single binaries that can easily be executed just by double clicking, following the ":ref:`one app = one file `" core principle. + +Making AppImages is very simple for a developer. There are different :ref:`tools ` that help with generating AppImages and even creating AppImages from existing packages, which are aware of potential cross distro incompatibilities, and try to avoid them. And once the AppImage has been built, it will "just run" on all major desktop distributions. + + +Advantages for software testers +------------------------------- + +Successful application projects run a lot of tests. Whereas some tests may be automated, manual tests are always important to ensure both functionality and usability. In regression testing, different versions of an application are compared to each other, concerning features and bugs. AppImage makes it easy to conduct application tests on local machines, since it allows to run various different versions of applications alongside each other. With :ref:`portable mode `, it is also possible to isolate the settings of each version of the application from each other, allowing for clean testing environments. + +The `LibreOffice `__ project, for example, uses AppImages to test new application versions. + + +Advantages for system administrators +------------------------------------ + +System administrators in corporate, educational or institutional settings usually need to support a large number of desktop systems, where they either need to lock down the system so that users cannot make changes such as application installations, or need to find a way to leave the base system supportable while users can run applications on top. + +AppImages provide an elegant solution here: Since the core operating system is not changed through the installation of applications, the system stays pristine and supportable no matter what kind of applications end users run on the system. Users are happy because they can run their favorite applications without having to ask a system administrator to install them. System administrators are happy because they have less work. diff --git a/source/introduction/motivation.rst b/source/introduction/motivation.rst deleted file mode 100644 index 26320f0..0000000 --- a/source/introduction/motivation.rst +++ /dev/null @@ -1,49 +0,0 @@ -Motivation -========== - -There's two different points of view when looking at AppImages: the user's and the developer's. The following section explains both of them. - - -.. contents:: Contents - :local: - :depth: 1 - - -Why would I as a user want to use AppImages? ----------------------------------------------------------------------------------------- - -Consider the following user stories: - - "I as a user want to run the latest version of my favorite app on my stable distribution, which ships only with an old outdated version." - - "I as a user need to use multiple versions of an application in parallel." - - "I as a user want to take my favorite applications with me on a portable disk together with my data, allowing me to use any Linux computer to work with my files." - - "I am in a corporate or university environment and want to simply run some specific software, but lack permissions to 'install' applications." - -All these use cases can be accomplished by using AppImages. They're a trade-off between a simple user experience and resulting file size. The unique user experience guarantees that even less tech-savvy people can get started without any major issues. AppImage is primarily a user-focused way of bundling software. - -As AppImage has been around for a while, a lot of useful, optional features have been developed, ranging from :ref:`efficient updates ` over so-called :ref:`desktop integration ` to :ref:`software catalogs `. None of these are required for the basic experience, though. AppImages are designed to :ref:`be run in three steps at most `. - -An important advantage is that AppImage is designed from ground to run without super user permissions. Almost all major distributions are compatible with AppImages, without requiring the user to make modifications to the base system. AppImages ship with their own runtime, and don't require external resources if packaged properly. Students in university labs for instance can simply put an AppImage on a USB disk and use it normally, on any machine. - -To sum up: AppImages provide a easy and unified user experience, have a large user base and eco system, and there's a lot of tools that improve the users' user experience. - - -Why would I as a developer want to make and distribute AppImages? ----------------------------------------------------------------------------------------- - -Many developers have found that they can deploy their apps to most operating systems with viable efforts. They can say, "I make binaries for Windows", or "I make binaries for macOS". However, when trying to do the same for Linux, they commonly face a situation where they cannot "make binaries for Linux", but they have to make them for Ubuntu, Debian, CentOS, openSUSE etc. Read: they have to make binaries for every distribution. - -The problem with this is that Linux is just the kernel, but the operating systems users run are separate projects with separate goals and concerns. They all ship with different versions and combinations of certain libraries, and most of them require software to be shipped separately, linking to binaries in the distribution. Therefore, in order to be able to run a certain binary, that binary must be compiled *against* the distribution's set of libraries. As soon as another distribution's collection of libraries is not the same as the one the binary was built on, it will crash or even refuse to run. - -To fix this issue, one has to do the same one would do to prevent issues like missing shared libraries (or version incompatibilities) that is used on other platforms: ship the dependency libraries along with the own software's binaries. - -This can be accomplished using traditional tarballs that contain all the libraries and maybe some sort of "run script" that makes sure only those libraries are run, but it has a few major disadvantages. First of all, it is hard to get the right set of libraries that must be shipped, excluding the ones that would cause issues (lowest level dependencies such as ``libc``, ``libdl``, etc.). But even worse, the user is presented with an archive that they must extract, and they must be explained how to actually run the software within it. Furthermore, they now have that data on their hard drive, and have to manage it themselves, without any kind of helpers. - -In order to improve the usability and reduce the maintenance effort, AppImage was created. AppImages are bundles of programs, their dependency libraries and all the resources they need during the runtime. They're single binaries, following the ":ref:`one app = one file `" core principle. - -Making AppImages is very simple for a developer. There's tools which generate an AppImage from a so-called :ref:`AppDir `. There's simple tools to create such an AppDir for an existing software, which are aware of potential cross distro incompatibilities, and try to avoid them. And once the AppImage has been built, it will "just run" on all major desktop distributions. - -Stop making binaries "for distributions" and start making binaries "for Linux" today! diff --git a/source/introduction/quickstart.rst b/source/introduction/quickstart.rst deleted file mode 100644 index 388152b..0000000 --- a/source/introduction/quickstart.rst +++ /dev/null @@ -1,58 +0,0 @@ -.. _ref-quickstart: - -Quickstart -========== - -This page contains information for users new to AppImage, and want to get started. - - -.. contents:: Contents - :local: - :depth: 1 - - -.. _ref-how-to-run-appimage: - -How to run an AppImage ----------------------- - -It's quite simple to run AppImages. All you have to do is download them, make them executable and run them. This can either be done using the GUI or via the command line. - - -Using the GUI -************* - -#. Open your file manager and browse to the location of the AppImage -#. Right-click on the AppImage and click the ‘Properties’ entry -#. Switch to the Permissions tab and -#. Click the ‘Allow executing file as program’ checkbox if you are using a Nautilus-based file manager (Files, Nemo, Caja), or click the ‘Is executable’ checkbox if you are using Dolphin, or change the ‘Execute’ drop down list to ‘Anyone’ if you are using PCManFM -#. Close the dialog -#. Double-click on the AppImage file to run - -Please see also the video below: - -.. image:: /_static/img/make-executable.gif - - -Using the Terminal -****************** - -#. Open a terminal -#. Change to the directory containing the AppImage, e.g., using :code:`cd ` -#. Make the AppImage executable: :code:`chmod +x my.AppImage` -#. Run the AppImage: :code:`./my.AppImage` - -That's it! The AppImage should now be executed. - - -Translated versions of this guide -********************************* - -Translated versions are available in a `post in the AppImage forum `__. - - -Getting help ------------- - -If you're new to AppImage and have problems getting up and running, please don't hesitate to contact the AppImage team and their awesome community. They're happy to help! Please see the :ref:`Contact page ` for more information. - diff --git a/source/introduction/software-overview.rst b/source/introduction/software-overview.rst deleted file mode 100644 index 8d2c3f6..0000000 --- a/source/introduction/software-overview.rst +++ /dev/null @@ -1,189 +0,0 @@ -.. _software-overview: - -Software Overview -================= - -.. todo:: - - list deprecated components - - -.. contents:: Contents - :local: - :depth: 2 - - -AppImage project -**************** - -.. _ref-appimagekit: - -AppImageKit ------------ - -`AppImageKit `__ is the reference implementation of the :ref:`AppImage specification `. It is split up into several components, which are described in this subsection. - - -.. _ref-runtime: - -runtime -^^^^^^^ - -The runtime provides the "executable header" of every AppImage. When executing an AppImage, the runtime within the AppImage is run, which mounts the embedded file system image read-only in a temporary location, and launches the payload application within there. After the payload application exited, the runtime unmounts the squashfs image and cleans up the temporary resources (such as, the temporary mountpoint directory). - -**Download:** There is usually no reason to download this manually, but if you still want to, you can get it from https://github.com/AppImage/AppImageKit/releases/continuous. Keep in mind that on its own it does nothing, it needs to be combined with a filesystem image to form a valid AppImage, usually by using appimagetool which comes with its own copy of the runtime. - - -.. _ref-appimagetool: - -appimagetool -^^^^^^^^^^^^ - -appimagetool is the easiest way to create AppImages from existing directories on the system, the so-called :ref:`AppDirs `. It creates the AppImage by embedding the :ref:`runtime `, and creating and appending the filesystem image. - -appimagetool implements all optional features, like for instance `update information `__, :ref:`signing `, and some linting options to make sure the information in the AppImage is valid (for instance, it can validate :ref:`AppStream files `). - -**Download:** You can get it as an AppImage from https://github.com/AppImage/AppImageKit/releases/continuous. - - -AppRun -^^^^^^ - -Every AppImage's AppDir must contain a file called :code:`AppRun`, providing the "entry point". When running the AppImage, the :ref:`runtime ` executes the :code:`AppRun` file within the :ref:`AppDir `. - -:code:`AppRun` doesn't necessarily have to be a regular file. If the application is :ref:`relocatable `, it can just be a symlink to the main binary. Tools like :ref:`ref-linuxdeploy` can turn applications into relocatable applications, and therefore create such a symlink. - -In some cases, though, when an existing application must not be altered (e.g., when the license prohibits any modifications) or tools like linuxdeploy cannot be used, AppImageKit's :code:`AppRun.c` can be used. :code:`AppRun.c` attempts to make programs load bundled shared libraries instead of system ones by manipulating environment variable. Furthermore, it attempts to prevent warnings users might encounter that are coming from the fact the :ref:`AppDir ` is mounted read-only. - -Using :code:`AppRun.c` is not a guarantee that an application will run, and the packager must provide all the resources an application could need manually (or by using external tools) before creating the AppImage with :ref:`appimagetool `. :code:`AppRun` force-changes the current working directory, and therefore applications can not detect where the AppImage was called originally. This may be especially annoying for CLI tools, but can also be a problem for GUI applications expecting paths via parameters. - -.. note:: - :code:`AppRun.c`, the binary from AppImageKit, is legacy technology and should be avoided if possible. Tools like :ref:`linuxdeploy ` deploy applications in a different way (they are smart enough so that a simple symlink called :code:`AppRun` to the main binary works just fine), and made using :code:`AppRun.c` obsolete in most cases. - - There are some edge cases where :code:`AppRun.c` is still in use, and there it might be useful. However, it suffers from many limitations and requires some workarounds (which require troublesome mechanisms, such as e.g., force-changing current working directory, as described in this section), which can cause a lot of trouble while trying to debug an AppImage. Please beware of these before thinking about using :code:`AppRun.c` in your AppImage. - -**Download:** There is usually no reason to download this manually, but if you still want to, you can get it from https://github.com/AppImage/AppImageKit/releases/continuous. - - -Helpers -^^^^^^^ - -AppImageKit ships with a few helpers that can be used to verify and validate some AppImage features. - - -validate -######## - -:code:`validate` can validate the PGP signatures inside AppImages. - -Normally there is no need to use this directly, this is mainly for debugging for AppImage developers. - -**Download:** Currently this needs to be build from source. The source is in https://github.com/AppImage/AppImageKit/. In the future it may become bundled with or its functionality may become integrated into appimagetool. - - -digest-md5 -########## - -Calculates the MD5 digest used for desktop integration purposes for a given AppImage. This digest depends on the path, not on the contents. - -Normally there is no need to use this directly, this is mainly for debugging for AppImage developers. - -**Download:** Currently this needs to be build from source. The source is in https://github.com/AppImage/AppImageKit/. In the future it may become bundled with or its functionality may become integrated into appimagetool. - -.. _ref-appimageupdate: - -AppImageUpdate --------------- - -AppImageUpdate_ lets you update AppImages in a decentralized way using information embedded in the AppImage itself. - -The project consists of two tools: :code:`appimageupdatetool`, a full-featured CLI tool for updating AppImages and dealing with `update information`_, and :code:`AppImageUpdate`, a user interface for updating AppImages written in Qt. - -.. _AppImageUpdate: https://github.com/AppImage/AppImageUpdate -.. _update information: https://github.com/AppImage/AppImageSpec/blob/master/draft.md\#update-information - -**Download:** You can get it as an AppImage from https://github.com/AppImage/AppImageUpdate/releases/continuous. - -.. _appimaged: - -appimaged ---------- - -`appimaged `__ is a daemon that monitors a predefined set of directories on the system, looking for AppImages. It automatically integrates all AppImages it can find during an initial search, and then live watches for new AppImage (or AppImages that were removed) and (de)integrates these immediately. - -It is shipped as an AppImage. - -.. warning:: - - One of the monitored directories is ``~/Downloads``. If the directory is very large, appimaged usually needs quite long to visit all files. It is likely to slow down the system (specifically, the filesystem). - -**Download:** You can get it as an AppImage from https://github.com/probonopd/go-appimage/releases. - -Third-party tools -***************** - -This section showcases a couple of third-party tools that can be used to create and handle AppImage files. - - -.. _ref-linuxdeployqt: - -linuxdeployqt -------------- - -`linuxdeployqt `__ is a simple Qt-based command line tool that can be used to create AppDirs and AppImages. It is based on the similar macdeployqt tool that comes with Qt. It can be used to produce AppDirs and AppImages for C, C++, and Qt/QML applications, as well as applications written in other compiled languages. - -.. seealso:: - - There is a copy-and-paste example for how to use it on Travis CI at https://github.com/probonopd/linuxdeployqt#using-linuxdeployqt-with-travis-ci. - -**Download:** You can get it as an AppImage from https://github.com/probonopd/linuxdeployqt/releases/tag/continuous. - - -linuxdeploy ------------ - -linuxdeploy_ is a simple yet flexible, plugins-based to use tool that can be used to create AppDirs and AppImages. It has been developed in 2018, and describes itself as an "AppDir creation and maintenance tool". - -linuxdeploy is planned to succeed of :ref:`linuxdeployqt `, and can be used in all projects that use :ref:`linuxdeployqt `. The list of plugins is continually growing, providing solutions for bundling frameworks such as `Qt `__ as well as complete environments for non-native programming languages such as `Python `__. - -.. _linuxdeploy: https://github.com/linuxdeploy/linuxdeploy - -.. seealso:: - - There's a guide on :ref:`native binary packaging ` and a general :ref:`linuxdeploy user guide ` in the :ref:`ref-packaging-guide`. - -**Download:** You can get it as an AppImage from https://github.com/linuxdeploy/linuxdeploy/releases/continuous. - -.. _ref-appimagelauncher: - -AppImageLauncher ----------------- - -AppImageLauncher_ is a helper application for Linux distributions serving as a kind of "entry point" for running and integrating AppImages. - -Quoting the README: - - AppImageLauncher makes your Linux desktop AppImage ready™. By installing it, you won't ever have to worry about AppImages again. You can always double click them without making them executable first, just like you should be able to do nowadays. You can integrate AppImages with a single mouse click, and manage them from your application launcher. Updating and removing AppImages becomes as easy as never before. - - Due to its simple but efficient way to integrate into your system, it plays well with other applications that can be used to manage AppImages, for example app stores. However, it doesn't depend on any of those, and can run completely standalone. - - Install AppImageLauncher today for your distribution and enjoy using AppImages as easy as never before! - - -- https://github.com/TheAssassin/AppImageLauncher/blob/master/README.md - -AppImageLauncher doesn't provide any kind of "app store" software, but integrates into system-provided launchers' context menus. It provides tools for updating (based on :ref:`AppImageUpdate `) and removing AppImages. - -.. _AppImageLauncher: https://github.com/TheAssassin/AppImageLauncher - -**Download:** You can get AppImageLauncher-Lite as an AppImage and the full version as a deb from https://github.com/TheAssassin/AppImageLauncher/releases/continuous. - - -NX Software Center ------------------- - -A portable Software Center for portable applications thanks to AppImage. - - -**Download:** You can get NX Software Center as part of Nitrux OS from https://nxos.org/. There are currently no recent continuous standalone AppImage builds available. - -.. todo:: - Describe the rest of the third-party tools diff --git a/source/introduction/upstream.rst b/source/introduction/upstream.rst index 72802f3..1aa447f 100644 --- a/source/introduction/upstream.rst +++ b/source/introduction/upstream.rst @@ -1,14 +1,17 @@ +.. include:: ../substitutions.rst + +.. _upstream-packaging: + A word on upstream packaging ============================ -The AppImage ecosystem is built around the notion of "upstream packaging". With AppImage, typically the application author is who packages and distributes the application. This is different from the traditional Linux distribution model, where the application author and the application packager (also called the maintainer) are often different persons. +The AppImage ecosystem is built around the notion of "upstream packaging". With AppImage, typically the application author is who packages and distributes the application. This is different from the traditional Linux distribution model, where the application author and the application packager (also called the maintainer) are often different people. -AppimageKit is designed with “upstream packaging” in mind. This means that we want the original author of an application to be the person that packages it as an AppImage, distributes it to end users, and supports it. +AppImage and its reference implementation are designed with "upstream packaging" in mind. This means that we want the original author of an application to be the person that packages it as an AppImage, distributes it to end users, and supports it. -In this regard, an AppImage is very similar to an :code:`.exe` file on Windows or a :code:`.dmg` file on the Mac. These files are normally prepared by the original application authors rather than by third parties. This ensures that the software works exactly the way the original application author has envisioned it to work. It also means that the application author does not have to follow arbitrary rules set by Linux distributions. +In this regard, an AppImage is very similar to an ``.exe`` file on Windows or a ``.dmg`` file on macOS. These files are normally prepared by the original application authors rather than by third parties. |upstream_advantage| It also means that the application author does not have to follow arbitrary rules set by Linux distributions. .. note:: - Before you package an application as an AppImage, ask yourself whether you are either the application author or a member of the application team. If not, it is most likely better to ask the original author of the application or the application team to provide an official AppImage. @@ -20,32 +23,32 @@ In this regard, an AppImage is very similar to an :code:`.exe` file on Windows o Advantages ---------- -Upstream packaging has a lot of advantages: first and foremost, it allows the application author to control the entire user experience from how the user gets the application to how it works. It also allows the original author of an application to support the application since no unauthorised changes are made to it by third parties. For end-users, it is clear that the original application author is who is responsible for fixing bugs as there is no shared responsibility between the application author and the third party, e.g. a Linux distribution, that has distributed the application. +Upstream packaging has a lot of advantages: First and foremost, it allows the application author to control the entire user experience from how the user gets the application to how it works. It also allows the original author of an application to support the application since no unauthorised changes are made to it by third parties. For end-users, it is clear that the original application author is who is responsible for fixing bugs as there is no shared responsibility between the application author and the third party, e.g. a Linux distribution, that has distributed the application. Disadvantages ------------- -However, upstream packaging also has disadvantages: most prominently, there is no curator who assesses the quality and integrity of the application. Hence, the end user has to trust the application author when running an application that has been distributed directly by the original application author. +However, upstream packaging also has disadvantages: Most prominently, there is no curator who assesses the quality and integrity of the application. Hence, the end user has to trust the application author when running an application that has been distributed directly by the original application author. If upstream packaging is not possible ------------------------------------- -In some cases, the original application author or application team may not be interested in providing an official AppImage. In this case you have the following options: for open source projects, you can often make and send a pull request, and for closed source applications you can create a yml recipe that can be used to convert the existing Linux binaries into an AppImage using :ref:`pkg2appimage `. +In some cases, the original application author or application team may not be interested in providing an official AppImage. In this case you have the following options: For open source projects, you can often make and send a pull / merge request, and for closed source applications, you can use :ref:`appimage-creation-tools` to create a yml recipe that can be used to convert the existing Linux binaries into an AppImage. Open source projects -^^^^^^^^^^^^^^^^^^^^ +++++++++++++++++++++ For open source projects, you can often make and send a pull request (GitHub) or merge request (GitLab) that generates an AppImage as part of the project's build pipeline. Most open source projects will gladly accept such pull requests, especially if you indicate that you are willing to maintain the AppImage generation going forward. -Many open source projects already use continuous integration on systems such as Travis CI, GitLab CI, Jenkins, or the :ref:`Open Build Service `. If a project already uses one of those services, it is most beneficial to generate the AppImage on that service. +Many open source projects already use continuous integration on systems such as GitHub Actions, GitLab CI, Gitea CI, Jenkins, or the :ref:`Open Build Service `. If a project already uses one of those services, it is most beneficial to generate the AppImage on that service. Closed source applications -^^^^^^^^^^^^^^^^^^^^^^^^^^ +++++++++++++++++++++++++++ -For closed source applications you can create a yml recipe that can be used to convert the existing Linux binaries into an AppImage using :ref:`pkg2appimage `. +For closed source applications, you can use :ref:`appimage-creation-tools` to create a yml recipe that can be used to convert the existing Linux binaries into an AppImage. -Note that you may not be allowed to redistribute the AppImage of the application. In this case, you can distribute :code:`.yml` recipes that end users can use to produce their own AppImages of the application easily. This applies to applications such as Google Chrome, Spotify, Skype, and others. +Note that you may not be allowed to redistribute the AppImage of the application. In this case, you can distribute ``.yml`` recipes that end users can use to produce their own AppImages of the application easily. This applies to applications such as Google Chrome, Spotify, Skype, and others. diff --git a/source/packaging-guide/appimage-creation-tools/appimage-builder.rst b/source/packaging-guide/appimage-creation-tools/appimage-builder.rst new file mode 100644 index 0000000..85fa5f7 --- /dev/null +++ b/source/packaging-guide/appimage-creation-tools/appimage-builder.rst @@ -0,0 +1,22 @@ +.. include:: ../../substitutions.rst + +.. _appimage-builder: + +appimage-builder +================ + +`appimage-builder `__ is a tool that can be used by both application authors to package their projects as AppImages and other people to turn existing Debian packages into AppImages if none are officially distributed. + +It does this by using the system package manager to resolve the application dependencies (instead of relying on them being installed on the host system like most other tools do). + +It requires a manual creation of the AppDir folder structure and file placement (if make isn't used). For more information on how to use make accordingly, or manually create the necessary structure, see :ref:`creating-appdir-structure`. + +Using appimage-builder, you write a so-called *recipe* that is then used to create the AppImage or convert the package into an AppImage. As some (mostly proprietary) applications don't allow redistribution, you can distribute these recipes to allow other users to easily convert existing packages to AppImages. + +appimage-builder creates a complete bundle. This means that it includes all dependencies, even core system libraries like glibc. |increased_appimage_size|. On the other hand, this removes the limitation of requiring an *old system* (meaning the oldest supported LTS distribution version) to compile the binaries, see :ref:`compiling-on-old-system`. It should only be used if linuxdeploy can't be used, e.g. if the AppImage can't be built on the oldest supported LTS distribution version. + +The officially supported distributions for AppImages created with appimage-builder are Debian, Ubuntu and Arch. + +|appimage_preferred_source| + +For more information about appimage-builder and how to use it, please visit: https://appimage-builder.readthedocs.io. diff --git a/source/packaging-guide/appimage-creation-tools/electron-builder.rst b/source/packaging-guide/appimage-creation-tools/electron-builder.rst new file mode 100644 index 0000000..d721446 --- /dev/null +++ b/source/packaging-guide/appimage-creation-tools/electron-builder.rst @@ -0,0 +1,34 @@ +.. _electron-builder: + +electron-builder +================ + +`electron-builder `__ is a tool that can be used by application authors to easily package their `Electron `__ projects not only as AppImages but also as other application formats for Linux (e.g. Flatpak or Snap), macOS (e.g. DMG) and Windows (e.g. Installer or Portable). + +With electron-builder, making AppImages is as simple as defining ``AppImage`` as a target for Linux (which is the default in the latest version of electron-builder). This should yield usable results for most applications. + +Therefore, it's the recommended solution if your app is Electron based. Otherwise, this AppImage creation method is not applicable. + +More information can be found in the `documentation on AppImage `__ in the `electron-builder manual `__. + +There are also a lot of examples on GitHub that can be found using the `GitHub search `__. + + +.. _electron-builder-update-information: + +Embedding updating information +------------------------------ + +``electron-builder`` promotes its own updater scheme rather than the :ref:`AppImage updating system ` described in this documentation, in order to have the same mechanism on Linux as on Windows. Unfortunately this means that AppImages generated by ``electron-builder`` cannot be updated with the usual tools. + +However, it's possible to additionally include the usual update information into an AppImage created with ``electron-builder`` manually. Follow the instructions at :ref:`updating-using-appimagetool` to do this. + + +.. _electron-builder-signing: + +Signing the AppImage +-------------------- + +Sadly, ``electron-builder`` doesn't support the :ref:`AppImage signature system `. This means that AppImages generated by ``electron-builder`` aren't signed per default. + +However, it's possible to embed a signature into an AppImage created with ``electron-builder`` manually. Follow the instructions at :ref:`signing-using-appimagetool` to do this. diff --git a/source/packaging-guide/appimage-creation-tools/go-appimagetool.rst b/source/packaging-guide/appimage-creation-tools/go-appimagetool.rst new file mode 100644 index 0000000..bc2b304 --- /dev/null +++ b/source/packaging-guide/appimage-creation-tools/go-appimagetool.rst @@ -0,0 +1,93 @@ +.. include:: ../../substitutions.rst + +.. _go-appimagetool: + +go-appimagetool +=============== + +`go-appimagetool `__ (the appimagetool part of the go-appimage project) is a tool that can be used by application authors to package their projects as AppImages. + +It requires a manual creation of the AppDir folder structure and file placement (if make isn't used). For more information on how to use make accordingly, or manually create the necessary structure, see :ref:`creating-appdir-structure`. + +.. note:: + go-appimagetool is not using the :ref:`reference implementation ` (called appimagetool) to create AppImages; instead, it creates them itself. This means that it might choose different :ref:`implementation decisions ` (e.g. CLI options like ``--appimage-extract`` the resulting AppImage supports), resulting in AppImages that behave differently to the usual ones (created with the reference implementation). + + |alternative_implementation_decisions| + + See :ref:`this ` for more information on the implementations and their decisions. + +It allows for both including core system libraries like glibc and not including them. If the core system libraries aren't included, |build_on_old_version|. + +However, it is less mature than linuxdeploy and doesn't support some advanced options (like not deploying specific libraries or copyright files). + + +Downloading go-appimagetool +--------------------------- + +Start by downloading go-appimagetool. The recommended way to get it is to use the latest continuous AppImage build provided on its `GitHub release page `__. After downloading the AppImage, you have to make it executable as usual: + +.. code-block:: shell + + > chmod +x appimagetool-*-x86_64.AppImage + +After that, you can use go-appimagetool. + + +Usage +----- + +To use go-appimagetool, you need to already have an AppDir with the main executable and the desktop, icon, etc. files. go-appimagetool will only deploy the dependency of the executables and libraries into this AppDir and create an AppImage out of it. + +To bundle the dependencies with go-appimagetool, use the ``deploy`` command with the desktop file as parameter like this: + +.. code-block:: shell + + > ./appimagetool-*.AppImage deploy appdir/usr/share/applications/*.desktop + +You can use the ``-s`` command line argument to bundle everything, including core system libraries like glibc. Otherwise, core system libraries are not included. + +To then turn your complete AppDir into an AppImage, call go-appimagetool with the AppDir as parameter like this: + +.. code-block:: shell + + > ./appimagetool-*.AppImage Some.AppDir + +.. todo:: + Include documentation on appimagetool environment variables like VERSION + +For more information, see `the project's README file `__ + + +.. _go-appimagetool-update-information: + +Embedding update information +---------------------------- + +You can find the basic explanation on how the AppImage update system works, what update information is and how AppImages can be updated at :ref:`appimage-updates`. + +Sadly, as of December 2024, go-appimagetool doesn't yet support embedding updating information from a custom updating information string. Instead, it always embeds updating information dependent on the CI pipeline. See `this issue `__ for more information. + + +.. _go-appimagetool-signing: + +Signing the AppImage +-------------------- + +You can find the basic explanation on how the AppImage signatures works and how they can be validated at :ref:`signing-appimages`. If you already know that, this section explains on how to use go-appimagetool to sign the AppImage. + +When creating an AppImage from an AppDir, go-appimagetool always tries to sign the resulting AppImage. However, in order to be able to do that, go-appimagetool (`as of December 2024 `__) requires the public key to be stored in the root directory of the git repository as ``pubkey.asc``, the encrypted private key to be stored in the current working directory as ``privkey.asc.enc`` and the environment variables ``$super_secret_password`` to be set to the passphrase to encrypt the private key. This could look like the following: + +.. code-block:: shell + + # Export the public key to the current working directory + # This assumes we are in the root directory of the git repository + > gpg --export --armor > pubkey.asc + + # Export the encrypted private key to the current working directory + > gpg --export-secret-keys --armor > privkey.asc.enc + + # Set the environment variable to the key passphrase + > export super_secret_password="..." + + # Call go-appimagetool + > ./appimagetool-*.AppImage Some.AppDir diff --git a/source/packaging-guide/appimage-creation-tools/index.rst b/source/packaging-guide/appimage-creation-tools/index.rst new file mode 100644 index 0000000..ad5cacf --- /dev/null +++ b/source/packaging-guide/appimage-creation-tools/index.rst @@ -0,0 +1,123 @@ +.. include:: ../../substitutions.rst + +.. _appimage-creation-tools: + +AppImage creation tools +======================= + +There are different tools that help with creating AppDirs and the corresponding AppImages (an AppImage is like a container which stores the AppDir with the actual application and everything required for it to run). They can help in several ways: + +1. Some of them create the AppDir from scratch and don't require manual AppDir creation or file placement. +2. They bundle the application dependencies (shared libraries) into the existing AppDir. +3. They remove hardcoded paths in the executables and libraries. +4. They create an AppImage out of the AppDir (usually by invoking `appimagetool `__ (the :ref:`reference implementation `) underneath). + +Some tools require you to manually create the AppDir structure prior to invoking the tool. :ref:`creating-appdir-structure` explains the different ways to do this. + +Additionally, many applications require additional resources, e.g. asset files for drawing a GUI, which have to be included in the AppImage. In this case, a directory with (only) these required resources needs to be created and given to the AppImage creation tool, no matter which tool is used. + +This section gives an overview of the different tools and their advantages, disadvantages and differences. For each of them, there is a corresponding page, explaining how to use it. + +If you are unsure which one to use, linuxdeploy and go-appimagetool are usually the best options. + + +.. _creation-comparison-table: + +Comparison table +---------------- + +.. + NOTE: When changing the order of the rows, make sure that the rows are correctly formatted + See custom.css (the table rows are formatted depending on their index) + +.. list-table:: + :widths: 25 75 + :header-rows: 1 + :class: formatted-table + + * - AppImage creation method + - Description and notes + * - linuxdeploy + - | A tool that can be used by application authors to package their projects as AppImages. + | Creates the AppDir from scratch and doesn't require any existing AppDir structure or manual file placement. + | Doesn't include core system libraries like glibc. This results in a reduced AppImage size. + | Doesn't use the :ref:`new static runtime ` as of January 2025. + | More mature; supports additional options (e.g. not deploying specific libraries or copyright files) go-appimagetool doesn't support (yet). + | Repository link: https://github.com/linuxdeploy/linuxdeploy + | Packaging guide: :ref:`linuxdeploy` + * - go-appimagetool + - | A tool that can be used by application authors to package their projects as AppImages. + | Requires manual creation of the AppDir folder structure and file placement (if make isn't used). + | Allows for both including core system libraries like glibc and not including them. + | Does not use the :ref:`reference implementation ` (appimagetool) underneath, but creates the AppImages itself. + | Less mature; doesn't support some options linuxdeploy does. + | Repository link: https://github.com/probonopd/go-appimage + | Packaging guide: :ref:`go-appimagetool` + * - appimage-builder + - | A tool that can be used by both application authors to package their projects as AppImages and other people to turn existing Debian packages into AppImages if none are officially distributed. + | Requires manual creation of the AppDir folder structure and file placement (if make isn't used). + | Includes core system libraries like glibc. This results in an increased AppImage size. + | Should only be used if linuxdeploy can't be used (e.g. if the AppImage can't be built on the oldest supported LTS distribution version). + | Repository link: https://github.com/AppImageCrafters/appimage-builder + | Packaging guide: :ref:`appimage-builder` + * - electron-builder + - | A tool that can be used by application authors to easily package their Electron projects not only as AppImages but also as other application formats for Linux (e.g. Flatpak or Snap), macOS (e.g. DMG) and Windows (e.g. Installer or Portable). + | Creates the AppDir from scratch and doesn't require any existing AppDir structure or manual file placement. + | Recommended solution if your app is Electron based, **otherwise not applicable**. + | Repository link: https://github.com/electron-userland/electron-builder + | Packaging guide: :ref:`electron-builder` + * - pkg2appimage + - | A tool that can be used by people other than the application authors to convert officially distributed binary packages (archives, .deb packages and PPAs) into AppImages if none are officially distributed. + | Requires manual creation of the AppDir folder structure and file placement. + | Doesn't include core system libraries like glibc. This results in a reduced AppImage size. + | **Do not use pkg2appimage if you are the application author. pkg2appimage should only be used if there is no officially distributed AppImage.** Application authors should use one of the other creation methods. + | pkg2appimage has a major `security issue `__; therefore it's only recommended for personal use. + | Repository link: https://github.com/AppImageCommunity/pkg2appimage + | Packaging guide: :ref:`pkg2appimage` + * - Manual packaging + - | Manual packaging means manually creating the entire AppDir structure and copying all files to their correct places in the structure. + | While manually creating a directory structure and copying some files might be necessary depending on the used tool, manually packaging *everything* should only be used as a last resort if all other methods aren't applicable. + | Using one of the tools above like linuxdeploy or go-appimagetool is usually much more convenient. + | It is explained nevertheless, mainly to illustrate how things work under the hood. + | Packaging guide: :ref:`manually-fully-creating-appdir` + * - linuxdeployqt + - | Deprecated. Succeeded by linuxdeploy and go-appimagetool. + | **Do not use linuxdeployqt to create new AppImages.** + + +Packaging as application author vs converting existing packages +--------------------------------------------------------------- + +There are two ways to create AppImages: + +1. Packaging the AppImage as application author (also called packaging from source) +2. Converting existing packages + +Ideally, upstream application authors should package the application and provide officially distributed AppImages. This is called packaging from source. The term packaging from source is actually a bit misleading as it's not actually depending on the source code: The project is still compiled like usual and then the resulting binaries are packaged as AppImage. However, the term is used as this method requires all dependencies for the project to be installed on the host system (which usually only applies to the system the source code is also compiled on). This method of packaging can and should be automated by using a CI system. + +Converting existing packages, on the other hand, doesn't require the dependencies to be installed on your system. Instead, they are downloaded during the packaging process from distribution repositories. To convert an existing package (ideally a PPA or .deb file), you write a so-called *recipe* that is then used to convert the package into an AppImage. As some (mostly proprietary) applications don't allow redistribution, you can distribute these recipes to allow other users to easily convert existing packages to AppImages. + +|appimage_preferred_source| + + +.. _compiling-on-old-system: + +Compiling the application on an old system +------------------------------------------ + +If the AppImage won't include core libraries like glibc (see the :ref:`creation-comparison-table`), the AppImage usually has to be built on the oldest still-supported Linux distribution version that we can assume users to still use. |old_compile_version_reason| + +For more information about this, exceptions to this and alternatives if you can't build your application on the oldest still-supported Linux distribution, see :ref:`exclude-expected-libraries`. + +The so-called *excludelist* of all core libraries that aren't included by most AppImage creation tools is available `here `__. + + +.. toctree:: + linuxdeploy + go-appimagetool + appimage-builder + electron-builder + pkg2appimage + :caption: Contents: + :maxdepth: 1 + diff --git a/source/packaging-guide/appimage-creation-tools/linuxdeploy.rst b/source/packaging-guide/appimage-creation-tools/linuxdeploy.rst new file mode 100644 index 0000000..c70e410 --- /dev/null +++ b/source/packaging-guide/appimage-creation-tools/linuxdeploy.rst @@ -0,0 +1,253 @@ +.. include:: ../../substitutions.rst + +.. _linuxdeploy: + +linuxdeploy +=========== + +`linuxdeploy `__ is a tool that can be used by application authors to easily create an AppDir (and by extension an AppImage) from scratch and bundle the executable and other resources that are passed as command line arguments into the right locations, as well as packaging dependencies of resources in an existing AppDir and making it relocatable. However, it doesn't require any existing AppDir structure or manual file placement. + +.. warning:: + As of January 2025, linuxdeploy doesn't use the :ref:`new static runtime `. This means that all AppImages built with its native AppImage output plugin :ref:`require ` FUSE 2 to be installed on every target system. + +Its primary focus is on AppDirs, and it uses plugins to create other outputs such as AppImages. + +linuxdeploy doesn't include core system libraries like glibc. This results in a reduced AppImage size. AppImages that are created with linuxdeploy should run on *almost* all modern linux distributions. However, when using it, |build_on_old_version|. + +The following sections explain how to use linuxdeploy. + + +.. contents:: Contents + :local: + :depth: 1 + + +Downloading linuxdeploy +----------------------- + +Start by downloading linuxdeploy. The recommended way to get it is to use the latest continuous AppImage build provided on its `GitHub release page `__. After downloading the AppImage, you have to make it executable as usual: + +.. code-block:: shell + + > wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + > chmod +x linuxdeploy-x86_64.AppImage + +After that, you can use linuxdeploy. + + +Using linuxdeploy with command line arguments +--------------------------------------------- + +linuxdeploy uses command line arguments to bundle files, like executables, libraries or icons. It creates the AppDir from scratch and puts all these files in the right positions. The user doesn't need to know the internal AppDir structure and where to put specific files. +The following command line flags are most commonly used: + +``--executable``/``-e`` + Bundle a native binary executable. **This is used to bundle your main binary executable.** + + This is also used to bundle executables that may be used by other libraries, executables, etc. + + Set up everything so that other libraries, executables, etc. use this bundled executable instead of a system one (if applicable). + + .. warning:: + |linuxdeploy_bundle_appimages| + +``--library``/``-l`` + Bundle a shared library (``.so`` file) into the AppDir. + + Set up everything so that other libraries, executables, etc. use this bundled library instead of a system one (if applicable). + +``--desktop-file``/``-d`` + Bundle a desktop file. Desktop files contain metadata and are required for desktop integration; there must be at least one of them in the AppDir / AppImage. Please see :ref:`desktop-entry-files` for a guide on how they can be created and what they should contain. + +``--icon-file``/``-i`` + Bundle one or several icon files. Please see :ref:`icon-files` for a guide on which formats, resolutions, etc. are supported. + + linuxdeploy will automatically calculate the image resolution and the correct output path, which depends on file format and resolution. + +``--appstream-file`` + Bundle an AppStream metadata file into the AppDir. For more information on AppStream files, see :ref:`appstream`. + +``--appdir``/``-a`` + The path to the AppDir. If this path does not exist, the AppDir is created from scratch. + + This can be used to include additional resources many applications might need, e.g. asset files for drawing a GUI. In that case, you can create a directory containing (only) such specific files in specific positions and then use its path as ``--appdir`` parameter. linuxdeploy then creates the AppDir and bundles all other files like usual. + + You can also use this to pass an existing AppDir to linuxdeploy if you only want to bundle its dependencies (shared libraries) and make it relocatable but not create a new AppDir. + +``--plugin``/``-p`` + Uses an input plugin. Input plugins can be used to bundle additional resources, such as Qt plugins or translations. They must be additionally downloaded. + + For more information on plugins, see :ref:`linuxdeploy-plugin-system`. + +``--output``/``-o`` + .. cssclass:: bold-link + + Uses an output plugin. Output plugins can be used to output something different than the raw AppDir. **linuxdeploy always comes with the** `AppImage output plugin`_ **preinstalled.** You can use it with ``--output appimage``. Other output plugins have to be additionally downloaded. + + For more information on plugins, see :ref:`linuxdeploy-plugin-system`. + +This list is not exhaustive and only includes the most commonly used command line argument. To get a full overview of all arguments, use ``--help``. + +The following example illustrates how an existing binary can be bundled into an AppDir: + +.. code:: bash + + > ./linuxdeploy-x86_64.AppImage -e my_application -d my_application.desktop -i my_application.png -a AppDir --output appimage + + +.. _linuxdeploy-plugin-system: + +Plugin system +------------- + +linuxdeploy provides a flexible packaging system for both bundling additional resources that cannot be discovered automatically by linuxdeploy (i.e., plugins loaded during runtime using ``dlopen()``, icon themes, etc.), and to convert the AppDir into an output format such as AppImage. + +Plugins are automatically recognized by linuxdeploy. They are executable files (scripts, native binaries, etc.), which must be in one of the following locations: + + - in case the linuxdeploy AppImage is used: next to the AppImage + - next to the linuxdeploy binary + - in any of the directories in ``$PATH`` + +Therefore, when downloading additional plugins, just put them into one of these locations, and linuxdeploy can use them. Plugins should be kept with their original name; otherwise linuxdeploy might not recognise them! + +Plugins are standalone executable files. This means they must be made executable by the user before they can be used by linuxdeploy. On the other hand, this also allows for calling plugins manually. + +The plugin system works by calling external executables, hence the only communication linuxdeploy can perform with plugins is via CLI parameters (communication via the ``stdin``/``stdout`` pipes would be a lot more complex to implement for both linuxdeploy and the plugin). Therefore, to influence plugin behavior, plugins may implement environment variables that the user can set *before* calling linuxdeploy. Examples how this works are shown in the following sections. + +You can use the ``--list-plugins`` flag to see what plugins are visible to linuxdeploy. This can come in handy when debugging plugin related issues. It lists the name of the plugin (i.e., what linuxdeploy refers to them as), the full path and the API level they implement. + +.. warning:: + Some plugins might be bundled in the linuxdeploy AppImage already for convenience. They're likely out of date, but should be stable. In case there are any issues or you need to use a newer version, please download the latest version of the respective plugin, and put it next to the linuxdeploy AppImage. linuxdeploy prefers plugins next to the AppImage over bundled ones. + +.. note:: + More information on plugins can be found in the `plugin specification `__. + +.. note:: + A list of plugins can be found in the `Awesome linuxdeploy README `__. + + +Using input plugins ++++++++++++++++++++ + +Input plugins can simply be switched on using the ``--plugin`` flag. For example: + +.. code:: bash + + > ./linuxdeploy-x86_64.AppImage --appdir AppDir <...> --plugin qt + +This causes linuxdeploy to call a plugin called ``qt``, if available. + + +Using environment variables to change plugins' behavior +####################################################### + +As mentioned previously, some plugins implement additional optional or mandatory parameters in the form of environment variables. These environment variables must be set *before* calling linuxdeploy. + +For example: + +.. code:: bash + + # set the environment variable + > export FOOBAR_VAR=example + + # call linuxdeploy with the respective plugin enabled + > ./linuxdeploy-x86_64.AppImage --appdir AppDir <...> --plugin foobar + +Please refer to the plugins' documentation to find a list of supported environment variables. If you can't find any, there's probably none. + +.. todo:: + Document existing input plugins' environment variables + + +Creating output files ++++++++++++++++++++++ + +Similar to the input plugins, output plugins are enabled through a command line parameter. To avoid any possible confusion, a second parameter is used: ``--output``. + +Example: + +.. code:: bash + + > ./linuxdeploy-x86_64.AppImage <...> --output appimage + +Most users are interested in generating AppImages, therefore the AppImage plugin is bundled in the official linuxdeploy AppImage. + + +Using environment variables to change plugins' behavior +####################################################### + +Analogous to the input plugins, output plugins usually implement additional optional or mandatory parameters in the form of environment variables. These environment variables must be set *before* calling linuxdeploy. For example: + +.. code:: bash + + # Set environment variable to embed update information in an AppImage + > export LDAI_UPDATE_INFORMATION="zsync|https://server.domain/path/MyApplication-latest_x86-64.AppImage.zsync" + + # Call linuxdeploy with the AppImage plugin enabled + > ./linuxdeploy-x86_64.AppImage --appdir AppDir <...> --output appimage + + +linuxdeploy-plugin-appimage environment variables +************************************************* + +As most plugins, linuxdeploy-plugin-appimage provides some environment variables to enable additional functionality, such as: + +``LDAI_SIGN=1`` + Sign the AppImage. See :ref:`linuxdeploy-signing` for more information. + +``LDAI_UPDATE_INFORMATION="zsync|..."`` + Add update information to the AppImage and generate the corresponding ``.zsync`` file. See :ref:`linuxdeploy-update-information` for more information. + +.. seealso:: + More information on the environment variables can be found in the `README `__, including a complete (and up to date) list of supported environment variables. + +.. todo:: + Document environment variables of other existing output plugins + + +.. _linuxdeploy-update-information: + +Embedding update information +---------------------------- + +You can find the basic explanation on how the AppImage update system works, what update information is and how AppImages can be updated at :ref:`appimage-updates`. If you already know that, this section explains on how to use linuxdeploy to embed update information. + +If you use the linuxdeploy `AppImage output plugin`_ to generate an AppImage from the AppDir, you can set the environment variable ``$LDAI_UPDATE_INFORMATION`` to the update information string to embed the update information in the AppImage and generate the corresponding ``.zsync`` file. This could look like the following: + +.. code-block:: shell + + > export LDAI_UPDATE_INFORMATION="zsync|https://server.domain/path/Application-latest_x86-64.AppImage.zsync" + > ./linuxdeploy-x86_64.AppImage <...> --output appimage + + +.. _linuxdeploy-signing: + +Signing the AppImage +-------------------- + +You can find the basic explanation on how the AppImage signatures works and how they can be validated at :ref:`signing-appimages`. If you already know that, this section explains on how to use linuxdeploy to sign the AppImage. + +If you use the linuxdeploy `AppImage output plugin`_ to generate an AppImage from the AppDir, you can set the environment variable ``$LDAI_SIGN`` to 1 and the environment variable ``$LDAI_SIGN_KEY`` to the key id of the gpg key you want to sign the AppImage with to sign the AppImage. This could look like the following: + +.. code-block:: shell + + > export LDAI_SIGN=1 + > export LDAI_SIGN_KEY="1234567890ABCDEF1234567890ABCDEF12345678" + > ./linuxdeploy-x86_64.AppImage <...> --output appimage + + +.. _linuxdeploy-appstream: + +Embedding an AppStream file +--------------------------- + +To embed an AppStream file in your AppDir (and by extension your AppImage), you have to pass it to linuxdeploy via the ``appstream-file`` parameter. For more information on AppStream files, see :ref:`appstream`. + + +Iterative workflow +------------------ + +linuxdeploy supports an iterative workflow, i.e., you run it, and it will start to bundle resources. If there is a problem, it will show a detailed error message, and exit with an error code. You can then fix the issue, and call it again to try again. + + +.. _AppImage output plugin: https://github.com/linuxdeploy/linuxdeploy-plugin-appimage diff --git a/source/packaging-guide/appimage-creation-tools/pkg2appimage.rst b/source/packaging-guide/appimage-creation-tools/pkg2appimage.rst new file mode 100644 index 0000000..6856b1f --- /dev/null +++ b/source/packaging-guide/appimage-creation-tools/pkg2appimage.rst @@ -0,0 +1,416 @@ +.. include:: ../../substitutions.rst + +.. _pkg2appimage: + +pkg2appimage +============ + +`pkg2appimage `__ is a tool that can be used by people other than the application authors to convert officially distributed binary packages (archives, .deb packages and PPAs) into AppImages if none are officially distributed. It doesn't require dependencies to be installed on your system; instead, they are downloaded during the packaging process from distribution repositories. To convert an existing package, you write a `.yml description file `__ (called recipe) and run it with pkg2appimage. As some (mostly proprietary) applications don't allow redistribution, you can distribute these recipes to allow other users to easily convert existing packages to AppImages. + +pkg2appimage doesn't include core system libraries like glibc. This results in a reduced AppImage size. However, as the recipes use binary packages that have already been built, invoking a recipe doesn't require using an old system (see :ref:`compiling-on-old-system`). + +|appimage_preferred_source| + +.. cssclass:: bold-link + +**Do not use pkg2appimage if you are the application author. Application authors should use one of the other creation methods, see** :ref:`appimage-creation-tools`\ **.** + +pkg2appimage requires a manual creation of the AppDir folder structure and file placement inside the recipe, see :ref:`manually-creating-appdir-structure`. + +.. contents:: Contents + :local: + :depth: 1 + + +Using a recipe +-------------- + +To use a distributed recipe (a ``.yml`` description file), you first have to download pkg2appimage. You can get it as an AppImage from its from its `GitHub release page `__. + +To then build an AppImage from the recipe, simply run pkg2appimage with the file as parameter: ``./pkg2appimage-*.AppImage Receipe.yml``. + + +Introduction +------------ + +The so-called recipe files (which are ``.yml`` description files) tell pkg2appimage where to get the ingredients from and how to convert them to an AppImage (besides the general steps that pkg2appimage always performs). Study some `examples `__ to see how it works. + +.. warning:: + pkg2appimage suffers from a few notable issues: + + - It is likely to add lots of bloat to the final AppImage. As it simply extracts the contents of packages, there is no check whether any of these resources are actually used by the application or not. You are recommended to check final AppImages, and add ``rm`` commands to your recipes to remove unused data. + - pkg2appimage uses distribution packages downloaded using the package managers, however, the packages are not authenticated, as most security functionality has been deactivated. This is a major security issue. pkg2appimage is therefore recommended for personal use only. Upstream authors should consider :ref:`other packaging methods `. + + .. seealso:: + See `this GitHub issue `__ for more information on the security issue. + + +Recipe files +------------ + +To convert a binary package into an AppImage, you have to write a so-called recipe, a specific ``.yml`` description file. This format describes how to build an AppImage by re-using pre-built binaries, e.g. from Debian packages, to save time for both creating and building an AppImage. + +``.yml`` is an extension used for *YAML*, a format to describe data. Similarly to JSON, it combines associative lists (key-value pairs, also known as maps or dicts), lists and scalar values (like strings). + +The format of these ``.yml`` files is not part of the AppImage :ref:`specification ` (which describes the AppImage container format) or :ref:`reference implementation ` (which implements a conforming runtime and a tool to create conforming AppImages); it is just defined and used by the pkg2appimage project. + +This section provides an introduction to the recipe structure and a few examples describing how to use all the advanced features. + + +General anatomy of ``.yml`` files +--------------------------------- + +The general format of ``.yml`` files is as follows: + +.. code-block:: yaml + + app: (name of the application) + (optional flags) + + ingredients: + (instructions that describe from where to get + the binary ingredients used for the AppImage) + + script: + (instructions on how to convert these ingredients to an AppImage) + + +As you can see, the ``.yml`` file consists of three sections: + +1. The **overall section** (containing the name of the application and optional flags) +2. The **ingredients section** (describing from where to get the binary ingredients used for the AppImage) +3. The **script section** (describing how to convert these ingredients to an AppImage) + +Note that the sections may contain sub-sections. For example, the ingredients section can also have a script section containing instructions on how to determine the most recent version of the ingredients and how to download them. + + +Overall section ++++++++++++++++ + +``app`` key +########### + +Mandatory. Contains the name of the application. If the ``.yml`` file uses ingredients from packages (e.g., ``.deb``), then the name must match the package name of the main executable. + + +Keys that enable ability to relocate +#################################### + +Optional. Either ``binpatch: true`` or ``union: true``. These keys enable workarounds that make it possible to run applications from different, changing places in the file system (i.e., make them relocateable) that are not made for this. For example, some applications contain hardcoded paths to a compile-time ``$PREFIX`` such as ``/usr``. This is generally discouraged, and application authors are asked to use paths relative to the main executable instead. Libraries like *binreloc* exist to make this easier. Since many applications are not relocateable yet, there are workarounds which can be used by one of these keys: + +* ``binpatch: true`` indicates that binaries in the AppImage should be patched to replace the string ``/usr`` by the string ``././``, an ``AppRun`` file should be put inside the AppImage that does a ``chdir()`` to the ``usr/`` directory of inside AppDir before executing the payload application. The net effect is this that applications can find their resources in the ``usr/`` directory inside the AppImage as long as they do not internally use ``chdir()`` operations themselves. +* ``union: true`` indicates that an ``AppRun`` file should be put inside the AppImage that tries to create the impression of a union file system, effectively creating the impression to the payload application that the contents of the AppImage are overlayed over ``/``. This can be achieved, e.g., using ``LD_PRELOAD`` and a library that redirects file system calls. This works as long as the payload application is a dynamically linked binary. + + +Ingredients section ++++++++++++++++++++ + +Describes how to acquire the binary ingredients that go into the AppImage. Binary ingredients can be archives like ``.zip`` files, packages like ``.deb`` files or APT repositories like Debian package archives or PPAs. + +.. note:: + In the future, source ingredients could also be included in the ``.yml`` file definition. Source ingredients could include tarballs and Git repositories. It would probably be advantageous if we could share the definition with other formats like snapcraft's ``.yaml`` files. Proposals for this are welcome. + + +``.yml`` files are supposed not to hardcode version numbers, but determine the latest version at runtime. If the ``.yml`` files describes the released version, it should determine the latest released version at runtime. If the ``.yml`` files describes the development version, it might reference the latest nightly or continuous build instead. + + +Using ingredients from a binary archive +####################################### + +The following example ingredients section describes how to get the latest version of a binary archive: + +.. code-block:: yaml + + ingredients: + script: + - DLD=$(wget -q "https://api.github.com/repos/atom/atom/releases/latest" -O - | grep -E "https.*atom-amd64.tar.gz" | cut -d'"' -f4) + - wget -c $DLD + - tar zxvf atom*tar.gz + + +The ``script`` section inside the ``ingredients`` section determines its URL, downloads and extracts the binary archive. + + +Using ingredients from a debian repository +########################################## + +The following example ingredients section describes how to get the latest version of a package from a Debian archive: + +.. code-block:: yaml + + ingredients: + dist: xenial + sources: + - deb http://archive.ubuntu.com/ubuntu/ xenial main universe + - deb http://download.opensuse.org/repositories/isv:/KDAB/xUbuntu_16.04/ / + + +The ``dist`` section inside the ``ingredients`` section defines which Debian distribution should be used as a base. The ``sources`` section inside the ``ingredients`` section describes the repositories from which the package should be pulled. The entries are in the same format as lines in a debian ``sources.list`` file. Note that the ``http://download.opensuse.org/repositories/isv:/KDAB/xUbuntu_16.04`` repository needs the ``http://archive.ubuntu.com/ubuntu/`` repository so that the dependencies can be resolved. + +.. note:: + In the future, other types of packages like ``.rpm`` could also be included in the ``.yml`` file definition. Proposals for this are welcome if the proposer also implements support for this in the `pkg2appimage script`_. + + +Using ingredients from an Ubuntu PPA +#################################### + +This is a special case of a Debian repository. PPAs can be uniquely identified with the pattern ``owner/name`` and can, for brevity, be specified like this: + +.. code-block:: yaml + + ingredients: + dist: xenial + sources: + - deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe + ppas: + - geany-dev/ppa + + +The ``ppas`` section inside the ``ingredients`` section lets you specify one or more Ubuntu PPAs. This is equivalent to, but more elegant than, adding the corresponding ``sources.list`` entries to the ``sources`` section inside the ``ingredients`` section. + +.. note:: + In the future, similar shortcuts for other types of personal repositories, such as projects on openSUSE build service, could also be included in the ``.yml`` file definition. Proposals for this are welcome if the proposer also implements support for this in the `pkg2appimage script`_. + + +Using local deb files +##################### + +This allows the use of local deb files (rather than downloading the deb ingredients) + +.. code-block:: yaml + + ingredients: + dist: xenial + sources: + - deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe + debs: + - /home/area42/kdenlive.deb + - /home/area42/kdenlive/* + + +As you can see, for a single file, just use + +.. code-block:: yaml + + - /path/to/file.deb + + +And for all files in a directory (like local repository). Note that the end of the path ends with ``/*``: + +.. code-block:: yaml + + - /path/to/local/repo/* + + +.. note:: + This is for personal use only. If you use it, your recipe will NOT work on another computer if the debs files are not in the specified directory. + + +Excluding certain packages +########################## + +Some packages declare dependencies that are not necessarily required to run the software. The ``.yml`` format allow overriding these by pretending that the packages are installed already. To exclude these dependencies (and any dependencies they would otherwise pull in), the packages have to be added to the ``exclude`` key in the ``ingredients`` section: + +.. code-block:: yaml + + ingredients: + dist: xenial + packages: + - multisystem + - gksu + sources: + - deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe + - deb http://liveusb.info/multisystem/depot all main + exclude: + - qemu + - qemu-kvm + - cryptsetup + - libwebkitgtk-3.0-0 + - dmsetup + + +In this example, excluding ``qemu`` means that the qemu package and all of its dependencies that it would normally pull into the AppImage will be excluded from the AppImage (unless something else in the AppImage pulls in some of those depdencies already). + + +Pretending certain versions of dependencies being installed +########################################################### + +The dependency information in some packages may result in the package manager to refuse the application to be installed if some **exact** versions of dependencies are not present in the system. In this case, it may be necessary pretend the **exact** version of a dependency to be installed on the target system by using the ``pretend`` key in the ``ingredients`` section: + +.. code-block:: yaml + + ingredients: + dist: xenial + sources: + - deb http://archive.ubuntu.com/ubuntu/ xenial main universe + ppas: + - otto-kesselgulasch/gimp-edge + pretend: + - libcups2 1.7.2-0ubuntu1 + + +The assumption here is that every target system has at least the pretended version available, and that newer versions of the pretended package are able to run the application just as well as the pretended version itself. *(If this is not the case, then the pretended package has broken downward compatibility and should be fixed.)* + + +Arbitrary scripts in the ingredients section +############################################ + +You may add arbitrary shell commands to the ``script`` section inside the ``ingredients`` section in order to facilitate the retrieval of the binary ingredients. This allows building AppImages for complex situations as illustrated in the following example: + +.. code-block:: yaml + + ingredients: + script: + - URL=$(wget -q https://www.fosshub.com/JabRef.html -O - | grep jar | cut -d '"' -f 10) + - wget -c "$URL" + - wget -c --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u66-b17/jre-8u66-linux-x64.tar.gz + + +This downloads the payload application, JabRef, and the required JRE which requires to set a special cookie header. + +The script could also be used to fetch pre-built Debian packages from a GitHub release page, or to override the version of a package. + +Use ``post_script`` instead of ``script`` if you need this to run *after* the other ingredient processing has taken place. + + +Script section +++++++++++++++ + +The ``script`` section may contain arbitrary shell commands that are required to translate the binary ingredients to an ``AppDir`` suitable for generating an AppImage. + + +The script section needs to copy ingredients into place +####################################################### + +If ``.deb`` packages, Debian repositories or PPAs have been specified in the ``ingredients`` section, then their dependencies are resolved automatically (taking a blacklist of packages that are assumed to be present on all target systems in a recent enough version into account, such as glibc) and the packages are extracted into an AppDir. The shell commands contained in the ``script`` section are executed inside the root directory of this AppDir. However, some packages place things in non-standard locations, i.e. the main executable is outside of ``usr/bin``. In these cases, the commands contained in the ``script`` section should normalize the file system structure. Sometimes it is also necessary to edit further files to reflect the changed file location. The following example illustrates this: + +.. code-block:: yaml + + ingredients: + dist: xenial + sources: + - deb http://archive.ubuntu.com/ubuntu/ xenial main universe + + script: + - DLD=$(wget -q "https://github.com/feross/webtorrent-desktop/releases/" -O - | grep _amd64.deb | head -n 1 | cut -d '"' -f 2) + - wget -c "https://github.com/$DLD" + + script: + - mv opt/webtorrent-desktop/* usr/bin/ + - sed -i -e 's|/opt/webtorrent-desktop/||g' webtorrent-desktop.desktop + + +In the ``ingredients`` section, a ``.deb`` package is downloaded. Then, in the ``script`` section, the main executable is moved to its standard location in the AppDir. Finally, the ``.desktop`` file is updated to reflect this. + +If other types of binary ingredients have been specified, then the shell commands contained in the ``script`` section need to retrieve these by copying them into place. Note that since the commands contained in the ``script`` section are executed inside the root directory of the AppDir, the ingredients downloaded in the `ingredients` sections are one directory level above, i.e., in ``../``. The following example illustrates this: + +.. code-block:: yaml + + ingredients: + script: + - wget -c "https://telegram.org/dl/desktop/linux" --trust-server-names + - tar xf tsetup.*.tar.xz + + script: + - cp ../Telegram/Telegram ./usr/bin/telegram-desktop + + +In the ``ingredients`` section, an archive is downloaded and unpacked. Then, in the ``script`` section, the main executable is copied into place inside the AppDir. + + +The script section needs to copy icon and `.desktop` file in place +################################################################## + +Since an AppImage may contain more than one executable binary (e.g. helper binaries launched by the main executable) and also may contain multiple ``.desktop`` files, a clear entry point into the AppImage is required. For this reason, there is the convention that there should be exactly one ``$ID.desktop`` file and corresponding icon file in the top-level directory of the AppDir. + +The script running the ``.yml`` file tries to do this automatically, which works if the name of the application specified in the ``app:`` key matches the name of the ``$ID.desktop`` file and the corresponding icon file. For example, if ``app: myapp` is set, and there is ``usr/bin/myapp``, ``usr/share/applications/myapp.desktop``, and ``usr/share/icons/*/myapp.png``, then the ``myapp.desktop`` and ``myapp.png`` files are automatically copied into the top-level directory of the AppDir. Unfortunately, many packages are in their naming. In that case, the shell commands contained in the ``script`` section must copy exactly one ``$ID.desktop`` file and the corresponding icon file into the top-level directory of the AppDir. The following example illustrates this: + +.. code-block:: yaml + + script: + - tar xf ../fritzing* -C usr/bin/ --strip 1 + - mv usr/bin/fritzing.desktop . + + +Unfortunately, many applications don't include a ``$ID.desktop`` file. If it is missing, the shell commands contained in the ``script`` section need to create it. The following (simplified) example illustrates this: + +.. code-block:: yaml + + script: + - # Workaround for: + - # https://bugzilla.mozilla.org/show_bug.cgi?id=296568 + - cat > firefox.desktop < usr/share/applications/mu.codewith.editor.desktop <<\EOF + - [Desktop Entry] + - Type=Application + - Name=Mu + - Comment=A Python editor for beginner programmers + - Icon=mu.codewith.editor + - Exec=python3 bin/mu-editor %F + - Terminal=false + - Categories=Application;Development; + - Keywords=Python;Editor;microbit;micro:bit; + - StartupWMClass=mu + - MimeType=text/x-python3;text/x-python3; + - EOF + - cp usr/share/applications/mu.codewith.editor.desktop . + - usr/bin/pip3 freeze | grep "mu-editor" | cut -d "=" -f 3 >> ../VERSION + + +Source: + https://github.com/AppImageCommunity/pkg2appimage/blob/9249a99e653272416c8ee8f42cecdde12573ba3e/recipes/Mu.yml + + +.. _pkg2appimage script: https://github.com/AppImageCommunity/pkg2appimage/blob/master/pkg2appimage diff --git a/source/packaging-guide/appstream-generator.html b/source/packaging-guide/appstream-generator.html new file mode 100644 index 0000000..18b03c5 --- /dev/null +++ b/source/packaging-guide/appstream-generator.html @@ -0,0 +1,890 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Application name + ? + The actual application name (capitalized properly). + : + + +
+ Application ID + ? + + The application ID must be a unique ID for the application and follow the + reverse DNS scheme. + + : + + +
+ Desktop file name + ? + The name of the desktop file without the file extension. + : + + +
+ Metadata license + ? + + The licence of this metadata (e.g. description). This is required as software catalogs need it + to use the metadata. + + : + + +
+ Project license + ? + The licence of the actual packaged application. + : + + +
+ Summary + ? + + A short summary of what the application is about (a single sentence without trailing dot). + This should equal the Comment field of the .desktop file. + + : + + +
+ Description + ? + + A longer description explaining what the application actually does and + its features (full sentences). + + : + + +
+ Homepage + ? + + The full URL of the application homepage (if none exists, the repository website). + Leave empty to omit this tag. + + : + + +
+ Screenshots + ? + + The full URL of all application screenshots. The screenshots should be separated by line breaks. + The first screenshot is taken as the main one. Leave empty to omit this tag. + + : + + +
+ +

+ This generates a rudimentary AppStream file with the most important tags. + However, there are more tags you should include for real-world applications, such as developer information, + application categories and supported MIME types. Please see the the + + AppStream documentation + for more information. +

+ + + + + + +
diff --git a/source/packaging-guide/appstream.rst b/source/packaging-guide/appstream.rst new file mode 100644 index 0000000..bf82718 --- /dev/null +++ b/source/packaging-guide/appstream.rst @@ -0,0 +1,51 @@ +.. _appstream: + +AppStream metadata +================== + +AppImages can optionally embed an AppStream file. AppStream is a cross-distribution standard to provide metadata for software in the Linux ecosystem. It is a convenient way to get information about (uninstalled) software and one of the building blocks for software centers. + + +.. contents:: Contents + :local: + :depth: 1 + + +Why should I include an AppStream file in my AppImage? +------------------------------------------------------ + +While the :ref:`desktop entry file ` provides some very rudimentary metadata (like the application name or icon), it lacks more specific metadata about the project like a description, a licence or screenshots. This all can be included in the optional AppStream file that is bundled inside your AppImage. + +While some desktop environments and file managers use this information, e.g. to display the description, it is especially important for app stores, AppImage catalogs and software centers. With an AppStream file, they all can get the metadata necessary to display an application (like a description, URLs and images) out of an AppImage itself without having to rely on manual input. + +This also allows your AppImage to be published in different app stores / catalogs with the same consistent descriptions, images, etc., without manual work. + +AppStream is a format that exists independently of AppImage and can be used in conjunction with other packaging formats as well. Many open source applications already come with AppStream files by default. + +.. seealso:: + More information on AppStream can be found in its `official documentation `__. + + +Generating an AppStream file +---------------------------- + +An easy way to generate an AppStream file is to use our generator: + +.. raw:: html + :file: appstream-generator.html + + +Validating an AppStream file +---------------------------- + +It is generally a good idea to check AppStream files for errors using the `appstreamcli `__ (or ``appstream-util``) CLI tools. ``apppimagetool`` will automatically attempt to validate the AppStream file if one of these are available on the ``$PATH``. + + +Embedding an AppStream file +--------------------------- + +If your :ref:`AppImage creation tool ` automatically creates the AppDir from CLI arguments, look at the guide for the respective tool: + +* To see how to embed an AppStream file with :ref:`linuxdeploy`, see :ref:`this ` section of the linuxdeploy guide. + +If your AppImage creation tool requires you to manually create an AppDir structure, you have to place the AppStream file under ``AppDir/usr/share/metainfo/myapp.metainfo.xml`` (preferred) or ``AppDir/usr/share/metainfo/myapp.appdata.xml``. After that, you can just generate the AppImage from the AppDir like usual. diff --git a/source/packaging-guide/converting-binary-packages/index.rst b/source/packaging-guide/converting-binary-packages/index.rst deleted file mode 100644 index cb7d3e4..0000000 --- a/source/packaging-guide/converting-binary-packages/index.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _ref-convert-existing-binary-packages: - -Converting binary packages -========================== - -In some cases, it is possible to convert existing binary packages to AppImages. This section introduces tools for this purpose. - -.. toctree:: - pkg2appimage - appimage-builder - :caption: Contents: - :maxdepth: 2 diff --git a/source/packaging-guide/converting-binary-packages/pkg2appimage.rst b/source/packaging-guide/converting-binary-packages/pkg2appimage.rst deleted file mode 100644 index 90675dd..0000000 --- a/source/packaging-guide/converting-binary-packages/pkg2appimage.rst +++ /dev/null @@ -1,417 +0,0 @@ -.. _ref-pkg2appimage: - -pkg2appimage -============ - -If you already have existing binaries (either in archive or :code:`.deb` format or a ppa) then the recommended way to convert these to an AppImage is to write a `.yml description file `__ and run it with `pkg2appimage`_. - - -.. contents:: Contents - :local: - :depth: 1 - - -Introduction ------------- - - -To build an AppImage from a :code:`.yml` description file, simply run: - -.. code-block:: shell - - bash -ex ./pkg2appimage recipes/XXX.yml - - -:code:`.yml` description files tell pkg2appimage where to get the ingredients from, and how to convert them to an AppImage (besides the general steps already included in pkg2appimage). Study some `examples `__ to see how it works. - -.. _pkg2appimage: https://github.com/AppImage/pkg2appimage/blob/master/pkg2appimage - -.. warning:: - pkg2appimage suffers from a few notable issues: - - - It is likely to add lots of bloat to the final AppImage. As it simply extracts the contents of packages, there is no check whether any of these resources are actually used by the application or not. You are recommended to check final AppImages, and add ``rm`` commands to your recipes to remove unused data. - - pkg2appimage uses distribution packages downloaded using the package managers, however, the packages are not authenticated, as most security functionality has been deactivated. This is a major security issue. pkg2appimage is therefore recommended for personal use only. Upstream authors should consider :ref:`packaging from source `. - - .. seealso:: - See `this GitHub issue `__ for more information on the security issue. - - -``.yml`` files --------------- - -The easiest way to build an AppImage is to write a :code:`.yml` file. We developed a rather simple format that allows developers to write a :code:`app.yml` file that describes how to build an AppImage for :code:`app`, being able to reuse pre-built binaries, e.g. from Debian packages, both to save time for creating and building an AppImage. - -This document provides an introduction to the :code:`.yml` files' purpose, their structure and a few examples describing how to use all the advanced features. - - -Purpose of ``.yml`` files -------------------------- - -:code:`.yml` is the file extension commonly used for *YAML* (*Yet Another Markup Language*, nowadays also serves as an abbreviation for *YAML Ain’t Markup Language*). - -YAML's approach to describing data is to combine associative lists (known as :code:`dict` in Python or :code:`object literal` in JavaScript, for example), lists (arrays) and scalar values. This results in an easy to parse and also easy to read format. - -The :code:`.yml` files are used by `pkg2appimage`_ which is used in the *AppImages* project to convert binary *ingredients* into AppImages for demonstration purposes. Their primary objective is to make it very simple to convert pre-existing binaries into the AppImage format. If you can build your software from source, you may generate AppImages directly as part of your build workflow; in this case you may not need a :code:`.yml` file (but a Travis CI :code:`.travis.yml` and/or a :code:`Makefile`, etc.). - -The :code:`.yml` file format is not part of the AppImage standard, which just describes the AppImage container format and is agnostic as to how the payload inside an AppImage gets generated. Neither it is part of AppImageKit, because AppImageKit is only concerned with taking a pre-existing *AppDir* and converting that into an AppImage. Such an AppDir is created from the instructions stored in the :code:`.yml` files, and converted to an AppImage using *AppImageKit*. - - -General anatomy of ``.yml`` files ---------------------------------- - -The general format of :code:`.yml` files is as follows: - -.. code-block:: yaml - - app: (name of the application) - (optional flags) - - ingredients: - (instructions that describe from where to get - the binary ingredients used for the AppImage) - - script: - (instructions on how to convert these ingredients to an AppImage) - - -As you can see, the :code:`.yml` file consists of three sections: - -1. The **overall section** (containing the name of the application and optional flags) -2. The **ingredients section** (describing from where to get the binary ingredients used for the AppImage) -3. The **script section** (describing how to convert these ingredients to an AppImage) - -Note that the sections may contain sub-sections. For example, the ingredients section can also have a script section containing instructions on how to determine the most recent version of the ingredients and how to download them. - - -Overall section -^^^^^^^^^^^^^^^ - -``app`` key -########### - -Mandatory. Contains the name of the application. If the :code:`.yml` file uses ingredients from packages (e.g., :code:`.deb`), then the name must match the package name of the main executable. - - -Keys that enable ability to relocate -#################################### - -Optional. Either :code:`binpatch: true` or :code:`union: true`. These keys enable workarounds that make it possible to run applications from different, changing places in the file system (i.e., make them relocateable) that are not made for this. For example, some applications contain hardcoded paths to a compile-time :code:`$PREFIX` such as :code:`/usr`. This is generally discouraged, and application authors are asked to use paths relative to the main executable instead. Libraries like *binreloc* exist to make this easier. Since many applications are not relocateable yet, there are workarounds which can be used by one of these keys: - -* :code:`binpatch: true` indicates that binaries in the AppImage should be patched to replace the string :code:`/usr` by the string :code:`././`, an :code:`AppRun` file should be put inside the AppImage that does a :code:`chdir()` to the :code:`usr/` directory of inside AppDir before executing the payload application. The net effect is this that applications can find their resources in the :code:`usr/` directory inside the AppImage as long as they do not internally use :code:`chdir()` operations themselves. -* :code:`union: true` indicates that an :code:`AppRun` file should be put inside the AppImage that tries to create the impression of a union file system, effectively creating the impression to the payload application that the contents of the AppImage are overlayed over :code:`/`. This can be achieved, e.g., using :code:`LD_PRELOAD` and a library that redirects file system calls. This works as long as the payload application is a dynamically linked binary. - - -Ingredients section -^^^^^^^^^^^^^^^^^^^ - -Describes how to acquire the binary ingredients that go into the AppImage. Binary ingredients can be archives like :code:`.zip` files, packages like :code:`.deb` files or APT repositories like Debian package archives or PPAs. - -.. note:: - - In the future, source ingredients could also be included in the :code:`.yml` file definition. Source ingredients could include tarballs and Git repositories. It would probably be advantageous if we could share the definition with other formats like snapcraft's :code:`.yaml` files. Proposals for this are welcome. - - -:code:`.yml` files are supposed not to hardcode version numbers, but determine the latest version at runtime. If the :code:`.yml` files describes the released version, it should determine the latest released version at runtime. If the :code:`.yml` files describes the development version, it might reference the latest nightly or continuous build instead. - - -Using ingredients from a binary archive -####################################### - -The following example ingredients section describes how to get the latest version of a binary archive: - -.. code-block:: yaml - - ingredients: - script: - - DLD=$(wget -q "https://api.github.com/repos/atom/atom/releases/latest" -O - | grep -E "https.*atom-amd64.tar.gz" | cut -d'"' -f4) - - wget -c $DLD - - tar zxvf atom*tar.gz - - -The :code:`script` section inside the :code:`ingredients` section determines its URL, downloads and extracts the binary archive. - - -Using ingredients from a debian repository -########################################## - -The following example ingredients section describes how to get the latest version of a package from a Debian archive: - -.. code-block:: yaml - - ingredients: - dist: xenial - sources: - - deb http://archive.ubuntu.com/ubuntu/ xenial main universe - - deb http://download.opensuse.org/repositories/isv:/KDAB/xUbuntu_16.04/ / - - -The :code:`dist` section inside the :code:`ingredients` section defines which Debian distribution should be used as a base. The :code:`sources` section inside the :code:`ingredients` section describes the repositories from which the package should be pulled. The entries are in the same format as lines in a debian :code:`sources.list` file. Note that the :code:`http://download.opensuse.org/repositories/isv:/KDAB/xUbuntu_16.04` repository needs the :code:`http://archive.ubuntu.com/ubuntu/` repository so that the dependencies can be resolved. - -.. note:: - - In the future, other types of packages like :code:`.rpm` could also be included in the :code:`.yml` file definition. Proposals for this are welcome if the proposer also implements support for this in the `pkg2appimage`_ script. - - -Using ingredients from an Ubuntu PPA -#################################### - -This is a special case of a Debian repository. PPAs can be uniquely identified with the pattern :code:`owner/name` and can, for brevity, be specified like this: - -.. code-block:: yaml - - ingredients: - dist: xenial - sources: - - deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe - ppas: - - geany-dev/ppa - - -The :code:`ppas` section inside the :code:`ingredients` section lets you specify one or more Ubuntu PPAs. This is equivalent to, but more elegant than, adding the corresponding :code:`sources.list` entries to the :code:`sources` section inside the :code:`ingredients` section. - -.. note:: - - In the future, similar shortcuts for other types of personal repositories, such as projects on openSUSE build service, could also be included in the :code:`.yml` file definition. Proposals for this are welcome if the proposer also implements support for this in the `pkg2appimage`_ script. - - -Using local deb files -##################### - -This allows the use of local deb files (rather than downloading the deb ingredients) - -.. code-block:: yaml - - ingredients: - dist: xenial - sources: - - deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe - debs: - - /home/area42/kdenlive.deb - - /home/area42/kdenlive/* - - -As you can see, for a single file, just use - -.. code-block:: yaml - - - /path/to/file.deb - - -And for all files in a directory (like local repository). Note that the end of the path ends with :code:`/*`: - -.. code-block:: yaml - - - /path/to/local/repo/* - - -.. note:: - - this is for personal use, if you use your recipe it will NOT work on another computer if the debs files are not in the specified directory - - -Excluding certain packages -########################## - -Some packages declare dependencies that are not necessarily required to run the software. The :code:`.yml` format allow overriding these by pretending that the packages are installed already. To exclude these dependencies (and any dependencies they would otherwise pull in), the packages have to be added to the :code:`exclude` key in the :code:`ingredients` section: - -.. code-block:: yaml - - ingredients: - dist: xenial - packages: - - multisystem - - gksu - sources: - - deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe - - deb http://liveusb.info/multisystem/depot all main - exclude: - - qemu - - qemu-kvm - - cryptsetup - - libwebkitgtk-3.0-0 - - dmsetup - - -In this example, excluding :code:`qemu` means that the qemu package and all of its dependencies that it would normally pull into the AppImage will be excluded from the AppImage (unless something else in the AppImage pulls in some of those depdencies already). - - -Pretending certain versions of dependencies being installed -########################################################### - -The dependency information in some packages may result in the package manager to refuse the application to be installed if some **exact** versions of dependencies are not present in the system. In this case, it may be necessary pretend the **exact** version of a dependency to be installed on the target system by using the :code:`pretend` key in the :code:`ingredients` section: - -.. code-block:: yaml - - ingredients: - dist: xenial - sources: - - deb http://archive.ubuntu.com/ubuntu/ xenial main universe - ppas: - - otto-kesselgulasch/gimp-edge - pretend: - - libcups2 1.7.2-0ubuntu1 - - -The assumption here is that every target system has at least the pretended version available, and that newer versions of the pretended package are able to run the application just as well as the pretended version itself *(if this is not the case, then the pretended package has broken downward compatibility and should be fixed)*. - - -Arbitrary scripts in the ingredients section -############################################ - -You may add arbitrary shell commands to the :code:`script` section inside the :code:`ingredients` section in order to facilitate the retrieval of the binary ingredients. This allows building AppImages for complex situations as illustrated in the following example: - -.. code-block:: yaml - - ingredients: - script: - - URL=$(wget -q https://www.fosshub.com/JabRef.html -O - | grep jar | cut -d '"' -f 10) - - wget -c "$URL" - - wget -c --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u66-b17/jre-8u66-linux-x64.tar.gz - - -This downloads the payload application, JabRef, and the required JRE which requires to set a special cookie header. - -The script could also be used to fetch pre-built Debian packages from a GitHub release page, or to override the version of a package. - -Use :code:`post_script` instead of :code:`script` if you need this to run *after* the other ingredient processing has taken place. - - -Script section -^^^^^^^^^^^^^^ - -The :code:`script` section may contain arbitrary shell commands that are required to translate the binary ingredients to an :code:`AppDir` suitable for generating an AppImage. - - -The script section needs to copy ingredients into place -####################################################### - -If :code:`.deb` packages, Debian repositories or PPAs have been specified in the :code:`ingredients` section, then their dependencies are resolved automatically (taking a blacklist of packages that are assumed to be present on all target systems in a recent enough version into account, such as glibc) and the packages are extracted into an AppDir. The shell commands contained in the :code:`script` section are executed inside the root directory of this AppDir. However, some packages place things in non-standard locations, i.e. the main executable is outside of :code:`usr/bin`. In these cases, the commands contained in the :code:`script` section should normalize the file system structure. Sometimes it is also necessary to edit further files to reflect the changed file location. The following example illustrates this: - -.. code-block:: yaml - - ingredients: - dist: xenial - sources: - - deb http://archive.ubuntu.com/ubuntu/ xenial main universe - - script: - - DLD=$(wget -q "https://github.com/feross/webtorrent-desktop/releases/" -O - | grep _amd64.deb | head -n 1 | cut -d '"' -f 2) - - wget -c "https://github.com/$DLD" - - script: - - mv opt/webtorrent-desktop/* usr/bin/ - - sed -i -e 's|/opt/webtorrent-desktop/||g' webtorrent-desktop.desktop - - -In the :code:`ingredients` section, a :code:`.deb` package is downloaded. Then, in the :code:`script` section, the main executable is moved to its standard location in the AppDir. Finally, the :code:`.desktop` file is updated to reflect this. - -If other types of binary ingredients have been specified, then the shell commands contained in the :code:`script` section need to retrieve these by copying them into place. Note that since the commands contained in the :code:`script` section are executed inside the root directory of the AppDir, the ingredients downloaded in the `ingredients` sections are one directory level above, i.e., in :code:`../`. The following example illustrates this: - -.. code-block:: yaml - - ingredients: - script: - - wget -c "https://telegram.org/dl/desktop/linux" --trust-server-names - - tar xf tsetup.*.tar.xz - - script: - - cp ../Telegram/Telegram ./usr/bin/telegram-desktop - - -In the :code:`ingredients` section, an archive is downloaded and unpacked. Then, in the :code:`script` section, the main executable is copied into place inside the AppDir. - - -The script section needs to copy icon and `.desktop` file in place -################################################################## - -Since an AppImage may contain more than one executable binary (e.g. helper binaries launched by the main executable) and also may contain multiple :code:`.desktop` files, a clear entry point into the AppImage is required. For this reason, there is the convention that there should be exactly one :code:`$ID.desktop` file and corresponding icon file in the top-level directory of the AppDir. - -The script running the :code:`.yml` file tries to do this automatically, which works if the name of the application specified in the :code:`app:` key matches the name of the :code:`$ID.desktop` file and the corresponding icon file. For example, if :code:`app: myapp` is set, and there is :code:`usr/bin/myapp`, :code:`usr/share/applications/myapp.desktop`, and :code:`usr/share/icons/*/myapp.png`, then the :code:`myapp.desktop` and :code:`myapp.png` files are automatically copied into the top-level directory of the AppDir. Unfortunately, many packages are in their naming. In that case, the shell commands contained in the :code:`script` section must copy exactly one :code:`$ID.desktop` file and the corresponding icon file into the top-level directory of the AppDir. The following example illustrates this: - -.. code-block:: yaml - - script: - - tar xf ../fritzing* -C usr/bin/ --strip 1 - - mv usr/bin/fritzing.desktop . - - -Unfortunately, many applications don't include a :code:`$ID.desktop` file. If it is missing, the shell commands contained in the :code:`script` section need to create it. The following (simplified) example illustrates this: - -.. code-block:: yaml - - script: - - # Workaround for: - - # https://bugzilla.mozilla.org/show_bug.cgi?id=296568 - - cat > firefox.desktop < usr/share/applications/mu.codewith.editor.desktop <<\EOF - - [Desktop Entry] - - Type=Application - - Name=Mu - - Comment=A Python editor for beginner programmers - - Icon=mu.codewith.editor - - Exec=python3 bin/mu-editor %F - - Terminal=false - - Categories=Application;Development; - - Keywords=Python;Editor;microbit;micro:bit; - - StartupWMClass=mu - - MimeType=text/x-python3;text/x-python3; - - EOF - - cp usr/share/applications/mu.codewith.editor.desktop . - - usr/bin/pip3 freeze | grep "mu-editor" | cut -d "=" -f 3 >> ../VERSION - - -Source: - https://github.com/AppImage/pkg2appimage/blob/9249a99e653272416c8ee8f42cecdde12573ba3e/recipes/Mu.yml diff --git a/source/packaging-guide/creating-appdir-structure/index.rst b/source/packaging-guide/creating-appdir-structure/index.rst new file mode 100644 index 0000000..afffe4a --- /dev/null +++ b/source/packaging-guide/creating-appdir-structure/index.rst @@ -0,0 +1,20 @@ +.. _creating-appdir-structure: + +Creating the AppDir structure +============================= + +As seen in the :ref:`table comparing the different AppImage creation methods `, some tools require you to create the AppDir structure and place files in it prior to invoking the tool. There are two ways to do this: + +1. Manually creating the AppDir structure and copying files to their correct places +2. Using make (this only works if you use Makefiles to build the project) + +This section explains both ways to do this. + +Additionally, it explains how to manually package *everything*. This should only be used as a last resort if all other methods aren't applicable. Using one of the :ref:`appimage-creation-tools` is usually much more convenient. The main reason it's explained nevertheless is to illustrate how things work under the hood. + +.. toctree:: + Manually + Using make + Manually creating everything + :caption: Contents: + :maxdepth: 1 diff --git a/source/packaging-guide/creating-appdir-structure/make.rst b/source/packaging-guide/creating-appdir-structure/make.rst new file mode 100644 index 0000000..a73a2f0 --- /dev/null +++ b/source/packaging-guide/creating-appdir-structure/make.rst @@ -0,0 +1,75 @@ +Using make to create the AppDir structure +========================================= + +.. note:: + This is only necessary if you use an :ref:`AppImage creation tool ` that requires prior creation of the AppDir folder structure and file placement. + + If you use a tool that doesn't require this, you don't have to do this. + +Alternatively to :ref:`manually creating the AppDir structure `, you can use make `make `__ to create the AppDir structure. However, this only works if you use Makefiles to build your project (which is mostly done for C/C++-based projects). + +If you use a modern make-based meta build system such as CMake_ or qmake_, you can use the provided `make install` command to create the AppDir structure. To do this, you have to set up an install configuration in your build system. The configuration should install all binaries, libraries, resources, etc. as well as the :ref:`desktop and icon files `. + +.. todo:: + This page is missing the most important part: How to set up the install configuration. This should be added. + + +CMake +----- + +CMake provides an additional parameter to configure where the files are installed when running ``make install`` called |destdir|. If |destdir| is specified, CMake will "install" the files into the given directory instead of the filesystem root (``/``). + +.. note:: + By default, CMake sets an internal variable called |cmake-install-prefix| to a path other than ``/usr`` to prevent users calling e.g., ``sudo make install`` from damaging their system. The variable must explicitly be set to ``/usr`` therefore. + +.. |destdir| replace:: ``DESTDIR`` +.. |cmake-install-prefix| replace:: ``CMAKE_INSTALL_PREFIX`` + +Here's an example how to use this method: + +.. code-block:: shell + + # Download project (you can use that project to test this method) + > git clone https://github.com/linuxdeploy/QtQuickApp.git + > cd QtQuickApp + + # Configure build system and build application on all CPU cores + # The used flag is the bare mimimum that's needed + # Depending on the app, other variables might have to be set as well + > mkdir build + > cd build + > cmake .. -DCMAKE_INSTALL_PREFIX=/usr + > make -j$(nproc) + + # Create the AppDir structure + > make install DESTDIR=AppDir + +|make_result|. + + +qmake +----- + +Qt's qmake_ also provides a variable to change the "target" of ``make install`` calls called ``INSTALL_ROOT``. The qmake-based method is very similar to the CMake one. There's just one major difference: qmake does install into ``/usr`` by default already. + +Preparing a basic application is very simple, as the following example illustrates: + +.. code-block:: shell + + # Download project (you can use that project to test this method) + > git clone https://github.com/linuxdeploy/QtQuickApp.git + > cd QtQuickApp + + # Configure build system and build application on all CPU cores + # Depending on the app, some variables might have to be set + > mkdir build + > cd build + > qmake .. + > make -j$(nproc) + + # Create the AppDir structure + > make install INSTALL_ROOT=AppDir + +|make_result|, just like after executing the CMake commands. + +.. |make_result| replace:: This creates a new directory called ``AppDir`` in the build directory, which should contain all binaries, shared libraries, etc. diff --git a/source/packaging-guide/creating-appdir-structure/manually-full.rst b/source/packaging-guide/creating-appdir-structure/manually-full.rst new file mode 100644 index 0000000..8877e1d --- /dev/null +++ b/source/packaging-guide/creating-appdir-structure/manually-full.rst @@ -0,0 +1,117 @@ +.. include:: ../../substitutions.rst + +.. _manually-fully-creating-appdir: + +Manually creating the entire AppDir +=================================== + +.. warning:: + While manually creating a directory structure and copying some files might be necessary depending on the used tool, manually packaging *everything* should only be used as a last resort if all other methods aren't applicable. + + Using one of the :ref:`appimage-creation-tools` is usually much more convenient. + + The main reason it's explained nevertheless is to illustrate how things work under the hood. + + If you only want to manually create an AppDir structure as the chosen AppImage creation tool requires an existing AppDir structure, go to :ref:`manually-creating-appdir-structure`. + + + +Manually creating the entire AppDir structure +--------------------------------------------- + +If you want to manually create the entire AppDir structure and copy all files to their correct places in it without using any :ref:`AppImage creation tool `, you first have to follow the steps described in :ref:`manually-creating-appdir-structure`. + +Additionally to the AppDir content described there, your AppDir needs to contain ``MyApp.AppDir/AppRun`` and ``MyApp.AppDir/.DirIcon``. + + +AppRun +++++++ + +In modern AppImages, ``AppRun`` is usually a symlink to the main binary. This works if the binary has been made relocatable (which is automatically done by modern AppImage creation tools; it's explained :ref:`later on this page ` how to manually do that). + +However, |why_apprun_c|, alternatives may be used. For more information, see :ref:`AppRun.c `. + + +.DirIcon +++++++++ + +``.DirIcon`` is the actual icon being used as application icon. It is usually a symlink to an icon stored in root or ``usr/share/icons/hicolor//apps/myapp.png``. Notice that ``.DirIcon`` **must be a PNG file**. + +For more information on it, see the :ref:`.DirIcon specification `. + + +Adding shared libraries +----------------------- + +Additionally to that, you have to place all required shared libraries in the AppDir. The shared libraries have to be placed under ``MyApp.AppDir/usr/lib/``. For example, a shared library called ``libfoo.so.0`` would be placed as ``MyApp.AppDir/usr/lib/libfoo.so.0``. + + +.. _removing-hard-coded-paths: + +Removing hard-coded paths +------------------------- + +In order to be packaged as AppImages, applications must load the resources relative to their main binary, and not from a hardcoded path (usually ``/usr/...``). This is called relocatability. + +.. note:: + If your app doesn't load resources from the AppImage, but e.g., shows errors it couldn't find resources, it is most likely not relocatable. + +You can check whether your app is relocatable by running + +.. code-block:: shell + + > strings MyApp.AppDir/usr/bin/myapp | grep /usr + +Should this return something, then you need to make your application relocatable, either by modifying the source code or by patching the executable. + + +Modifying the source code ++++++++++++++++++++++++++ + +The best way is to modify the source code of the application in order to not use absolute paths. While there are several ways to do this, the canonical way on Linux is to resolve ``/proc/self/exe`` to get the path of the main executable and use a path relative to it. This should work both in normal installations and in relocatable installations such as AppImages. There are also libraries such as `BinReloc `__ which make this easier. + +Some modern frameworks such as Qt have this functionality built-in, e.g. in ``QString QCoreApplication::applicationDirPath()`` so you don't have to resolve ``/proc/self/exe``. In some cases, there are also flags you can specify when building from source to make applications relocatable. + +Another way to make your application relocatable is to use the `GNU relocatable-prog module `__. + + +Patching the executable ++++++++++++++++++++++++ + +If you don't want to or can't change the source code and recompile the application, you can also patch the binaries. This can be done with the following command (which needs to be executed inside the AppDir): + +.. code-block:: shell + + > find usr/ -type f -executable -exec sed -i -e "s|/usr|././|g" {} \; + +It replaces all occurrences of ``/usr`` in each binary with the same length string ``././``, which simply means "here". This command is also available in the :ref:`convenience functions script `. + +.. + TODO: Is this still true? It hasn't been mentioned in this section originally. + > For the binary-patched application to work, you need to change to the ``usr/`` directory inside the application directory before you launch the application. + +This usually works as long as the application is not calling ``chdir()`` (changing the current working directory). Such a call would break this workaround as ``././`` would then not be pointing to ``$APPDIR/usr`` anymore. You can run the following command to see whether the application is calling ``chdir()`` (99% of GUI applications don't): + +.. code-block:: shell + + > strace -echdir -f ./AppRun + +.. note:: + An alternative approach to making an application relocatable is to use the AppRun.c script / program, see :ref:`apprun.c`. It can be used |why_apprun_c|. However, this approach is deprecated and should be avoided if possible. + + +Creating an AppImage from the AppDir +------------------------------------ + +To create an AppImage from the AppDir, you need :ref:`appimagetool`. You can get it by downloading the `latest release `__. After downloading the AppImage, you have to make it executable as usual: + +.. code-block:: shell + + > wget https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage + > chmod +x appimagetool-x86_64.AppImage + +After that, you can call it with the AppDir path as parameter in order to turn it into an AppImage: + +.. code-block:: shell + + > ./appimage-tool-x86_64.AppImage MyApp.AppDir diff --git a/source/packaging-guide/creating-appdir-structure/manually.rst b/source/packaging-guide/creating-appdir-structure/manually.rst new file mode 100644 index 0000000..9ad6a97 --- /dev/null +++ b/source/packaging-guide/creating-appdir-structure/manually.rst @@ -0,0 +1,27 @@ +.. _manually-creating-appdir-structure: + +Manually creating the AppDir structure +====================================== + +.. note:: + This is only necessary if you use an :ref:`AppImage creation tool ` that requires prior creation of the AppDir folder structure and file placement. + + If you use a tool that doesn't require that, you don't have to do this. + +To prepare an AppDir structure for an :ref:`AppImage creation tool `, create a structure that looks (at a minimum) like this: + +.. code-block:: text + + MyApp.AppDir/ + MyApp.AppDir/myapp.desktop + MyApp.AppDir/myapp.svg or -.png + MyApp.AppDir/usr/bin/myapp + +.. note:: + There are additional files (``AppRun``, ``.DirIcon`` and shared libraries) that have to be placed in every AppDir. However, they should not be manually copied into the AppDir, but are created by the used :ref:`AppImage creation tool `. + +For a complete guide on and explanation of the AppDir content, including more advanced options such as to include icon files in multiple resolutions or adapted to other well-known themes to fit in better, see :ref:`the AppDir specification `. + +This AppDir structure can then be used by the :ref:`appimage-creation-tools` to bundle the application dependencies (shared libraries) and create an AppImage out of the AppDir. + +Additionally, many applications require additional resources, e.g. asset files for drawing a GUI, which have to be included in the AppImage. In this case, these required resources need to be copied into the AppDir as well. diff --git a/source/packaging-guide/desktop-icon-files.rst b/source/packaging-guide/desktop-icon-files.rst new file mode 100644 index 0000000..5ad1ea0 --- /dev/null +++ b/source/packaging-guide/desktop-icon-files.rst @@ -0,0 +1,85 @@ +.. include:: ../substitutions.rst + +.. _desktop-entry-files: + +Desktop entry & icon files +========================== + +To create an AppImage for your application, you first have to create a desktop entry file, colloquially also called desktop file. A desktop file contains metadata about the application, e.g. name or icon name, but also the executable name, which is used by the user's system to correctly display and execute the application. It's a central component of the Linux desktop and every AppImage must contain one in its :ref:`AppDir `. + +A desktop entry file is an `INI-style `__ text document, which means that it contains (mandatory and optional) key-value pairs in the format ``Key=Value`` and group headers in the format ``[Header]``, most notably the ``[Desktop Entry]`` header for the main information. The official `Desktop Entry Specification`_ describes all possible ways to configure a desktop entry file in detail. An AppImage desktop entry file should at least contain these keys: + +.. code-block:: ini + + [Desktop Entry] + Name=My application + Exec=my-application + # Icon name without the file format + Icon=my-application + Type=Application + Terminal=false + Categories=Utility;TextEditor; + +The ``Categories`` value should be a list of all `specific registered categories `__ that apply to your application. + +The list of all keys can be found in the `Desktop Entry Specification (Recognized keys) `__. Further keys that are recommended for AppImages are ``GenericName`` (the name of the application category, e.g. "Browser" for Firefox), ``Comment`` (an application description) and ``Version`` (not the application version, but the used version of the Desktop Entry Specification itself as well as the custom AppImage keys (see the next section). + +The desktop entry file should be named according to the `Reverse domain name notation `__ and have ``.desktop`` as file ending, for example ``org.AppImage.ExampleApp.desktop``. + +After creating your desktop file, make sure that it's valid using ``desktop-file-validate org.example.application.desktop``. + + +Custom keys introduced for AppImage purposes +-------------------------------------------- + +Aside from the standardized mandatory and optional keys, desktop entry files may contain additional, use case dependent keys. They're usually prepended with ``X-`` to differentiate between standard and custom keys. + +The AppImage project defined a few custom keys with special meaning that provide information to enhance our desktop integration algorithm. These should also be included in your AppImage desktop entry file. + +X-AppImage-Name + Name of the application. Used to relate two AppImages of the same application but different versions. + + **Examples:** ``Krita``, ``Kdenlive``, ``Ultimaker Cura`` + +X-AppImage-Version + Version of the application bundled in the AppImage. + + **Examples:** ``4.9.2``, ``1.0.0-beta-2``, ``2019.1.1`` + +X-AppImage-Arch + Architecture of the AppImage. + + **Examples:** ``x86_64``, ``aarch64``, ``i386`` + +The reference implementation (:ref:`appimagetool`) and libappimage currently make use mostly of ``X-AppImage-Version``. + +.. seealso:: + The following discussions in issue trackers contain some background information: + + * `AppImageKit#59 `__ + * `AppImageKit#662 `__ + + +.. _icon-files: + +Icon files +---------- + +As a desktop entry file should link to an icon file, you should also create an icon file in one or several resolutions. This icon is used on the user's system to display your application. + +|supported_icon_formats| + +You only have to specify one icon (ideally in the resolution ``512x512``), but it might make sense to also create icon file versions that don't contain as many details in smaller resolutions. An advanced option would be to even include icon files adapted to well-known themes and include them (exchanging ``hicolor`` in the icon path with the theme name, see :ref:`manually-creating-appdir-structure`). + +To include the icon in several resolutions or theme styles, each file must be named the same. If they're placed correctly in the AppDir and the icon name (without the file format) is included in the desktop file, the icon will be correctly used by the user's system. + +For more information, see the `Icon Theme Specification `__. + + +Advanced options +---------------- + +For advanced options of the desktop entry file, e.g. using localized strings to change the application name and description based on the user's system language or registering supported `MIME types `__, see the official `Desktop Entry Specification`_. + + +.. _Desktop Entry Specification: https://specifications.freedesktop.org/desktop-entry-spec/latest diff --git a/source/packaging-guide/distribution.rst b/source/packaging-guide/distribution.rst index a789d55..db13e48 100644 --- a/source/packaging-guide/distribution.rst +++ b/source/packaging-guide/distribution.rst @@ -1,148 +1,138 @@ -.. _ref-distribution: +.. include:: ../substitutions.rst Distributing AppImages ====================== -There are several ways to distribute AppImages to users. Most likely, AppImages are distributed from their creator to the users. - -The following section contains some details on how AppImages are commonly distributed. - +This sections contains some details on how AppImages can be distributed and what you should consider when doing so. .. contents:: Contents :local: :depth: 1 -.. _ref-hosting-appimages: - Hosting AppImages ----------------- -Most commonly, AppImage creators host the files on a standard web server. This is the easiest and most accessible way. +The most accessible way to host AppImages is on a project website. -We recommend that you put the AppImage for Linux on your project's download page alongside the dmg for macOS and the exe for Windows, like so: +We recommend that you put the AppImage for Linux on your project's download page alongside the dmg for macOS and the exe for Windows, like this: .. image:: /_static/img/packaging-guide/release-page-screenshot.png :width: 80% :align: center :alt: Download page overview, showing Windows, MacOS, Linux and Source code downloads -For open source projects, if your project is located on GitHub, we recommend that you publish your AppImage in addition on `GitHub Releases`_. +If your project is open source and located on GitHub, we recommend that you also publish your AppImage on `GitHub Releases `__. .. note:: - For :ref:`AppImageUpdate ` to work properly, it is required that the web server supports HTTP range requests. Most web hosts support this, as the same technology is used for navigating an MP3 files, for example. + For :ref:`AppImageUpdate ` to work properly, it is required that the web server supports HTTP range requests. While most web hosts support this, some hosted services are known not to support range requests right now. These include - Some hosted services are known not to support range requests right now. These involve: + - `Gitlab releases `__ - - `Gitlab releases `_ + If you use such a service and wish to use :ref:`AppImageUpdate ` with it, please ask the providers to enable range requests. - If you use such a service and wish to use :ref:`AppImageUpdate ` with it, please ask the providers to enable range requests. -.. _GitHub Releases: https://help.github.com/en/articles/creating-releases/ +'Download as an AppImage' button +++++++++++++++++++++++++++++++++ + +You can use a "Download as an AppImage" button alongside other similar buttons: +.. image:: /_static/img/download-appimage-banner.svg + :alt: Download as an AppImage -.. _ref-complying-with-licenses: +Link this button directly to the latest version of your AppImage or to a download page with the latest version of your AppImage. -Complying with licenses ------------------------ +Button by `Khushraj Rathod `__ under the `CC0 license `__ (Public Domain). -Even under open source licenses, distributing and/or using code in source or binary form may create certain legal obligations, such as the distribution of the corresponding source code and build instructions for GPL licensed binaries, and displaying copyright statements and disclaimers. As the author of an application which you are distributing as an AppImage, you are responsible to obey all licenses for any third-party dependencies that you include in your AppImage, and ensure that their licenses and source code are made available, where required, together with the release binaries. AppImageKit itself is released under the permissive MIT license. -.. _ref-no-linux-in-appimage-filename: +.. _software-catalogs-dev: -Do not put "Linux" into the Appimage file name ----------------------------------------------- +Software catalogs +----------------- -Please **DO NOT** put "linux" into the file name of an AppImage. It is abundantly clear that an :code:`.exe` is for Windows, a :code:`.dmg` is for the Mac and that :code:`.AppImage` is for Linux (and compatible systems such as Windows with WSL2 and FreeBSD with the Linuxulator). No need to duplicate. +Additionally to hosting your AppImage, you may want to add your AppImage to a software catalog. Those are crowd-sources lists of available AppImages with data that 3rd party app stores and software centers can use. This way, users can also find your AppImage when browsing through such catalogs and stores or searching for a specific tool. -.. _ref-no-appimages-in-archives: +Some software catalogs use the :ref:`AppStream metadata ` inside the AppImage, therefore your AppImage will be presented consistently across them and you don't have to input information manually. -Do not put AppImages into other archives ----------------------------------------- +The following software catalogs are known to us: -Please **DO NOT** put an AppImage into another archive like a :code:`.zip` or :code:`.tar.gz`. -While it may be tempting to avoid users having to set permission, this breaks desktop integration with the optional :code:`appimaged` daemon, among other things. Besides, the beauty of the AppImage format is that you never need to unpack anything. Furthermore, packing an AppImage into some form of archive prevents the AppImage from being added to the central catalog of available AppImages at https://github.com/AppImage/appimage.github.io. +AppImage.github.io +++++++++++++++++++ +AppImage.github.io (`source code `__) is the oldest software catalog. It automatically inspects and tests all added AppImages to make sure they are functioning correctly. -Making your AppImages discoverable ----------------------------------- +You can see the list of all AppImages in it in alphabetical order under https://appimage.github.io/apps/. There also is a more modern frontend under https://g.srev.in/get-appimage/all/p/0 (`source code `__). Each entry links to the original download location (usually GitHub releases) where you can download it. -Now that you have produced your AppImage, you want users to be able to easily find it. To get users, you need to make your AppImage known to the world. +To get your own AppImage included, see the `detailed tutorial on its readme `__. If you want to add your AppImage to this catalog, you have to host it raw, and not inside another archive like a ``.zip`` or ``.tar.gz``. +To use the dataset, simply parse https://appimage.github.io/feed.json. -Application website -''''''''''''''''''' +Projects using this data include: -The most obvious place to advertise your AppImage is to prominently featured on your application’s download page. +* Bauh (https://github.com/vinifmor/bauh) +* LiureX Software Store (https://github.com/lliurex/lliurex-store) +* Zap (https://github.com/srevinsaju/zap) -'Download as an AppImage' button -'''''''''''''''''''''''''''''''' -You can use a "Download as an AppImage" button alongside other similar buttons: +AppImageHub.com ++++++++++++++++ -.. image:: /_static/img/download-appimage-banner.svg - :alt: Download as an AppImage +AppImageHub.com is a software catalog that is related to opendesktop.org. -Link this button directly to the latest version of your AppImage, or to a download page containing the link to the latest version of your AppImage. +You can see the list of all AppImages in it in alphabetical order under https://www.appimagehub.com/browse?ord=alphabetical. Each entry contains a download button which will download the AppImage from its original location (usually GitHub releases). -Button by `Khushraj Rathod `__ under the `CC0 license `_ +To get your own AppImage included, you have to register / login on the site with your opendesktop.org - Account and then add it via the website GUI. -Social Media -'''''''''''' +To use the dataset, you have to use the official API which is located at ``https://api.appimagehub.com/ocs/v1``. The API is following the `OCS `__ standard (`specification `__). Sadly as of December 2024, there is no good tutorial on how to use the API. If you want to use it, it's best to look at `this `__ and test the API yourself with ``/content/categories`` and ``/content/data``. -Also be sure to advertise your new AppImage on social media, for example on Twitter, blogs, etc. Be sure to use the :code:`#AppImage` hashtag for additional discoverability. +Projects using this data include: +* NX Software Center (Nitrux OS) (https://github.com/Nitrux/nx-software-center) +* appimage-cli-tool (https://github.com/AppImageCrafters/appimage-cli-tool) +* AppImagePool (https://github.com/prateekmedia/appimagepool) -.. _ref-appimagehub: -AppImageHub -''''''''''' +Portable Linux Apps / AM +++++++++++++++++++++++++ -You may want to add your AppImage to `AppImageHub `__, a crowd-sourced directory of available, automatically tested AppImages with data that 3rd party app stores and software centers can use. Given an URL to an AppImage, it inspects the AppImage and puts it into a community-maintained catalog. +Portable Linux apps (`source code `__) is another AppImage software catalog that has been created because of `dissatisfaction `__ with appimage.github.io and appimagehub.com. -App stores and software centers can consume the metadata collected by this project. See `AppImage ecosystem`_. +Differently to those two, its main purpose is not to provide links to download the original AppImages, but rather to be used through `AM / AppMan`_, a related package manager that can install, update and manage the AppImages from this catalog. Therefore, PLA contains an install script (which uses the original AppImage location) for each AppImage, which is used by AM. -Projects already using this data include: +Nevertheless, you can see the list of all AppImages in it in alphabetical order under https://portable-linux-apps.github.io/apps.html. To download an AppImage from the original location, navigate to its website over the entry description or install script. - * Nitrux, NX Software Center: https://github.com/Nitrux/nx-software-center - * https://github.com/simoniz0r/spm - * https://github.com/sillasleal/appcenter - * https://github.com/lliurex/lliurex-store - * Please contact us if you are using this data so that we can list your project here +To get your own AppImage included, you have to `make a pull request `__ in which you add your AppImage to the `index `__ and create an installer script (see `this tutorial `__). -To get your AppImage included, create a new file at https://github.com/AppImage/AppImageHub/new/master/data and send a pull request. -The file should contain one line with a link to the GitHub repository that hosts AppImages on its Releases page. +SoarPkgs +++++++++ -Alternatively, a link to the AppImage. Nothing else. +SoarPkgs is another software catalog with AppImages as well as other package types, following a similar approach to PLA. -Then send a pull request. Travis CI will instantly perform an automated review of the AppImage, and in case it succeeds, you will see a green result in your pull request. If you get a red result, check the log of the Travis CI build, and fix it. +As PLA, its main purpose is not to provide links to download the original AppImage, but rather to be used through a related package manager called `Soar`_, which can install, update and manage the packages from this catalog. Like PLA, SoarPkgs contains an install script (which uses the original AppImage location) for each AppImage, which is used by Soar. -Once an application is added to AppImageHub, it is not updated automatically anymore unless its input file changes. In case you need to get your entry on AppImageHub updated (e.g., you provided new meta information in your latest AppImage release), you need to submit another pull request. At the bottom of your AppImageHub page, you will find a link named "Edit the input for this page" with which you can do this. If the URL has stayed the same, adding or removing a "#" character in a new line will trigger an update. Remember that AppImageHub does not keep track of versions, so it is not necessary to do this just because you released a new version of your application. +You can see the list of all AppImages in it in alphabetical order under https://github.com/pkgforge/soarpkgs/tree/main/packages (SoarPkgs doesn't have a website displaying the list). To download an AppImage from the original location, navigate to its website over the entry install script. + +To get your own AppImage included, see the `detailed tutorial in its documentation `__ + + +Complying with licenses +----------------------- -As a format, AppImage is designed in a way that does not impose restrictions on the person generating AppImages. Basically you are free to put inside an AppImage whatever you want. For AppImageHub, however, additional rules apply. AppImages submitted to AppImage hub undergo automatic and possibly additional manual review. +Even under open source licenses, distributing and/or using code in source or binary form may create certain legal obligations, such as the distribution of the corresponding source code and build instructions for GPL licensed binaries, and displaying copyright statements and disclaimers. As the author of an application which you are distributing as an AppImage, you are responsible to obey all licenses for any third-party dependencies that you include in your AppImage, and ensure that their licenses and source code are made available, where required, together with the release binaries. The AppImage reference implementation itself is released under the permissive MIT license. -* Must be downloadable from an URL. Our testing system fetches the AppImage using :code:`wget`. Currently we cannot get AppImages from locations behind authentication and/or cookie-protected locations. For commercial applications we recommend to have a generally downloadable demo/trial version. Please contact us if you would like to add your commercial AppImage to the directory and it is not available for general download -* Must run on the `oldest still-supported Ubuntu LTS release`_ (16.04 as of 2019, for up to date information see https://en.wikipedia.org/wiki/Ubuntu#Releases) without the installation of additional packages. Targeting the oldest still-supported LTS is to ensure that the AppImage will run not only on the very latest, but also on older target systems, such as enterprise distributions (not limited to Ubuntu) -* Must execute in our Travis CI based testing environment -* Must pass `appdir-lint.sh`_ -* Must have a desktop file that passes :code:`desktop-file-validate` -* Must run without active Internet connection (and at least show some information) -* Should have an `AppStream metainfo file`_ in :code:`usr/share/metainfo`. If it does, must pass :code:`appstreamcli` validation -* Should show a useful screen rather than some crude dialog box since the main window will be used for the main screenshots. Note that you can provide your own screenshots by using an `AppStream metainfo file`_ -* Should be available under a constant URL that does not contain the version number. Alternatively, should be available on GitHub Releases or the openSUSE Build Service (you are free to suggest additional serices like these) -.. _AppImage ecosystem: https://github.com/AppImage/AppImageKit/wiki/Ecosystem -.. _oldest still-supported Ubuntu LTS release: https://www.ubuntu.com/info/release-end-of-life -.. _appdir-lint.sh: https://github.com/AppImage/pkg2appimage/blob/master/appdir-lint.sh -.. _AppStream metainfo file: https://people.freedesktop.org/~hughsient/appdata/ +Recommendations +--------------- +Don't put "Linux" into the Appimage file name +++++++++++++++++++++++++++++++++++++++++++++++ -Future catalogs -''''''''''''''' +You shouldn't put "linux" into the file name of an AppImage. It is clear that an ``.exe`` is for Windows, an ``.app`` is for macOS and that an ``.AppImage`` is for Linux (and compatible systems such as Windows with WSL2 and FreeBSD with the Linuxulator). Especially as this is the file your users will always have on their system, you shouldn't put redundant information in its name. -In the future, we may want to use decentralized peer-to-peer databases for the catalog of AppImages. -We are currently investigating technologies such as IPFS and would be happy to win contributors in this area. +Make your AppImage discoverable ++++++++++++++++++++++++++++++++ +To help users to easily find your AppImage, you can post about it on social media, e.g. on a blog. You can use the ``#AppImage`` hashtag for discoverability. diff --git a/source/packaging-guide/environment-variables.rst b/source/packaging-guide/environment-variables.rst index e1070f9..42c1a7a 100644 --- a/source/packaging-guide/environment-variables.rst +++ b/source/packaging-guide/environment-variables.rst @@ -1,80 +1,51 @@ -.. _ref-env_vars: +.. include:: ../substitutions.rst + +.. _environment-variables: Environment variables ===================== -The AppImage runtimes make some environment variables available that can be used by applications bundled as AppImages -during runtime, e.g., to recognize whether it's currently run from an AppImage, or to get some path information. - -Depending on the type of the AppImage, the runtimes offer different feature sets. +The AppImage runtime sets some environment variables available to the applications bundled as AppImages, e.g. to get the path of the mounted AppDir (AppImage content). This can be necessary in some situations, e.g. to call other bundled executables. +This section gives an overview over those environment variables. .. contents:: Contents :local: :depth: 1 -Type 1 AppImage runtime ------------------------ +Environment variables set in every AppImage +------------------------------------------- -.. note:: +The following environment variables are set in every AppImage. - Type 1 is the deprecated/outdated AppImage type that is only in legacy support mode. It is not recommended to make - new type 1 AppImages. We strongly recommend you to use :code:`appimagetool` to make type 2 AppImages. - -+------------------+--------------------------------------------------------------------------------------------------+ -| Variable name | Contents | -| | | -+==================+==================================================================================================+ -| :code:`APPIMAGE` | (Absolute) path to AppImage file (with symlinks resolved) | -| | | -+------------------+--------------------------------------------------------------------------------------------------+ -| :code:`APPDIR` | Path of mountpoint of the ISO9660 image contained in the AppImage | -| | | -+------------------+--------------------------------------------------------------------------------------------------+ -| :code:`OWD` | Path to working directory at the time the AppImage is called | -| | | -+------------------+--------------------------------------------------------------------------------------------------+ - - - -Type 2 AppImage runtime ------------------------ - -The type 2 AppImage runtime makes a few environment variables available for use in e.g., ``AppRun`` scripts: - -+------------------+--------------------------------------------------------------------------------------------------+ -| Variable name | Contents | -| | | -+==================+==================================================================================================+ -| :code:`APPIMAGE` | (Absolute) path to AppImage file (with symlinks resolved) | -| | | -+------------------+--------------------------------------------------------------------------------------------------+ -| :code:`APPDIR` | Path of mountpoint of the SquashFS image contained in the AppImage | -| | | -+------------------+--------------------------------------------------------------------------------------------------+ -| :code:`OWD` | Path to working directory at the time the AppImage is called | -| | | -+------------------+--------------------------------------------------------------------------------------------------+ -| :code:`ARGV0` | Name/path used to execute the script. This corresponds to the value you'd normally receive via | -| | the :code:`argv` argument passed to your :code:`main` method. | -| | Usually contains the filename or path to the AppImage, relative to the current working | -| | directory. | -| | | -+------------------+--------------------------------------------------------------------------------------------------+ +.. list-table:: + :header-rows: 1 -.. note:: + * - Variable name + - Contents + * - ``APPIMAGE`` + - Absolute path of the AppImage (with symlinks resolved) + * - ``APPDIR`` + - Path of the mounted AppDir (AppImage content) + * - ``OWD`` + - Path of the working directory at the time the AppImage is called + +For example, if you want to call another bundled executable from your AppImage, you can do that with ``$APPDIR/usr/lib/other_executable``. |shell_command| ``Command::new("sh").arg("-c").arg("$APPDIR/usr/lib/other_executable").output()``. - :code:`APPIMAGE` and :code:`ARGV0` have very different use cases. - :code:`APPIMAGE` shall be used every time the full path of the AppImage is needed, e.g., if you need to touch the - AppImage file, for example when you want to update it or read some meta information. +``ARGV0`` +--------- + +Type 2 AppImages have another environment variable called ``ARGV0`` set. (Every reasonably recent AppImage is type 2 as all modern :ref:`appimage-creation-tools` and the reference implementation (:ref:`appimagetool`) create type 2 AppImages. |different_types|) + +``ARGV0`` is the path used to execute the AppImage. This corresponds to the value you'd normally receive as the ``argv`` argument passed to your ``main`` method. This usually contains the path of the AppImage, relative to the current working directory. + +.. note:: + ``APPIMAGE`` and ``ARGV0`` have very different use cases. + + ``APPIMAGE`` should be used every time the path of the AppImage is needed, e.g. if you need to touch the AppImage file to update it. - :code:`ARGV0` provides information how the AppImage was called. When you call an AppImage through a symlink for - instance, you can get the path to this symlink through :code:`ARGV0`, while :code:`APPIMAGE` would contain the - absolute path to the file behind that symlink. + ``ARGV0`` provides information on how the AppImage was called. When you call an AppImage through a symlink for instance, you can get the path to this symlink through ``ARGV0``, while ``APPIMAGE`` would contain the absolute path to the file behind that symlink. - Scenarios where :code:`ARGV0` is really useful involve so-called multi-binary AppImages, where the filename - in :code:`ARGV0` defines which program is called inside the AppImage. This concept is also known from - single-binary tools like `BusyBox `__, and can be implemented in a custom - :code:`AppRun` script (see :ref:`Architecture ` for more information). + Scenarios where ``ARGV0`` is really useful involve so-called multi-binary AppImages, where the filename in ``ARGV0` defines which program is called inside the AppImage. This concept is also known from single-binary tools like `BusyBox `__, and can be implemented in a custom ``AppRun`` script (see :ref:`Architecture ` for more information). diff --git a/source/packaging-guide/from-source/examples/.travis.yml b/source/packaging-guide/from-source/examples/.travis.yml deleted file mode 100644 index b22a784..0000000 --- a/source/packaging-guide/from-source/examples/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -language: cpp -# needed for installing packages with apt -sudo: required - -# we use the Qt PPAs to have some more recent Qt versions that are compatible with Ubuntu trusty -before_install: - - sudo add-apt-repository ppa:beineri/opt-qt-5.10.1-trusty -y - - sudo apt-get update - -# install Qt from the PPA, and set up environment so that calls to Qt tools end up in the new Qt installation -install: - - sudo apt-get -y install qt510base qt510declarative - - . /opt/qt*/bin/qt*-env.sh - -# use CMake based build script shown in previous section -script: - - bash travis/build-with-cmake.sh - -# OPTIONAL: uploading binaries using uploadtool -# see https://github.com/probonopd/uploadtool for more information - -branches: - except: - # Do not build tags that we create when we upload to GitHub Releases - # required for uploadtool - - /^(?i:continuous)/ diff --git a/source/packaging-guide/from-source/examples/bundle-qtquickapp-with-cmake.sh b/source/packaging-guide/from-source/examples/bundle-qtquickapp-with-cmake.sh deleted file mode 100644 index 8bfb53e..0000000 --- a/source/packaging-guide/from-source/examples/bundle-qtquickapp-with-cmake.sh +++ /dev/null @@ -1,54 +0,0 @@ -#! /bin/bash - -set -x -set -e - -# building in temporary directory to keep system clean -# use RAM disk if possible (as in: not building on CI system like Travis, and RAM disk is available) -if [ "$CI" == "" ] && [ -d /dev/shm ]; then - TEMP_BASE=/dev/shm -else - TEMP_BASE=/tmp -fi - -BUILD_DIR=$(mktemp -d -p "$TEMP_BASE" appimage-build-XXXXXX) - -# make sure to clean up build dir, even if errors occur -cleanup () { - if [ -d "$BUILD_DIR" ]; then - rm -rf "$BUILD_DIR" - fi -} -trap cleanup EXIT - -# store repo root as variable -REPO_ROOT=$(readlink -f $(dirname $(dirname $0))) -OLD_CWD=$(readlink -f .) - -# switch to build dir -pushd "$BUILD_DIR" - -# configure build files with CMake -# we need to explicitly set the install prefix, as CMake's default is /usr/local for some reason... -cmake "$REPO_ROOT" -DCMAKE_INSTALL_PREFIX=/usr - -# build project and install files into AppDir -make -j$(nproc) -make install DESTDIR=AppDir - -# now, build AppImage using linuxdeploy and linuxdeploy-plugin-qt -# download linuxdeploy and its Qt plugin -wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage - -# make them executable -chmod +x linuxdeploy*.AppImage - -# make sure Qt plugin finds QML sources so it can deploy the imported files -export QML_SOURCES_PATHS="$REPO_ROOT"/src - -# initialize AppDir, bundle shared libraries for QtQuickApp, use Qt plugin to bundle additional resources, and build AppImage, all in one single command -./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt --output appimage - -# move built AppImage back into original CWD -mv QtQuickApp*.AppImage "$OLD_CWD" diff --git a/source/packaging-guide/from-source/examples/bundle-qtquickapp-with-qmake.sh b/source/packaging-guide/from-source/examples/bundle-qtquickapp-with-qmake.sh deleted file mode 100644 index d9df153..0000000 --- a/source/packaging-guide/from-source/examples/bundle-qtquickapp-with-qmake.sh +++ /dev/null @@ -1,55 +0,0 @@ -#! /bin/bash - -set -x -set -e - -# building in temporary directory to keep system clean -# use RAM disk if possible (as in: not building on CI system like Travis, and RAM disk is available) -if [ "$CI" == "" ] && [ -d /dev/shm ]; then - TEMP_BASE=/dev/shm -else - TEMP_BASE=/tmp -fi - -BUILD_DIR=$(mktemp -d -p "$TEMP_BASE" appimage-build-XXXXXX) - -# make sure to clean up build dir, even if errors occur -cleanup () { - if [ -d "$BUILD_DIR" ]; then - rm -rf "$BUILD_DIR" - fi -} -trap cleanup EXIT - -# store repo root as variable -REPO_ROOT=$(readlink -f $(dirname $(dirname $0))) -OLD_CWD=$(readlink -f .) - -# switch to build dir -pushd "$BUILD_DIR" - -# configure build files with qmake -# we need to explicitly set the install prefix, as CMake's default is /usr/local for some reason... -qmake "$REPO_ROOT" - -# build project and install files into AppDir -make -j$(nproc) -make install INSTALL_ROOT=AppDir - -# now, build AppImage using linuxdeploy and linuxdeploy-plugin-qt -# download linuxdeploy and its Qt plugin -wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage - -# make them executable -chmod +x linuxdeploy*.AppImage - -# make sure Qt plugin finds QML sources so it can deploy the imported files -export QML_SOURCES_PATHS="$REPO_ROOT"/src - -# QtQuickApp does support "make install", but we don't use it because we want to show the manual packaging approach in this example -# initialize AppDir, bundle shared libraries, add desktop file and icon, use Qt plugin to bundle additional resources, and build AppImage, all in one command -./linuxdeploy-x86_64.AppImage --appdir AppDir -e QtQuickApp -i "$REPO_ROOT"/resources/qtquickapp.png -d "$REPO_ROOT"/resources/qtquickapp.desktop --plugin qt --output appimage - -# move built AppImage back into original CWD -mv QtQuickApp*.AppImage "$OLD_CWD" diff --git a/source/packaging-guide/from-source/index.rst b/source/packaging-guide/from-source/index.rst deleted file mode 100644 index ce53352..0000000 --- a/source/packaging-guide/from-source/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _ref-from-source: -.. _ref-packaging-from-source: - -Packaging from source -===================== - -This section contains guides how AppImages can be created from source code. It shows a few tricks how functionality of widely used build tools like e.g., CMake, can be re-used to reduce the amount of code required for building AppImages. Also, it is shown how externally maintained tools with support for building AppImages can be used. - -.. toctree:: - native-binaries - linuxdeploy-user-guide - appimage-builder user guide - :caption: Contents - :maxdepth: 2 diff --git a/source/packaging-guide/from-source/linuxdeploy-user-guide.rst b/source/packaging-guide/from-source/linuxdeploy-user-guide.rst deleted file mode 100644 index 332ff9f..0000000 --- a/source/packaging-guide/from-source/linuxdeploy-user-guide.rst +++ /dev/null @@ -1,178 +0,0 @@ -.. _ref-linuxdeploy: - -linuxdeploy user guide ----------------------- - -This page illustrates how linuxdeploy can be used. - -.. todo:: - - Write introduction - - Add references to examples in packaging guide - -linuxdeploy is capable of packaging dependencies of resources in an existing AppDir, or creating the AppDir from scratch, bundling resources into the right locations that the user passes to it. - -linuxdeploy describes itself as an `"AppDir maintenance tool" `__. Its primary focus is on AppDirs, and it uses plugins to create output formats such as AppImages. - - -.. contents:: Contents - :local: - :depth: 1 - - - -Packaging dependencies of files in an existing AppDir -+++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Sometimes, the build system can be used to install resources into an :ref:`AppDir `-like structure. If this so-called "install configuration" is feature complete, i.e., all the resources an AppImage needs (a binary, an icon and a desktop file), all linuxdeploy has to do is bundle the dependencies of these files. - -This workflow is described in :ref:`ref-make-install-workflow`. - -In case some of the required files described above are *not* installed by ``make install``, you can instruct linuxdeploy to bundle these resources manually. Please see the next section for more information. - - -.. _ref-linuxdeploy-bundle-manually: -.. _ref-linuxdeploy-package-manually: - -Packaging binaries and other resources manually -++++++++++++++++++++++++++++++++++++++++++++++++ - -Unlike the old tools, linuxdeploy doesn't need any existing directory with files in the right positions, etc. Instead, it puts files specified via CLI parameters into the right positions. This makes bundling easier than ever before, as users don't need to know where to put files any more. - -linuxdeploy provides different flags to bundle different kinds of resources. Only resources whose destination can be calculated by linuxdeploy can be bundled this way. Additional resources applications need, which linuxdeploy can not know about, must be bundled by hand. However, the most common resources are covered by the parameters. - -``--executable``/``-e`` - Bundle a native binary executable. |rpath-comment| - -``--library``/``-l`` - Bundle a shared library (:code:`.so` file) into the AppDir. |rpath-comment| - -``--desktop-file``/``-d`` - Bundle a desktop file into the AppDir. These are required for desktop integration, and there must always be at least one of them in the AppDir. Please see :ref:`ref-desktop-integration` for a guide how they can be created, and for best practices related to AppImages. - -``--icon-file``/``-i`` - Bundle icon file. Supported are all formats which the `Icon Theme Specification `__ lists. linuxdeploy will automatically calculate the right output path, which depends on file format and resolution. You can specify multiple icons for multiple resolutions in the form of ``/.``. - -.. |rpath-comment| replace:: Set up everything so that other libraries, executables etc. use this one instead of a system one. - -The following example illustrates how an existing binary can be bundled into an AppDir: - -.. code:: bash - - > ./linuxdeploy-x86_64.AppImage --appdir AppDir --executable ./foobar <...> --output appimage - - -.. _ref-linuxdeploy-plugin-system: - -Plugin system -+++++++++++++ - -linuxdeploy provides a flexible packaging system for both bundling additional resources that cannot be discovered automatically by linuxdeploy (i.e., plugins loaded during runtime using ``dlopen()``, icon themes, etc.), and to convert the AppDir into an output format such as AppImage. - -Plugins are automatically recognized by linuxdeploy. They are executable files (scripts, native binaries, etc.), which must be in one of the following locations: - - - in case the linuxdeploy AppImage is used: next to the AppImage - - next to the linuxdeploy binary - - in any of the directories in ``$PATH`` - -Therefore, when downloading additional plugins, just put them into one of these locations, and linuxdeploy can use them. - -Plugins are standalone executable files. This means they must be made executable by the user before they can be used by linuxdeploy. On the other hand, this also allows for calling plugins manually. - -The plugin system works by calling external executables, hence the only communication linuxdeploy can perform with plugins is via CLI parameters (communication via the ``stdin``/``stdout`` pipes would be a lot more complex to implement for both linuxdeploy and the plugin). Therefore, to influence plugin behavior, plugins may implement environment variables that the user can set *before* calling linuxdeploy. Examples how this works are shown in the following sections. - -You can use the ``--list-plugins`` flag to see what plugins are visible to linuxdeploy. This can come in handy when debugging plugin related issues. It lists the name of the plugin (i.e., what linuxdeploy refers to them as), the full path and the API level they implement. - -.. warning:: - Some plugins might be bundled in the linuxdeploy AppImage already for convenience. They're likely out of date, but should be stable. In case there are any issues or you need to use a newer version, please download the latest version of the respective plugin, and put it next to the linuxdeploy AppImage. linuxdeploy prefers plugins next to the AppImage over bundled ones. - -.. note:: - More information on plugins can be found in the `plugin specification`_. - -.. _plugin specification: https://github.com/linuxdeploy/linuxdeploy/wiki/Plugin-system - - -.. _ref-linuxdeploy-input-plugins: - -Using input plugins -''''''''''''''''''' - -Input plugins can simply be switched on using the ``--plugin`` flag. For example: - -.. code:: bash - - > ./linuxdeploy-x86_64.AppImage --appdir AppDir <...> --plugin qt - -This causes linuxdeploy to call a plugin called ``qt``, if available. - -.. note:: - A list of plugins can be found in the `Awesome linuxdeploy README`_. - -.. _Awesome linuxdeploy README: https://github.com/linuxdeploy/awesome-linuxdeploy#linuxdeploy-plugins - - -.. _ref-linuxdeploy-input-plugins-environment-variables: - -Using environment variables to change plugins' behavior -******************************************************* - -As mentioned previously, some plugins implement additional optional or mandatory parameters in the form of environment variables. These environment variables must be set *before* calling linuxdeploy. - -For example: - -.. code:: bash - - # set the environment variable - > export FOOBAR_VAR=example - - # call linuxdeploy with the respective plugin enabled - > ./linuxdeploy-x86_64.AppImage --appdir AppDir <...> --plugin foobar - -Please refer to the plugins' documentation to find a list of supported environment variables. If you can't find any, there's probably none. - -.. todo:: - - Document existing input plugins' environment variables - - -Creating output files -''''''''''''''''''''' - -Similar to the input plugins, output plugins are enabled through a command line parameter. To avoid any possible confusion, a second parameter is used: ``--output``. - -Example: - -.. code:: bash - - > ./linuxdeploy-x86_64.AppImage <...> --output appimage - -Most users are interested in generating AppImages, therefore the AppImage plugin is bundled in the official linuxdeploy AppImage. Please see the :ref:`plugin's user guide ` for more information. - - -Using environment variables to change plugins' behavior -******************************************************* - -Users can use environment variables to :ref:`change input plugins' behavior ` or enable additional features. Output plugins use the same method to provide similar functionality. Just set an environment variable *before* calling linuxdeploy with the respective plugin enabled. For example: - -.. code:: bash - - # set environment variable to embed update information in an AppImage - > export UPDATE_INFORMATION="zsync|https://foo.bar/myappimage-latest.AppImage.zsync" - - # call linuxdeploy with the AppImage plugin enabled - > ./linuxdeploy-x86_64.AppImage --appdir AppDir <...> --output appimage - - -.. todo:: - - Document environment variables of existing output plugins - - - -.. _ref-linuxdeploy-iterative-workflow: - -Iterative workflow -++++++++++++++++++ - -.. todo:: - - This section is missing. Please consider adding it by filing a pull request against our `repository `__. diff --git a/source/packaging-guide/from-source/native-binaries.rst b/source/packaging-guide/from-source/native-binaries.rst deleted file mode 100644 index ccedda1..0000000 --- a/source/packaging-guide/from-source/native-binaries.rst +++ /dev/null @@ -1,272 +0,0 @@ -.. _ref-packaging-native-binaries: - -Packaging native binaries -========================= - -The easiest packaging methods are available for *native binaries*, like e.g., produced when compiling C++ or C code. Native binaries have a well defined and reliable behavior to find their runtime dependencies, the so-called shared libraries. These are the primary dependencies you will have to ship with your application. Of course, some applications might require additional resources, e.g., icon files. Also, some applications try to load libraries dynamically during the runtime. But for now, let's assume we have a basic binary application (this is the most common type). - -The AppImage team provides tools that simplify the packaging process significantly. These tools are semi-automatic, and ship with various features needed to bundle said shared library dependencies correctly. The one we are going to use in this guide is linuxdeploy_. - -.. _linuxdeploy: https://github.com/linuxdeploy - -linuxdeploy is an AppDir maintenance tool. Its primary focus is on AppDirs, AppImage is just one possible output format. It features a plugin system for greater flexibility in use. Plugins can either bundle additional resources for e.g., frameworks such as `Qt `__, toolkits such as `GTK `__, but are also used to provide output generators, e.g., for `AppImages `__. - - -.. contents:: Contents - :local: - :depth: 2 - - -Packaging from source ---------------------- - -Building applications from source and packaging them as AppImages is the most common scenario. In this section, it is described how apps that were built from source can be packaged into AppDirs, from which AppImages are being generated. - - -.. _ref-make-install-workflow: - -Using the build system to build the basic AppDir -++++++++++++++++++++++++++++++++++++++++++++++++ - -If you use a modern build system (such as for instance CMake_ or qmake_), you can use the provided `make install` commands to create an AppDir-like directory that can be used with linuxdeploy. - -As install configurations usually install all binaries, libraries, resources etc. in a way defined by the application author, this method provides a very easy and fast way to set up the basic AppDir. - -.. note:: - Of course, the application authors need to set up install configurations in their buildsystem, otherwise this method is not usable. Many applications have working install configurations, though. If not, you should ask the authors to add the relevant code to their build system. - - -CMake -''''' - -CMake provides an additional parameter to configure where the files are installed when running ``make install`` called |destdir|. If |destdir| is specified, CMake will "install" the files into the given directory instead of the filesystem root (:code:`/`). - -.. note:: - By default, CMake sets an internal variable called |cmake-install-prefix| to a path other than ``/usr`` to prevent users calling e.g., :code:`sudo make install` from damaging their system. The variable must explicitly be set to ``/usr`` therefore. - -.. |destdir| replace:: :code:`DESTDIR` -.. |cmake-install-prefix| replace:: :code:`CMAKE_INSTALL_PREFIX` - -Here's an example how to use this method: - -.. code-block:: bash - - # fetch sources (you could as well use a tarball etc.) - > git clone https://github.com/linuxdeploy/QtQuickApp.git - > cd QtQuickApp - - # build out of source - > mkdir build - > cd build - - # configure build system - # the flags below are the bare minimum that is needed, the app might define additional variables that might have to be set - > cmake .. -DCMAKE_INSTALL_PREFIX=/usr - - # build the application on all CPU cores - > make -j$(nproc) - - # now "install" resources into future AppDir - > make install DESTDIR=AppDir - -Now, ideally all the binaries and libraries the app needs are installed into a new directory called :code:`AppDir` in your build directory. - -.. note:: - The quality of the install configurations will vary from app to app. Please don't be surprised if the application is installed partially only. If the command doesn't exist at all, please fall back to bundling manually, which is described below. - - -qmake -''''' - -Qt's qmake_ also provides a variable to change the "target" of :code:`make install` calls called :code:`INSTALL_ROOT`. The qmake-based method is very similar to the CMake one. There's just one major difference: qmake does install into ``/usr`` by default already. - -Preparing a basic application is very simple, as the following example illustrates: - -.. code-block:: bash - - # get the source code - > git clone https://github.com/linuxdeploy/QtQuickApp.git - > cd QtQuickApp - - # create out-of-source build dir and run qmake to prepare the Makefile - > mkdir build - > cd build - > qmake .. - - # build the application on all CPU cores - > make -j$(nproc) - - # use make install to prepare the AppDir - > make install INSTALL_ROOT=AppDir - -Now, you have a new directory ``AppDir`` which ideally contains all the binaries, shared libraries etc., just like after finishing the CMake method. - - -Using linuxdeploy for building AppImages -++++++++++++++++++++++++++++++++++++++++ - -Now that we have the basic AppDir, we need to bundle dependencies into it to make the AppDir self-contained in preparation to make an AppImage from it. The following guide shows how linuxdeploy_ is used for this purpose. - -linuxdeploy describes itself as an `"AppDir maintenance tool" `__. Its primary focus is on AppDirs, and it uses plugins to create output formats such as AppImages. - -The following section describes how it can be used to deploy dependencies of applications into an AppDir that was created using the methods described in the :ref:`previous section `, and shows how this AppDir can eventually be packaged as an AppImage. - -.. seealso:: - Please see :ref:`ref-linuxdeploy` for more information on how to use linuxdeploy. - - -Bundling resources into the AppDir -'''''''''''''''''''''''''''''''''' - -Start by downloading linuxdeploy. The recommended way to get it is to use the AppImages provided on the `GitHub release page`_. - -.. note:: - At the moment, AppImages are provided for :code:`x86/i386` and :code:`x86_64/amd64` architectures, as other platforms cannot be targeted properly on the build service. The tool itself should support all major platforms, including ARM. You can compile linuxdeploy yourself to test it. Contributions adding new platforms welcome! - -.. _GitHub release page: https://github.com/linuxdeploy/linuxdeploy/releases/ - -After downloading the AppImage, you have to make it executable, as usual. Then, you can first run linuxdeploy on your AppDir: - -.. code-block:: bash - - > ./linuxdeploy-x86_64.AppImage --appdir AppDir - -This creates :code:`AppDir` if it doesn't exist yet. Inside :code:`AppDir` some basic directory structure is created that isn't necessarily required, but might be handy when adding resources manually to the AppImage. - -.. note:: - linuxdeploy supports an iterative workflow, i.e., you run it, and it will start to bundle resources. If there is a problem, it will show a detailed error message, and exit with an error code. You can then fix the issue, and call it again to try again. See :ref:`ref-linuxdeploy-iterative-workflow` for more information. - -If your application has installed itself properly, it should have installed a desktop file and an icon as well. The desktop file is used for :ref:`AppImage desktop integration `, and since desktop files require icons, an icon is always required, too. - -Example: - -.. code-block:: bash - - # get linuxdeploy's AppImage - > wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - > chmod +x linuxdeploy-x86_64.AppImage - - # run linuxdeploy and generate an AppDir - > ./linuxdeploy-x86_64.AppImage --appdir AppDir - -You can bundle additional resources such as icon files, executable and desktop files using the respective flags described in the ``--help`` text or on linuxdeploy's `homepage `__. - -.. note:: - Desktop file and icon are used for so-called :ref:`desktop integration `. If your build system didn't install such files into the right location, you can have linuxdeploy put your own files into the right places. Please see :ref:`ref-linuxdeploy-bundle-manually` for more information. - - -.. _ref-package-existing-binaries: - -Packaging existing binaries (or: manually packaging everything) ---------------------------------------------------------------- - -Packaging existing binaries is very simple as well. As the existing binaries don't provide facilities to :ref:`create a basic AppDir with the build system `, you have to package everything into the right place manually. - -Luckily, linuxdeploy supports such a workflow as well. It provides functionalities to automatically put the most common resources an application might use (such as binaries, libraries, desktop files and icons) into the right places without having the user to create any sort of structure or know where to put files. This is described in :ref:`ref-linuxdeploy-package-manually`. - -.. note:: - Many applications require more resources during runtime than just the binaries and libraries. Often, they require graphics for drawing a UI, or other files that are normally in a "known good location" on the system. These resources should be bundled into the AppImage as well to make sure the AppImage is as standalone as possible. However, linuxdeploy cannot know which files to bundle. - - Please consult the applications' documentation (e.g., homepage or man pages) to see what kinds of resources must be put into the AppImage. This can involve some trial-and-error, as you need to :ref:`test your AppImages on different systems ` to find possible errors. - -.. warning:: - In order to be packaged as AppImages, applications must load the resources relative to their main binary, and not from a hardcoded path (usually ``/usr/...``). This is called :ref:`relocatability `. - - If your app doesn't load resources from the AppImage, but e.g., shows errors it couldn't find resources, it is most likely not relocatable. In this case, you must ask the author of the application to make it relocatable. Many modern frameworks such as Qt even provide functionality to implement this easily. In some cases, there's also flags you can specify when building from source to make applications relocatable. - - -Bundling additional resources using linuxdeploy plugins -------------------------------------------------------- - -As mentioned previously, linuxdeploy provides a plugin system. So-called "input" plugins can be used to bundle additional resources, such as Qt plugins, translations, etc. - -Please see :ref:`ref-linuxdeploy-input-plugins` for more information. - - -.. _ref-linuxdeploy-plugin-appimage-user-guide: - -Build AppImages from AppDir using linuxdeploy ---------------------------------------------- - -As mentioned previously, linuxdeploy uses plugins to create actual output files from AppDirs. For AppImages, there's `linuxdeploy-plugin-appimage `__. - -To create AppImages, just add ``--output appimage`` to your linuxdeploy call to enable the plugin. An AppImage will be created using :ref:`ref-appimagetool`. - -Minimal example: - -.. code-block:: bash - - > ./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage - -As most plugins, linuxdeploy-plugin-appimage provides some environment variables to enable additional functionality, such as: - -``SIGN=1`` - Sign AppImage. See :ref:`ref-signing-appimages` for more information. - -``UPDATE_INFORMATION=zsync|...`` - Add update information to the AppImage, and generate a ``.zsync`` file. - -.. seealso:: - More information on the environment variables can be found in the `README `__, including a complete (and up to date) list of supported environment variables. - - -Examples --------- - -In this section, some examples how linuxdeploy can be used are shown. - -QtQuickApp -++++++++++ - -This section contains a few example scripts that showcase how AppImages can be built for `QtQuickApp `__, a basic demonstration app based on QtQuick, using some QML internally. It can be built using both CMake and qmake. We use it to show some example scripts how AppImages can be built for it, using the methods introduced in this guide. - - -Using qmake and ``make install`` -'''''''''''''''''''''''''''''''' - -The following script might be used to create AppImages for QtQuickApp, using qmake and ``make install`` strategy. - -.. literalinclude:: examples/bundle-qtquickapp-with-qmake.sh - :name: bundle-qtquickapp-with-qmake - :caption: :code:`travis/build-with-qmake.sh` - :language: bash - :linenos: - -.. note:: - We're using a separate bash script that runs in an isolated, temporary directory to prevent modifications to the existing source code or the system. - - Many examples "hack" those instructions directly into their CI configuration, e.g., ``.travis.yml``. This approach has many problems, most notably that it's impossible to test those scripts locally. By extracting the whole process into a script, it becomes quite simple to test the build script locally as well as run it in the CI system. - - An example :code:`.travis.yml` is included in a later section, showing how the script can be run on Travis CI. It's quite generic, you should be able to copy it without having to make too many modifications. - - -Using CMake and ``make install`` -'''''''''''''''''''''''''''''''' - -The following script might be used to create AppImages for QtQuickApp, using CMake and ``make install`` strategy. It is effectively the same script as the ``qmake`` one, but uses CMake instead of qmake to build the binaries and install the data into the AppDir. - -.. literalinclude:: examples/bundle-qtquickapp-with-cmake.sh - :name: bundle-qtquickapp-with-cmake - :caption: :code:`travis/build-with-cmake.sh` - :language: bash - :linenos: - - -Integrate build scripts into CI systems -''''''''''''''''''''''''''''''''''''''' - -Travis CI -********* - -The scripts introduced in the previous subsections will move the files back into the directory where they're called. Therefore, the :code:`.travis.yml` and especially the :code:`script` file can be kept delightfully short: - -.. literalinclude:: examples/.travis.yml - :name: bundle-qtquickapp - :caption: :code:`.travis.yml` - :language: yaml - :linenos: - - -.. seealso:: - - Please see the :ref:`ref-travis-ci` section in the :ref:`ref-hosted-services` section for more information on Travis CI. It also contains a guide on :ref:`uploadtool `. diff --git a/source/packaging-guide/hosted-services/index.rst b/source/packaging-guide/hosted-services/index.rst deleted file mode 100644 index 611aed7..0000000 --- a/source/packaging-guide/hosted-services/index.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. _ref-hosted-services: - -Hosted services -=============== - -There's some hosted services which can help with building AppImages. These services are described in the following section. - -.. note:: - The services listed in this section is not exclusive. Many other services, especially generic CI services, can be used to build AppImages. The following services just have been tested and are known to work. For some of them, there's some example scripts, etc. - -.. toctree:: - travis-ci - opensuse-build-service - :caption: Contents - :maxdepth: 2 diff --git a/source/packaging-guide/hosted-services/travis-ci.rst b/source/packaging-guide/hosted-services/travis-ci.rst deleted file mode 100644 index a29710e..0000000 --- a/source/packaging-guide/hosted-services/travis-ci.rst +++ /dev/null @@ -1,97 +0,0 @@ -.. _ref-travis-ci: - -Bundling your Travis CI builds as AppImages -=========================================== - -Services such as Travis CI make it easy to build software automatically whenever a new commit is pushed to the source code repository. How you turn your build products into an AppImage depends on how your application is built. Generally there are two main methods, namely :ref:`producing an application directory `, and using :ref:`tools to automate the process `. - - -.. contents:: Contents - :local: - :depth: 1 - - -Producing an application directory using bash scripts ------------------------------------------------------ - -Some types of applications can best be converted into application directories using custom bash script. However, to facilitate this, there is a collection of convenience functions in https://github.com/AppImage/pkg2appimage/blob/master/functions.sh which can use in your own scripts. - -.. todo:: - - Document the functions in :code:`functions.sh` that are for public consumption based on comments in the file. - - -.. note:: - - For most types of applications, especially those compiled with compilers such as :code:`gcc` or :code:`g++` using a tool like :ref:`ref-linuxdeploy` is much easier than doing this in a bash script because it automates much of the process. - - -Producing an application directory using linuxdeploy ----------------------------------------------------- - -Please refer to the chapter :ref:`ref-packaging-from-source`. - -For general information on linuxdeploy, see :ref:`ref-linuxdeploy`. - - -.. _ref-uploadtool: - -Uploading the generated AppImage --------------------------------- - -Once an Appimage has been generated, you want to upload it to GitHub Releases. For this, you can use the :code:`upload.sh` script available in the `uploadtool repository`_. - -.. note:: - - It is best practice to upload binaries (such as AppImages) to GitHub Releases rather than committing them into the repository itself. - - -Super simple uploading of continuous builds (each push) to GitHub Releases. If this is not the easiest way to upload continuous builds to GitHub Releases, then it is a bug. - - -Using ``upload.sh`` -^^^^^^^^^^^^^^^^^^^ - -The :code:`upload.sh` script in the `uploadtool repository`_ is designed to be called from Travis CI after a successful build. By default, this script will *delete* any pre-existing release tagged with :code:`continuous`, tag the current state with the name :code:`continuous`, create a new release with that name, and upload the specified binaries there. For pull requests, it will upload the binaries to transfer.sh instead and post the resulting download URL to the pull request page on GitHub. - -.. _uploadtool repository: https://github.com/probonopd/uploadtool - -- On https://github.com/settings/tokens, click on "Generate new token" and generate a token with at least the :code:`public_repo`, :code:`repo:status`, and :code:`repo_deployment` scopes -- On Travis CI, go to the settings of your project at :code:`https://travis-ci.org/yourusername/yourrepository/settings` -- Under "Environment Variables", add key :code:`GITHUB_TOKEN` and the token you generated above as the value. **Make sure that "Display value in build log" is set to "OFF"!** -- In the :code:`.travis.yml` of your GitHub repository, add something like this (assuming the build artifacts to be uploaded are in out/): - -.. code-block:: yaml - - after_success: - - ls -lh out/* # Assuming you have some files in out/ that you would like to upload - - wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh - - bash upload.sh out/* - - branches: - except: - - # Do not build tags that we create when we upload to GitHub Releases - - /^(?i:continuous)$/ - - -Environment variables -##################### - -:code:`upload.sh` normally only creates one stream of continuous releases for the latest commits that are pushed into (or merged into) the repository. - -It's possible to use :code:`upload.sh` in a more complex manner by setting the environment variable :code:`UPLOADTOOL_SUFFIX`. If this variable is set to the name of the current tag, then :code:`upload.sh` will upload a release to the repository (basically reproducing the :code:`deploy:` feature in :code:`.travis.yml`). - -If :code:`UPLOADTOOL_SUFFIX` is set to a different text, then this text is used as suffix for the :code:`continuous` tag that is created for continuous releases. This way, a project can customize what releases are being created. - -One possible use case for this is to set up continuous builds for feature or test branches: - -.. code-block:: shell - - if [ ! -z $TRAVIS_BRANCH ] && [ "$TRAVIS_BRANCH" != "master" ] ; then - export UPLOADTOOL_SUFFIX=$TRAVIS_BRANCH - fi - - -This will create builds tagged with :code:`continuous` for pushes/merges to :code:`master` and with :code:`continuous-` for pushes / merges to other branches. - -The two environment variables :code:`UPLOADTOOL_PR_BODY` and :code:`UPLOADTOOL_BODY` allow the calling script to customize the messages that are posted either for pull requests or merges/pushes. If these variables aren't set, generic default texts are used. diff --git a/source/packaging-guide/index.rst b/source/packaging-guide/index.rst index 786cd30..7ed83b3 100644 --- a/source/packaging-guide/index.rst +++ b/source/packaging-guide/index.rst @@ -1,18 +1,20 @@ -.. _ref-packaging-guide: +.. include:: ../substitutions.rst + +.. _packaging-guide: Packaging Guide =============== -This chapter shows application developers how to produce AppImages, how to make them updateable and how to digitally sign them. +This chapter shows application developers how to create AppImages using modern AppImage creation tools (and explains the advantages, disadvantages and differences between the individual tools). It also covers all requirements for that, e.g. creating desktop entry and icon files, |packaging_optional| .. toctree:: - introduction - overview - from-source/index - converting-binary-packages/index - optional/index - hosted-services/index - manual + desktop-icon-files + appimage-creation-tools/index + creating-appdir-structure/index + updates + signatures + appstream + packaging-automation/index testing distribution environment-variables diff --git a/source/packaging-guide/ingredients.rst b/source/packaging-guide/ingredients.rst deleted file mode 100644 index dcd011b..0000000 --- a/source/packaging-guide/ingredients.rst +++ /dev/null @@ -1,7 +0,0 @@ -:orphan: - -.. _ref-ingredients: - -What goes into an AppImage -========================== - diff --git a/source/packaging-guide/introduction.rst b/source/packaging-guide/introduction.rst deleted file mode 100644 index 761a27a..0000000 --- a/source/packaging-guide/introduction.rst +++ /dev/null @@ -1,13 +0,0 @@ -Introduction to Packaging -========================= - -So you decided to make an AppImage or two? Great! Or did you just come here to get some insights into how AppImages can be built? Let's have a look. - -There are many different approaches how to build AppImages. Often, packaging an AppImage correctly depends on the application that you're trying to put into one, the so-called *payload*. Different programming languages (or, rather, different application types (i.e., native binaries, scripts, bytecode, etc.)) require different methods. - -All application bundling attempts have one thing in common: the "input format" which is then turned into an AppImage using :ref:`appimagetool `. This input format is called AppDir, and is described in the :ref:`AppDir specification `. - -In a nutshell: packaging AppImages is building an AppDir. This AppDir is then simply turned into an AppImage. But if your AppDir is not built correctly, the AppImage won't work. - -Of course, you're not left alone with this challenge. There are official as well as unofficial tools that allow you to create working AppDirs. These are described in the following sections. Just pick the one you think suits your needs, and start making AppImages. - diff --git a/source/packaging-guide/manual.rst b/source/packaging-guide/manual.rst deleted file mode 100644 index 885004b..0000000 --- a/source/packaging-guide/manual.rst +++ /dev/null @@ -1,97 +0,0 @@ -.. _ref-manual: - -Manual packaging -================ - -Create an AppDir manually, then turn it into an AppImage. Start out with the example below, then check the examples on bundling certain applications or type of applications as AppImages from the right-hand side **"Pages"** menu. - - -.. contents:: Contents - :local: - :depth: 1 - - -.. _ref-creating-an-appdir-manually: - -Creating an AppDir manually -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In practice, you will probably never do this by hand. So this is mainly to illustrate the concept. - -Create an AppDir structure that looks (as a minimum) like this:: - - MyApp.AppDir/ - MyApp.AppDir/AppRun - MyApp.AppDir/myapp.desktop - MyApp.AppDir/myapp.png - MyApp.AppDir/usr/bin/myapp - MyApp.AppDir/usr/lib/libfoo.so.0 - -The :code:`AppRun` file can be a script or executable. It sets up required environment variables such as :code:`$PATH` and launches the payload application. You can write your own, but in most cases it is easiest (and most error-proof) to use a precompiled one from this repository. - -Of course you can leave out the library if your app does not need one, or if all libraries your app needs are already contained in every base operating system you are targeting. - - -.. _ref-no-hard-coded-paths: - -No hard-coded paths -^^^^^^^^^^^^^^^^^^^ - -Your binary, myapp, must not contain any hardcoded paths that would prevent it from being relocateable. You can check this by running - -.. code-block:: shell - - strings MyApp.AppDir/usr/bin/myapp | grep /usr - -Should this return something, then you need to modify your app programmatically (e.g., by using relative paths, using `binreloc `__, or using :code:`QString QCoreApplication::applicationDirPath()`). - -If you prefer not to change the source code of your app and/or would not like to recompile your app, you can also patch the binary, for example using the command - -.. code-block:: shell - - sed -i -e 's#/usr#././#g' MyApp.AppDir/usr/bin/myapp - -This usually works as long as the application is not doing a :code:`chdir()` which would break this workaround, because then :code:`././` would not be pointing to :code:`$APPDIR/usr` any more. You can run the following command to see whether the application is doing a :code:`chdir()` (99% of GUI applications don't) - -.. code-block:: shell - - strace -echdir -f ./AppRun - -Also see: - https://www.gnu.org/software/gnulib/manual/html_node/Supporting-Relocation.html - - -It has been a pain for many users of GNU packages for a long time that packages are not relocatable. The relocatable-prog module aims to ease the process of making a GNU program relocatable. - -.. note:: - The same is true for any helper binaries and/or libraries that your app depends on. You check this and patch it with - - .. code-block:: shell - - cd MyApp.AppDir/usr/ - find . -type f -exec sed -i -e 's#/usr#././#g' {} \; - cd - - - which replaces all occurrences of :code:`/usr` with :code:`././`, which simply means "here". - -myapp.desktop should contain (as a minimum): - -.. code-block:: ini - - [Desktop Entry] - Name=MyApp - Exec=myapp - Icon=myapp - Type=Application - Categories=Utility; - -Be sure to pick one of the `Registered Categories`_, and be sure that your desktop file passes validation by using :code:`desktop-file-validate your.desktop`. If you are not deploying an application with a graphical user interface (GUI) but a command line tool (for the terminal), make sure to add :code:`Terminal=true`. - - -Creating an AppImage from the AppDir -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To create an AppImage, run :code:`appimagetool` on the AppDir in order to turn it into an AppImage. You can get it from this repository's `Releases`_ page (it comes as an AppImage itself; yes, we eat our own dogfood). - -.. _Registered Categories: https://standards.freedesktop.org/menu-spec/latest/apa.html -.. _Releases: https://github.com/AppImage/AppImageKit/releases diff --git a/source/packaging-guide/optional/appstream-generator.html b/source/packaging-guide/optional/appstream-generator.html deleted file mode 100644 index 0d938f2..0000000 --- a/source/packaging-guide/optional/appstream-generator.html +++ /dev/null @@ -1,812 +0,0 @@ - - -
-

General Settings

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Metadata license: - -
Project license: - -
Name of the desktop file (without .desktop): - -
Name of the application (proper capitalization): - -
Summary (no dot at the end): - -
Description (full sentence(s) with a dot at the end): - -
Homepage (full URL): - -
Screenshot (full URL) - -
- -

For more information, please refer to the AppStream documentation's Quickstart section.

- - - - - - -
diff --git a/source/packaging-guide/optional/appstream.rst b/source/packaging-guide/optional/appstream.rst deleted file mode 100644 index de4f975..0000000 --- a/source/packaging-guide/optional/appstream.rst +++ /dev/null @@ -1,39 +0,0 @@ -.. _ref-appstream: - -AppStream metadata -================== - -AppStream is a cross-distribution effort for providing metadata for software in the (Linux) ecosystem. -It provides a convenient way to get information about not installed software, -and is one of the building blocks for software centers. - - -.. contents:: Contents - :local: - :depth: 1 - - -Why should I include AppStream metadata in my AppImage? -------------------------------------------------------- - -Desktop environments, file managers, AppImage catalogs, software centers, and app stores can use metadata about the application from inside the AppImage to get a description, URLs, screenshots, and other information that describes the application. This optional metadata travels inside the AppImage. - -So if you would like your application to show a nice screenshot in app centers, you should add an AppStream metainfo file to your AppImage. AppStream is a format that exists independently of AppImage and can be used in conjunction with other packaging formats as well. Many open source applications already come with AppStream metainfo files by default. - -.. seealso:: - More information on AppStream can be found on the `FreeDesktop.org pages `__. - - -Using the AppStream generator ------------------------------ - -An easy way to generate an AppStream metainfo file is to use our generator below. - -.. raw:: html - :file: appstream-generator.html - - -Embedding the AppStream metadata --------------------------------- - -Once you have generated a suitable AppStream metainfo file, place it into :code:`usr/share/metainfo/myapp.appdata.xml` in your AppDir, and generate an AppImage from it. It is generally a good idea to check AppStream metainfo files for errors using the :code:`appstreamcli` and/or :code:`appstream-util` command line tools. :code:`appimagetool` will automatically attempt to validate the AppStream metainfo file if :code:`appstreamcli` and/or :code:`appstream-util` are available on the :code:`$PATH`. diff --git a/source/packaging-guide/optional/index.rst b/source/packaging-guide/optional/index.rst deleted file mode 100644 index 76d0ba8..0000000 --- a/source/packaging-guide/optional/index.rst +++ /dev/null @@ -1,19 +0,0 @@ -Optional Resources and Features -=============================== - -If you have followed our packaging guide to this point: congratulations! You should have a working AppImage by now. - -However, the produced AppImage can be improved further. We provide some additional features such as :ref:`binary delta updating ` and a standardized and verifiable :ref:`signature mechanism `. - -Also, you can add optional resources such as :ref:`AppStream metadata ` to allow tools which work with AppImages such as :ref:`AppImageHub ` to display additional information about your AppImage. - -The following section explains these optional features and resources, and shows how these can be enabled resp. added. - - -.. toctree:: - updates - signatures - appstream - :caption: Contents - :maxdepth: 2 - diff --git a/source/packaging-guide/optional/signatures.rst b/source/packaging-guide/optional/signatures.rst deleted file mode 100644 index 1a71b00..0000000 --- a/source/packaging-guide/optional/signatures.rst +++ /dev/null @@ -1,83 +0,0 @@ -Signing AppImages -================= - -AppImages can be digitally signed by the person that has produced the AppImage. This ensures that the AppImage comes from the person who pretends to be the author, and ensures that the file has not been tampered with. - -The AppImages specification allows the AppImage file to carry a digital signature built into the AppImages. This means that the signature does not need to be an external file, but can be carried inside the AppImage itself, similar to how signatures work for traditional Linux packages (such as :code:`.deb` or :code:`.rpm` files). - - -.. contents:: Contents - :local: - :depth: 1 - - -Embedding a signature inside an AppImage ----------------------------------------- - -While it would be possible to embed signatures manually, the easiest way to produce a digitally signed AppImage is to use the :code:`appimagetool` command line tool. The internally uses :code:`gpg` or :code:`gpg2` if it is installed and configured on the system. - -Especially, a key for signing must be prepared before AppImages can be signed. If the machine on which the AppImage is being generated does not have a valid signing key yet, a new one can be generated using - -.. code-block:: shell - - $ gpg2 --full-gen-key - - -Please refer to the :code:`gpg` or :code:`gpg2` documentation for additional information. You should take additional care to backup your private and public keys in a secure location. - -Once you're signing keys have been set up, you can sign AppImages at AppImage creation time using - -.. code-block:: shell - - $ ./appimagetool-x86_64.AppImage some.AppDir --sign - - -This will sign the AppImage with :code:`gpg[2]` and will put the signature into the AppImage. - - -Reading the signature ---------------------- - -You can display the digital signature that is embedded in AppImage by running the AppImage with the :code:`--appimage-signature` option like this: - -.. code-block:: shell - - $ ./XChat_IRC-x86_64.AppImage --appimage-signature - - -----BEGIN PGP SIGNATURE----- - Version: GnuPG v2 - - iQEcBAABCAAGBQJX6CN9AAoJENBdKWeGw9/dsvoH/RgEggMiNTwgyA4io2Dyy1j1 - 6U3CQST9HVmh9PjeFKZCgFCZbHvpFz9mzhLTPlOAbczBnSmmbgqROINaLW+1tqEx - stOy67D3Z1cySzRTOhSkjiUOP5unmZL6QTNPxRHmuRkyihv7YfAlkrogXQlYbZ1h - Ilt6jU1b97GSPox/EE3Z002iZGJYQ3FfjAlp9o947goY5koA5KYqyzTCvEjhTk/L - wz1mFcjEkzHt9CaHZfrZCE3QVSBTq071wzsHCFHaJswPhA6iI0psCnFY56PPResi - uljTQr3nOBaqNyUgU3y4Tbd+36cwggSaTpGAzlhgNoalIwB1ltFSdPeRPe4Q3Qc= - =MR0w - -----END PGP SIGNATURE----- - - -.. note:: - - Please note that while this displays the signature, it does not validate the signature. In other words, this does not tell you whether the signature is valid or not, or whether the file has been tampered with or not. To validate the signature, an external tool (which is not part of AppImage that needs to be validated) needs to be used. - - -Validating the signature ------------------------- - -To validate a signature of an an AppImage and to determine whether an AppImage has been compromised, an external tool needs to be used. There is a very simple tool called :code:`validate` that can do this. - -.. code-block:: shell - - $ chmod a+x ./validate - $ ./validate ./XChat_IRC-x86_64.AppImage - - gpg: Signature made Sun 25 Sep 2016 10:41:24 PM CEST using RSA key ID 86C3DFDD - gpg: Good signature from "Testkey" [ultimate] - - -Signature validation can also be integrated into higher level software such as the optional :code:`appimaged` daemon and/or :code:`AppImageUpdate`. For example the :code:`appimaged` daemon may decide to run applications without a valid signature in a confined sandbox in the future, if the system is set up accordingly. - -.. todo:: - - It may be desirable to integrate validate functionality into :code:`libappimage` and into tools like :code:`appimagetool`, the optional :code:`appimaged` demon and/or :code:`AppImageUpdate`. diff --git a/source/packaging-guide/optional/updates.rst b/source/packaging-guide/optional/updates.rst deleted file mode 100644 index ae3bfc7..0000000 --- a/source/packaging-guide/optional/updates.rst +++ /dev/null @@ -1,336 +0,0 @@ -.. _ref-updates: - -Making AppImages updateable -=========================== - -AppImages can be updated: - - * Via external tools (e.g., :code:`AppImageUpdate` or the :code:`appimageupdatetool` command line tool) - * Via an updater tool built into the AppImage itself - * By consuming :code:`libappimageupdate` functionality inside the payload application - - -.. contents:: Contents - :local: - :depth: 2 - - -Making AppImages updateable via external tools ----------------------------------------------- - -To make an AppImage updateable, you need to embed information that describes where to check for updates and how into the AppImage. Unlike other Linux distribution methods, the information where to look for updates is not contained in separate repository description files such as :code:`sources.list` that need to be managed by the user, but is directly embedded inside the AppImage by the author of the respective AppImage. This has the advantage that the update information always travels alongside the application, so that the end user does not have to do anything special in order to be able to check for updates. - - -Using appimagetool -^^^^^^^^^^^^^^^^^^ - -Use :code:`appimagetool -u` to embed update information (as specified in the AppImageSpec) and generate the corresponding :code:`.zsync` file you can upload to the place mentioned in the update information. - -.. code-block:: shell - - appimagetool videocapture.AppDir/usr/share/applications/*.desktop -u "zsync|https://lyrion.ch/opensource/repositories/videocapture/uv/videocapture.AppImage.zsync" - - -The string - -.. code-block:: text - - zsync|https://lyrion.ch/opensource/repositories/videocapture/uv/videocapture.AppImage.zsync - -is called the *update information*. - -Please see https://github.com/AppImage/AppImageSpec/blob/master/draft.md#update-information for a description of allowable types of update information. - - -Using linuxdeploy -^^^^^^^^^^^^^^^^^ - -:ref:`linuxdeploy's ` `AppImage plugin `__ supports an environment variable ``$UPDATE_INFORMATION`` (or short ``$UPD_INFO``) that can be used to set the update information manually. - -Please see `the README `__ for details. - - -Using linuxdeployqt -^^^^^^^^^^^^^^^^^^^ - -:code:`linuxdeployqt` uses :code:`appimagetool` internally. If it recognizes that it is running on Travis CI, then it automatically generates the matching update information. - - -Using electron-builder -^^^^^^^^^^^^^^^^^^^^^^ - -:code:`electron-builder` promotes its own updater scheme rather than the update information described in this documentation, in order to have the same mechanism on Linux as is used on Windows. Unfortunately this means that AppImages generated by :code:`electron-builder` cannot be updated using the usual tools. - -One way to inject the update information into the AppImage created with :code:`electron-builder` nevertheless is to extract the AppImage generated with :code:`electron-builder` to an AppDir using the --appimage-extract command line option of the AppImage, and then re-packing it as an AppImage by using :code:`appimagetool -u`. - - -Making AppImages self-updateable --------------------------------- - -Once you have made your AppImage updateable via external tools as described above, you may optionally go one step further and bundle everything that is required to update an AppImage inside the AppImage itself, so that the user can get updates without needing anything besides the AppImage itself. This is conceptually similar to how the `Sparkle Framework `__ works on macOS. - - -Via AppImageUpdate built into the AppImage -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You can bundle :code:`AppImageUpdate` itself inside the AppImage of your application. In order to have the bundled AppImageUpdate update your running AppImage when the user invokes some command in your application (e.g., an "Update..." menu) in your GUI, simply have your application invoke :code:`AppImageUpdate $APPIMAGE`. If :code:`AppImageUpdate` is bundled inside the AppImage and is on the :code:`$PATH`, this will work. - - -By using `libappimageupdate` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Recommended user experience -########################### - -One advantage of the AppImage format is that it gives full control to application authors over the end user experience. Hence, using AppImage and AppImageUpdate, application authors can implement almost any of the schemes outlined above. In order to maintain a consistent and positive user experience with AppImages and AppImageUpdate, we recommend application authors to follow the following **Golden Rules**: - -* Never download updates without the user's explicit consent, be it in the form of per-update consent, or, optionally, opt-in consent for automatic updates. Thanks for not killing users' mobile data plans by downloading stuff without asking -* Respect global flags for **"do not check for new versions"** and **"do not attempt to update"**. The user may be running a central updating daemon that manages updates for the whole system, in which case any and all attempts to update the application from within itself should be skipped. **We need to define those flags for 1) per-system and 2) per-user configuration and 3) ENV** (similar to how the old :code:`desktopintegration` script was set up not to interfere with :code:`appimaged`) -* Do not bother the user with updates directly as the first thing when the application is launched. When opening an application for the first time, users should see something meaningful to give a positive impression and show immediately what the application is all about (after all, we are automatically taking a screenshot of what your application shows directly after it has been launched for AppImageHub) -* Ask the user for permission before doing version checks. Many open source users value privacy highly and don't appreciate the "phone home" aspect of forced version checks, which effectively are a form of tracking - -.. Old image can be found here: https://github.com/AppImage/appimage.github.io/blob/ef13aae415fae3c8f52b1326585b4b5df1b94de8/database/SonicVisualiser/screenshot.png - -.. image:: /_static/img/packaging-guide/updates-realworld-example.png - :alt: SonicVisualiser GUI asking for network access permission - :width: 80% - -* The update should ideally be nicely integrated into the GUI of your application, using whatever GUI toolkit you are using. We are interested in getting libraries for popular GUI toolkits like Qt, Gkt+ 2 and 3, WxWidgets, etc. - so if you implement this, please share with the world -* During the update process, your application should remain fully usable (this works because the original file is not changed by the update process; instead a new file with the new version is placed next to the original one) -* Releases should always update to releases, nightlies always to nightlies, etc. ("channels") -* Whenever the application encounters issues (e.g., a crash reporter comes up) it could ask the user to check for updates, and accept bug reports only if no newer version is available in the channel - - -Building and linking libappimageupdate -###################################### - -.. note:: This guide assumes you are using Git and CMake to build your project. - -There's two options how to add libappimageupdate to your project: Either you use a Git submodule (the preferred way), or you use CMake's :code:`ExternalProject`. The latter is a more complex issue and has some implications, therefore this guide focuses on the former option. - -The guide assumes the following directory layout:: - - / # repository root - lib/ # external libraries - ... # other libraries that might be used - CMakeLists.txt # manages the dependencies for CMake - src/ # source files - CMakeLists.txt # defines the binaries to build - main.cpp # main application - CMakeLists.txt # top level CMake configuration - - -First of all, add the AppImageUpdate repository as a submodule. - -.. code-block:: shell - - $ git submodule add https://github.com/AppImage/AppImageUpdate lib/AppImageUpdate - - -You will have to initialize your submodule. AppImageUpdate pulls in some dependencies as well. Therefore, anyone using your repository will have to run the following command after cloning (unless they called :code:`git clone --recursive`): - -.. code-block:: shell - - $ git submodule update --init --recursive - - -Please refer to the `Git book `__ for more information about submodules and how they work, how to update them etc. - -Next, instruct CMake that you want to use the library. Add :code:`add_subdirectory(AppImageUpdate)` to :code:`lib/CMakeLists.txt`. - -.. note:: - - You need to call :code:`add_subdirectory(lib)` within the top-level :code:`CMakeLists.txt` near the top before defining executables etc. to make this work. Furthermore, somewhere below, CMakeLists.txt needs to include the :code:`src` directory. Like with the :code:`lib` directory, there should be a :code:`add_subdirectory(src)` call. - - -Now instruct CMake to link your libraries and/or executables to libappimageupdate. AppImageUpdate's CMake build infrastructure defines a target :code:`libappimageupdate`. - -Open :code:`src/CMakeLists.txt`, find your :code:`add_library/add_executable` call, and add the following snippet below: - -.. code-block:: cmake - - target_link_libraries(mytarget PRIVATE libappimageupdate) - - -Now everything should be up and running! Congratulations! - - -Using libappimageupdate within app store like applications -########################################################## - -Consider the following scenario: - -You have an app store app managing AppImages. As you know, AppImages don't require an installation. The only thing you have to do is download them and make them executable, and your users can run them. To remove them from the system, all that has to be done is removing a single file from the file system. - -So far, so good. But what about updates? Ideally, the upstream projects are actively developed, and publish releases regularly. However, with technologies like Electron becoming more and more popular, AppImage file sizes of several 10s of MiB are pretty common. Games even have a few 100 MiB, bundling all the data. - -To mitigate those problems, AppImageUpdate provides an efficient solution to these problems. It compares the local AppImage with the remote, up to date file, uses all usable data from the existing file, and downloads the remaining data only. This does not only save a lot of bandwidth, but also speeds up the update processes. - -libappimageupdate provides a class called :code:`appimage::update::Updater` capable of updating a single AppImage. It contains features like an update check, running updates in a separate thread, a status message system, progress indicator support and a lot more. - -Basic usage: - -.. code-block:: cpp - - using namespace appimage::update; - using namespace std; - - Updater updater("test.AppImage"); - - -Now, you can use the :code:`updater` object to perform operations. The API is built on the principle of *pervasive error handling*, i.e., all operations that might fail in any way provide error handling. In libappimageupdate, this is implemented by making such methods become boolean, and accept a reference to the result type which is set in case of success. The method returns either :code:`true`, which means the operation succeeded, or :code:`false` otherwise. - -See this easy example for an update check: - -.. code-block:: cpp - - // check for update - bool updateAvailable; - - if (!updater.checkForChanges(updateAvailable)) { - // return error state - return 1; - } - - if (updateAvailable) { - // perform update ... - - -This is faster and less verbose than an exception based workflow, however, you can't see what caused the update check to fail. - -This can be found out using the built in status message system. Every :code:`Updater` instance contains a message queue. All methods within the updater and the systems it uses (like e.g., `ZSync2 `__, which is one of the backends for the binary delta updates) add messages to this queue, which means that all kinds of status messages ever generated by any of the libraries will end up there. - -.. note:: - - Beware that this is a totally optional system, and it might not necessarily improve the user experience to show those messages. It is recommended to show them only in case of errors to help debugging. There is also no guarantee on the order of these messages. - - -All messages are preserved, so if they are not fetched, they might stack up. However, that shouldn't be a problem really. Just make sure to clean up (:code:`delete`) your :code:`Updater` objects as soon as you don't need them any more. - -Let's rewrite the update check code from above, with advanced error handling: - -.. code-block:: cpp - - // check for update - bool updateAvailable; - - if (!updater.checkForChanges(updateAvailable)) { - // log status messages before exiting - - // nextStatusMessage will return true as long as there are status messages - // by calling it in a loop as follows, all available messages will be fetched - string nextMessage; - while (updater.nextStatusMessage(nextMessage)) { - // imagine log() to do something meaningful - log(nextMessage); - } - - // return error state - return 1; - } - - if (updateAvailable) { - // perform update ... - } - - -Now, in case the update check fails, the messages are logged. - -At the moment, the update check is performed synchronously as it won't take too long. This might be changed eventually, but now allows for running an update check without modifying the updater state. - -Talking about updater states, the state is modified by running an update. As mentioned previously, updates are performed in their own thread automatically, using C++11 threading functionality. This allows for displaying progress, status messages etc. in a UI without any blocking issues or the need to run your own thread. - -.. note:: - - **Important**: Before actually performing an upgrade, it is recommended to check for updates first. The update check only performs reading IO, but a pointless update will create an entirely new file, even if it copies all the data from its predecessor. - - -Here's some code how to run an update, and log progress and status messages until the update has finished: - -.. code-block:: cpp - - updater.start() - - // isDone() returns true as soon as the update has finished - // error handling is performed later - while (!updater.isDone()) { - // sleep for e.g., 100ms, to prevent 100% CPU usage - this_thread::sleep_for(chrono::milliseconds(100)); - - double progress; - // as with all methods, check for error - if (!updater.progress(progress)) { - log("Call to progress() failed"); - // return error state - return 1; - } - - // progress() returns a double between 0 and 1 - // you might have to scale its return value accordingly - // this assumes that the progress bar expects a percentage - updateProgressBar(progress * 100); - - // fetch all status messages - // this is basically the same as before - string nextMessage; - while (updater.nextStatusMessage(nextMessage)) { - log(nextMessage); - } - } - - -As you will have noticed, this code will just run until the update is done. However, there is no way to verify that the update actually worked. Therefore, you need to check for errors in the next step: - -.. code-block:: cpp - - if (updater.hasError()) { - log("Error occurred. See previous messages for details."); - // return error state - return 1; - } - - -As the background work has finished, and :code:`hasError()` itself doesn't log any messages, all messages from the status message queue are displayed already, hence the note about checking the previous messages. It was mentioned previously that logging all messages might not be good for the user experience, so you could as well move the little loop fetching the messages to this error handler, and show a modal dialog containing all the messages issued during the update process. But this is up to you. - -One last thing to notice is that AppImageUpdate by default takes the filename of the remote file for creating the updated AppImage file instead of overwriting the local file. This is done on purpose for several reasons. First, it might not be intended to overwrite previous versions of an AppImage, allowing to have different versions in parallel, or testing the current version versus the update that has just been downloaded. - -This behavior implies the need for a method to actually fetch the path to this new file from the updater. This can be done as follows: - -.. code-block:: cpp - - ostringstream oss; - - string pathToUpdatedFile; - - // this method shouldn't fail at this point(1) any more - // but it's better to check for its return value to make sure everything's alright - // (1) when calling this before or while the update is running, the new path is not - // available, causing this method to return false, but we're past those points already - if (!updater.pathToNewFile(pathToUpdatedFile)) - - oss << "Path to updated AppImage: " << pathToUpdatedFile; - log(oss.str()); - - -.. note:: - - The updater takes care of putting the new file in the same directory as the previous one. - - -As you might not be interested in this feature, and probably don't trust on remote filenames and choose your own ones when "installing" (well, downloading) AppImages to make it easier to find them again, you can override this feature. You can instantiate the :code:`Updater` object with an optional flag: - -.. code-block:: cpp - - // constructor signature as of 2017/11/14: - // Updater::Updater(std::string path, bool overwrite = false); - - Updater updater("my.AppImage", true); - - -Now, the updater will perform the update and move the new file to the original file's location after successfully verifying the file integrity (and, as soon as it is implemented, validating the file's signature, see `the related issue on GitHub `__). - -.. note:: - - **Important**: The updater will never overwrite a file before all validation mechanisms report success. - -ZSync2 based methods will furthermore always keep the old file as a backup. If the :code:`overwrite` flag is :code:`true`, the current file will be moved to :code:`my.AppImage.zs-old`. If it is `false`, the old file will remain untouched. Furthermore, if there is a file with the new filename, that file will be backed up with the :code:`.zs-old` suffix. This behavior is not ideal, the standalone UI has error handling code specific to this problem. This behavior is going to be subject of a GitHub issue soon. It is recommended to watch the discussion before implementing any code dealing with backups. Thad said, it is probably safe to check whether a :code:`.zs-old` file is created when using :code:`overwrite = true`, and delete it. diff --git a/source/packaging-guide/overview.rst b/source/packaging-guide/overview.rst deleted file mode 100644 index 6d10841..0000000 --- a/source/packaging-guide/overview.rst +++ /dev/null @@ -1,95 +0,0 @@ -Overview -======== - -There are different ways to create AppImages. The following section gives you an overview of which ways are available, their advantages and disadvantages, and where to find more information. - - -.. contents:: Contents - :local: - :depth: 1 - - -.. _sec-from-source: - -Packaging from source ---------------------- - -The recommended approach is to package software from source. Ideally, upstream application authors take over maintenance of AppImages, and provide them on their release pages. - -To learn more about how packaging from source works, please refer to :ref:`ref-packaging-from-source`. - -The process of packaging from source can and should be automated. CI systems like Travis CI can help with that. - - -.. _sec-travis-ci: - -Automated continuous builds on Travis CI -**************************************** - -This option might be the easiest if you already have continuous builds on Travis CI in place. In this case, you can write a small scriptfile and in many cases are done with the AppImage generation. - -More information on using Travis CI for making AppImages can be found in :ref:`ref-travis-ci`. - -.. seealso:: - There are a lot of examples on GitHub that can be found using the `GitHub search `__. - - -.. _sec-electron-builder: - -Using electron-builder -********************** - -For `Electron`_ based applications, a tool called electron-builder_ can be used to create AppImages. - -With electron-builder, making AppImages is as simple as defining ``AppImage`` as a target for Linux (default in the latest version of electron-builder). This should yield usable results for most applications. - -.. seealso:: - More information can be found in the `documentation on AppImage `__ and `the documentation on distributable formats `__ in the `electron-builder manual `__. - - There are a lot of examples on GitHub that can be found using the `GitHub search `__. - -.. _Electron: https://electronjs.org/ -.. _electron-builder: https://www.electron.build/ - - -.. _sec-convert-packages: - -Converting existing binary packages ------------------------------------ - -This option might be the easiest if you already have up-to-date packages in place, ideally a PPA for the oldest still-supported Ubuntu LTS release (xenial as of 2019, see https://en.wikipedia.org/wiki/Ubuntu#Releases for up to date information) or earlier or a debian repository for oldstable. In this case, you can write a small :code:`.yml` recipe and in many cases are done with the package to AppImage conversion. See :ref:`ref-convert-existing-binary-packages` for more information. - - -.. _sec-using-obs: - -Using the Open Build Service ----------------------------- - -This option is recommended for open source projects because it allows you to leverage the existing Open Build Service infrastructure, security and license compliance processes. - -More information on using OBS for making AppImages can be found in :ref:`ref-obs`. - - -.. _sec-using-appimage-builder: - -Using appimage-builder ----------------------- - -appimage-builder is a novel tool for creating AppImages. It uses the system package manager to resolve the -application dependencies and creates a complete bundle. It can be used to pack almost any kinds of applications -including those made using: C/C++, Python, and Java. - -This tool removes the limitations of requiring an *old system* to compile the binaries. It can be used to -pack an application from sources or to turn an existing Debian package into an AppImage. - -For more information about appimage-builder please visit: https://appimage-builder.readthedocs.io - - -.. _sec-create-appdir-manually: - -Manually creating an AppDir ---------------------------- - -Create an AppDir manually, then turn it into an AppImage. Please note that this method should only be your last resort, as the other methods are much more convenient in most cases. Manually creating an AppDir is explained mainly to illustrate how things work under the hood. - -See :ref:`ref-manual` for more information. diff --git a/source/packaging-guide/packaging-automation/index.rst b/source/packaging-guide/packaging-automation/index.rst new file mode 100644 index 0000000..cbf5362 --- /dev/null +++ b/source/packaging-guide/packaging-automation/index.rst @@ -0,0 +1,99 @@ +Packaging automation +==================== + +Packaging an Application is a repetitive effort. Once you packaged the application, you need to do the same for every new version you release. Depending on the :ref:`chosen AppImage creation method `, this might be executing a list of several specific commands. Always manually entering them to build your AppImage is a bad idea: You might forget something or mix something up and produce a flawed AppImage, or even forget how to do it alltogether. + +So, to avoid this, it's (obviously) better to write down the list of commands and create a (usually shell) script which builds the AppImage when executed. However, you still have to manually build your application and then execute the script for every new version, which is an (unnecessary) repetitive effort. + +The solution to this is packaging automation. This means connecting a system (a so-called CI pipeline) to your repository which then builds the AppImage on its own (e.g. for each tag, commit or at certain intervals). This also has the advantages of documenting exactly how your AppImages are built and making the process more transparent. Additionally, you can carry out tests on the pipeline to make sure the AppImage continues to work as expected. + +There are many systems you can use, for example GitHub Actions, GitLab CI, Gitea CI, Jenkins, or the Open Build Service. This section explains how to use some of them. + + +GitHub Actions +-------------- + +GitHub Actions is now one of the most wildly used CI pipelines, mainly due to its very good integration with GitHub repositories and it being free to use (with a maximum number of minutes per month for private repositories). Therefore, it's the recommended CI pipeline. To start using GitHub Actions, read the `official guide `__. + +Often, it's easier to learn from examples and adapt them. To help starting with GitHub Actions, we provide an example on how to build an AppImage using GitHub Actions and :ref:`linuxdeploy`, which serves as a good starting point: + +.. code-block:: yaml + + name: GitHub Actions Demo + run-name: Package AppImage with linuxdeploy + on: [push] + jobs: + create_tag: + name: Create tag and release + runs-on: ubuntu-latest + outputs: + tag_name: ${{ steps.create_tag.outputs.tag_name }} + steps: + - name: Clone repository + uses: actions/checkout@v4 + - name: Create tag and release + id: create_tag + run: | + tag_name="test-tag" + gh release create $tag_name --title "Test Release" + echo "tag_name=$tag_name" >> $GITHUB_OUTPUT + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build_and_publish: + name: Build and publish the application + needs: create_tag + runs-on: ubuntu-latest + steps: + - name: Clone repository + uses: actions/checkout@v4 + - name: Install project dependencies + run: | + apt update + apt install -y # Install your project dependencies + - name: Build project + run: # Invoke your compiler, e.g. cargo for Rust or gcc / clang for C + - name: Create AppImage + run: | + wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x linuxdeploy-x86_64.AppImage + LINUXDEPLOY_OUTPUT_APP_NAME="MyApplication.AppImage" ./linuxdeploy-x86_64.AppImage -e my_application -d packaging/my_application.desktop -i packaging/my_application.png -a AppDir --output appimage + - name: Upload AppImage + run: gh release upload "${{ needs.create_tag.outputs.tag_name }}" "MyApplication.AppImage" + + + +Travis CI +--------- + +Travis CI is a historically important CI pipeline. It gained popularity as it was the first CI pipeline that was free to use for open source projects. However, since an acquisition in 2019, it no longer is, and **it's recommended to not use it anymore as CI pipeline**. `Existing users should migrate off of it, e.g. to GitHub actions. `__ + + +Open Build Service +------------------ + +The Open Build Service is another system that can be used to automate the packaging. It allows you to leverage the existing Open Build Service infrastructure, security and licence compliance processes. If you're already using the Open Build Service to build other packages, it makes most sense to use it for AppImages as well. + +For more specific information on how to use the Open Build Service, see :ref:`open-build-service`. + + +.. _convenience-functions-script: + +Convenience functions +--------------------- + +There is a collection of convenience functions in https://github.com/AppImageCommunity/pkg2appimage/blob/master/functions.sh. To use them in your own scripts, you need to source ``functions.sh`` like this: + +.. code:: bash + + > wget -q https://github.com/AppImage/AppImages/raw/master/functions.sh -O ./functions.sh + > . ./functions.sh + +.. todo:: + Document the functions in ``functions.sh`` that are for public consumption based on comments in the file. + + +.. toctree:: + open-build-service + :hidden: + :maxdepth: 2 diff --git a/source/packaging-guide/hosted-services/opensuse-build-service.rst b/source/packaging-guide/packaging-automation/open-build-service.rst similarity index 57% rename from source/packaging-guide/hosted-services/opensuse-build-service.rst rename to source/packaging-guide/packaging-automation/open-build-service.rst index faaf6f1..8d00759 100644 --- a/source/packaging-guide/hosted-services/opensuse-build-service.rst +++ b/source/packaging-guide/packaging-automation/open-build-service.rst @@ -1,14 +1,14 @@ -.. _ref-obs: +.. _open-build-service: Using the Open Build Service ============================ -`Open Build Service `__ is a generic system to build and distribute packages from sources in an automatic, consistent and reproducible way. It allows you to build software for various package formats and distributions. Now it can also build AppImages that run on a variety of distributions. - -The `openSUSE Build Service`_ is the public instance of the Open Build Service (OBS). This infrastructure can can be used for free by open source projects. However, you are not limited to it - you can set up your own Open Build Service instance if you like. +.. todo:: + Make sure everything on this page is still up to date. -.. _openSUSE Build Service: https://build.opensuse.org/ +`Open Build Service `__ is a generic system to build and distribute packages from sources in an automatic, consistent and reproducible way. It allows you to build software for various package formats and distributions. Now it can also build AppImages that run on a variety of distributions. +The `openSUSE Build Service`_ is the public instance of the Open Build Service (OBS). This infrastructure can can be used for free by open source projects. However, you are not limited to it - you can set up your own Open Build Service instance if you like. .. contents:: Contents :local: @@ -22,12 +22,13 @@ There are different ways to build AppImages. Why is using Open Build Service int * If you are already using Open Build Service, then *also* generating an AppImage should be straightforward * You can use the public `openSUSE Build Service`_ instance and use the existing infrastructure to build and distribute your AppImage (for open source projects only) -* You can build AppImages in "automatic, consistent and reproducible way". This means that unlike when you build your AppImages on, e.g., Travis CI, where you can pull in arbitrarily changing build dependencies and AppImage ingredients from the net, your builds on Open Build Service can only use build dependencies and AppImage ingredients that have their source code in distribution repositories or on Open Build Service. While this may be a limitation in some cases (e.g., for agile/continuous builds), it means that the build result is much more reproducible -* OBS helps you to keep the ingredients of your AppImage up-to-date all the time using proven distribution methodologies and tool, relieving the person or group providing AppImages from manual work as discussed `here `_ +* You can build AppImages in "automatic, consistent and reproducible way". This means that unlike when you build your AppImages on, e.g., GitHub Actions, where you can pull in arbitrarily changing build dependencies and AppImage ingredients from the net, your builds on Open Build Service can only use build dependencies and AppImage ingredients that have their source code in distribution repositories or on Open Build Service. While this may be a limitation in some cases (e.g., for agile/continuous builds), it means that the build result is much more reproducible +* OBS helps you to keep the ingredients of your AppImage up-to-date all the time using proven distribution methodologies and tool, relieving the person or group providing AppImages from manual work as discussed `here `__ * OBS automatically builds a new AppImage for you if one if its ingredients is updated on OBS * OBS automatically signs AppImages using the user's key on OBS * OBS automatically embeds update information into AppImages to enable binary delta updates using AppImageUpdate. This means that if in a 100 MB AppImage only 1 MB changed between versions, then the user has to download only 1 MB rather than 100 MB + The osc command line tool ------------------------- @@ -45,7 +46,7 @@ This page describes how to use the public `openSUSE Build Service`_ instance. If Hello world -^^^^^^^^^^^ ++++++++++++ On the https://build.opensuse.org/ homepage, click on "New Image". @@ -69,14 +70,14 @@ The following sections describe how to do the same manually. Setting up an AppImage target for the project -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++++++++++++++++++++++++++++++++++++++++++++++ -You need to tell OBS that for all source code packages in your home project you want to generate AppImages. To enable a target for AppImage, you can either use the command line tool :code:`osc meta prj -e ...` or use the OBS web interface: +You need to tell OBS that for all source code packages in your home project you want to generate AppImages. To enable a target for AppImage, you can either use the command line tool ``osc meta prj -e ...`` or use the OBS web interface: * Go to your home project * Click on "Advanced" * Click on "Meta" -* Copy and paste the :code:`` tags from the following: +* Copy and paste the ```` tags from the following: .. code-block:: xml @@ -88,13 +89,13 @@ You need to tell OBS that for all source code packages in your home project you - + armv7l aarch64 - + x86_64 i586 @@ -102,47 +103,47 @@ You need to tell OBS that for all source code packages in your home project you -.. note:: +.. todo:: + This XML file might be outdated. - The :code:`AppImage.arm` repository is used for the ARM architectures for now. This will possibly change in the future. +.. note:: + The ``AppImage.arm`` repository is used for the ARM architectures for now. This will possibly change in the future. -Be sure to just insert the :code:`` tags into your existing file. For AppImage, we need to select one of the build targets that is built in your obs project. In the example above, please make sure to replace :code:`home:probono` with the actual name of the obs project where :code:`appimage.yml` should look for its resources - this can be the current project, and even RPMs created by the same package work as resources for AppImage. -Also check if openSUSE_13.1 is still alive or use something slightly newer instead. +Be sure to just insert the ```` tags into your existing file. For AppImage, we need to select one of the build targets that is built in your obs project. In the example above, please make sure to replace ``home:probono`` with the actual name of the obs project where ``appimage.yml`` should look for its resources - this can be the current project, and even RPMs created by the same package work as resources for AppImage. + +Also check whether openSUSE:Leap:15.6 is still currently supported and update the version if necessary. Use native AppImage build support -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++++++++++++++++++++++++++++++++++ -In order to build an AppImage you need to provide a file called :code:`appimage.yml`. OBS needs to get all the required resources before building. This is needed in order to be able to track changes and to find out whether a rebuild is needed, and to provide the resources in a secured and reproducible environment without network access. +In order to build an AppImage you need to provide a file called ``appimage.yml``. OBS needs to get all the required resources before building. This is needed in order to be able to track changes and to find out whether a rebuild is needed, and to provide the resources in a secured and reproducible environment without network access. -The :code:`build:` section can be used to define resources which are required to build. This can be binary packages (currently only rpm) or URLs to any other source control management systems or file. The binary packages listed in the build section get installed to the build environment, but not extracted into the AppDir. +The ``build:`` section can be used to define resources which are required to build. This can be binary packages (currently only rpm) or URLs to any other source control management systems or file. The binary packages listed in the build section get installed to the build environment, but not extracted into the AppDir. The packages listed in the ingredients section do not get installed into the build environment but get extracted into the AppDir. URLs for the supported source control management systems (git, svn, cvs, hg, bzr) get handled via the appimage source service, which is a part of `obs-service-tar_scm `__. It is downloading the sources and provides them to the build system as directory structure. .. todo:: - - **not yet implemented** + **Not yet implemented** URLs to files get handled via the download_files source service. It is handy to provide single files to the build. -Scripts can be executed in the form of the script hooks of the :code:`appimage.yml` file. +Scripts can be executed in the form of the script hooks of the ``appimage.yml`` file. .. note:: - - :code:`Recipe` files are **not** supported, anything they can do can be done inside the :code:`script` sections of :code:`appimage.yml`. + ``Recipe`` files are **not** supported, anything they can do can be done inside the ``script`` sections of ``appimage.yml``. .. note:: It is optional to either + * create the AppImage root via packages by using the ingredients section. This is useful especially for larger software, because it avoid the need of a recompilation and just repackages the content of binary packages. -* create the AppImage root via packages by using the ingredients section. This is useful especially for larger software, because it avoid the need of a recompilation and just repackages the content of binary packages. - -* create the AppImage root only from source using the scripts. This is useful when you want to avoid to build a binary package first. + * create the AppImage root only from source using the scripts. This is useful when you want to avoid to build a binary package first. -Both approaches can also get combined if wanted. + Both approaches can also get combined if wanted. `appimage.yml` file @@ -150,20 +151,20 @@ Both approaches can also get combined if wanted. Please note that it uses the following environment variables which are provided by the build system: -* :code:`BUILD_SOURCE_DIR`: The absolute directory name where all source files or directories are hosted -* :code:`BUILD_APPDIR`: The directory which will get packaged as AppImage file +* ``BUILD_SOURCE_DIR``: The absolute directory name where all source files or directories are hosted +* ``BUILD_APPDIR``: The directory which will get packaged as AppImage file Most simple example -^^^^^^^^^^^^^^^^^^^ ++++++++++++++++++++ -This :code:`APPIMAGE_NAME` application will get package into an :code:`.AppImage` file just by installing the :code:`RPM_PACKAGE_NAME`. The binary can get patched automatically when using the :code:`binpatch: true` option +This ``APPIMAGE_NAME`` application will get package into an ``.AppImage`` file just by installing the ``RPM_PACKAGE_NAME``. The binary can get patched automatically when using the ``binpatch: true`` option |question| From which repositories can rpms be installed? Only my own or those of all OBS users? |question| Can additional repositories be added? -:: +.. code-block:: yaml app: APPIMAGE_NAME binpatch: true @@ -182,9 +183,9 @@ This :code:`APPIMAGE_NAME` application will get package into an :code:`.AppImage Simple example building from source -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++++++++++++++++++++++++++++++++++++ -:: +.. code-block:: yaml app: QtQuickApp @@ -204,7 +205,7 @@ Simple example building from source - linuxdeployqt $BUILD_APPDIR/usr/share/applications/*.desktop -qmldir=$BUILD_SOURCE_DIR/ -bundle-non-qt-libs -verbose=2 -We have to also upload a file called :code:`_service` containing +We have to also upload a file called ``_service`` containing .. code-block:: xml @@ -213,11 +214,13 @@ We have to also upload a file called :code:`_service` containing -When trying this on a private OBS instance, please make sure to have :code:`obs-service-appimage` installed. This can be done e.g. on a Leap 42.1 machine with:: +When trying this on a private OBS instance, please make sure to have ``obs-service-appimage`` installed. This can be done e.g. on a Leap 42.1 machine with: + +.. code-block:: shell - zypper addrepo http://download.opensuse.org/repositories/openSUSE:Tools/openSUSE_42.1/openSUSE:Tools.repo - zypper ref - zypper in obs-service-appimage + > zypper addrepo http://download.opensuse.org/repositories/openSUSE:Tools/openSUSE_42.1/openSUSE:Tools.repo + > zypper ref + > zypper in obs-service-appimage Options inside of the build section @@ -225,7 +228,7 @@ Options inside of the build section you can add multiple items in the sections. -:: +.. code-block:: yaml build: packages: @@ -241,7 +244,7 @@ you can add multiple items in the sections. Inspecting the results ---------------------- -Be sure to download the resulting AppImage from OBS and test it on your target system(s). It is recommended to test at least on the oldest still-supported Ubuntu LTS, the recent Ubuntu, the oldest still-supported openSUSE Leap, possibly the latest openSUSE Tumbleweed, CentOS 7, and the latest Fedora release (although you may to choose to support different target systems). +Be sure to download the resulting AppImage from OBS and test it on your target system(s). For more information about AppImage testing, see :ref:`testing-appimages`. Working examples @@ -249,16 +252,10 @@ Working examples Feel free to put yours here, too. -* https://build.opensuse.org/package/show/home:probono/QtQuickApp?repository=AppImage -* https://build.opensuse.org/package/show/home:probono/DSRemote?repository=AppImage -* https://build.opensuse.org/package/show/home:probono/Qactus?repository=AppImage -* https://build.opensuse.org/package/show/home:probono/leafpad?repository=AppImage * https://github.com/olav-st/screencloud/blob/master/deploy/linux/appimage.yml -* https://build.opensuse.org/package/view_file/home:pbek:QOwnNotes/desktop/appimage.yml?expand=1 -* https://build.opensuse.org/package/view_file/home:pbartfai/LDView/_service:extract_file:appimage.yml?expand=1 -* https://build.opensuse.org/package/view_file/home:lachs0r:taisei/taisei/appimage.yml?expand=1 +* https://build.opensuse.org/projects/home:pbek:QOwnNotes/packages/desktop/files/appimage.yml +* https://build.opensuse.org/projects/home:pbartfai/packages/LDView/files/_service:extract_file:appimage.yml?expand=1 * https://github.com/orschiro/dslli/blob/master/show_state.yml -* https://build.opensuse.org/package/view_file/home:cecilios/lenmus-appimage/appimage.yml?expand=1 Continuous builds with GitHub and OBS @@ -266,23 +263,14 @@ Continuous builds with GitHub and OBS If your source code lives on GitHub, then you can set up a mechanism that makes GitHub inform OBS about any changes to the source code, and trigger a rebuild automatically. -A token needs to be generated, this can be done using the :code:`osc` OBS command line client: +A token needs to be generated, this can be done using the ``osc`` OBS command line client with the command ``osc token --create``. You can install ``osc`` with your package manager. -.. code-block:: shell +If you have already generated a token in the past, you can show it with ``osc token``. - sudo apt update && sudo apt install osc # or your package manager's equivalent - osc token --create +On the GitHub project page, click on "Settings", then click on "Integrations & services", then click on "Add service", enter "Obs" and select it. For example, for the `QtQuickApp `__ project go to ``https://github.com/probonopd/QtQuickApp/settings/installations``, and corresponding to https://build.opensuse.org/package/show/home:probono/QtQuickApp enter ``home:probono`` for the project and ``QtQuickApp`` in the Package field, as well as the token generated above in the "Token" field. Please note that you need to supply your own username and project name instead of the one in the example above. -If you have already generated a token in the past, you can show it with +Now, whenever you do a ``git push`` to your project, OBS will build it for you. -.. code-block:: shell - osc token - - -On the GitHub project page, click on "Settings", then click on "Integrations & services", then click on "Add service", enter "Obs" and select it. For example, for the `QtQuickApp`_ project go to :code:`https://github.com/probonopd/QtQuickApp/settings/installations`, and corresponding to https://build.opensuse.org/package/show/home:probono/QtQuickApp entered :code:`home:probono` for the project and :code:`QtQuickApp` for in the Package field, as well as the token generated above in the "Token" field. Please note that you need to supply your own username and project name instead of the one in the example above. - -Now, whenever you do a :code:`git push` to my `QtQuickApp`_ project, OBS will build it for me. - -.. _QtQuickApp: https://github.com/probonopd/QtQuickApp/ +.. _openSUSE Build Service: https://build.opensuse.org/ diff --git a/source/packaging-guide/signatures.rst b/source/packaging-guide/signatures.rst new file mode 100644 index 0000000..2e700bb --- /dev/null +++ b/source/packaging-guide/signatures.rst @@ -0,0 +1,86 @@ +.. _signing-appimages: + +Signing AppImages +================= + +AppImages can optionally be digitally signed by the person that has produced the AppImage. This ensures that the AppImage comes from the person who pretends to be the author, and ensures that the file has not been tampered with. + +The AppImages specification allows the AppImage file to carry a digital signature built into the AppImages. This means that the signature does not need to be an external file, but can be carried inside the AppImage itself, similar to how signatures work for traditional Linux packages (such as ``.deb`` or ``.rpm`` files). + +.. contents:: Contents + :local: + :depth: 1 + + +Embedding a signature inside an AppImage +---------------------------------------- + +To embed a signature, you have to have ``gpg`` (GnuPG 2) installed. + +You first need to prepare a key for signing. If the machine on which the AppImage is generated doesn't have a valid signing key, you can generate a new one using ``gpg --full-gen-key`` (see the gpg documentation for more information about this). You should also make sure to backup your private and public keys in a secure location. + +If you use an :ref:`AppImage creation tool `, you should use its built-in feature to sign the AppImage. However, if your AppImage creation tool doesn't support signing the AppImage, or if you create your AppImage manually, you can also use :ref:`appimagetool` directly to manually sign the AppImage. + +Using an AppImage creation tool ++++++++++++++++++++++++++++++++ + +Most AppImage creation tools come with a built-in feature to sign the AppImage at AppImage creation time. + +| To see how sign an AppImage with :ref:`linuxdeploy`, see :ref:`this ` section of the linuxdeploy guide. +| To see how to sign an AppImage with :ref:`go-appimagetool`, see :ref:`this ` section of the go-appimagetool guide. +| To see how to sign an AppImage with :ref:`electron-builder`, see :ref:`this ` section of the electron-builder guide. + +.. todo:: + Research whether a corresponding feature exists for all other AppImage creation tool and add an updating section to each guide. + + +.. _signing-using-appimagetool: + +Using ``appimagetool`` directly ++++++++++++++++++++++++++++++++ + +If you use an AppImage creation tool that doesn't support signing the AppImage, you have to extract the created AppImage by calling it with the ``--appimage-extract`` option (for more information, see :ref:`inspect-appimage-content`) and then recreate the AppImage with the embedded signature using :ref:`appimagetool`. + +To (re)create an AppImage from the AppDir and embed its signature in it, use the ``--sign`` flag. That command could for example look like this: ``appimagetool MyApplication.AppDir --sign``. Keep in mind that you also have to use the ``-u`` parameter if you want to add updating information to your AppImage, see :ref:`updating-using-appimagetool`. + + +Validating the signature +------------------------ + +To validate the signature of an AppImage and make sure it hasn't been compromised, you have to use an external tool. This can be done by ``validate``, which you can download from the `AppImage Update release page `__: + +.. code-block:: shell + + > chmod +x ./validate + > ./validate ./XChat_IRC-x86_64.AppImage + + gpg: Signature made Sun 25 Sep 2016 10:41:24 PM CEST using RSA key ID 86C3DFDD + gpg: Good signature from "Testkey" [ultimate] + +Signature validation can also be integrated into higher level software. For example, ``AppImageUpdate`` uses it to ensure that an updated AppImage has been signed by the same person who signed the original version. + + +Reading the signature +--------------------- + +You can display the digital signature that is embedded in an AppImage by running the AppImage with the ``--appimage-signature`` option like this: + +.. code-block:: shell + + > ./XChat_IRC-x86_64.AppImage --appimage-signature + + -----BEGIN PGP SIGNATURE----- + Version: GnuPG v2 + + iQEcBAABCAAGBQJX6CN9AAoJENBdKWeGw9/dsvoH/RgEggMiNTwgyA4io2Dyy1j1 + 6U3CQST9HVmh9PjeFKZCgFCZbHvpFz9mzhLTPlOAbczBnSmmbgqROINaLW+1tqEx + stOy67D3Z1cySzRTOhSkjiUOP5unmZL6QTNPxRHmuRkyihv7YfAlkrogXQlYbZ1h + Ilt6jU1b97GSPox/EE3Z002iZGJYQ3FfjAlp9o947goY5koA5KYqyzTCvEjhTk/L + wz1mFcjEkzHt9CaHZfrZCE3QVSBTq071wzsHCFHaJswPhA6iI0psCnFY56PPResi + uljTQr3nOBaqNyUgU3y4Tbd+36cwggSaTpGAzlhgNoalIwB1ltFSdPeRPe4Q3Qc= + =MR0w + -----END PGP SIGNATURE----- + + +.. note:: + Please note that while this displays the signature, it does not validate the signature. This means that it doesn't tell you whether the signature is valid or whether the file has been tampered with. To validate the signature, see the previous section. diff --git a/source/packaging-guide/testing.rst b/source/packaging-guide/testing.rst index c28844a..a4402bb 100644 --- a/source/packaging-guide/testing.rst +++ b/source/packaging-guide/testing.rst @@ -1,67 +1,61 @@ -.. _ref-testing-appimages: +.. _testing-appimages: Testing your AppImage ===================== -Testing your AppImage is a very important step in producing an AppImage. Since AppImage files are supposed to run on a variety of Linux distributions, it is important to test your AppImage on a wide variety of distributions. +Testing your AppImage is an important step you shouldn't skip when producing it. Since AppImages are supposed to run on a variety of Linux distributions, it is important to test your AppImage on a wide variety of distributions. .. centered:: **Test your AppImage on all base operating systems you are targeting!** -This is an important step which you should not skip. Subtle differences in distributions make this a must. While it is possible in most cases to create AppImages that run on various distributions, this does not come automatically, but requires careful hand-tuning. - -To ensure that the AppImage runs on the intended base systems, it should be thoroughly tested on each of them. The following testing procedure is both efficient and effective: Get the previous version of Ubuntu, Fedora, and openSUSE Live CDs and test your AppImage there. Using the three largest distributions increases the chances that your AppImage will run on other distributions as well. Using the previous (current minus one) version ensures that your end users who might not have upgraded to the latest version yet can still run your AppImage. - -Using Live CDs has the advantage that unlike installed systems, you always have a system that is in a factory-fresh condition that can be easily reproduced. Most developers just test their software on their main working systems, which tend to be heavily customized through the installation of additional packages. By testing on Live CDs, you can be sure that end users will get the best experience possible. +Subtle differences in distributions make this necessary. While most AppImages run on various distributions, this can sometimes require hand-tuning; therefore AppImages should always be thoroughly tested on several base systems. +We recommend to test your AppImage on both the current and the oldest still-supported version of Ubuntu, Fedora and openSUSE each. Using three of the largest distributions increases the chances that your AppImage will run on other distributions as well. Using the current and the oldest still-supported versions ensures that your end users can still run your AppImage as long as they use a supported version. .. contents:: Contents :local: :depth: 1 -Using testappimage ------------------- +Using live images +----------------- -You can use ISOs of Live CDs, loop-mount them, chroot into them, and run the AppImage there. This way, you need approximately 700 MB per supported base system (distribution) and can easily upgrade to newer versions by just exchanging one ISO file. The following script automates this for Ubuntu-like (Casper-based) and Fedora-like (Dract-based) Live ISOs: - -.. code-block:: shell +Using live images has the advantage that unlike installed systems, you always have a system that is in a factory-fresh condition that can be easily reproduced. Many developers just test their software on their main working systems, which tend to be heavily customized through the installation of additional packages. By testing on live images, you can be sure that the AppImage will also work on different systems. - $ wget https://raw.githubusercontent.com/AppImage/AppImageKit/master/testappimage - $ sudo bash testappimage /path/to/elementary-0.2-20110926.iso AppImageAssistant.AppImage +If you use live images, you should get one of each base system version you want to test your AppImage on. You can then boot each live image (as ISO file) in a virtual machine (using a virtual machine application) to test your AppImage on it. -Using the Docker-based appimage-testsuite ------------------------------------------ +Using Docker +------------ -In addition to Live CD ISOs, it is possible to use Docker containers to test an AppImage package on a large variety of Linux distributions. This approach works for virtually any Linux distribution for which a base Docker container is available. For each of the supported distributions, there is a corresponding DockerFile that allows to build a container with a minimal set of dependencies needed to run an AppImage package. +Alternatively to live images, you can use docker containers to test an AppImage on different Linux distributions. -Currently, only type2 AppImages that provide the ``--appimage-extract`` option are supported. - -For example, to test an AppImage package on Ubuntu 18.04, the steps to be followed are: +The following script can be used to run the given AppImage in the given distribution docker container. The distribution container must be either locally installed or available on `Docker Hub `__. Your system must use X.Org for this to work with GUI AppImages. .. code-block:: shell - $ git clone https://github.com/aferrero2707/appimage-testsuite.git - $ cd appimage-testsuite - $ ./run.sh PATH_TO_APPIMAGE/package.AppImage ubuntu-18.04 - # /aitest/aitest.sh - -The ``run.sh`` script will build the corresponding Docker container, determine the IP address of the host system, and run the container with convenient parameters. The host ``HOME`` folder is mapped to the ``/shared`` folder in the running container, and the X server is forwarded to the host system so that graphical applications can be correctly executed. + # Take the given AppImage path and distribution container + > appimage="MyApplication.AppImage" + > distro="ubuntu:latest" -The following Linux distributions are supported out-of-the-box: + # Allow the docker container to connect to your host X11 server (required for GUI applications) + > xhost + local: -* Ubuntu 14.04, 16.04 and 18.04 -* CentOS 6 and 7 -* Fedora 26 and 27 -* Debian stable and testing -* Manjaro (Arch Linux derivative) -* Sabayon (Gentoo Linux derivative) + # Start the docker container and enter its shell + > sudo docker run --rm -it -e DISPLAY=:0 -v /tmp/.X11-unix:/tmp/.X11-unix -v "$appimage":/AppImage -v "$HOME":/shared --cap-add=SYS_PTRACE --security-opt seccomp:unconfined ${distro} bash -Other distributions can be added by writing an appropriate Dockerfile. + # Install system packages and default packages that are expected on any target OS (inside the docker container) + # You can see the full excludelist of packages that may be expected at https://github.com/AppImageCommunity/pkg2appimage/blob/master/excludelist + # Some examples of packages that could be installed are: + # On Ubuntu: + > apt update && apt install -y software-properties-common libx11-6 libgl1 libglx-mesa0 expat binutils fontconfig libsm6 libgomp1 dbus desktop-file-utils xorg libasound2t64 + # On Fedora: + > dnf update -y && dnf install -y xorg-x11-server-Xorg fontconfig binutils findutils mesa-libEGL libSM dbus-tools mesa-dri-drivers -Users might need to modify the ``run.sh`` script and change the line used to guess the host IP address: + # Run the AppImage (inside the docker container) + > /AppImage --appimage-extract-and-run -.. code-block:: shell +(Credits: `Original scripts `__ by `aferrero2707 `__; improvements by `Korne127 `__.) - IP=$(ifconfig en0 | grep inet | awk '$1=="inet" {print $2}') +.. todo:: + Update this script to also support Wayland. diff --git a/source/packaging-guide/updates.rst b/source/packaging-guide/updates.rst new file mode 100644 index 0000000..8b7102a --- /dev/null +++ b/source/packaging-guide/updates.rst @@ -0,0 +1,211 @@ +.. include:: ../substitutions.rst + +.. _appimage-updates: + +Making AppImages updateable +=========================== + +AppImages can optionally embed information that allows for them to be updated (essentially storing where an update can be fetched from). This information can be used by external tools (e.g. ``AppImageUpdate`` or ``AppImageLauncher``) to update the AppImage, but also by an updater tool build into the AppImage itself (we call this a *self-updateable AppImage*). + +This not only makes it easier for users to update their AppImages, but also speeds up the process and saves bandwidth as not the full AppImage is downloaded, but only the update changes. + +This page shows how to create an updateable and self-updateable AppImage and what you should consider when making a self-updateable AppImage. + +.. contents:: Contents + :local: + :depth: 2 + + +Embedded update information +--------------------------- + +In order for AppImages to be updateable, they need to embed something called update information. That information describes how and where to look for updates. Because this information is embedded in the AppImage itself and not contained in separate description files (like with other Linux distribution methods), the update information always travels alongside the application, so that the end user does not have to do anything special in order to be able to check for updates. + +There are two non-deprecated update information types: ``zsync`` (if you use an external server to store the update data) and ``gh-releases-zsync`` (if you upload the update data to Github releases). In both cases, you will store a ``.zsync`` file that contains the update data on a server. In the next section, you'll see how to generate such a file. + +| If you want to use an external server, the update information string looks like ``zsync|``, e.g. ``zsync|https://server.domain/path/Application-latest_x86-64.AppImage.zsync``. +| If you want to use Github releases, the update information string looks like ``gh-releases-zsync|||latest|``, e.g. ``gh-releases-zsync|MyAccount|MyProject|latest|MyProject-*_x86-64.AppImage.zsync`` (``*`` can be embedded as a wildcard). + +For more detailed information on update information strings and their formal specification, see https://github.com/AppImage/AppImageSpec/blob/master/draft.md#update-information. + + +Step 1: Making AppImages updateable +----------------------------------- + +To make an AppImage updateable, you need to embed this update information into it. You can do this with one command that adds the update information to your AppImage and simultaneously creates the ``.zsync`` file you have to store online. + +If you use an :ref:`AppImage creation tool `, you should use its built-in feature to add the update information and create the ``.zsync`` file. However, if your AppImage creation tool doesn't support adding update information, or if you create your AppImage manually, you can also use :ref:`appimagetool` directly to manually add the update information and create the ``.zsync`` file. After doing that, you should upload the ``.zsync`` file to the place mentioned in the update information string. + + +Using an AppImage creation tool ++++++++++++++++++++++++++++++++ + +Most AppImage creation tools come with a built-in feature to add update information to the AppImage and create the ``.zsync`` file. + +| To see how to add update information with :ref:`linuxdeploy`, see :ref:`this ` section of the linuxdeploy guide. +| To see how to add update information with :ref:`go-appimagetool`, see :ref:`this ` section of the go-appimagetool guide. +| To see how to add update information with :ref:`electron-builder`, see :ref:`this ` section of the electron-builder guide. + +.. todo:: + Research whether a corresponding feature exists for all other AppImage creation tool and add an updating section to each guide. + + +.. _updating-using-appimagetool: + +Using ``appimagetool`` directly ++++++++++++++++++++++++++++++++ + +If you use an AppImage creation tool that doesn't support adding update information, you have to extract the created AppImage by calling it with the ``--appimage-extract`` option (for more information, see :ref:`inspect-appimage-content`) and then recreate the AppImage with the update information and create the ``.zsync`` file using :ref:`appimagetool`. + +To (re)create an AppImage from the AppDir, embed update information in it and create the ``.zsync`` file, use the ``-u`` flag with the update information string. That command could for example look like this: ``appimagetool MyApplication.AppDir/usr/share/applications/MyApplication.desktop -u "zsync|https://server.domain/path/MyApplication-latest_x86-64.AppImage.zsync"``. Keep in mind that you also have to use the ``--sign`` parameter if you want to sign your AppImage, see :ref:`signing-using-appimagetool`. + + +.. _self-updateable-appimages: + +Step 2: Making AppImages self-updateable +---------------------------------------- + +To make the AppImage self-updateable, it needs to be updateable in the first place. Only if the AppImage already embeds the update information, you can additionally bundle everything that is required to update an AppImage in the AppImage itself, so that the user can get updates without needing anything besides the AppImage. (This is conceptually similar to how the `Sparkle Framework `__ works on macOS.) + +By default, `AppImageUpdate`_ (which is used to achieve self-updateability) creates the updated AppImage file in the same directory as the current AppImage with the filename of the remote file, and doesn't overwrite the current AppImage file. This is done on purpose, as it might not be intended to overwrite previous versions of an AppImage to allow having different versions in parallel or testing the current version against the update that has just been downloaded. However, this behaviour can be overwritten. + + +Via ``appimageupdatetool`` bundled in the AppImage +++++++++++++++++++++++++++++++++++++++++++++++++++ + +You can bundle `appimageupdatetool `__ inside the AppImage of your application to achieve self-updateability. In that case, you have to invoke the bundled ``appimageupdatetool`` to update your running AppImage after corresponding user interaction (e.g. clicking an update button). + +To call another bundled executable, you need to know its path. Luckily, when running an AppImage, the :ref:`environment variable ` ``$APPDIR`` is set to the location of the mounted AppDir. As bundled executables are usually in ``./usr/lib``, its path should be something like ``$APPDIR/usr/lib/appimageupdatetool.AppImage`` + +To update your AppImage with ``appimageupdatetool``, you need to give the path of your AppImage as parameter. This path is set as ``$APPIMAGE`` by the runtime. Therefore the whole call should look like ``$APPDIR/usr/lib/appimageupdatetool.AppImage $APPIMAGE``. |shell_command| ``Command::new("sh").arg("-c").arg("$APPDIR/usr/bin/appimageupdatetool.AppImage $APPIMAGE").output()``. + +.. note:: + As of December 2024, appimageupdatetool requires FUSE 2 to run. If you aren't sure that your users have FUSE 2, you might want to check that before executing it. If a user doesn't have FUSE 2, you can still run appimageupdatetool with ``$APPDIR/usr/bin/appimageupdatetool.AppImage --appimage-extract-and-run $APPIMAGE``. + +.. warning:: + |linuxdeploy_bundle_appimages| + + +Via ``libappimageupdate`` ++++++++++++++++++++++++++ + +If bundling ``appimageupdatetool`` requires too much space, you can alternatively also bundle the library internally used, ``libappimageupdate``. This will result in a smaller size, but it's more manual work to do so. + +There is currently no precompiled version of this library. Therefore you have to manually compile `AppImageUpdate`_ with the following commands (this requires you to install a lot of dependencies, see its `build tutorial `__): + +.. code-block:: shell + + > git clone --recursive https://github.com/AppImage/AppImageUpdate + > cd AppImageUpdate + > mkdir build + > cd build + > cmake -DBUILD_QT_UI=OFF -DCMAKE_INSTALL_PREFIX=/usr .. + > make -j $(nproc) + > sudo make install + +After you built it, the libraries will be in ``AppImageUpdate/build/src/updater``. These libraries are C++11 - libraries; sadly there is currently no C interface yet, which makes it more difficult to use in other programming languages. To use the library in a different programming language, you can use a C++ FFI if available in your programming language or create a C wrapper, e.g. with `SWIG `__ (and then use the C FFI in your programming language). + +libappimageupdate provides the class ``appimage::update::Updater`` which is used to update the AppImage. Using it, you can check for updates (this is currently performed synchronously as it doesn't take long) and run updates in a separate thread. This means that you have to check for the state periodically, but allows for progress indication and status messages without any blocking. + +You have to create an ``Updater`` object and then use it to perform operations. All operations that might fail return a boolean that indicates whether it finished successfully (``true``) or an error occurred (``false``). The real result of the operation is given as a parameter which is set in case of success. To see what caused an operation to fail, you can (optionally) read the status message queue (onto which the updater and its systems write messages); this is implemented in ``logStatusMessages`` in the example code. + +The following example code (in C++) shows how to use the ``Updater`` class to check for an update, update if available, show the progress until the update is finished and check for an error after it has finished: + +.. code-block:: cpp + + using namespace appimage::update; + using namespace std; + + // Create an Updater object + Updater updater("MyApplication.AppImage"); + + bool updateAvailable; + if (!updater.checkForChanges(updateAvailable)) { + log("An error happened while searching for updates."); + logStatusMessages(); + return 1; + } + + if (updateAvailable) { + updater.start(); + + while (!updater.isDone()) { + // Sleep to prevent busy waiting + this_thread::sleep_for(chrono::milliseconds(100)); + + double progress; + if (!updater.progress(progress)) { + log("An error happened while updating."); + logStatusMessages(); + return 1; + } + + // Use the progress value (between 0 and 1), e.g. in a loading animation + } + } + + if (updater.hasError()) { + log("The update could not be loaded correctly."); + logStatusMessages(); + return 1; + } + + delete updater; + + + void logStatusMessages(Updater updater) { + string nextErrorMessage; + while (updater.nextStatusMessage(nextErrorMessage)) { + log(nextErrorMessage); + } + } + + +As previously stated, this will create a new updated AppImage file with the remote file name and not overwrite the local file. To get the path of the new AppImage file, you simply use the following code snippet after the update has finished without any errors: + +.. code-block:: cpp + + string updatedFilePath; + if !(updater.pathToNewFile(updatedFilePath)) { + log("The updated AppImage could not be located."); + logStatusMessages(); + return 1; + } + +However, if you want to directly replace the local AppImage, this default behaviour can be overwritten by creating the updater with ``Updater updater("MyApplication.AppImage", true);`` instead of ``Updater updater("MyApplication.AppImage");``. This leads to the updater moving the new file to the original file location after successfully downloading and verifying the update. But due to how ZSync2 works, the old file is not deleted; instead, it's moved to ``.zs-old`` and kept as a backup (see `this issue `__). If you don't want the old file hanging around after the update, you can remove ``.zs-old`` after the update finished successfully. + + +Using an update GUI library ++++++++++++++++++++++++++++ + +If you don't want to create your own GUI for updating (meaning an update button and optionally features like a progress bar), you can also use specific update GUI libraries that provide a pre-designed GUI managing all that. + +Currently, there only exists a GUI library for QT-based applications. We are interested in getting libraries for other popular GUI toolkits like Gtk/Libadwaita, so please contribute if you implement something like this. + + +libappimageupdate-qt +#################### + +Like with ``libappimageupdate``, there is currently no precompiled version of this library. Therefore you have to manually compile `AppImageUpdate`_ (this requires you to install a lot of dependencies). + +.. todo:: + Add instructions on how to build ``libappimageupdate-qt`` and how it can be used and integrated in an application. + + +Recommended user experience ++++++++++++++++++++++++++++ + +One advantage of the AppImage format is that it gives full control to application authors over the end user experience. In order to maintain a consistent and positive user experience with AppImages and AppImageUpdate, we recommend application authors to follow the following **Golden Rules**: + +* Never download updates without the user's explicit consent, either in the form of per-update consent or opt-in consent for automatic updates. Thanks for not killing users' mobile data plans by downloading stuff without asking. +* Don't bother the user with updates directly when the app is opened for the first time. Users should initially see something meaningful to give a positive impression and recognize immediately what the application is all about. +* Ask the user for permission before doing version checks. Some open source users consider forced version checks as a form of tracking which violates their privacy. +* The update UI should ideally be nicely integrated into the GUI of your application, using whatever GUI toolkit you are using. +* During the update process, your application should remain fully usable. +* Releases should always update to releases, nightlies always to nightlies, etc. +* Whenever the application encounters issues (e.g., a crash reporter comes up), it could ask the user to check for updates. + +.. + * Respect global flags for "do not check for new versions" and "do not attempt to update". The user may be running a central updating daemon that manages updates for the whole system, in which case any and all attempts to update the application from within itself should be skipped. + We need to define those flags for 1) per-system configuration, 2) per-user configuration and 3) ENV (similar to how the old ``desktopintegration`` script was set up not to interfere with ``appimaged``). + TODO: Such a flag currently doesn't exist and isn't documented diff --git a/source/reference/appdir-specification.rst b/source/reference/appdir-specification.rst new file mode 100644 index 0000000..9c51428 --- /dev/null +++ b/source/reference/appdir-specification.rst @@ -0,0 +1,121 @@ +.. include:: ../substitutions.rst + +.. _appdir-specification: + +AppDir specification +==================== + +This page describes the *AppDir* format. AppDirs are the "source" of AppImages. When building an AppImage, a file system image is built from such a directory, to which a runtime is prepended. + +An AppDir contains |appimage_content|. + + +.. contents:: Contents + :local: + :depth: 1 + + +History +------- + +The AppDir format has first been described by `ROX Filer`_, and has since been extended and modified by the AppImage project to suit their needs. + + +Required content +---------------- + +As the name intends, AppDirs are normal directories with some special content. An AppImage must contain the following four types of entries in its root to conform to this specification: + + +.. _apprun-specification: + +AppRun +++++++ + +Every AppImage's AppDir must contain a file (executable, script, etc.) or symlink called ``AppRun``, providing the "entry point" of the application. When running the AppImage, the :ref:`runtime ` executes the ``AppRun`` file within the :ref:`AppDir `. + +It is located in the root directory that makes up an AppDir, so it can be used to calculate paths relative to the (later mounted) AppDir. + +In modern AppImages (especially if modern :ref:`appimage-creation-tools` are used), ``AppRun`` is usually a symlink to the main binary. This works if the binary has been made relocatable (which is automatically done by modern AppImage creation tools, but can also be done :ref:`manually `). + +There also exists a pre-written AppRun.c script / program, which can be used |why_apprun_c| as it attempts to make the application relocatable without modifying it. See :ref:`apprun.c` for more information on this. + +.. warning:: + |apprun_c_warning| + + +Other ++++++ + +.. _dir-icon: + +``.DirIcon`` + The main application icon in the best resolution as PNG file. This is used, e.g. by thumbnailers, to display the application. + + The valid resolutions are |valid_resolutions|. + +These two entries have been re-used from `ROX Filer`_'s specification. ROX Filer actually specifies additional (but optional) entries, however, AppImage doesn't use these. Instead, the following ones have been introduced: + +``myapp.desktop`` + A :ref:`desktop entry file ` located in the root directory, describing the payload application. As AppImage is following the principle :ref:`one app = one file `, one desktop file is enough to describe the entire AppImage. There must not be more than one desktop file in the root directory. The name of the file doesn't matter, as long as it carries the ``.desktop`` extension. The file can be a symlink to subdirectories such as ``usr/share/applications/...`` + + For more information about desktop files, see :ref:`desktop-entry-files`. + +.. _root-icon: + +``myapp.`` (e.g., ``myapp.svg``, ``myapp.png``) + The :ref:`application icon ` in the best available quality, ideally a vector graphic. |supported_icon_formats| + + Can be a symlink to subdirectories such as ``usr/share/icons/hicolor/...``. In most cases, :ref:`.DirIcon ` is a symlink to this file. The filename must be equal to what is set as ``Icon`` value in the desktop file. + + .. note:: + The ``Icon`` value should not contain the file extension, the actual file's filename however should carry the extension. + + For more information about icon files, see :ref:`icon-files`. + + +Conventions +----------- + +In contrary to the rules in the previous section, the ones introduced in this section are no strict requirement. However, this is the recommended structure to put applications into AppDirs. It's picking up ideas from well-known, widely spread Linux standards such as the `Filesystem Hierarchy Standard `__ (part of the `Linux Standards Base `__). + +.. seealso:: + A very good summary of the FHS can be found on `Wikipedia `__. + + +``usr`` subdirectory +++++++++++++++++++++ + +Analog to the FHS, most AppDirs, especially the ones created by the official tools such as :ref:`linuxdeploy `, contain a ``usr`` directory. + +``usr`` originally abbreviated *unix system resources*. According to the FHS, it contains shared, read-only data, which perfectly suits AppImage's needs, as AppImages are read-only, too. + +The directory contains applications, (shared) libraries, desktop files, icons etc., in separate subdirectories: + +``bin`` + Executables that can be called by a user. + +``lib`` + (Shared) libraries used by applications in ``bin``. + +``share`` + Architecture-independent (shared) data. Inside this directory, some special subdirectories are commonly placed: + + ``applications`` + Contains :ref:`desktop entry files ` for applications in ``bin``. Normally, there's just one desktop file in this directory, which is symlinked in the root directory. For more information about desktop files, see :ref:`desktop-entry-files`. + + ``icons`` + Directory containing so-called `icon themes `__. Contains at least one, but often a set of :ref:`icon files ` for the main application. The icons are referred to by the root desktop file, which means the :ref:`same constraints ` apply. The default theme is ``hicolor``, but icon files can also be adapted to other well-known themes to fit in better. Icon themes placed in this directory are copied to the system during so-called :ref:`desktop integration `. + + Example path: ``/usr/share/icons///apps/myapp.``, e.g. ``/usr/share/icons/hicolor/scalable/apps/myapp.svg`` or ``/usr/share/icons/hicolor/512x512/apps/myapp.png``. + + For more information about icon files, see :ref:`icon-files`. + + +Summary ++++++++ + +Modern AppImage creation tools such as :ref:`linuxdeploy ` create these directories by default to standardize and harmonize AppDir creation. If you intend to :ref:`create the entire AppDir manually `, you should follow these recommendations. + + +.. _ROX Filer: https://rox.sourceforge.net/desktop/AppDirs.html diff --git a/source/reference/appdir.rst b/source/reference/appdir.rst deleted file mode 100644 index 395f1a8..0000000 --- a/source/reference/appdir.rst +++ /dev/null @@ -1,106 +0,0 @@ -.. TODO: create extra page on AppDir concept and move label there - -.. _ref-appdir-specification: -.. _ref-appdir: - -AppDir specification -==================== - -This page describes the *AppDir* format. AppDirs are the "source" of AppImages. When building an AppImage, a file system image is built from such a directory, to which a runtime is prepended. - - -.. contents:: Contents - :local: - :depth: 1 - - -History -------- - -The AppDir format has first been described by `ROX Filer`_, and has since been extended by the AppImage project to suit their needs. - -.. _ROX Filer: http://rox.sourceforge.net/desktop/AppDirs.html - - - -.. _ref-diricon: - -General description -------------------- - -As the name intends, AppDirs are normal directories with some special contents. The AppDir format is coming from ROX Filer http://rox.sourceforge.net/desktop/AppDirs.html: - -``AppRun`` - A file (executable, script, etc.) or symlink, serving as the "entry point" for a specific application. It is located in the root directory that makes up an AppDir, so it can be used to calculate paths relative to the (later mounted) AppDir. - -``.DirIcon`` - PNG icon located in the root directory. Can be used by e.g., thumbnailers, to display application icons rather than a generic filetype symbol. Should be in one of the standard image sizes, e.g., 128x128 or 256x256 pixels. - -These two entries have been re-used from `ROX Filer`_'s specification. `ROX Filer`_ actually specifies additional (but optional) entries, however, AppImage doesn't use these. Instead, the following ones have been introduced: - -``myapp.desktop`` - A desktop file located in the root directory, describing the payload application. As AppImage is following the principle :ref:`one app = one file `, one desktop file is enough to describe the entire AppImage. There |must not| be more than one desktop file in the root directory. The name of the file doesn't matter, as long as it carries the ``.desktop`` extension. Can be a symlink to subdirectories such as ``usr/share/applications/...`` - -.. _root-icon: - -``myapp.`` (e.g., ``myapp.png``, ``myapp.svg``) - Application's icon in the best available quality, ideally a vector graphic. Can be a symlink to subdirectories such as ``usr/share/icons/hicolor/...``. In most cases, :ref:`.DirIcon ` is a symlink to this file. The filename must be equal to what is set in the ``Icon=`` entry in the desktop file. It is recommended by AppImage and also the XDG icon specifications to use a lower-case filename which is equal to the desktop file's name. - - .. note:: - The ``Icon=`` entry |should not| contain the file extension, the actual file's filename however |should| carry the extension. - -These four types of entries |must| be contained in the AppDir to conform to this specification. - - -Conventions ------------ - -In contrary to the rules in the previous section, the ones introduced in this section are no basic requirement. However, this is the recommended structure to put applications into AppDirs. It's picking up ideas from well-known, widely spread Linux standards such as the `Filesystem Hierarchy Standard`_ (part of the `Linux Standards Base`_). - -.. seealso:: - A very good summary of the FHS can be found on `Wikipedia `__. - -.. _Filesystem Hierarchy Standard: https://wiki.linuxfoundation.org/lsb/fhs -.. _Linux Standards Base: https://wiki.linuxfoundation.org/lsb/start - - -``usr`` subdirectory -'''''''''''''''''''' - -Analog to the FHS, most AppDirs, especially the ones created by the official tools such as :ref:`linuxdeploy `, contain a ``usr`` directory. - -``usr`` originally abbreviated *unix system resources*. According to the FHS, it contains shared, read-only data, which perfectly suits AppImage's needs, as AppImages are read-only, too. - -The directory contains applications, (shared) libraries, desktop files, icons etc., in separate directories. Only a few of them are useful for AppDirs: - -``bin`` - Executables that can be called by a user. - -``lib`` - (Shared) libraries used by applications in ``bin``. - -``share`` - Architecture-independent (shared) data. Inside this directory, some special directories are commonly placed: - - ``applications`` - Contains desktop files for applications in ``bin``. Normally, there's just one desktop file in this directory, which is symlinked in the root directory. - - ``icons`` - Directory containing so-called `icon themes`_. Contains at least one, but often a set of icons for the main application. The icons are referred to by the root desktop file, which means the :ref:`same constraints ` apply. - Example path: ``/usr/share/icons///apps/myapp.``, e.g., ``/usr/share/icons/hicolor/256x256/apps/myapp.png`` - Icon themes placed in this directory are copied to the system during so-called :ref:`desktop integration `. - -.. _icon themes: https://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html - - -Summary -''''''' - -The modern packaging tools such as :ref:`linuxdeploy ` create these directories by default to standardize and harmonize AppDir creation. If you intend to :ref:`create AppDirs manually `, you are recommended to follow these recommendations. - - -.. |must| replace:: **MUST** -.. |must not| replace:: **MUST NOT** -.. |should| replace:: **SHOULD** -.. |should not| replace:: **SHOULD NOT** - diff --git a/source/reference/appimage/appimage-specification.rst b/source/reference/appimage/appimage-specification.rst new file mode 100644 index 0000000..d5f62a2 --- /dev/null +++ b/source/reference/appimage/appimage-specification.rst @@ -0,0 +1,43 @@ +.. include:: ../../substitutions.rst + +.. _appimage-specification: + +AppImage specification +====================== + +.. contents:: Contents + :local: + :depth: 1 + + +.. _architecture: + +Architecture +------------ + +AppImages follow a very simple architecture, which is explained in this section: + +An AppImage consists of two parts: a *runtime* and a *file system image*. For current :ref:`type 2 AppImages `, SquashFS is usually used as the file system (although that's not a strict specification requirement but rather a decision made in the :ref:`reference implementation `). + +.. figure:: /_static/img/reference/architecture-overview.svg + :align: center + + AppImage file structure. Copyright © `@TheAssassin `__ 2019. Licensed under CC-By-SA Intl 4.0. + +When launching an AppImage, the operating system initially runs the executable runtime part. The runtime then tries to mount the file system image part. If that succeeds, the :ref:`AppDir ` is available at a temporary mountpoint, and can be used like a read-only directory. + +The runtime then calls the AppDir's "entrypoint" :ref:`AppRun ` using the operating system facilities. While the AppRun of a modern AppImage is often a symlink to the main executable, this provides a lot of flexibility, as the AppRun can be an arbitrary executable, e.g. a script with a `shebang `__. However, it must be executable. + +The content of an AppDir is completely user-specified, although tools that help with packaging are usually used. For more information, see the :ref:`packaging guide `. + + +Specification development +------------------------- + +The specification's repository contains a description of the current :ref:`type 2 ` format. You can find the `full text `__ in its `GitHub repository `__. + +The documentation receives updates regularly, e.g. to fix bugs or document new features. For type 2, a decision was made to not release specific versions but work with continuous releases. + +As both the AppImage specification and its reference implementation |appimage_history_link|. + +Please feel free to file `issues on GitHub `__ if you encounter bugs or have ideas for additional features. Improvements on wording and such are also highly appreciated. diff --git a/source/reference/appimage/appimage-types.rst b/source/reference/appimage/appimage-types.rst new file mode 100644 index 0000000..e533709 --- /dev/null +++ b/source/reference/appimage/appimage-types.rst @@ -0,0 +1,161 @@ +.. include:: ../../substitutions.rst + +.. _appimage-types-history: + +AppImage types and history +========================== + +In this documentation, you might have already come across things like "In type 2 AppImages". This page explains why such different types and versions of AppImages exist and goes over their differences. It also shows how to determine the type of a specific AppImage. + +.. contents:: Contents + :local: + :depth: 2 + + +Why are there different AppImage types? +--------------------------------------- + +There are two main reasons for different AppImage types: + +#. **Specification changes** + + When the AppImage concept and the reference implementation creating them got initially released, they were called type 1 AppImages. However, when they were in use, some downsides came apparent over time, resulting in a new improved specification which changed the way AppImages work and were formatted like. Of course, the reference implementation has been adapted to now create those new AppImages that work differently: They were called type 2 AppImages. Type 1 and type 2 AppImages have some fundamental differences. + + Additionally to that, the type 2 specification is continuously updated, e.g. to add more features. Therefore, newer AppImages that are built according to a newer version of the specification might have additional features. + +#. **Implementation changes** + + The AppImage specification is relatively broad, which means there are some decisions the implementation (used to create AppImages) can decide, for example which parameters like ``--appimage-extract`` are available. In theory, different implementations can make different decisions, resulting in different AppImages having different features (like CLI flags). + + In practice, however, |appimage_implementations_practice|. Therefore, their implementation details influence almost all AppImages and also change its "type / version". (This is also why this documentation can assume AppImages to follow those implementations and have corresponding features (like CLI flags).) + +.. + TODO: When / if go-appimagetool becomes or uses the reference implementation, change this to + In practice, however, basically all modern AppImage creation tools use ``appimagetool``, the reference implementation. Therefore, its implementation details influence almost all AppImages… + + +Specification changes +--------------------- + +.. _differences-type-1-type-2: + +Type 1 AppImages vs type 2 AppImages +++++++++++++++++++++++++++++++++++++ + +Type 1 AppImages have been the original type of AppImages produced by the reference implementation. Nowadays, only old legacy AppImages are type 1. In September of 2016, the new improved specification of type 2 AppImages has been released, and the reference implementation has been adapted to create those new type 2 AppImages. + +The following are the main specification differences between type 1 and type 2 AppImages: + +- Type 1 AppImages use an ISO 9660 file system with Rock Ridge extensions (and should preferably use ``zisofs`` compression). This means that type 1 AppImages are ISO 9660 files. Meanwhile, type 2 AppImages don't have to use a specific file system (although the type 2 reference implementation uses only SquashFS). +- Type 1 AppImages contain the update information in the ISO 9660 Volume Descriptor field while type 2 AppImages contain it in the ELF section ``.upd_info``. +- Type 2 AppImages can also contain a digital signature in the ELF section ``.sha256_sig``. + +However, many of the important changes |new_type_2_features|. For more information on those changes, see :ref:`new-type-2-features`. + + +Notable type 2 changes +++++++++++++++++++++++ + +The following are notable changes that have been made to the type 2 specification: + +- The type 2 specification originally didn't define how type 2 AppImages can contain a digital signature. + +For all specification changes, see the git history of the `specification repository `__. + + +Implementation changes +---------------------- + +.. _new-type-2-features: + +New type 2 features ++++++++++++++++++++ + +Many of the important changes between type 1 and type 2 AppImages |new_type_2_features|. The following are some of those new features: + +- The runtime of type 2 AppImages sets an additional :ref:`environment variable ` called ``ARGV0``. +- The runtime of type 2 AppImages uses SquashFS as file system. +- Type 2 AppImages support the ``--appimage-extract`` and ``--appimage-mount`` :ref:`command line options `. +- Type 2 AppImages support the :ref:`portable mode `. + +.. todo:: + Make sure all of these features are actually available for all type 2 AppImages and not new features that have been added to the implementation at some point. + + +.. _new-generation-appimages: + +New Generation AppImages +++++++++++++++++++++++++ + +While the specification doesn't explicitly mention how the AppImage runtime mounts the AppDir filesystem, the reference implementation has originally done this with FUSE 2 (linked dynamically). + +However, due to most distributions dropping FUSE 2 from their default installed libraries after 2021, this has created a dependency that has to be installed manually in many cases in order to run AppImages - a direct contradiction to :ref:`our goals `. + +Therefore, the (runtime) reference implementation has been rewritten in order to link to all dependencies statically and therefore contain the necessary FUSE 2 parts in every AppImage. These new AppImages can be run on any system, no matter whether FUSE 2 is installed on it or not. + +This also has the additional benefit that the runtime has no dynamically linked dependencies (like ``glibc``) anymore, so that the new runtime can also work on non-glibc systems (like Alpine Linux, FreeBSD or NixOS) without having to manually install libraries. + +While it's not an official name, these new AppImages with a statically linked runtime are also known as "New Generation" AppImages. + + +Adaption problems & history +########################### + +When distributions started dropping FUSE 2 support in 2022, the AppImage team started to develop a new static runtime, whose first experimental version was available in May of 2022. +This version has been embedded in :ref:`go-appimagetool `, an experimental alternative to the reference implementation. +There were still discussions about potential other solutions in 2022 and early 2023 until it became clear in February of 2023 that this static version would become the future reference implementation. + +After testing the runtime for a while, it was supposed to "be made official" (replace the old reference implementation) in April of 2023. But that didn't happen due to multiple issues: + +- Some software that worked with AppImages (mainly the AppImageLauncher) were not compatible with this new runtime. This also resulted in bad error messages. +- There were aspirations to officially create a new specification type that's adapted to the new runtime and helps other tools to have full compatibility. + +However, the efforts stalled in 2023. Because of the importance of this issue, many people switched to go-appimagetool as it already used the static runtime instead of the (old) reference implementation. + +In `December 2024 `__, the new runtime has been made the official runtime reference implementation; the other :ref:`AppImage creation tools ` are in the process of being adapted to use it. + +For more detailed information on the exact history, see the related issues (`1 `__, `2 `__, `3 `__, `4 `__). + + +Repository change +################# + +This partial recode of the reference implementation has been taken as an opportunity to change the repository structure: While prior to it, there has only been one repository containing all parts of the reference implementation, called `AppImageKit `__, with the change to the new statically linked runtime, it has been replaced with new repositories for the individual components of the reference implementation (see :ref:`reference-implementation`). + + +Other implementation changes +++++++++++++++++++++++++++++ + +As the reference implementation is being continously changed, there are also other features that only AppImages built with a newer reference implementation version might support. The following are some of the features that have been added to the type 2 reference implementation: + +- Newer type 2 runtimes support the ``--appimage-extract-and-run`` :ref:`command line option `. +- The ``APPIMAGE_EXTRACT_AND_RUN`` environment variable that does the same has been introduced even later. + +.. todo:: + Update this page (without removing information) if / after the `new versioning scheme `__ has been implemented and if / after the specification has been majorly changed `due to the static runtime `__. + + +How to determine the type of an AppImage +---------------------------------------- + +This section shows how you can determine the type / version of a specific AppImage: + + +Type 1 or type 2 +++++++++++++++++ + +As every reasonably recent AppImage should be type 2, you shouldn't need to determine whether your AppImage is type 1 or type 2. However, if you need it nevertheless, you can use the command ``xxd ./YourApplication.AppImage | head -n 1`` (with the path to your real AppImage) in the terminal (command line). + +This returns a bunch of numbers and should look like ``00000000: 7f45 4c46 0201 0100 4149 0200 0000 0000 .ELF....AI......``. + +- If you see ``4149 02`` in there, the AppImage is type 2. +- If you see ``4149 01`` in there, the AppImage is type 1. +- If you don't see either there, the AppImage is *most likely* type 1. + + +Dynamic runtime (old) or static runtime (new generation) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +To determine whether your AppImage uses the new static runtime (and is a so-called :ref:`New Generation AppImage `) or uses the old dynamic runtime which :ref:`requires ` FUSE 2 to be installed on every target system, you can use the ``file`` command: ``file YourApplication.AppImage``. + +If the output contains ``dynamically linked``, the AppImage uses the old dynamic runtime. If it contains ``statically linked``, the AppImage uses the new static runtime. diff --git a/source/reference/appimage/index.rst b/source/reference/appimage/index.rst new file mode 100644 index 0000000..accbe2e --- /dev/null +++ b/source/reference/appimage/index.rst @@ -0,0 +1,26 @@ +.. include:: ../../substitutions.rst + +AppImage +======== + +This section contains the AppImage specification, reference implementation and history. + +The AppImage specification defines the format of an AppImage file: What AppImages consist of and the way the application data is bundled together with a runtime executing the actual application. +|specification_advantage| + +The reference implementation is the actual first party implementation of both a conforming runtime and a tool that creates AppImages (with given application data) conforming to the specification. + +While in theory, many different tools could independently create AppImages conforming to the specification, in practice, |appimage_implementations_practice|, making their implementation details very important. + +.. + TODO: When / if go-appimagetool becomes or uses the reference implementation, change this to + basically all modern AppImage creation tools use the reference implementation under the hood, making its implementation details very important + +Historical changes in both the specification and reference implementation are also covered here. + +.. toctree:: + Specification + Reference implementation + Types and history + :maxdepth: 2 + :caption: Contents: diff --git a/source/reference/appimage/reference-implementation.rst b/source/reference/appimage/reference-implementation.rst new file mode 100644 index 0000000..dea9579 --- /dev/null +++ b/source/reference/appimage/reference-implementation.rst @@ -0,0 +1,111 @@ +.. include:: ../../substitutions.rst + +.. _reference-implementation: + +AppImage reference implementation +================================= + +The reference implementation of the :ref:`AppImage specification ` is split up into several components, which are described on this page. + +It is formerly known as *AppImageKit* (more information on its history can be found :ref:`here `). + +These tools are low-level and should usually not be directly used by end users or application authors. However, if you still want to download them, you can get them from the GitHub releases page of the respective repository. + +For packaging software that should be used by application authors to create AppImages, see :ref:`appimage-creation-tools`. + +For desktop integration tools that can be used by end users to improve the AppImage user experience, see :ref:`desktop-integration`. + +.. seealso:: + The AppImage updating mechanism is implemented in `AppImageUpdate`_. For more information on updating AppImages, see :ref:`updates-user`. + +.. contents:: Contents + :local: + :depth: 2 + + +.. _runtime: + +runtime +------- + +The runtime (`source code `__) provides the "executable header" of every AppImage. The general way the runtime works is described in the :ref:`specification section `. + +|specification_broad| The following are some of the decisions the runtime reference implementation made: + +- The runtime sets specific :ref:`environment variables ` that can be used in the application before invoking it. +- The file system is mounted with FUSE. +- The runtime is statically linked, which means that there are no dependencies (like ``glibc``) required on the system. +- The runtime doesn't check the AppRun file in any way before running it; it simply tasks the operating system to execute it. +- After the AppRun file exited, the runtime unmounts the image and cleans up the temporary resources (such as the temporary mountpoint directory). +- The runtime defines the specific error messages that are printed if an error occurs (e.g. if the file system can't be mounted). + +As both the AppImage specification and those implementation decisions |appimage_history_link|. + +Keep in mind that on its own it does nothing; it needs to be combined with a file system image to form a valid AppImage, which is what ``appimagetool`` does. + + +.. _appimagetool: + +appimagetool +------------ + +appimagetool (`source code `__) can be used to create AppImages from complete pre-existing :ref:`AppDirs `. It creates the AppImage by embedding the :ref:`reference implementation runtime `, and creating and appending the file system image. + +appimagetool implements all specification features, like :ref:`embedding update information ` or :ref:`signing the AppImage`. + +|specification_broad| The following are some of the decisions appimagetool made as reference implementation: + +- appimagetool checks some of the information in the AppDir to make sure it's valid (for example, it validates :ref:`AppStream files `) +- appimagetool uses SquashFS as the file system for the file system image. +- appimagetool defines the CLI flags and environment variables it supports (like ``--appimage-extract`` or ``APPIMAGE_EXTRACT_AND_RUN``) and their effects. + +As both the AppImage specification and those implementation decisions |appimage_history_link|. + +appimagetool shouldn't be directly used to create AppImages. Instead, using one of the modern :ref:`appimage-creation-tools` is strongly preferred as they're much more convenient and help with creating the AppDir. These tools usually use appimagetool under the hood. + +appimagetool should also not be confused with the alternative go implementation, which is discussed in the next section. + + +Alternative implementation +-------------------------- + +There also exists an alternative go implementation, called go-appimagetool. go-appimagetool offers a wider feature set, which makes it usable as AppImage creation tool; however, unlike other AppImage creation tools, it doesn't use the reference implementation (appimagetool) under the hood, but instead creates the AppImages itself. This means that it might choose different implementation decisions, resulting in AppImages that behave differently to the usual ones (created with the reference implementation). + +|alternative_implementation_decisions| + +More information on how to use go-appimagetool as an AppImage creation tool can be found :ref:`here ` and it's source code can be found `here `__. + + +Helpers +------- + +There also are helper tools that can be used to verify and validate some AppImage features (mostly for debugging). + + +.. _apprun.c: + +AppRun.c (Legacy) ++++++++++++++++++ + +``AppRun.c`` is a deprecated program that attempts to make the application relocatable without modifying it in any way. This can be necessary in some cases, e.g. if its licence prohibits any modifications. It does this by manipulating environment variables, so that the bundled shared libraries are used and related warnings are suppressed. However, using it doesn't guarantee the application to run correctly. It is available as precompiled binary `here `__. + +.. warning:: + |apprun_c_warning| + + There are some edge cases where ``AppRun.c`` might be useful and is still in use. However, it suffers from many limitations and requires some workarounds which themselves require troublesome mechanisms. For example, ``AppRun`` force-changes the current working directory, and therefore applications cannot detect where the AppImage was originally called. This may be especially annoying for CLI tools, but can also be a problem for GUI applications expecting paths via parameters. This and other workarounds & mechanisms can cause a lot of trouble while trying to debug an AppImage. Please beware of that before thinking about using ``AppRun.c`` in your AppImage. + +.. + TODO: Update this section when AppRun.c is moved into pkg2appimage + + +digest-md5 +++++++++++ + +``digest-md5`` calculates the MD5 digest used for desktop integration purposes for a given AppImage. This digest depends on the path, not on the content. Its source code is available under https://github.com/AppImage/AppImageKit/blob/master/src/digest_md5.c. It currently needs to be built from source and is not available as a pre-compiled binary. + + +validate +++++++++ + +.. note:: + The ``validate`` tool has been moved into the ``AppImageUpdate`` project and is available as a pre-compiled binary there. diff --git a/source/reference/architecture.rst b/source/reference/architecture.rst deleted file mode 100644 index 10809c5..0000000 --- a/source/reference/architecture.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _ref-architecture: - -Architecture -============ - -AppImage follows a very simple architecture, which is explained in this section. - - -.. contents:: Contents - :local: - :depth: 1 - - -Overview --------- - -An AppImage consists of two parts: a *runtime* and a *file system image*. For the current type 2, the file system in use is SquashFS. - -.. figure:: /_static/img/reference/architecture-overview.svg - :align: center - - AppImage file structure. Copyright © `@TheAssassin `__ 2019. Licensed under CC-By-SA Intl 4.0. - -What happens when an AppImage is run is that the operating system runs the AppImage as an executable. The runtime, the executable part, tries to mount the file system image using :ref:`FUSE `. If that succeeds, the :ref:`AppDir ` is available in a :ref:`temporary mountpoint `, and can be used like a read-only directory. - -The runtime continues by calling the AppDir's "entrypoint" :ref:`AppRun ` using the operating system facilities. There are no checks performed by the runtime, the operating system is simply tasked with the execution of ``/AppRun``. This provides a lot of flexibility, as AppRun can be an arbitrary executable, a script with a shebang_, or even a simple symlink to another executable within the AppDir. The file must be executable. - -.. _shebang: https://en.wikipedia.org/wiki/Shebang_(Unix) - -The contents of an AppDir are completely user-specified, although there are tools that help with packaging. For more information, see the :ref:`packaging guide `. - diff --git a/source/reference/best-practices.rst b/source/reference/best-practices.rst deleted file mode 100644 index 82394ce..0000000 --- a/source/reference/best-practices.rst +++ /dev/null @@ -1,118 +0,0 @@ -Best practices -============== - -This section contains some best practices and recommendations how to generally design and write software so that it can be easily put into AppImages. - - -.. contents:: Contents - :local: - :depth: 2 - - -General Recommendations -''''''''''''''''''''''' - -It is crucial to understand that AppImage is merely a format for distributing applications. In this regard, AppImage is like a :code:`.zip` file or an :code:`.iso` file. It does not define how to compile applications. It it is also not a build system. - -It is crucial to put binaries inside AppImages that are compatible with a variety of target systems. What goes into the AppImage is called the “payload”, or the “ingredients”. Producing the payload requires some thought, as you want your AppImage to run on as many targets systems as possible. - -For an AppImage to run on most systems, the following conditions need to be met: - -#. :ref:`Binaries must not use compiled-in absolute paths ` (and if they do, they need to be binary-patched) -#. The AppImage needs to include all libraries and other dependencies that are not part of all of the base systems that the AppImage is intended to run on. -#. The binaries contained in the AppImage need to be compiled on a system not newer than the oldest base system that the AppImage is intended to run on. -#. The AppImage should actually be tested on the base systems that it is intended to run on. - -.. _ref-binaries-no-abs-paths: - -Binaries must not use compiled-in absolute paths ------------------------------------------------- - -Since an AppImage is mounted at a different location in the filesystem every time it is run, it is crucial not to use compiled in absolute paths. For example, if the application accesses a resource such as an image, it should do so from a location relative to the main executable. Unfortunately, many applications have absolute paths compiled in (:code:`$PREFIX`, most commonly :code:`/usr`) at compile time. - - -.. _ref-open-source-applications: - -Open source applications -^^^^^^^^^^^^^^^^^^^^^^^^ - -Wherever possible you should change the Source Code of the application in order not to use absolute paths. There are several ways to do this. The canonical way on Linux is to resolve ``proc/self/exe`` to get the path to the main executable and construct a relative path from there. As a result, it should work both in normal installations and in relocatable installations such as AppImages. - -There are libraries which make this easier, for example `BinReloc`_. Also see `Resourceful`_, a project to study of cross-platform techniques for building applications and libraries that use resource files (e.g. icons, configuration, data). - -Some application frameworks such as Qt have this functionality built-in, for example in :code:`QString QCoreApplication::applicationDirPath()` (`see documentation`_), and construct a *relative* path to :code:`../share/kaidan/images/` from there. - -.. seealso:: - - For an example, see: https://github.com/KaidanIM/Kaidan/commit/da38011b55a1aa5d17764647ecd699deb4be437f - -.. warning:: - - :code:`QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)` **does not work reliably.** - - According to the `Qt documentation`_, this resolves to :code:`~/.local/share/`, :code:`/usr/local/share/`, :code:`/usr/share/`, but clearly :code:`/usr` is not where these things are located in an AppImage. - -.. _BinReloc: https://github.com/limbahq/binreloc -.. _Resourceful: https://github.com/drbenmorgan/Resourceful -.. _Qt documentation: https://doc.qt.io/qt-5/qstandardpaths.html -.. _see documentation: https://doc.qt.io/qt-5/qcoreapplication.html#applicationDirPath - - -.. _ref-closed-source-apps-abs-paths: - -Closed source applications with compiled-in absolute paths -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In case it is not possible to change the source code of the application, for example because it is a closed source application, you could binary patch the executable. - -The trick is to search for :code:`/usr` in the binary and replace it by the same length string :code:`././` which means “here”. This can be done by using the following command:: - - find usr/ -type f -executable -exec sed -i -e "s|/usr|././|g" {} \; - -This command is also available as part of the bash function collection at `AppImage/pkg2appimage/functions.sh#L79`_. For the binary-patched application to work, you need to change to the :code:`usr/` directory inside the application directory before you launch the application. - -.. _AppImage/pkg2appimage/functions.sh\#L79: https://github.com/AppImage/pkg2appimage/blob/9249a99e653272416c8ee8f42cecdde12573ba3e/functions.sh#L79 - - -.. _ref-binaries-compiled-on-old-system: - -Binaries compiled on old enough base system -------------------------------------------- - -The ingredients used in your AppImage should not be built on a more recent base system than the oldest base system your AppImage is intended to run on. - -Some core libraries, such as glibc, tend to break compatibility with older base systems quite frequently, which means that binaries will run on newer, but not on older base systems than the one the binaries were compiled on. - -If you run into errors like this:: - - failed to initialize: /lib/tls/i686/cmov/libc.so.6: version `GLIBC_2.11' not found - -then the binary is compiled on a newer system than the one you are trying to run it on. You should use a binary that has been compiled on an older system. Unfortunately, the complication is that distributions usually compile the latest versions of applications only on the latest systems, which means that you will have a hard time finding binaries of bleeding-edge software that runs on older systems. A way around this is to compile dependencies yourself on a not too recent base system, and/or to use LibcWrapGenerator_ or glibc_version_header_ or bingcc_. - -When producing AppImages for the Subsurface project, we have had very good results by using **CentOS 7**, which is the oldest still-supported Linux distribution at the time of writing. This distribution is not too recent. However, there are still the most recent Qt and modern compilers available in the EPEL_ and devtools-2_ repositories (the community equivalent of the Red Hat Developer Toolset 2). Binaries built on this distribution run on nearly any distribution, including **Debian oldstable**. - -Be sure to check https://github.com/AppImage/pkg2appimage, this is how I build and host my AppImages and the build systems to produce them in the cloud using travis-ci, docker, docker-hub, and bintray. Especially check the recipes for Subsurface and Scribus. - -See https://github.com/AppImage/AppImageKit/wiki/Docker-Hub-Travis-CI-Workflow for a description on how to set up a workflow involving your GitHub repository, Docker Hub, and Travis CI for a fully automated continuous build workflow. - -You could also consider to link some exotic libraries statically. Yes, even Debian does that: -https://wiki.debian.org/Lintian - -.. _LibcWrapGenerator: https://github.com/AppImage/AppImageKit/tree/stable/v1.0/LibcWrapGenerator -.. _bingcc: https://github.com/sulix/bingcc -.. _glibc_version_header: https://github.com/wheybags/glibc_version_header -.. _EPEL: https://fedoraproject.org/wiki/EPEL -.. _devtools-2: http://people.centos.org/tru/devtools-2/ - -.. seealso:: - - This concept is also described in :ref:`build-on-old-systems`. - - -.. _ref-libstdc++.so.6: - -libstdc++.so.6 --------------- - -.. note:: - **As a general rule of thumb, please use no libstdc++.so.6 newer than the one that comes with the oldest distribution that you still want to support, i.e., the oldest still-supported LTS version of Ubuntu**. diff --git a/source/reference/desktop-integration.rst b/source/reference/desktop-integration.rst deleted file mode 100644 index 1f5076b..0000000 --- a/source/reference/desktop-integration.rst +++ /dev/null @@ -1,51 +0,0 @@ -Desktop integration -=================== - -This section discusses how we integrate AppImages into the Linux desktops, what technologies are involved and what customizations and additions we implemented to adapt them to work for AppImages. - - -.. contents:: Contents - :local: - :depth: 2 - - -Desktop files -------------- - -A central component of the Linux desktop, so-called *desktop entries* (or, colloquially, *desktop files*) are also relevant for AppImage desktop integration. Every AppImage ships with such a file in its :ref:`AppDir `. - -The FreeDesktop_ project maintains the so-called `Desktop Entry Specification`_. Desktop Entry files are `INI `__-style text documents containing key-value pairs, one per line. The file is structured in multiple sections, most notably the :code:`[Desktop Entry]`, where the main information goes into. There's a set of mandatory and optional keys to be set in these documents, and there may be additional sections. - -.. _FreeDesktop: https://www.freedesktop.org/ -.. _Desktop Entry Specification: https://specifications.freedesktop.org/desktop-entry-spec/latest/ - - -Custom keys introduced for AppImage purposes -******************************************** - -Aside from the standardized mandatory and optional keys, there may be additional, proprietary keys. They're usually prepended with :code:`X-` to differentiate between standard and custom keys. - -The AppImage project defined a few custom keys with special meaning that provide information to enhance our desktop integration algorithm. - -X-AppImage-Name - Name of the application. Used to relate two AppImages of the same application but different versions. - - **Examples:** :code:`Krita`, :code:`Kdenlive`, :code:`Ultimaker Cura` -X-AppImage-Version - Version of the application bundled in the AppImage. - - **Examples:** :code:`1.0.0-beta-2`, :code:`2019.1.1` -X-AppImage-Arch - Architecture of the AppImage. - - **Examples:** :code:`x86_64`, :code:`i386` - -:ref:`appimagetool ` and :ref:`libappimage ` currently make use mostly of :code:`X-AppImage-Version`. - -.. seealso:: - - The following discussions in issue trackers contain some background information: - - * `AppImageKit#59 `_ - * `AppImageKit#662 `_ - diff --git a/source/reference/index.rst b/source/reference/index.rst index 637e8c8..7de1746 100644 --- a/source/reference/index.rst +++ b/source/reference/index.rst @@ -1,16 +1,14 @@ +.. include:: ../substitutions.rst + .. _reference: -.. _ref-reference: Reference ========= -The following section contains reference documents like standards, etc. +This chapter goes over |reference_content|. .. toctree:: - architecture - specification - best-practices - appdir - desktop-integration + appimage/index + appdir-specification :maxdepth: 2 :caption: Contents: diff --git a/source/reference/specification.rst b/source/reference/specification.rst deleted file mode 100644 index 9963f62..0000000 --- a/source/reference/specification.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _ref-appimage-specification: -.. _ref-specification: -.. _ref-spec: - -AppImage specification -======================= - -The AppImage project maintains a work-in-progress specification on the AppImage format. - -Being designed as a standard with a reference implementation allows users to implement their own tools to build AppImages, and helps maintaining compatibility between different tools and components. - - -.. contents:: Contents - :local: - :depth: 1 - - -Development ------------ - -The specification's repository contains a description of the current **type 2** format. You can find the -`full text `_ -in the `GitHub repository `__. - -The documentation receives updates regularly, e.g., to fix bugs or document new features. For type 2, a decision was made to not release specific versions but work with continuous releases. This implies there might be some AppImages that lack newer features because they're using an older runtime, etc. Backwards compatibility is maintained by the team in the reference implementation. - -Please feel free to file `issues on GitHub `__ if you encounter bugs or have ideas for additional features. Also, improvements on wording etc. are highly appreciated. - - -Reference implementation ------------------------- - -The project maintains a reference implementation of the standard which is called :ref:`ref-appimagekit`. diff --git a/source/substitutions.rst b/source/substitutions.rst new file mode 100644 index 0000000..dbcc411 --- /dev/null +++ b/source/substitutions.rst @@ -0,0 +1,38 @@ +.. |appimage_preferred_source| replace:: In general, AppImages should be officially distributed by application authors. If application authors don't provide an AppImage, you should create an issue and ask them to start packaging the application as AppImage, or make a pull / merge request to add the creation of one if possible. Converting existing packages should only be used as a last resort if the application authors won't provide an officially distributed AppImage. +.. |valid_resolutions| replace:: ``8x8``, ``16x16``, ``20x20``, ``22x22``, ``24x24``, ``28x28``, ``32x32``, ``36x36``, ``42x42``, ``48x48``, ``64x64``, ``72x72``, ``96x96``, ``128x128``, ``160x160``, ``192x192``, ``256x256``, ``384x384``, ``480x480`` and ``512x512`` +.. |supported_icon_formats| replace:: Supported icon formats are ``png`` and ``svg``. (``xpm`` is also supported, but deprecated and shouldn't be used for new packages). The valid resolutions for raster icons are |valid_resolutions|. +.. |old_compile_version_reason| replace:: The reason for this is that other included shared libraries and executables might reference these core libraries - this often doesn't work if the system libraries are older than the libraries that are referenced at compile-time. By compiling on the oldest supported Linux distribution version, your application can be run on all supported Linux distribution versions. +.. |build_on_old_version| replace:: all binaries bundled in the AppImage should be built on the oldest supported LTS distribution version to make sure that the resulted AppImage works on all current (newer) distribution versions, see :ref:`exclude-expected-libraries` +.. |appimage_standalone_bundles| replace:: AppImages are standalone bundles, and do not need to be installed. After downloading an AppImage (and marking it as executable), you can simply double-click to run it without having to install anything. +.. |desktop_integration| replace:: However, users may want their AppImages to be integrated into the system so that they show up in menus with their icons, have their MIME types associated, can be launched from the desktop environment's launcher, etc. +.. |contact| replace:: If you're new to AppImage, or have any problems with or questions about AppImages, please don't hesitate to contact the AppImage team and their community. They're happy to help! Please see the :ref:`Contact page ` for more information. +.. |group_user_add| replace:: After adding a user to a group, that user must logout and login again for the change to take effect! +.. |fuse_docker| replace:: Most docker containers don't permit to use FUSE inside containers for security reasons. In that case, you will see this or a similar error: +.. |recent_type_2| replace:: but every reasonably recent AppImage is type 2 +.. |different_types| replace:: For more information on the different AppImage types, see :ref:`appimage-types-history`. +.. |depends_on_appimage_type| replace:: The way on how to do this depends on the AppImage type (every reasonably recent AppImage is type 2). |different_types| +.. |linuxdeploy_bundle_appimages| replace:: As of December 2024, :ref:`linuxdeploy` has a `bug `__ that causes it to corrupt AppImages when they're given as additional executables that should be bundled. Therefore, when using it, other bundled AppImages have to manually be copied into the AppDir and :ref:`appimagetool` has to be used to create the AppImage. +.. |upstream_advantage| replace:: This ensures that the software works exactly the way the original application author has envisioned it to work. +.. |software_catalogs_short| replace:: They basically work as app stores in which you can look through a list of all indexed AppImages, read their description and search for something specific or even filter by categories. +.. |shell_command| replace:: The way how you can execute such a shell command depends on the programming language. For example, in Rust you can do this with +.. |apprun_c_warning| replace:: ``AppRun.c`` (and its compiled binary in the AppImageKit releases) is legacy technology and should be avoided if possible. Using a modern :ref:`AppImage creation tool ` is strongly preferred; they made ``AppRun.c`` obsolete in most cases. +.. |why_apprun_c| replace:: if an existing application must not be altered (e.g. if the licence prohibits any modification) +.. |introduction_content| replace:: the ideas behind AppImage, its advantages and underlying core concepts +.. |packaging_optional| replace:: and explains further optional features like making your AppImages updateable or adding additional metadata. +.. |reference_content| replace:: the formal specification, reference implementation and history of AppImages as well as the AppDir specification +.. |appimages_without_fuse| replace:: without FUSE by using the ``--appimage-extract-and-run`` parameter (like ``./MyApp.AppImage --appimage-extract-and-run``) +.. |appimage_implementations_practice| replace:: basically all modern AppImage creation tools use one of only two implementations (the reference implementation and a related experimental implementation with new features) +.. |appimage_history_link| replace:: have changed and might be changed in the future (e.g. to add new features), there might be some older AppImages that lack certain features. To learn more about the different types of AppImages and their history, see :ref:`appimage-types-history`. However, backwards compatibility is maintained +.. |specification_advantage| replace:: Having a specification means that different tools can deal with AppImages and rely on them behaving consistently and fulfilling the defined requirements. It also helps maintaining compatibility between different tools and components. +.. |new_type_2_features| replace:: from a user perspective are not due to specification changes but rather due to new features that have been added to the implementation while adapting it to the new specification +.. |specification_broad| replace:: However, the specification is pretty broad, which means that there are some things the implementation can decide. +.. |appimage_not_starting_1| replace:: If you double-click your AppImage and it doesn't start / nothing happens, you should open it with the terminal as it prints additional error information there if it crashes. This information can help to determine the issue with your AppImage. +.. |appimage_not_starting_2| replace:: To do that, simply enter its full path in a terminal (command line) like this: ``~/Downloads/MyApplication.AppImage``. +.. |appimage_content| replace:: an application and everything the application needs to run on all modern Linux distribution versions (e.g. libraries, icons and fonts) +.. |increased_appimage_size| replace:: This increases the AppImage size (often by more than 10MB, although the amount depends on the linked libraries) +.. |alternative_implementation_decisions| replace:: However, in the past, go-appimagetool usually made similar implementation decisions as the reference implementation so that the AppImages behave consistently. It sometimes includes newer more experimental features though (e.g. it already used the new static runtime for a longer time before the official reference implementation started to do so). + + +.. _AppImageUpdate: https://github.com/AppImageCommunity/AppImageUpdate +.. _AM / AppMan: https://github.com/ivan-hc/AM +.. _Soar: https://github.com/pkgforge/soar diff --git a/source/user-guide/desktop-integration.rst b/source/user-guide/desktop-integration.rst new file mode 100644 index 0000000..db2c644 --- /dev/null +++ b/source/user-guide/desktop-integration.rst @@ -0,0 +1,91 @@ +.. include:: ../substitutions.rst + +.. _desktop-integration: + +Desktop integration +=================== + +|appimage_standalone_bundles| + +|desktop_integration| This concept is called *desktop integration*. + +This page presents several tools that can be used for this purpose. + +.. contents:: Contents + :local: + :depth: 1 + + +Gear Lever +---------- + +`Gear Lever `__ is an AppImage desktop integration tool. It allows to easily integrate AppImages into the desktop by just dragging them into its GUI and optionally moves them into a (configurable) application directory. + +Gear Lever also contains other features that make it easier to use AppImages, such as allowing users to update one or all AppImages with it or optionally renaming CLI tools to their executable name to open them more easily with the terminal. + +**Download:** You can get it as a Flatpak from `Flathub `__ or as an unofficial AppImage `here `__. + + +appimaged +--------- + +`appimaged `__ is a daemon that monitors a predefined set of directories on the system and detects new and removed AppImages. It automatically integrates all AppImages it can find during an initial search, and then continues to watch for new and removed AppImages and (dis-)integrates these immediately. + +Using appimaged, AppImages still need to be marked as executables and moved into the user's application directory manually; only the integration works automatically. + +.. warning:: + As of January 2025, the directories monitored by appimaged are not configurable, but hardcoded. Therefore, it might not be suitable for every use case. + + One of the monitored directories is ``~/Downloads``. If this directory is very large, appimaged usually needs quite some time to visit all files. It is likely to slow down the system (specifically, the filesystem). + +**Download:** You can get it as an AppImage from its `Github release page `__. + + +AppImageLauncher +---------------- + +.. warning:: + As of January 2025, AppImageLauncher doesn't support AppImages created with the current :ref:`reference implementation ` (after it has been changed to the new static runtime). + +`AppImageLauncher `__ contains a daemon internally, appimagelauncherd, that works similarly to appimaged, automatically integrating and disintegrating all new and removed AppImages. But unlike appimaged, the list of monitored directories in which AppImages are stored, is configurable. + +Additionally to that, AppImageLauncher integrates into the system itself so that when any AppImage is double-clicked (no matter whether it's marked as executable or not), it will open via AppImageLauncher. The first time any AppImage is opened, you'll be prompted whether to integrate the AppImage or to just run it once. When you choose to integrate your AppImage, the file will be moved into ``~/Applications``, a monitored directory in which it's automatically integrated by the daemon. This also helps to keep a clean place for all your AppImages and prevents you from having to search through a haystack of files for a specific AppImage. + +This means that AppImages don't have to be marked as executable and moved into the application directory manually, but just be double-clicked once to fully integrate them into the system. + +Furthermore, AppImageLauncher can be opened itself and provides an overview of all detected AppImages. You can run and delete any AppImage through this overview and even update AppImages that support it. + +To be able to do this all, AppImageLauncher must be installed into the system. It should run on most distributions. A Lite version with reduced functionality exists as AppImage itself, but it's recommended to use the full version. + +| **Download:** You can get AppImageLauncher as a ``.deb`` or ``.rpm`` file from its `GitHub release page `__ or download it from the community-managed packages in the Arch User Repository (AUR), see `this wiki-entry `__. +| You can get AppImageLauncher-Lite as an AppImage from its `Github release page `__ as well. + + +AppImage package managers +------------------------- + +There also exist several AppImage package managers. Those allow for installing AppImages on the command line while simultaneously integrating them into the desktop: + +- **zap** + + `zap `__ is a package manager that can install an AppImage from any URL as well as all AppImages from the appimage.github.io :ref:`software catalog `. + + When downloading & installing an AppImage with zap, it will automatically integrate it into the desktop. Users can update one or all AppImages with zap. + + **Download:** You can get it as a CLI binary from its `Github release page `__ or alternatively install it via a shell script (see its `README `__). + +- **Soar** + + `Soar`_ is a package manager that can install AppImages as well as static binaries and other portable formats from its own :ref:`software catalog ` (called PkgForge). However, it can't install AppImages from arbitrary URLs. + + When downloading & installing an AppImage with Soar, it will automatically integrate it into the desktop. Users can update one or all AppImages with Soar. + + **Download:** You can get it as a CLI binary from its `Github release page `__ or alternatively install it via a shell script (see its `documentation `__). + +- **AM / AppMan** + + `AM / AppMan`_ is a package manager that can install AppImages as well as other application formats from its own own :ref:`software catalog ` (called Portable Linux Apps). However, it can't install AppImages from arbitrary URLs. + + When downloading & installing an AppImage with AM, it will automatically integrate it into the desktop. Users can update one or all AppImages with AM. + + **Download:** You can install it via a shell script (see its `README `__). diff --git a/source/user-guide/downloading-updating.rst b/source/user-guide/downloading-updating.rst new file mode 100644 index 0000000..7e268dc --- /dev/null +++ b/source/user-guide/downloading-updating.rst @@ -0,0 +1,44 @@ +.. include:: ../substitutions.rst + +Downloading and updating AppImages +================================== + +This page provides an overview on where to download and how to update AppImages. + +.. contents:: Contents + :local: + :depth: 2 + + +Download AppImages +------------------ + +AppStreams are usually downloaded from the creator themself. The AppImage ecosystem is built around the notion of :ref:`upstream packaging `. |upstream_advantage| However, there still are several ways to get them: + +The most common way is to download AppImages directly from the website on which the creator hosts them. This is usually either a project website or GitHub releases (or both). This is intuitive: If you search for a specific application, you just go to its website and download the AppImage of the latest release. + + +.. _software-catalogs-user: + +Software catalogs ++++++++++++++++++ + +However, there also is a second option: If you don't want to download a specific application, but rather just *an* application that does something you need, e.g. audio editing, it might be frustrating to search for something that fits your needs and is available in the format you want. That's why so-called *software catalogs* exist: |software_catalogs_short| + +These stores link to or use the original download location, so that you can be sure to get the originally packaged applications; they merely act as an index of available AppImages to find the applications you need more easily. + +You can browse the two most user friendly software catalogs under https://appimage.github.io/apps/ resp. https://www.appimagehub.com/browse?ord=alphabetical. For more specific information on other catalogs, see :ref:`this section `. + + +.. _updates-user: + +Update AppImages +---------------- + +Many AppImages embed so-called update information. This means that you don't have to manually download a new version, but the AppImages already contain information where an update can be fetched from. Such AppImages can be updated with external tools that use this embedded update information (see below). This also speeds up the process and saves bandwidth as not the full AppImage is downloaded, but only the update changes. + +Some AppImages are even self-updateable. This means that they embed not only update information, but also the functionality that automatically downloads and performs the update. If you use a self-updateable AppImage, you can simply update it using the AppImage's user interface / menu. + +However, in case you don't find any such option or don't know whether the AppImage is self-updateable, you can update any updateable AppImage with `AppImageUpdate`_. AppImageUpdate is a program in which you can select any updateable AppImage and update it. Alternatively, you can also use appimageupdatetool, which allows you to do the same with a CLI. + +Both AppImageUpdate and appimageupdatetool can be downloaded at https://github.com/AppImageCommunity/AppImageUpdate/releases. diff --git a/source/user-guide/faq.rst b/source/user-guide/faq.rst deleted file mode 100644 index 6445427..0000000 --- a/source/user-guide/faq.rst +++ /dev/null @@ -1,66 +0,0 @@ -.. _faq: - -Frequently Asked Questions -========================== - -The most common questions are answered directly here to save you from having to read the entire user guide. - - -.. contents:: Contents - :local: - :depth: 1 - - -|question| What is an AppImage? -------------------------------- - -An AppImage is a downloadable file for Linux that contains an application and everything the application needs to run (e.g., libraries, icons, fonts, translations, etc.) that cannot be reasonably expected to be part of each target system. - - -|question| How do I run an AppImage? ------------------------------------- - -Make it executable and double-click it. - - -|question| How can I integrate AppImages with the system? ---------------------------------------------------------- - -Using the optional appimaged daemon, you can easily integrate AppImages with the system. The daemon puts AppImages into the menus, registers MIME types, icons, all on the fly. You can download it from this repository. But it is entirely optional. - - -|question| Where can I download AppImages? ------------------------------------------- - -See the "repository" of upstream-generated AppImages. - - -|question| Where do I store my AppImages? ------------------------------------------ - -An important point about the AppImage format is that you can store AppImage files wherever you want. This includes your home directory, your downloads directory, a dedicated applications directory, a USB thumb drive, a CD-ROM or DVD, or even a network file share. No matter where you keep your AppImages, you are still able to run them. This is very similar to how applications work on macOS. Unlike with traditional Linux packages, you do not need to install AppImages or put them into some special location in order for them to work. - -If you don't want to leave them in :code:`$HOME/Downloads`, then :code:`$HOME/Applications` is a good choice. Many third-party tools (especially the ones managing desktop integration) use this location, too. Other options involve :code:`$HOME/.local/bin` and :code:`$HOME/bin`, which are useful mainly for CLI tools. - -**On CentOS/RHEL and Fedora:** When you login, the script :code:`$HOME/.bash_profile` is executed and this script adds :code:`$HOME/.local/bin:$HOME/bin` to your path. - -**On Ubuntu:** When you login, the script :code:`$HOME/.profile` is executed and this script adds :code:`"$HOME/bin:$HOME/.local/bin"` to your path. - -Besides, every other location works, e.g., a USB thumbdrive, a network location, or a CD-ROM, but then the AppImages won't be on your path, which means that you cannot simply type their name into a terminal but have to use the full path. - - -|question| Where can I request AppImages? ------------------------------------------ - -If there is no AppImage of your favorite application available, please request it from the author(s) of the application, e.g., as a feature request in the issue tracker of the application. - -For example, if you would like to see an AppImage of Mozilla Firefox, then please leave a comment at https://bugzilla.mozilla.org/show_bug.cgi?id=1249971. The more people request an AppImage from the upstream authors, the more likely is that an AppImage will be provided. - - -|question| Where do I get support? ----------------------------------- - -Please refer to the :ref:`contact page `. - - -.. |question| image:: /_static/img/question.png diff --git a/source/user-guide/index.rst b/source/user-guide/index.rst index 5b06061..34357ca 100644 --- a/source/user-guide/index.rst +++ b/source/user-guide/index.rst @@ -1,11 +1,15 @@ +.. _user-guide: + User Guide ========== -This chapter shows users what AppImages are from a user perspective, how they can be used, what desktop integration is and how it is accomplished, and what other tools are provided to manage, update etc. AppImages. +This chapter shows users what AppImages are from a user perspective and everything they need to know: How they can be used, what desktop integration is and how it is accomplished, how they can be updated, used portably and much more. .. toctree:: - faq - run-appimages + quickstart + downloading-updating + inspect-appimage-content + desktop-integration portable-mode mac troubleshooting/index diff --git a/source/user-guide/inspect-appimage-content.rst b/source/user-guide/inspect-appimage-content.rst new file mode 100644 index 0000000..d2a4e9e --- /dev/null +++ b/source/user-guide/inspect-appimage-content.rst @@ -0,0 +1,90 @@ +.. include:: ../substitutions.rst + +.. _inspect-appimage-content: + +Inspect AppImage content +=========================== + +To inspect the content of any AppImage, it is possible to extract their content to a directory or to temporarily mount them on the system for read-only access. The resulting directory is a valid :ref:`AppDir `, and users can create AppImages from it again using an :ref:`AppImage creation tool `. This page describes the different ways to inspect the content of an AppImage, their advantages and disadvantages. + +.. contents:: Contents + :local: + :depth: 1 + + +Calling the AppImage with special parameters +-------------------------------------------- + +The most convenient way to inspect the content of an AppImage is to call it with the ``--appimage-extract`` or ``--appimage-mount`` option. (This only works for type 2 AppImages, |recent_type_2|. If you have to inspect a type 1 AppImage, see the other options described on this page. |different_types|) + +.. warning:: + You should only do this if you trust the AppImage (as the runtime could be altered to execute different code, even if you use these parameters). If you want to inspect the AppImage as you don't trust it, you should follow the instructions in the section :ref:`inspect-using-external-tools`. + + +\-\-appimage-extract +++++++++++++++++++++ + +To extract the content of a type 2 AppImage without an external tool, call the AppImage with the parameter ``--appimage-extract``. This will cause the :ref:`runtime` to create a new directory called ``squashfs-root`` in the current working directory, containing the content of the AppImage's :ref:`AppDir `. + + +\-\-appimage-mount +++++++++++++++++++ + +To mount the content of a type 2 AppImage without an external tool, call the AppImage with the parameter ``--appimage-mount``. This will cause the :ref:`runtime` to mount the AppImage content with read-only access and return the directory it is mounted on, which can then be inspected with a file manager or another terminal window. + +The AppImage is unmounted when the application called in the example is interrupted (e.g. by pressing :kbd:`Ctrl+C` or closing the terminal window). + +.. _inspect-using-external-tools: + + +Using external tools +-------------------- + +This is the safest way to inspect the content of an AppImage. You should use this way if you don't trust the AppImage and don't want to call it. + +|depends_on_appimage_type| + + +Type 2 AppImages +++++++++++++++++ + +You can safely inspect the content of a type 2 AppImage with these commands (replace ``path/to/AppImage`` with the path of your AppImage): + +.. code-block:: shell + + > wget -c "https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-x86_64" + > chmod +x runtime-x86_64 + > TARGET_APPIMAGE=path/to/AppImage ./runtime --appimage-extract ./runtime-x86_64 + +This will call ``--appimage-extract`` on the downloaded AppImage runtime to extract your AppImage without having to rely on the (possibly tampered) runtime of your AppImage. + +You can also use ``--appimage-mount`` instead of ``--appimage-extract`` if you rather want to temporarily mount the AppImage content. + + +Type 1 AppImages +++++++++++++++++ + +Type 1 AppImages are legacy; however you still might want to inspect the content of an old AppImage. To do this safely, you can rename them to ``.iso`` instead of ``.AppImage`` and then extract them by using a tool like ``Iso7z`` or ``bsdtar`` that can handle ``zisofs``. + + +Mounting with root permissions +------------------------------ + +Another possible way to inspect the content of an AppImage is to use the normal ``mount`` toolchain of your Linux distribution. This requires root permissions. + +The other options described on this page are usually preferred. This is primarily useful if you have to inspect a type 1 AppImage without any external tools. + +.. code-block:: shell + + > mkdir mountpoint + > sudo mount -o loop my.AppImage mountpoint/ + # You can now inspect the AppImage content in mountpoint/ + > sudo umount mountpoint/ + +.. note:: + This only works for type 1 AppImages. To mount a type 2 AppImage, see the other options described on this page. + +.. warning:: + AppImages mounted using this method are not unmounted automatically. Please do not forget to call ``umount`` the AppImage as soon as you don't need it mounted any more. + + If an AppImage is not unmounted properly, and is moved to a new location, a so-called "dangling mount" can be created. This should be avoided by properly unmounting the AppImages. diff --git a/source/user-guide/mac.rst b/source/user-guide/mac.rst index c2a4af7..5669dbd 100644 --- a/source/user-guide/mac.rst +++ b/source/user-guide/mac.rst @@ -1,48 +1,37 @@ +.. include:: ../substitutions.rst + AppImage for macOS switchers ============================ .. image:: /_static/img/dmg-AppImage.png -This page compares the AppImage terms to its macOS equivalents. It -should help macOS to Linux switchers to "get" AppImage concepts quickly. - -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| AppImage concept | Rough macOS equivalent | -+=================================================================================+===========================================================================================+ -| ``.AppImage`` file | ``.app`` inside a ``.dmg`` file | -| | that mounts itself automatically | -| | when executed | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| ``.AppDir`` directory | ``.app`` directory | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| ``.desktop`` file | ``Info.plist`` file | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| ``*.metainfo.xml`` file and ``package.json`` file (for Electron apps) | ``Info.plist`` file (more elaborate version thereof) | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| ``usr/`` inside the AppDir | ``Resources/`` inside the ``.app`` | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| `AppImageUpdate`_ | `Sparkle Framework`_ | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| No direct equivalent, but `update information`_ in ELF section ``.upd_info`` | `Sparkle appcast`_ | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| Optional ``appimaged`` daemon | `Launch Services`_ to register applications in the system (e.g., MIME types, icons, etc.) | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| No direct equivalent, but AppImageHub_ central directory of available AppImages | Mac App Store | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| Optional signature in ELF section | Signatures in ``/Contents/_MASReceipt/`` | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| No direct equivalent (yet?), but use `linuxdeployqt`_ (for Qt, C++, C) or | **Xcode** IDE generates ``.app`` when you click "compile" | -| `electron-builder`_ for Electron apps in the build chain | | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ -| ``appimagetool my.AppDir my.AppImage`` | ``hdiutil create -volname myApp -srcfolder my.app/../ -ov -format UDZO myApp.dmg`` | -+---------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +This page compares the AppImage terms to its macOS equivalents. It should help macOS to Linux switchers to "get" AppImage concepts quickly. +.. list-table:: + :widths: 50 50 + :header-rows: 1 -.. _AppImageUpdate: https://github.com/AppImage/AppImageUpdate -.. _AppImageHub: https://github.com/appimage/appimage.github.io -.. _Sparkle Framework: https://sparkle-project.org/ -.. _update information: https://github.com/AppImage/AppImageSpec/blob/master/draft.md#update-information -.. _Sparkle appcast: https://sparkle-project.org/ -.. _Launch Services: https://developer.apple.com/documentation/coreservices/launch_services -.. _linuxdeployqt: https://github.com/probonopd/linuxdeployqt -.. _electron-builder: https://github.com/electron-userland/electron-builder + * - AppImage concept + - Rough macOS equivalent + * - ``.AppImage`` file + - ``.app`` directory (treated as a file) + * - ``.AppDir`` directory + - ``.app`` directory content (in ``.app/Contents``) + * - ``.desktop`` file + - ``Info.plist`` file + * - ``*.metainfo.xml`` file and ``package.json`` file (for Electron apps) + - ``Info.plist`` file (more elaborate version thereof) + * - ``usr/`` inside the AppDir + - ``Resources/`` inside ``.app/Contents`` + * - `AppImageUpdate`_ (powering :ref:`self-updateable AppImages `) + - `Sparkle Framework `__ + * - Embedded :ref:`update information ` + - `Sparkle appcast `__ + * - Optional :ref:`desktop integration tools ` + - `Launch Services `__ to register applications in the system (e.g. MIME types or icons) + * - :ref:`Software catalogs ` of available AppImages + - Mac App Store + * - :ref:`AppImage signature ` + - Signatures in ``/Contents/_CodeSignature/`` + * - :ref:`appimage-creation-tools` that generate an AppImage from the executable + - **Xcode** IDE generates ``.app`` when you click "compile" diff --git a/source/user-guide/notes/external-tool-to-mount-and-extract-appimages.rst b/source/user-guide/notes/external-tool-to-mount-and-extract-appimages.rst deleted file mode 100644 index 7cf89e5..0000000 --- a/source/user-guide/notes/external-tool-to-mount-and-extract-appimages.rst +++ /dev/null @@ -1,4 +0,0 @@ -.. seealso:: - There is currently no way to use the former method without calling the target AppImage. This might not always be appropriate, e.g., if the AppImage is not trustworthy. - - The AppImage team is working on implementing a mount option in :ref:`ref-appimagetool`. Please see the related `GitHub issue `__ for progress on this. diff --git a/source/user-guide/portable-mode.rst b/source/user-guide/portable-mode.rst index 385a86f..b1ec106 100644 --- a/source/user-guide/portable-mode.rst +++ b/source/user-guide/portable-mode.rst @@ -1,8 +1,11 @@ +.. include:: ../substitutions.rst + +.. _portable-mode: + Using portable mode =================== -This page describes a mode some newer AppImages (i.e., built in 2017 or later) provide, the *portable mode*. This mode allows for bundling an application's data next to the application's AppImage. - +This page describes the portable mode. It allows for bundling an application's data next to the application's AppImage. Only type 2 AppImages provide it, |recent_type_2|. |different_types| .. contents:: Contents :local: @@ -12,42 +15,40 @@ This page describes a mode some newer AppImages (i.e., built in 2017 or later) p Introduction ------------ -Sometimes it can be useful for data of an application to travel along with the application, for example to put the application on a USB stick that can be used with different computers. In the windows world, this concept is known as “portable applications”. - -Normally the application contained inside an AppImage will store its configuration files wherever it always stores them (most frequently somewhere inside :code:`$HOME`). In other words, the fact that an application is contained inside an AppImage normally does not change where the application stores its data. +Sometimes it can be useful for data of an application to travel along with the application, for example to put the application on a USB drive that can be used with different computers. In the Windows world, this concept is known as "portable applications". -However, there is functionality in newer AppImages that can make the application's data travel along with the application, if certain directories are present *next to the AppImage file*. +Normally, the application contained inside an AppImage will store its application data (e.g. configuration files) wherever it always stores them (most frequently somewhere inside ``$HOME``). In other words, the fact that an application is contained inside an AppImage normally does not change where the application stores its data. -If you invoke an AppImage built with a recent version of AppImageKit and have one of these special directories in place, then the configuration files will be stored alongside the AppImage. This can be useful for portable use cases, e.g., carrying an AppImage on a USB stick, along with its data. +However, there is functionality in type 2 AppImages that can make the application's data travel along with the application. If you invoke a type 2 AppImage and have certain directories present *next to the AppImage file* (in the same directory), the AppImage will store its application data and configuration files alongside the AppImage. This can be useful for portable use cases, e.g., carrying an AppImage on a USB drive, along with its data. -- If there is a directory with the same name as the AppImage plus :code:`.home`, then :code:`$HOME` will automatically be set to it before executing the payload application -- If there is a directory with the same name as the AppImage plus :code:`.config`, then :code:`$XDG_CONFIG_HOME` will automatically be set to it before executing the payload application +- If there is a directory with the same name as the AppImage plus ``.home``, then ``$HOME`` will automatically be set to it before executing the payload application. This means that all application data that the application would usually store in ``$HOME`` will now be stored in the ``.home`` folder and can be moved across devices. +- If there is a directory with the same name as the AppImage plus ``.config``, then ``$XDG_CONFIG_HOME`` will automatically be set to it before executing the payload application. This means that all application data that the application would usually store in ``$XDG_CONFIG_HOME`` will now be stored in the ``.config`` folder and can be moved across devices. Example ------- -Imagine you want to use the Leafpad text editor, but carry its settings around with the executable. You can do the following: +Imagine you want to use Inkscape, but carry its settings around with the executable. You can do the following: -.. Tell Pygments to use 'shell' syntax, otherwise it defaults to 'python' -.. See http://www.sphinx-doc.org/en/1.4.9/markup/code.html#directive-code-block for more information .. code-block:: shell - # Download Leafpad AppImage and make it executable - $ wget -c "https://bintray.com/probono/AppImages/download_file?file_path=Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage" -O Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage - $ chmod a+x Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage + # Download the Inkscape AppImage and make it executable + # This is just an example code; you should use the up to date version of the program + > wget https://inkscape.org/gallery/item/53678/Inkscape-e7c3feb-x86_64.AppImage -O Inkscape.AppImage + > chmod +x Inkscape.AppImage # Create a directory with the same name as the AppImage plus the ".config" extension # in the same directory as the AppImage - $ mkdir Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage.config + > mkdir Inkscape.AppImage.config - # Run Leafpad, change some setting (e.g., change the default font size) then close Leafpad - $ ./Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage + # Run Inkscape.AppImage, change some setting in the preferences panel (e.g. the interface + # language) and close it + > ./Inkscape.AppImage.config # Now, check where the settings were written: - $ find Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage.config + > find Inkscape.AppImage.config (...) - Leafpad-0.8.18.1.glibc2.4-x86_64.AppImage.config/leafpad/leafpadrc + Inkscape.AppImage.config/Inkscape/preferences.xml -Note that the file :code:`leafpadrc` was written in the directory we have created before. +Note that the file ``preferences.xml`` was written in the new directory next to the AppImage that can be carried around together with the AppImage itself. diff --git a/source/user-guide/quickstart.rst b/source/user-guide/quickstart.rst new file mode 100644 index 0000000..473f84b --- /dev/null +++ b/source/user-guide/quickstart.rst @@ -0,0 +1,99 @@ +.. include:: ../substitutions.rst + +.. _quickstart: + +Quickstart +========== + +This page contains information for users new to AppImage that helps them to get started quickly and easily. + +It also answers the most common questions to save you from having to read the entire user guide. + +.. contents:: Contents + :local: + :depth: 1 + + +What is an AppImage? +-------------------- + +An AppImage is a downloadable file for Linux that contains |appimage_content|. + +The AppImage format is standardized. However, the specification doesn't define to compile applications in a specific way: It's not a build system, but rather like a ``.zip`` file, just that the application data is bundled in a specific way. + + +.. _how-to-run-appimage: + +How to run an AppImage +---------------------- + +It's very easy to run an AppImage. All you have to do is to download it, make it executable and run it (e.g. by double-clicking it). + +Making a file executable can both be done using the terminal or the file manager: + + +Using the terminal +++++++++++++++++++ + +#. Open a terminal (command line) +#. Make the AppImage executable: ``chmod +x ~/Downloads/MyApplication.AppImage`` +#. Run the AppImage by entering its path: ``~/Downloads/MyApplication.AppImage`` + + +Using the file manager +++++++++++++++++++++++ + +#. Open your file manager and browse to the location of the AppImage +#. Right-click the AppImage and select "Properties" +#. Switch to the "Permissions" tab +#. Check the box to set executable permissions. Depending on your file manager, this might be called **"Allow executing file as program"** or **"Is executable"**. + In some file managers, you might not have such a checkbox, but instead have to change an "Execute" drop down list to "Anyone" or an "Access" drop down list to "Read, Write & Execute". +#. Close the dialog and double-click the AppImage to run it + +The following video also shows how to do this: (This might look slightly different for you, depending on your file manager.) + +.. image:: /_static/img/make-executable.gif + +This guide is also available in other languages `here `__. + + +How to run an AppImage in a docker container +-------------------------------------------- + +Most docker containers don't permit something called :ref:`FUSE `, which is usually required for AppImages to run. However, you can run AppImages |appimages_without_fuse|. For more information on that, see :ref:`fuse-fallback`. + + +The AppImage doesn't start / work +--------------------------------- + +|appimage_not_starting_1| + +|appimage_not_starting_2| + +If the error information includes "Fuse", e.g. "AppImages require FUSE to run.", :ref:`this page ` can help you fixing this issue. + +Otherwise, report this issue with the printed error messages to the application author or :ref:`contact us ` for further help. + + +How to integrate AppImages into the system +------------------------------------------ + +|appimage_standalone_bundles| + +|desktop_integration| This can easily be done with one of the desktop integration tools that are introduced in :ref:`desktop-integration`. + + +Where to store AppImages +------------------------ + +An important point about the AppImage format is that you can store AppImage files wherever you want. This includes your home directory, your downloads directory, a dedicated applications directory, a USB drive, or even a network file share. No matter where you keep your AppImages, you are still able to run them. This is very similar to how applications work on macOS. Unlike with traditional Linux packages, you do not need to install AppImages or put them into some special location in order for them to work. + +If you don't want to leave them in ``~/Downloads``, then ``~/Applications`` is a good choice. Many third-party tools (e.g. the ones managing desktop integration) use this location, too. + +For CLI tools, ``~/.local/bin`` and ``~/bin`` are also good places, as these are usually included in the path, meaning that you can simply type the application name into the terminal to start it. + + +Getting help +------------ + +|contact| diff --git a/source/user-guide/run-appimages.rst b/source/user-guide/run-appimages.rst deleted file mode 100644 index 3a5a54f..0000000 --- a/source/user-guide/run-appimages.rst +++ /dev/null @@ -1,131 +0,0 @@ -Running AppImages -================= - -This page shows how a user can run AppImages, on their favorite distribution using the desktop environment tools or via the terminal. Also, it explains the concept of desktop integration, and presents tools that can be used for this purpose. - - -.. contents:: Contents - :local: - :depth: 2 - - -.. _ref-download-make-executable-run: - -Download, make executable, run ------------------------------- - -It's quite simple to run AppImages. As the heading says, just download them, make them executable and run them. This can either be done using the GUI or via the command line. - -.. seealso:: - - Information on how to run AppImages was moved into our :ref:`ref-quickstart` page. - - Please see :ref:`ref-how-to-run-appimage` for more information. - - -Mount or extract AppImages --------------------------- - -To inspect the contents of any AppImage, it is possible to either mount them without running them, or extract the contents to a directory in the current working directory.. - - -Mount an AppImage -***************** - -AppImages can be mounted in the system to provide *read-only* access for users to allow for inspecting the contents. - -To mount an AppImage temporarily, you have two options. The easiest way to do so is to call AppImages with the special parameter ``--appimage-mount``, for example:: - - > my.AppImage --appimage-mount - /tmp/mount_myXXXX - # now, use another terminal or file manager to inspect the contents in the directory printed by --appimage-mount - -The AppImage is unmounted when the application called in the example is interrupted (e.g., by pressing :kbd:`Ctrl+C`, closing the terminal etc.). - -.. note:: - This is only available for type 2 AppImages. Type 1 AppImages do not provide any self-mounting mechanism. To mount type 1 AppImages, use ``mount -o loop``. - -This method is to be preferable, as other methods have some major disadvantages explained below. - -Another way to mount AppImages is to use the normal ``mount`` command toolchain of your Linux distribution. Mounting and unmounting devices, files, images and also AppImages requires root permissions. Also, you need to provide a mountpoint. Please see the following example: - -For type 1 AppImages:: - - > mkdir mountpoint - > sudo mount my.AppImage mountpoint/ - # you can now inspect the contents - > sudo umount mountpoint/ - -For type 2 AppImages:: - - > mkdir mountpoint - > my.AppImage --appimage-offset - > 123456 - > sudo mount my.AppImage mountpoint/ -o offset=123456 - # you can now inspect the contents - > sudo umount mountpoint/ - -Note that the number `123456` is just an example here, you will likely see another number. - -.. warning:: - AppImages mounted using this method are not unmounted automatically. Please do not forget to call ``umount`` the AppImage as soon as you don't need it mounted any more. - - If an AppImage is not unmounted properly, and is moved to a new location, a so-called "dangling mount" can be created. This should be avoided by properly unmounting the AppImages. - - .. note:: - Type 2 AppImages which are mounted using the ``--appimage-mount`` parameter are **not** affected by this problem! - -.. include:: notes/external-tool-to-mount-and-extract-appimages.rst - - -Extract the contents of an AppImage -*********************************** - -An alternative to mounting the AppImages is to extract their contents. This allows for modifying the contents. The resulting directory is a valid :ref:`AppDir `, and users can create AppImages from them again using :ref:`ref-appimagetool`. - -Analog to mounting AppImages, there is a simple commandline switch to extract the contents of type 2 AppImages without external tools. Just call the AppImage with the parameter :code:`--appimage-extract`. This will cause the :ref:`ref-runtime` to create a new directory called :code:`squashfs-root`, containing the contents of the AppImage's :ref:`AppDir `. - -Type 1 AppImages require the deprecated tool AppImageExtract_ to extract the contents of an AppImage. It's very limited functionality wise, and requires a GUI to run. It creates a new directory in the user's desktop directory. - -.. _AppImageExtract: https://github.com/AppImage/AppImageKit/releases/6 - -.. include:: notes/external-tool-to-mount-and-extract-appimages.rst - - -.. _ref-desktop-integration: - -Integrating AppImages into the desktop --------------------------------------- - -AppImages are standalone bundles, and do not need to be *installed*. However, some users may want their AppImages to be available like distribution provided applications. This primarily involves being able to launch desktop applications from their desktop environments' launchers. This concept is called *desktop integration*. - -appimaged -********* - -`appimaged `__ is a daemon that monitors the system and integrates AppImages. It monitors a predefined set of directories on the user's system searching for AppImages, and integrates them into the system using :ref:`libappimage `. - -.. seealso:: - More information on appimaged can be found in :ref:`appimaged`. - - -AppImageLauncher -**************** - -AppImageLauncher_ is a helper application for Linux distributions serving as a kind of "entry point" for running and integrating AppImages. It makes a user's system AppImage-ready™. - -AppImageLauncher must be installed into the system to be able to integrate into the system properly. It uses technologies that are independent from any desktop environment features, and therefore should be able to run on most distributions. - -After install AppImageLauncher, you can simply double-click AppImages in file managers, browsers etc. You will be prompted whether to integrate the AppImage, or run it just once. When you choose to integrate your AppImage, the file will be moved into the directory :code:`~/Applications`. This helps reducing the mess of AppImages on your file system and prevents you from having to search for the actual AppImage file if you want to e.g., remove it. - -To provide a complete solution for managing AppImages on the system, AppImageLauncher furthermore provides solutions for updating and removing AppImages from the system. These functions can be found in the context menus of the entries in the desktop's launcher. - -.. _AppImageLauncher: https://github.com/TheAssassin/AppImageLauncher - -.. seealso:: - More information about AppImageLauncher can be found in :ref:`ref-appimagelauncher`. - - -Troubleshooting ---------------- - -Please refer to our :ref:`Troubleshooting page `. diff --git a/source/user-guide/troubleshooting/electron-sandboxing.rst b/source/user-guide/troubleshooting/electron-sandboxing.rst index 6d92d8c..5b11488 100644 --- a/source/user-guide/troubleshooting/electron-sandboxing.rst +++ b/source/user-guide/troubleshooting/electron-sandboxing.rst @@ -1,59 +1,68 @@ -.. _ref-troubleshooting-electron: - I have issues with Electron-based AppImages and their sandboxing ================================================================ -AppImages based on `Electron `__ require the kernel to be configured in a certain way to allow for its sandboxing to work as intended (specifically, the kernel needs to be allowed to provide "unprivileged namespaces"). Many distributions come with this configured out of the box (like `Ubuntu `__ prior to `24.04 `__), but some do not (for example `Debian `__). +AppImages based on `Electron `__ require the kernel to be configured in a certain way to allow for its sandboxing to work as intended (specifically, the kernel needs to be allowed to provide "unprivileged namespaces"). Many distributions come with this configured out of the box (like `Ubuntu `__ prior to `24.04 `__), but some do not (for example `Debian `__). + +This page explains how to check your kernel configuration and change it for Electron AppImages to work on your system. If an AppImage suffers from this issues, you should ask the developers to implement the workaround described in :ref:`this section ` so this won't be a problem for other users in the future anymore. .. warning:: + Please note that the AppImage team does not provide any guarantees that enabling this kernel feature is secure and safe. If in doubt, you should contact your distribution first. If they enable it securely by default, all users can benefit from this feature. + +.. contents:: Contents + :local: + :depth: 2 - Please note that the AppImage team does not provide any guarantees that enabling this feature is secure and safe. If in doubt, you need to contact your distribution first. If they enable those securely by default, all users can benefit from this feature. +Check if the kernel is configured correctly already +--------------------------------------------------- -Check if kernel is configured correctly already ------------------------------------------------ +To check if your distribution has unprivileged namespaces enabled, please run: -To check if your distribution has unprivileged namespaces enabled, please run:: +.. code-block:: shell > sysctl kernel.unprivileged_userns_clone kernel.unprivileged_userns_clone = 1 -A ``1`` means that the unprivileged namespaces are enabled already, and you do not have to take any action. -A ``0`` indicates that the feature is available, but not enabled at the moment. Please see the following sections on how to enable it. -.. note:: +This command does not need to be run as ``root``. - The command does not need to be run as ``root``. +A ``1`` means that the unprivileged namespaces are already enabled, and you do not have to take any action. +A ``0`` indicates that the feature is available, but not enabled at the moment. Please see the following sections on how to enable it. -.. _ref-electron-sandboxing-configure-temporarily: +.. _electron-configure-sandboxing: Configure unprivileged sandboxes -------------------------------- -To temporarily enable unprivileged namespaces, you can run this command:: +To temporarily (until the system is rebooted) enable unprivileged namespaces, you can run this command: + +.. code-block:: shell + + > sudo sysctl -w kernel.unprivileged_userns_clone=1 - sudo sysctl -w kernel.unprivileged_userns_clone=1 +You can run the same command, swapping the ``1`` for a ``0``, to disable it again. -You can run the same command, swapping the ``1`` for a ``0``, to disable this again. +To permanently enable the feature, you should create a new file with this setting in ``/etc/sysctl.d/``. You can do that by using the following command: -To permanently enable the feature, it is recommended to create a new file in ``/etc/sysctl.d/``. For your convenience, we have prepared the following command which creates the file on the fly:: +.. code-block:: shell - echo kernel.unprivileged_userns_clone = 1 | sudo tee /etc/sysctl.d/00-local-userns.conf + > echo "kernel.unprivileged_userns_clone = 1" > /etc/sysctl.d/enable-unprivileged-namespaces.conf .. note:: + This command will take effect after the next reboot. To change this on a running system, please refer to the :ref:`previous section `. - This command will take effect only on the next reboot. To change this on a running system, please refer to the :ref:`previous section `. + +.. _electron-without-sandboxing: Allow Electron AppImages to run without unprivileged namespaces --------------------------------------------------------------- -@gergof made a tool that automatically applies the `--no-sandbox` flag when the `unprivileged_userns_clone` kernel feature is not enabled: https://www.npmjs.com/package/electron-builder-sandbox-fix - +`@gergof `__ made a tool that automatically applies the ``--no-sandbox`` flag when the ``unprivileged_userns_clone`` kernel feature is not enabled: https://www.npmjs.com/package/electron-builder-sandbox-fix More information on unprivileged namespaces ------------------------------------------- -For more information on unprivileged namespaces, please see https://lwn.net/Articles/673597/. +For more information on unprivileged namespaces, see https://lwn.net/Articles/673597/. diff --git a/source/user-guide/troubleshooting/fuse.rst b/source/user-guide/troubleshooting/fuse.rst index 766f7f7..a029086 100644 --- a/source/user-guide/troubleshooting/fuse.rst +++ b/source/user-guide/troubleshooting/fuse.rst @@ -1,275 +1,202 @@ -.. _ref-ug-troubleshooting-fuse: +.. include:: ../../substitutions.rst + +.. _fuse-troubleshooting: I get some errors related to something called "FUSE" ==================================================== -AppImages require a Linux technology called *Filesystem in Userspace* (or short *FUSE*). The majority of systems ships with a working FUSE setup. However, sometimes, it doesn't quite work. This section explains a few solutions that fix the most frequently reported problems. - -.. contents:: Contents - :local: - :depth: 2 +:ref:`Older AppImages ` that haven't been created with the new static runtime yet require FUSE 2, the second version of a Linux technology called *Filesystem in Userspace*, to be installed on the system. As many systems don't ship with FUSE 2 out of the box anymore, such AppImages might write the following or a similar message to the console: - -The AppImage tells me it needs FUSE to run ------------------------------------------- - -Sometimes, an AppImage writes the following message to the console: - -.. can not use :: syntax to highlight raw text blocks, as pygments usually recognizes some language even if there is no code .. code-block:: text - AppImages require FUSE to run. + Cannot mount AppImage, please check your FUSE setup. You might still be able to extract the contents of this AppImage if you run it with the --appimage-extract option. See https://github.com/AppImage/AppImageKit/wiki/FUSE for more information -In this case, FUSE is not properly set up on your system. You will have to :ref:`install FUSE ` in order to fix the problem. +In this case, you need to :ref:`install FUSE 2 ` manually or use a workaround to run AppImages without FUSE. This page explains how to do this. -.. note:: - When trying to run AppImages which weren't built specifically for your platform, you might see this message as well, even if it doesn't occur while using AppImages built for your platform. Please see :ref:`these instructions ` on how to fix the issue. +.. + Add + You should also ask the application author to use a modern AppImage creation tool (which uses the new static runtime) so users don't have to manually install any dependencies anymore. + after the main AppImage creation tools (especially linuxdeploy) started using the new static runtime. +|fuse_docker| -.. _ref-install-fuse: +.. + You can't include code blocks in substitutions; therefore this block is duplicated. -How to install FUSE -------------------- +.. code-block:: text -Most Linux distributions come with a functional FUSE 2.x setup. However, if it is not working for you, you may have to install and configure FUSE 2.y yourself. + fuse: device not found, try 'modprobe fuse' first + open dir error: No such file or directory -The process of installing FUSE highly differs from distribution to distribution. This section shows how to install FUSE on the most common distributions. +If you want to run an AppImage inside a docker container, follow the instructions at :ref:`fuse-docker` instead. .. note:: - If your distribution is not listed, please ask the distribution developers for instructions. + When trying to run an AppImages which wasn't built for your architecture (e.g. a 32-bit one), you might see this message as well, even if it doesn't occur while using AppImages built for your architecture. In that case, you have to install the FUSE 2 runtime library for the architecture the AppImage was built for. -.. _ref-ug-troubleshooting-fuse-fuse2: +.. contents:: Contents + :local: + :depth: 2 -Setting up FUSE 2.x on Ubuntu (pre-22.04), Debian and their derivatives -*********************************************************************** -.. warning:: +.. _install-fuse: - This is valid only for distributions *not* having ``fuse3`` installed by default. To be sure, check whether the :code:`fuse3` package is installed, e.g., by running :code:`dpkg -l | grep fuse3` in the terminal and checking for a line starting with :code:`ii fuse3`. +How to install FUSE 2 +--------------------- - If your distribution is using :code:`fuse3`, please refer to the :ref:`next section `. +The process of installing FUSE 2 highly differs from distribution to distribution. This section shows how to install FUSE on the most common distributions. -Install the required packages:: +.. note:: + If your distribution is not listed, please ask the distribution developers for instructions. - > sudo apt-get install libfuse2 -.. note:: - In Ubuntu 24.04, the libfuse2 package was renamed to libfuse2t64. +.. _fuse-ubuntu-new: -Now, FUSE should be working. On some older distributions, you will have to run some additional configuration steps: +Setting up FUSE 2 alongside of FUSE 3 on recent Ubuntu (>=22.04), Debian and their derivatives +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -Make sure the FUSE kernel module is loaded:: +.. note:: + This is valid only for recent distributions having ``fuse3`` installed by default. To be sure, check whether the ``fuse3`` package is installed, e.g. by running ``dpkg -l | grep fuse3`` in the terminal and checking for a line starting with ``ii fuse3`` (if there is none, your distribution is not using ``fuse3``). - > sudo modprobe -v fuse + If your distribution is not using ``fuse3``, please refer to the :ref:`next section `. -Then, add the required group (should be created by the install command, if this is the case, this call *will* fail), and add your own user account to this group:: +First, add the official repository with FUSE 2 with ``sudo add-apt-repository universe``. Then, install it with ``sudo apt install libfuse2t64`` for Ubuntu >= 24.04 or ``sudo apt install libfuse2`` for Ubuntu >= 22.04 and < 24.04 (the package has been renamed in Ubuntu 24.04). Now, FUSE 2 should be working alongside of FUSE 3. - > sudo addgroup fuse - > sudo adduser $USER fuse +To install the 32-bit version of FUSE 2, use ``sudo apt install libfuse2:i386`` on ``x86_64`` or ``sudo apt install libfuse2:armhf`` on ``arm64``. -.. include:: notes/user-group-modifications.rst +.. todo:: + Add information on how to install the 32-bit version on newer versions after the rename. -.. _ref-ug-troubleshooting-fuse-fuse3: +.. _fuse-ubuntu-old: -Setting up FUSE 2.x alongside of FUSE 3.x on recent Ubuntu (>=22.04), Debian and their derivatives -************************************************************************************************** +Setting up FUSE 2 on old Ubuntu (pre-22.04), Debian and their derivatives ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. warning:: + This is valid only for older distributions *not* having ``fuse3`` installed by default. To be sure, check whether the ``fuse3`` package is installed, e.g. by running ``dpkg -l | grep fuse3`` in the terminal and checking for a line starting with ``ii fuse3``. - This is valid only for very recent (as of April 2022) distributions having :code:`fuse3` installed by default. To be sure, check whether the :code:`fuse3` package is installed, e.g., by running :code:`dpkg -l | grep fuse3` in the terminal and checking for a line starting with :code:`ii fuse3` (if there is none, your distribution is not using :code:`fuse3`). + If your distribution is using ``fuse3``, please refer to the :ref:`previous section `. - If your distribution is not using :code:`fuse3`, please refer to the :ref:`previous section `. + Installing the ``fuse`` package with ``fuse3`` installed might break your system! If this happened to you, follow `these instructions `__ to recover your system. -Install the required package:: +Install FUSE 2 with ``sudo apt install fuse libfuse2``. Now, it should be working. On some older distributions, you will have to run some additional configuration steps: - > sudo apt install libfuse2 +.. code-block:: shell -Now, FUSE 2.x should be working alongside of FUSE 3.x without breaking your system. + # Make sure the FUSE kernel module is loaded + > sudo modprobe -v fuse + # Then add the required group and add your user account to the group + # This should usually be created by the install command; if this is the case this will fail + # Then, you don't have to do anything else + > sudo groupadd fuse + > sudo usermod -aG fuse "$(whoami)" -Setting up FUSE 2.x on openSUSE -******************************* +|group_user_add| -Install the required package:: - > sudo zypper install fuse libfuse2 +Setting up FUSE 2 on Fedora ++++++++++++++++++++++++++++ -FUSE should now be working. +Install FUSE 2 with ``dnf install fuse fuse-libs``. -Setting up FUSE on CentOS and RHEL -********************************** +Setting up FUSE 2 on RHEL ++++++++++++++++++++++++++ .. note:: - The following instructions may be out of date. Contributions welcome! + The following instructions might be out of date. Contributions to update them are welcome! -Install FUSE from EPEL:: +Install FUSE 2 from EPEL with ``yum --enablerepo=epel install fuse-sshfs``. Then, add yourself to the related group in order to authorize yourself for using FUSE with ``sudo usermod -aG fuse "$(whoami)"``. |group_user_add| - > yum --enablerepo=epel install fuse-sshfs -Now, add yourself to the related group in order to authorize yourself for using FUSE:: +Setting up FUSE 2 on Arch Linux ++++++++++++++++++++++++++++++++ - > usermod -a -G fuse $(whoami) +Install FUSE 2 with ``sudo pacman -S fuse2``. -.. include:: notes/user-group-modifications.rst +A common issue, however, is that the ``fusermount`` binary's permissions may be incorrect. In that case, you would see the error message "fusermount: mount failed: Operation not permitted". Fortunately, you can easily fix this with the command ``sudo chmod u+s "$(which fusermount)"``. -.. _ref-warning-fuse-cross-architecture: -.. warning:: - If you are on a 64-bit system and want to run 32-bit AppImages (e.g., ``x86_64``/``amd64`` to ``i386``, or ``arm64`` to ``armhf``), you will have to install the FUSE runtime libraries for those architectures.:: - > sudo apt-get install libfuse2:i386 - > sudo apt-get install libfuse2:armhf +Setting up FUSE 2 on openSUSE ++++++++++++++++++++++++++++++ +Install FUSE 2 with ``sudo zypper install fuse libfuse2``. -Setting up FUSE on Clear Linux OS -********************************* +In order to use ``fusermount`` on openSUSE with the "secure" file permission settings (see ``/etc/permissions.secure``), your user needs to be part of the trusted group. To add yourself, run ``sudo usermod -a -G trusted "$(whoami)"``. |group_user_add| -On Clear Linux OS, FUSE *should* be enabled by default. However, if you see the error message mentioned before nevertheless, you can try the following trick: -.. code-block:: shell +Setting up FUSE 2 on Chromium OS, Chrome OS, Crostini or other derivatives +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - sudo mkdir -p /etc/modules-load.d/ - echo "fuse" | sudo tee /etc/modules-load.d/fuse.conf - sudo reboot +Install FUSE 2 with ``sudo apt install fuse``. -.. seealso:: - - This bug was also reported on `reported on GitHub `__. +Setting up FUSE 2 on Clear Linux OS ++++++++++++++++++++++++++++++++++++ -Setting up FUSE on Chromium OS, Chrome OS, Crostini or other derivatives -************************************************************************ - -FUSE is not operational out of the box. However, starting with release 73, it's fairly easy to install it: +On Clear Linux OS, FUSE *should* be enabled by default. However, if you see the error message mentioned before nevertheless, you can try the following: .. code-block:: shell - sudo apt install fuse - - -Setting up FUSE on Arch Linux -***************************** - -Install the required package: - -.. code-block:: shell - - sudo pacman -S fuse2 - -A common issue, however, is that the ``fusermount`` binary's permissions may be incorrect. Fortunately, there's an easy fix: - -.. code-block:: shell + > sudo mkdir -p /etc/modules-load.d/ + > echo "fuse" > /etc/modules-load.d/fuse.conf + > sudo reboot - # bash, dash, bourne shell: - sudo chmod u+s "$(which fusermount)" - - # fish shell: - sudo chmod u+s (which fusermount) +.. seealso:: + This bug was also `reported on GitHub `__. -.. _ref-fuse-fallback: +.. _fuse-fallback: Fallback (if FUSE can't be made working) ---------------------------------------- -If you do not want to (or cannot) set up FUSE, there are fallback solutions. Depending on the AppImage type, you can either mount the AppImage, or extract it and run the contents. +If you don't want to (or cannot) set up FUSE, there are fallback solutions. Depending on the AppImage type, you can either run it with a specific parameter (which will work for you like it would with FUSE) or manually extract or mount and then execute it. However, this is computationally more expensive, so it should usually only be done if you can't run it normally. +|depends_on_appimage_type| -.. _ref-extract-and-run-type-2: -Extract and run type 2 AppImages -******************************** +Run type 2 AppImages without FUSE ++++++++++++++++++++++++++++++++++ -Most AppImages nowadays are type 2 AppImages. The easiest way to run such an AppImage, if FUSE is not available, is to extract it and then run its contents. +Type 2 AppImages can easily be run |appimages_without_fuse|. This will cause the runtime to automatically extract the AppImage, run its content, wait until the app closes, and then clean up the file again. For an end user, this essentially has the same effect as just running it, although the operations are more expensive. -.. warning:: - Extracting an AppImage to run its contents is pretty expensive. It should only be done if you have no other options left. +Alternatively, you could also use an environment variable (``export APPIMAGE_EXTRACT_AND_RUN=1``) (which is forwarded to child processes as well) instead of the parameter (although this has been introduced a while after the parameter, so it might not work for every AppImage). +Optionally, you can also disable the cleanup, e.g. if you need to run the AppImage more than once, with an environmental variable: ``export NO_CLEANUP=1``. -The AppImage runtime has a built-in feature we call "extract-and-run". It extracts the AppImage, runs the contents, waits until the app closes, and then cleans up the files again: - -.. code-block:: shell - # using a parameter - ./my.AppImage --appimage-extract-and-run [...] +Manually extract and run AppImages +++++++++++++++++++++++++++++++++++ - # using an environment variable (which is usually forwarded to AppImage child processes, too) - # note that this was implemented a while after we introduced the parameter - # for older AppImages, you might have to use the parameter nevertheless - export APPIMAGE_EXTRACT_AND_RUN=1 - ./my.AppImage [...] - - # optionally, you can disable the cleanup if you need to run the AppImage more than once - export APPIMAGE_EXTRACT_AND_RUN=1 - env NO_CLEANUP=1 ./my.AppImage - -In case you have a very old AppImage (i.e., it uses a runtime from the time before "extract-and-run" was implemented), you can extract the AppImage manually: - -.. code-block:: shell +Alternatively, you can manually extract or mount an AppImage in any way described in :ref:`inspect-appimage-content`. After that, you can run the ``AppRun`` entry point in the directory the AppImage has been extracted to or mounted on: ``appimage_directory/AppRun``. - ./my.AppImage --appimage-extract - # the contents are extracted into the directory "squashfs-root" in the current working directory - # you can now run the "AppRun" entry point - squashfs-root/AppRun [...] - # optionally, you can clean up the directory again - rm -r squashfs-root/ +This mostly makes sense if you have an older AppImage which doesn't support the ``--appimage-extract-and-run`` parameter. -Mount or extract type 1 AppImages -********************************* - -If the process described in the :ref:`previous section ` does not work, you likely have a type 1 AppImage. - -Type 1 AppImages are regular ISO9660 files. They can therefore be *loop-mounted*. Note that you need ``root`` permissions to do so. - -.. code-block:: shell - - sudo mount -o loop my.AppImage /mnt - # now, you can run the contents - /mnt/AppRun - # when you're done, you can unmount the AppImage again - sudo unmount /mnt - -You can alternatively extract the AppImage, either using `AppImageExtract `__ or using an extraction tool which supports ISO9660 images (e.g., ``bsdtar``): - -.. code-block:: shell - - # install bsdtar - sudo apt install libarchive-tools - # create target directory - mkdir AppDir - # extract the contents into the new directory - cd AppDir - bsdtar xfp .../my.AppImage - # now, you can run the entry point - ./AppRun - +.. _fuse-docker: FUSE and Docker --------------- -Most Docker installations do not permit the use FUSE inside containers for security reasons. Instead, you can extract and run AppImages as described in the :ref:`previous section `. - -.. warning:: - - There's a lot of advice on the internet that follows the scheme, "just add the arguments ``--cap-add SYS_ADMIN --cap-add MKNOD --device /dev/fuse:mrw`` and it will work". It is, however, insecure to do so. There's a reason why Docker doesn't support FUSE by default. - - - - - - - - - +|fuse_docker| +.. + You can't include code blocks in substitutions; therefore this block is duplicated. +.. code-block:: text + fuse: device not found, try 'modprobe fuse' first + open dir error: No such file or directory +Instead, you can extract and run AppImages as described in the :ref:`previous section `. +If you want to decide whether to run the AppImage as usual or without FUSE, depending on whether you're in a container or not, for example in a build script, you can do that with `this detection code `__. +.. warning:: + There's a lot of advice on the internet that follows the scheme "just add the arguments ``--cap-add SYS_ADMIN --cap-add MKNOD --device /dev/fuse:mrw`` and it will work". It is, however, insecure to do so. There's a reason why Docker doesn't support FUSE by default. diff --git a/source/user-guide/troubleshooting/index.rst b/source/user-guide/troubleshooting/index.rst index d2edfe0..46b0c95 100644 --- a/source/user-guide/troubleshooting/index.rst +++ b/source/user-guide/troubleshooting/index.rst @@ -1,22 +1,18 @@ -.. _ref-ug-troubleshooting: +.. include:: ../../substitutions.rst Troubleshooting =============== -You have issues with AppImages in some way? Well, good you found your way to this section. Here, we present solutions to -the most common issues you can have when using AppImages. +This section gives an overview on the most common issues when using AppImages and their solutions. -.. note:: - - If you as a user think there are errors within this section or you would like to have some additional problems covered, please do not hesitate to `create an issue `__ on `GitHub `__ (or ideally send a pull request right away). We're always open for feedback! +.. cssclass:: bold -This page is not considered to be exhaustive. For additional help, please see the :ref:`Contact page `. +|appimage_not_starting_1| |appimage_not_starting_2| +This page is not considered to be exhaustive. |contact| -.. seealso:: - - The basic operation of AppImages is shown on our :ref:`ref-quickstart` page. This section covers issues which you should only - encounter if there's actual issues with your system, its configuration or with the AppImages themselves. +.. note:: + If you'd like to have some additional problems covered, please do not hesitate to `create an issue `__ (or ideally send a pull request right away). We're always open for feedback! .. toctree:: diff --git a/source/user-guide/troubleshooting/notes/user-group-modifications.rst b/source/user-guide/troubleshooting/notes/user-group-modifications.rst deleted file mode 100644 index e8f0dbf..0000000 --- a/source/user-guide/troubleshooting/notes/user-group-modifications.rst +++ /dev/null @@ -1,2 +0,0 @@ -.. note:: - After adding users to groups, these users must logout and login again for the change to take effect!