Sailfish FAQ

Last updated 24.1.2023


  • What should I name the application?
    You have to use the prefix "harbour-" in front of the application name. Only lower case characters are allowed.
  • Why do I have to name my Application with a prefix?
    The reason for this requirement is so that applications do not clash with other installed packages on the device. It also allows us to verify certain things automatically, e.g. imports of your own QML modules.
  • What is that '<HARBOUR_APP_NAME>' you use here in the FAQ's?
    That is your application name including the prefix "harbour-" (e.g. harbour-myawesomeapp).
  • How can I name the app in the application launch grid? I don't want that long name with prefix to appear there!
    In the .desktop file, there is the "Name=" field. The string defined there is shown in the application launcher as the application name. That name does not have to be unique. So there might be more than one application called "HelloWorld!" in the application launcher grid. The package name of the application (<HARBOUR_APP_NAME>) does not appear in the UI.
  • Where must this <HARBOUR_APP_NAME> be used?
    1. the executable binary: /usr/bin/<HARBOUR_APP_NAME>
    2. the .desktop file: /usr/share/applications/<HARBOUR_APP_NAME>.desktop
    3. the icon: /usr/share/icons/hicolor/<size>/apps/<HARBOUR_APP_NAME>.png
    4. the folder in /usr/share where you can install other application files: /usr/share/<HARBOUR_APP_NAME>
    5. The RPM package name, note that is not necessarily the same as the RPM file name!
      The name you get with:
      rpm -q --queryformat='%{NAME}\n' -p <HARBOUR_APP_NAME>-1.0-1.<architecture>.rpm
      That is what is set in .spec resp. .yaml file under "Name: "
    6. the RPM file name e.g. <HARBOUR_APP_NAME>-1.0-1.<architecture>.rpm
  • Do I need to put that unique <HARBOUR_APP_NAME> into the "Title" field when I upload an app to the Harbour?
    No, in the "Title" field you can use a pretty name that will be shown to the user in the store client UI.


  • In which locations can I install files?
    You are allowed to install:
    /usr/bin/<HARBOUR_APP_NAME> <- the executable binary
    /usr/share/applications/<HARBOUR_APP_NAME>.desktop <- the desktop file
    /usr/share/icons/hicolor/<size>/apps/<HARBOUR_APP_NAME>.png <- the icon files
    /usr/share/<HARBOUR_APP_NAME>/* <- anything else (data files, private shared libraries, private QML imports, etc..) goes here
  • Why are you so restrictive? Why can't I install my libraries, images etc in places where I think it makes sense?
    We have to ensure that RPM can be installed and do not conflict with other RPMs. It will also allow us to install store applications under a different path (rpm --relocate) in the future.
  • What does the package name have to be? (.spec/.yaml "Name: foo")
    Use "Name: <HARBOUR_APP_NAME>". See Naming section in this FAQ.
  • Can I install files in /home/nemo?

    No! We don't allow installation of files into /home/nemo from RPM. The user, the path for the home dir, or the user under which the app runs could change in future! It could also overwrite user data during an upgrade of the RPM package!

    If you need a place to write files during run time: Please create a subfolder during run time named <HARBOUR_APP_NAME> inside a folder defined by the XDG Base Directory Specification (e.g. $XDG_CONFIG_HOME/<HARBOUR_APP_NAME>, see also the 'Naming' section above).

  • I have a huge amount of data files which the user can edit/change during run time. What can I do?

    You could install them to /usr/share/<HARBOUR_APP_NAME>, and then just have a flag in $XDG_*_HOME/<HARBOUR_APP_NAME> if the user wants to disable the system-wide data. Of course, this doesn’t free the data, but in case hiding/not loading the data will improve e.g. the startup time or user experience.

    Also, another thing: Having big pre-installed data in the app packaged (=inside the RPM) is bad, as it will require this data to be re-downloaded every time the package is installed, and (during installation time) will take up the space for the - temporarily downloaded - RPM and the extracted data (you will need ~400 MB free to extract a 200 MB RPM file with 200 MB of data inside, not taking into account compression and stuff).

    So, you have an app plus some big data that probably doesn’t change as often as the code does (either it changes more often or it doesn’t change as often - the data doesn’t usually have anything to do with code updates to your app except if you happen to do some data format changes). There are basically two options:

    1. Don’t ship any data with your application
      • Small download and upgrade size, no wasted space
      • For the “pre-packaged” data, you could download them in the app on first start
      • Requires some web space where the data can be downloaded
    2. Ship data with your application, and don’t let the user delete it
      • No need to host any data packages
      • Package upgrades and first download will be unnecessarily large
    We'd suggest you do variant 1 for the time being. If there is enough interest we might come up with a solution for "expansion" packages in the store in the future. Show your interest on this question at

  • I got the following reject reason: "ERROR [] 'Provides:' not allowed in RPM". What can I do?

    You most likely have your own libraries packaged to the RPM. Harbour RPM packages should not provide anything, also not own provided libraries. To exclude libraries from the 'Provides section', which you ship with your RPM, please add the following to the .spec file between the "# >> macros" and "# << macros".

    # >> macros
    %define __provides_exclude_from ^%{_datadir}/.*$
    # << macros
  • I got the following reject reason: "ERROR [] Cannot require shared library: ''". What can I do?

    You most likely have your own libraries packaged to the RPM. Harbour RPM packages should not require any library which is not allowed (see allowed libraries below), also not own provided libraries. To exclude libraries from the 'Requires section', which you ship with your RPM, please add the following to the .spec file between the "# >> macros" and "# << macros". You have to specify each library name!

    # >> macros
    # list here all the libraries your RPM installs
    %define __requires_exclude ^libFoo|libBar|libFooBar.*$
    # << macros
  • I got the following warning when my package got rejected: "WARNING [<HARBOUR_APP_NAME>] 'Provides: <HARBOUR_APP_NAME>' not allowed in RPM". What can I do?
    This is not the reason your package got rejected, it's just a warning! But in future we won't allow such provides any more. We currently investigate which changes to the SDK are needed, so we can enforce this rule.
  • Which RPM file naming convention must the RPM file name follow?
    The file name of the RPM must be in the the form: <HARBOUR_APP_NAME>-version-release.architecture.rpm e.g.
    harbour-awesomeapp-1.0-1.armv7hl.rpm for armv7hl RPM packages
    harbour-awesomeapp-1.0-1.i486.rpm for i486 RPM packages
    harbour-awesomeapp-1.0-1.noarch.rpm for QML only noarch RPM packages
    See also Naming section in this FAQ and the more detailed binary guidelines on the application submit page.
  • Can the rpm package contain %pre scripts, %post scripts, %preun scripts, %postun scripts or %verifyscript scripts?
    No, these scripts run as user root and currently allowed applications in store do not need to run such maintainer scripts.
  • Why can't I set a folder or a file under /usr/share/<HARBOUR_APP_NAME>/ to be world writeable? E.g. chmod 666 resp. chmod 777.
    Files and folders provided by the rpm package have to stay under the control of the package manager. Deleting files doesn’t work, as those files will be re-created each time the package is upgraded. Modifying files doesn’t work, as those files will be overwritten each time the package is upgraded. See the next question for where to store such data.
  • Where should I store application configuration, application data and cache files?

    Depending on the purpose, you should store files according to the XDG Base Directory Specification. You should append an organization name and an application name to the path. The organization name and the application name should be the same ones as you have defined in the .desktop file.

    On Sailfish OS, the config, data and cache directories are used as follows:

    • Config directory ($XDG_CONFIG_HOME/<ORGANIZATION_NAME>/<APP_NAME>): Used to store user preferences, e.g. mode of operation, optional feature toggles, theme settings, behavior configuration, etc. Clearing the config directory should reset the application settings, but keep user data.
    • Data directory ($XDG_DATA_HOME/<ORGANIZATION_NAME>/<APP_NAME>): Used to store user-generated data, application-generated data and everything that doesn't fall under the "config" category. Clearing the data directory should remove user data.
    • Cache directory ($XDG_CACHE_HOME/<ORGANIZATION_NAME>/<APP_NAME>): Used to store cached data (e.g. web cached, derived data such as thumbnails that can be re-generated, etc..). Clearing the cache directory should not affect user data or configuration (i.e. the system is free to clear the cache directory when space runs low, and the application should be unaffected and still function normally / no user data should be lost).

    You must not hardcode /home/nemo/ or $HOME/.config/, etc. - use the Qt 5 QStandardPaths, GLib convenience methods or the xdg-helper library to determine the paths. This will make sure your application keeps working for sandboxed use cases, multi-user use cases as well as multi-profile single-user use cases.

  • $XDG_CONFIG_HOME, $XDG_DATA_HOME and $XDG_CACHE_HOME are not set in the device environment. So which path should I use?
    Yes, these environment variables are currently not set. Though we have plans for it in the future. So do what the XDG Base Directory Specification defines:
    • If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used.
    • If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME/.config should be used.
    • If $XDG_CACHE_HOME is either not set or empty, a default equal to $HOME/.cache should be used.
  • Can the SUID-Bit be set on my binaries?
    No, SUID/SGID binaries are not allowed in Harbour. There is no need for your application to run as user root. Packages that need such permissions should be either rewritten to not require SUID permissions or be distributed via other means, Harbour is not the right place for such packages - this is an application store for end user applications.
  • Which 'Requires' is the RPM package allowed to have?
    You can find a list of the currently allowed 'Requires' in documentation.
    Please note that:
    'Requires' must not be versioned, only non-versioned requires are allowed.
  • How must the RPM version be incremented?
    If you submit an update to an existing application in Store, you have to increment the RPM 'version', it's not enough to increment the RPM 'release'.
    RPM 'version' and RPM 'release' are defined in the .spec-file resp. .yaml-file. RPM 'version' is the value in the field Version and has normally the form of #.# or #.#.#, e.g. 1.2 or 1.3.5. RPM 'release' is the value in the field Release and has normally the form of #, e.g. 7.
    Some examples:
    Version in StoreUpdate versionComment
    1.0-11.0-4Not OK, just release is incremented
    1.6.3-11.6.3-8Not OK, just release is incremented
    1.7.8-11.1-1Not OK, update version is lower than version in Store
  • Can I set a vendor in the RPM?
    No, because the used zypper configuration does not allow to update RPM packages from different vendors. Starting with RPM validator 1.23 RPMs with a vendor set are not allowed any more.
  • RPM validator warns me that the vendor is set to 'meego', why?
    See previous question. Since RPM validator 1.23 we do not allow anymore that the vendor in the RPM is set. Unfortunately there are already some apps in the store having 'meego' set as vendor. In order to still allow these apps RPM validator gives a warning. In case you have set your vendor to 'meego' for previous uploads, you also have to set 'meego' as vendor for future uploads of the same app. If you are uploading a new app, or have not set the vendor to 'meego' in previous uploads, you must not use 'meego' as the vendor.
  • I want to build the RPM in public Mer QBS, but that sets the vendor to 'meego', what can I do?
    In the project config add the following to the Macros: section.
    %vendor %%foo
    The extra % expands to nil string in case %foo does not exist. So the vendor will be empty and not set in that OBS project.


OS versions

  • What does "Detected OS versions compatibility" mean?

    The uploaded RPM's 'Requires' are checked against the provided packages in different OS versions and a preliminary list of compatible OS versions is provided.

    Note that this is only indication that the RPM is installable on the OS versions listed as compatible. It does not guarantee that the application will actually work, as there are currently some compatibility aspects which are not automatically detectable.

  • What should I set in the "From OS version" option?

    With the "From OS version" option you can select the lowest OS version your application is compatible with and available from the store.

    But usually you don't need to set it and the the detected OS version compatibility is just fine. Only set it if you know that your application does not work on older versions.

  • Does Harbour QA test the application on all OS versions?
    No. Normally QA tests the application only with the latest released OS version.

Device Type

  • What does the "device type" option mean

    Device type option will define on what type of devices your application will be available in the store. If you select "phone", it will be only available on phones. If you select "tablet" it will be only available on tablets. If you select both, or nothing, your application will be available on all types of devices.

    Note that at the moment this is mainly about the screen size and scalability of your application's UI.

  • What are the CPU architectures of the Jolla devices?

    CPU Architecture for the Jolla phone is armv7hl and for the Jolla tablet i486. But the device type and CPU architecture are not in any way tied together. In the future there can be phones and tablets with different architectures, other types of devices, etc.

  • How does the architecture of the uploaded binaries affect the device compatibility?

    If your application contains compiled parts, it needs to be built for all the supported architectures. At the moment we support armv7hl and i486 architectures.

    If you do not provide RPM for certain architecture, your application won't be available in store on devices with that architecture. E.g. if you only upload armv7hl RPM, your application won't be available for the Jolla tablet, even if you select "tablet" as a compatible device type.

    If your application is architecture independet, i.e. pure QML or QML + python application, then you only need to upload one "noarch" RPM, which will then be available for all device architectures.

    Android applications are also considered architecture independent and will be treated like "noarch" native applications.

  • I can not build my application for architecture X, what should I do?

    If that is really the case, for example when your application depends on binary blob that is only available for certain architectures, then just note that in the "Message for QA".


  • Which size should the application icon be?
    You should provide icon in sizes 86x86, 108x108, 128x128 and 172x172.

    This is needed for showing the best possible icon on different devices with different screen sizes and resolutions. If there is no icon with the appropriate size, the closest one is selected and scaled to fit the UI, which in case of upscaling can lead to rather ugly results.

    Please note that:

    Older SDK versions contain a template which suggests a size of 90x90 and also a different install path. That is obsolete and not supported anymore.

  • Where shall the icon be installed?

    Where <size> is one of 86x86, 108x108, 128x128 or 172x172

    Please note that:

    Older SDK versions contain a template which suggests a size of 90x90 and also a different install path. That is obsolete and not supported anymore.

    And at the moment the RPM validator gives an error about the other icon sizes except 86x86. That can be ignored for now and the validator will be fixed in future SDK releases.

  • What file formats are supported for the icon?
    The icon must be a PNG file.
  • How do I define an icon in the .desktop file, so it shows up in the application launcher?
    You must not use absolute path names. The reason to not use absolute path names is: it would allow us in the future to install store applications under a different path.
    Please note that:
    There was a bug in older SDK versions (lipstick < 0.18.6) so the absolute path was necessary and the template suggested it.
  • Where can I find information about icon designs?
    Please check out the Apps icons page, for more information about icon designs.


  • What do I have to put into the Exec= line?

    For Silica applications using C++ and QML

    For QML-only Silica applications without an application binary
    Exec=sailfish-qml <HARBOUR_APP_NAME>

  • What do I have to put into the Icon= line?
  • What do I have to put into the Name= line?
    The name defined there is shown in the application launcher as the application name. That name does not have to be unique. So there might be more than one application called "HelloWorld!" in the application launcher grid.
  • What do I have to put into the X-Nemo-Application-Type= line and what is it good for?
    For Silica Qt 5 applications, use "X-Nemo-Application-Type=silica-qt5" - this will make sure that the application is launched using the right booster, and will make startup faster.
  • How can I disable single-instance launching?
    In general, you should use single-instance launching (tapping on the application icon will bring the existing window to the foreground). If for some reason your application conflicts with single-instance launching, you can add "X-Nemo-Single-Instance=no" to your .desktop file to disable this behaviour.
  • What is the 'Categories' field used for in SailfishOS?
    Lipstick uses Categories so that if you create a new folder by dragging two icons on top of each other, the folder will be named based on the category common to both of these applications. For example, if file1.desktop has Categories=Office;Science; and file2.desktop has Categories=Utility;Office;, the folder will be called Office. The supported category names are listed in Desktop Menu Specification. We may add more in the future.
  • What should I put in the X-Sailjail section?

    You should have three fields there: OrganizationName, ApplicationName and Permissions. Additionally starting from Sailfish OS 4.5.0 you may have ExecDBus field.

    OrganizationName and ApplicationName are used for determining the directory names used for storing application configuration, data and cache files. See above for more details on the directory names. The Permissions field is used for requesting permissions for your application. See Sailjail Permissions documentation for details, and a list of permissions which are allowed in Harbour.

  • What should I put in the ExecDBus field?
    The value of ExecDBus field in X-Sailjail section should be the same as Exec field's value in Desktop Entry section, but additionally it may have an extra argument, like --dbus, to distinguish D-Bus activation from regular launch from icon. Only letters, numbers, dash and underscore are allowed in this argument. See Launchers documentation for more details on D-Bus activation with launchers.


  • Which QML modules (imports) are allowed?
    You can find a list of the currently allowed QML modules (imports) in the documentation. Modules which are deprecated are listed in the documentation as well.
  • Why do you not allow more QML modules from Qt/Nemo/Mer or other 3rd party?
    Not all modules have a stable API. Before promising compatibility, we must first make sure that we can promise the API is of high quality and will not change (through a review process). We are open for suggestions to provide more APIs.
  • Can I use QML modules, which I ship together with the application?
    Yes, you can do that. Just ensure the name of the imports does not match any of those listed in disallowed_qmlimport_patterns.conf. And you have to install them under /usr/share/<HARBOUR_APP_NAME> (loadable QML plugins or the QML files) if the type is not built into the application (qmlRegisterType). Since Sailfish OS release, libsailfishapp adds /usr/share/<HARBOUR_APP_NAME> automatically to the QML import path. It is also possible to ship own QML modules as compiled-in resources.

Shared Libraries

  • Which shared libraries can I link against?
    You can find a list of the currently allowed libraries in the documentation.
  • Why do you allow just such a limited amount of shared libraries?
    We can only whitelist libraries that have both a stable API and ABI, and which we are sure we can provide for the forseeable future. For now, the list is quite small, but as Sailfish OS matures, we expect to add more. We are open for suggestions to allow more stable shared libraries.
  • Can I link against shared libraries which I ship with the app together in the same RPM?
    Yes, you can do that. But you have to install the library under /usr/share/<HARBOUR_APP_NAME>/lib. If you built your application against libsailfishapp >= 0.0.11 then the rpath in the binary should be set correctly. If you are not using libsailfishapp you have to ensure yourself that the rpath in your executable is set correct, so the linker finds the library. In qmake you can use QMAKE_RPATHDIR to set the rpath. You can verify the rpath in the binary with the readelf command from inside the mersdk virtual machine:
    [mersdk@SailfishSDK src]$ readelf -d <HARBOUR_APP_NAME> | grep RPATH
     0x0000000f (RPATH)                      Library rpath: [/usr/share/<HARBOUR_APP_NAME>/lib]
    [mersdk@SailfishSDK src]$
    Also the 'RPM validator' which you can find in the Harbour Tools verifies the rpath and prints it out:
    OK [rpath in binary seems to be ok: '/usr/share/<HARBOUR_APP_NAME>/lib']
  • You do not allow QtOpenGL, what is the alternative?

    QtGui in Qt 5 includes a number of classes to replace the QtOpenGL classes. In many cases, using the QtGui equivalents will just involve a renaming (QGL* -> QOpenGL*) and removing the linking against QtOpenGL. There are API changes involved in some cases, but these should not be too difficult.

    Startup performance is better without using QtOpenGL, which is one reason we are disallowing it. This is due to its dependency on QtWidgets, which is quite a large library.

  • Why do you not allow QtWidgets?
    QtWidgets is not optimized for (or well tested) on Sailfish OS. Furthermore, it is generally not going to result in a good user experience due to using non-touch-optimized controls, and software rendering (which will be much slower than rendering using OpenGL ES on Sailfish OS).
  • I think library XYZ would be useful for others too, I want to make that library available in the store. Can I submit a library only RPM?
    No, the app store, is as the name says, an application store and not a shared library store. But if you think an important library is missing in SailfishOS and you want to see it available in the platform, then please join the Mer and Nemo project and make the library available in one of these projects. Then suggest the library to become a supported one (by making sure it has a stable API, and is well-maintained and supported).
  • What is the current status of $LIBRARY / $API?
    libsoupUse libcurl instead (which is already supported in Harbour) - it's faster, more portable and has a better history of ABI stability:
    QtLocationThis Qt module is not yet stabilized in upstream Qt, we can therefore not guarantee a stable API. Once upstream Qt stabilizes the QtLocation API, it will be available for Harbour apps.
    GStreamer APIs and plug-insWe are currently investigating the best way to support GStreamer API usage. Currently it is still lacking support for resource policies. Consider using QtMultimedia instead, which is already a supported API in Harbour, handles resource policies, and has C++ bindings as well as QML components ready to use.
    PackageKit D-Bus APIThis API is not allowed to prevent unrequested sideloading. See "I want an 'RPM install' feature in my application..." question and "Why can't I use PackageKit's D-Bus API?" question below.


  • Can I configure a D-Bus 'Activation' with a .service file?
    No, but starting from Sailfish OS 4.5.0 you can enable automatic generation of service files with ExecDBus field in .desktop-file to use D-Bus activation. See Launchers documentation for more details on D-Bus activation with launchers.
  • Why can't I use PackageKit's D-Bus API?
    The D-Bus API will be made unavailable to 3rd party applications (probably in update 5) to prevent unrequested (from the user not approved) sideloading of RPM packages. See "I want an 'RPM install' feature in my application..." question below.
  • What D-Bus API's can I use?
    D-Bus APIs generally are available to you if you have the right to access them from your application without raising the applications privileges. The PackageKit D-Bus API is the one big exception there at the moment. See question above.
  • What about the notifications D-Bus API?
    There are no plans to restrict the access to the D-Bus API interface org.freedesktop.Notifications in future.


  • Can I submit Python applications?
    Python is allowed in connection with PyOtherSide. This allows you to write the application logic in Python and use the Sailfish Silica UI written in QML.
  • Do you have a simple example with PyOtherSide?
    No, but you can check out gPodder. It's accepted in store and uses PyOtherSide.
  • Can I use PIP (the Python package manager) to install missing Python-libraries on the device?
    No, the RPM file containing the application must include all the needed Python-libraries.
  • Can I submit Perl/Ruby/$MY_FAVOURITE_LANGUAGE applications?
    No, and we currently do not plan to support that. But feel free to request it, if there is enough interest, we might allow it in the future.

Android Applications

  • How do I need to version my Android applications

    Android APKs have two version attributes, 'android:versionCode' and 'android:versionName'. The versionCode is an integer value that is used to compare package versions and the versionName is a string that is used only for human presentation.

    The only rule on android is that the versionCode needs to be incremented on each successive release of the application. See Android app versioning instructions

    The android APKs submitted to Harbour are wrapped into RPM packages, so that they can be installed by the native Sailfish OS package management system. When the APK is wrapped in a RPM package it gets a version number in format


    This is bacause the RPM packaging system does not have a differentation between the human and machine readable versions. And this also means that Android applications submitted to Harbour need to follow both rules

    • 'android:versionName'-atribute has to follow the format and incrementation rules of the RPM package versions here
    • 'android:versionCode'-attribute has to follow the Android incrementation rule


  • Is there a way to verify that the RPM package is in compliance with these rules?
    The SDK Control Center offers a method in the view 'Harbour Tools' to run some basic Harbour requirements checks. A successful validation means that the basic packaging is okay, however, it does not guarantee that the package or app will be accepted in Harbour. Validation is just one step in the QA process, and your application can fail validation for other reasons.
  • I want an 'RPM install' feature in my application, how can I install/sideload RPMs from a program?
    As mentioned above you are not allowed to use PackageKit's D-Bus API. Use Qt.openFileExternally() method in QML and QDesktopServices::openUrl() in C++ to trigger a sideload. Use the absolute file path to the RPM file. If you want to monitor the progress, the following signals on the session D-Bus are available:

    signal path=/StoreClient; interface=com.jolla.jollastore; member=packageProgressChanged
      string "filename.rpm"
      int32 progress (0-100)
    signal path=/StoreClient; interface=com.jolla.jollastore; member=packageStatusChanged
      string "filename.rpm"
      int32 0 (not installed?), 1 (installed?) and 2 (progressing?)
    signal path=/StoreClient; interface=com.jolla.jollastore; member=packageError
      string "details"

  • If my application is not responding, a pop-up banner says "Unnamed application is not responding". How can I name the application?
    In Qt applications ensure you have the name set with QGuiApplication::setApplicationDisplayName(const QString&) or QCoreApplication::setApplicationName(const QString&). libsailfishapp does the latter automatically if you use it in your application.
  • I want to update some of the information (description, screenshots, etc.) for my application, what is the best way?

    Just edit the information on the application edit page and submit it to QA again. In these cases when you only change the store "assets", you don't need to reupload or touch the binary in any way. Changing the binary in any way, even reuploading the same package, will require it to go through the full set of QA tests and slows down the process.

    If your submission got rejected because the binary was incorrectly marked as changed (there was a bug in Harbour binary change detection, or you accidentally deleted it and had to reupload it), then make a note in the "Message to QA" that this is an assets only change and resubmit.