AppImage / AppImageSpec

This repository holds the specification for the AppImage format.
http://appimage.org/
MIT License
71 stars 22 forks source link

Provide facility to invoke alternate payload applications #8

Open tvierling opened 7 years ago

tvierling commented 7 years ago

While most applications do have a main entry point to get to all their functionality, plenty of apps ship with additional executables for various purposes, like cvlc (a command-line-only interface for VLC), editcap (a command-line pcap file splicer with Wireshark), and so forth. These might be additional binaries, or might be a change of behavior based on the argv[0] value of the main application at runtime.

There should be some way to invoke these alternate programs.


  1. The spec should provide a way to invoke an alternate program than the main payload.

    • The spec could provide a way to enumerate additional names and the locations of the respective programs within the AppDir explicitly, through a metadata file (not strictly necessary if the other options below are also implemented).

    • In the absence of explicit enumeration, or if an attempted program name was not enumerated, the AppImage should fallback by looking for the program name in a standard search path within the AppDir, e.g., /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin.

    • If there is still no matching program after looking at the explicit list and the search path, fallback to invoking the main payload application.

    • In all cases, set argv[0] to the attempted program name, possibly with a prepended path if one is found within the AppDir. This allows a program to change behavior based only on the name used to invoke it.

  2. The spec should specify one or more standard ways to identify which program was intended to be invoked by the user. Possibilities include (any or all could be implemented; the first two are probably the most useful):

    • Use argv[0] of the invoked AppImage to select the desired program (this works simply by symlinking the AppImage itself to the desired alternate name).

    • Use a special command argument at the start of the argument list which is unlikely to be meaningful to payload applications, e.g. --AppImageRun foobar contained in argv[1] and argv[2], with the remaining arguments passed through to the application. This could be used in .desktop files.

    • Use a predefined environment variable name, which could be used in a wrapper script.

probonopd commented 7 years ago

Thanks for your suggestion and ideas how to implement this. From time to time (very rarely) this topic comes up.

Let's collect very concrete use cases here. Do you have/are you interested in bundling an application that would benefit from this, here and now?

tvierling commented 7 years ago

Wireshark is the immediate poster example. It ships with a flurry of utility applications to do bulk work on packet capture files: capinfos, dumpcap, editcap, mergecap, rawshark, reordercap, text2cap. All these are command-line tools.

However, this concept allows for AppImage distribution of many packages that are designed to have many applications in them -- packages which may not even have a GUI or a designated "main" application. For instance: moreutils offers a set of small but useful tools, though perhaps so small that the AppImage overhead might be too much. ImageMagick would be a more appropriate and larger example, which is a set of ten applications with no main app. An extreme example would be something like netpbm.

KurtPfeifle commented 7 years ago

"ImageMagick would be a more appropriate and larger example, which is a set of ten applications with no main app."

As of v7.0.0 release of ImageMagick and thereafter, this is no longer true.

While for backward compatibility the ten (actually: twelve!) CLI tools (from IM v6.x and earlier) you mentioned are still invokable through their old names ("convert", "compare", "indentify", "compose", "animate", "montage" etc.), IM v7.x has one single new executable replacing the twelve, called magick. But you can run it as

 magick convert
 magick compare
 magick identify
 magick compose
 magick animate
 magick montage
 [....]

to get the same behaviour as in IM v6. Also, IM ships with symlinks using the old names which all point to the same magick executable, and which behave the same.

However, there are quite a few examples on MY personal wish list, all of them CLI utilities, which are developed as a set of distinguished executables. All these would benefit from a standard implementation of your feature request: poppler-utils, ghostscript, podofo, qpdf, ... Currently one can only work around it by adding an own custom AppRun (possibly through a more or less simple Shell script).

Also, if one looks closely enough, one discovers quite a few more GUI apps which are widley used and ship with little helper tools alongside represented through separate binaries: Blender, Calibre, All their extra functionalities "fall under the table" when using their respective AppImage packages. Granted, 99% of user may not be using these. But the 1% using them are the power users. If they miss out on something, they'll have a reason to not like AppImage, and they will tell the 99% about their unhappiness...

probonopd commented 7 years ago

A custom AppRun script can solve this easily.

KurtPfeifle commented 7 years ago

@probonopd wrote above:

"A custom AppRun script can solve this easily."

I know.

You didn't see that I wrote exactly that in my previous comment?

@KurtPfeifle:

"Currently one can only work around it by adding an own custom AppRun (possibly through a more or less simple Shell script)."

But couldn't this be made even more easy for AppImage packagers to achieve? Without requiring them to write a custom AppRun script for almost every additional application they want to package?

For example... let's assume, it could work the following way:

  1. AppImage packager knows that his application "Calibre" consists not only of the main GUI application, but also of a bunch of CLI utilities:
    • ebook-edit, ebook-viewer, lrfviewer, calibre, calibre-smtp, fetch-ebook-metadata, calibre-complete, calibre-customize, calibre-parallel, calibredb, calibre-debug, lrs2lrf, lrf2lrs, calibre-server, web2disk, markdown-calibre, ebook-polish, ebook-convert, ebook-meta, ebook-device
  2. AppImage packager knows, that he could add a simple ASCII text file named binaries.list into the root of the AppDir listing all the binaries (with their paths) he wants to expose to the user. (At this time I do not want to attempt to define the format of this .list file....)
  3. Application developer decides that he wants the AppImage not to support calibre-debug and calibre-server because they crash every time (this is an example invented by me), so he does not put them into the binaries.list file.
  4. Upon execution of the AppImage (or processing of it with one of the tools of the standard AppImage toolchain) the binaries.list file gets read (by whatever component -- you decide).
  5. Hence, when the user runs ./calibre.AppImage --appimage-binaries (or when `appimaged` digests it), he gets a list of available binaries.
  6. Now he knows which binaries are available.
  7. He can now ask the AppImage to start a non-default payload by running ./calibre.Appimage --appimage-launch=ebook-edit
  8. Likewise, appimaged also knows about the available binaries and can expose them in the desktop menus.
  9. The AppImage packager also wanted to expose the respective man pages too, so he created a simple ASCII text file, manpages.list.
  10. User can now also look at man pages by invoking ./calibre.Appimage --appimage-man=calibre or ./calibre.Appimage --appimage-man=lrfviewer.
    (After all, user is running the latest 'hot-from-the-oven' calibre.AppImage -- what use would it be to look at the system-provided man pages from 4 years ago?! Especially when calibre has a new release every one or two weeks, as is the case...)

A big part of this 'extra' work could be automated, by providing tools which create the .list files by themselves. And letting the AppImage packager only intervene and modify these, if something is not going according to his wishes...


I challenge you: This is sooooo overly complex and difficult to implement. We'll surely need a custom AppRun shell script to get this working. You will not be able to implement this into runtime.c or AppRun.c. The Snap and FlatPak people will be wayyyy ahead of you (or are they already??), to get this working!

probonopd commented 7 years ago

Yes, I can see the value in this, but It is clearly way more functionality than we can have in runtime.c and exceeds its scope (my estimation is that it would easily duplicate the LOC). So I suggest we should do a separate sub-project working on such an AppRun.c that would implement this and that people putting together AppImages can choose to use. Once this is in a working state, we can even consider that tools like linuxdeployqt could pick this up automatically for applications that have Terminal=true set.

The question is, who has the time to implement this? @tvierling maybe?

shoogle commented 6 years ago

If all of the executables are stored in the AppImage's bin directory then this could be as simple as checking if the first command line argument corresponds to the name of one of the executables. If so, run that executable with the remaining arguments. If it doesn't, pass all arguments (including the first) to the default executable.

# AppRun (or runtime.c, reimplemented in C)
if [[ -f "${APPDIR}/bin/$1" && -x "${APPDIR}/bin/$1" ]]; then
  cmd="$1"
  shift
  "${APPDIR}/bin/${cmd}" "$@"
else
  "${APPDIR}/bin/default-cmd" "$@"
fi

This might be small enough for runtime.c, and could be excluded at compile time for applications that don't need it, if a particular compile option or environment variable was specified (or unspecified, depending on what you want the default behaviour to be).

probonopd commented 6 years ago

True @shoogle - the only thing that complicates this a bit is the fact that nothing mandates to put commands into {APPDIR}/bin/ or {APPDIR}/usr/bin/. AppImage just says "provide an AppDir", and the AppDir spec iirc doesn't mandate a certain filesystem layout besides having some files like AppRun and .DirIcon.

shoogle commented 6 years ago

Maybe, but I think it would be useful to have a recommended/suggested internal structure for AppImages, specifically to enable useful optional features like this one. People who don't need the optional features can use their own layout; they wouldn't have to follow the recommendation.

The recommended structure would simply be the usual FHS + FreeDesktop.org layout, which pretty much everyone is using already. This makes it trivial matter to extract and "install" files from the AppImage that are needed for a full desktop integration.

${APPDIR}/bin/*                                    # binaries
${APPDIR}/lib/*.so                                 # libraries
${APPDIR}/share/applications/*.desktop             # desktop files
${APPDIR}/share/bash-completion/completions/*      # bash completions
${APPDIR}/share/icons/hicolor/scalable/apps/*.svg  # icons
${APPDIR}/share/man/man1/*.1.gz                    # manuals
${APPDIR}/share/mime/packages/*.xml                # filetype associations
${APPDIR}/share/MyApp/*                            # application files

I suppose you could prefix these with /usr if you want, but I kind of see the AppDir itself as being the /usr directory.

(Now what would be awesome is if we could have a write-enabled ${APPDIR}/home directory!)

Following this layout would be entirely optional, but would enable special features like:

probonopd commented 6 years ago

(Now what would be awesome is if we could have a write-enabled ${APPDIR}/home directory!)

We have something similar, ${APPIMAGE}.home support...