[Development] QStandardPaths could be helpful for cross platform portability, Qt Everywhere

Jeremy Whiting jpwhiting at kde.org
Tue Feb 24 07:24:07 CET 2015

Hello list,

I discussed a bit with Thiago and some others on irc this evening and have
realized that the QStandardPaths patch from [1] and discussion on [2] is
trying to solve too many problems at once. I'll list the problems here and
some possible solutions to these problems afterwards so we can discuss what
are appropriate/purposeful fixes to the problems and get these issues fixed.

QStandardPaths is useful to give paths to various places that are common to
all platforms. ConfigLocation tells where configurations should be stored
or read from, GenericDataLocation is where data should be, AppDataLocation
is where application specific location should be, etc. This works fairly
well except where assumptions are made as to where data, configurations,
applications, etc. are installed based on one platform. For example
applications written with Linux as a target can assume that
GenericDataLocation will include /usr/share/ and that ConfigLocation will
include ~/.config, then expect those to "just work" when the code is built
on other platforms. A few of the KDE Frameworks have been written with
these assumptions in mind. One difference between the different platforms
that Qt supports is that on some platforms these paths can be easily
modified at runtime, while that's not currently possible on all platforms.
On Linux GenericDataLocation can be modified at run time by setting
XDG_DATA_DIRS, ConfigLocation can likewise be modified at run time by
setting XDG_CONFIG_DIRS, but there's not currently a way to set or modify
those on Windows or OS X platforms.

One possible solution to this for app bundles on OS X is to include the
data files any application needs inside the .app itself. The problem with
that is that QStandardPaths doesn't look for files inside the .app bundle
so if we included icons, data files, etc. in addition to libraries and
application icon resources the library code that uses QStandardPaths
unmodified to find these files would still fail. The same argument could be
used for relative paths on Windows.

One use case for the above problem are applications that use data files
from their own project and also files from other projects. kdoctools
meinproc5 executable is one use case. It uses QStandardPaths to locate the
xsl stylesheets required to create documentation. These stylesheets come
from kdoctools and also kdelibs4support. These two separate projects could
be modified to put their files into /Library/Application Support on OS X so
QStandardPaths can find them. This is a tool used by developers, not end
users, so installing here shouldn't be a problem.

Another use case are data files used by multiple applications. These are
stored and safely looked up via QStandardPaths on Linux/Unix in /usr/share
followed by some application or data type prefix and the data files
themselves. If we want to use these libraries with their accompanying data
files on other platforms we either need to rewrite them with #ifdef code to
search in different places, which is not possible when using
QStandardPaths::locate/locateAll since it only looks in it's standard
locations, or search manually for the data files shipped with the
library/application or improve QStandardPaths itself. (Note one considered
solution to this would be to use DocumentsLocation or one of the other user
locations, but this isn't available for applications to install data files
that come with the applications into).

Proposed and considered solutions:

One solution is to use/support XDG_*_DIRS environment variables on all
platforms. This has one advantage in that the same tools can be used on all
platforms to customize the paths given by the standard. This is ok for
developers working on software, but not the best idea for shipping actual
software to end users since setting environment variables is not often easy
or advisable and has other effects. Note this is the approach of the patch
in gerrit, but it's a non-solution because of the above mentioned issues.

A second solution is to add some API to QStandardPaths to modify the paths
at run time. This would allow libraries to add paths to QStandardPaths'
standard paths that it needs in its initialization methods. For example a
library that requires data files that it knows are installed to /some/path
can add /some/path to the GenericDataLocation via something like
QStandardPaths::addCustomPath(GenericDataLocation, "/some/path") and it's
subsequent calls to QStandardPaths::locate(GenericDataLocation,
"somedatafile") would get the file required.

Another similar option would be to always add relative paths based on the
application binary or library (or both) so libraries installed inside a
.app bundle on OS X could find the data files that are also inside the .app
bundle. This way binaries on Windows could also find data files and
libraries relative to the installation path of the executable itself, so if
end users install MyProgram into D:\Some\Path\Myprogram, and the installer
puts the data files beneath that, QStandardPaths api could find the data
files wanted.

Obviously some changes will be required to any software that has made the
above mentioned assumptions about QStandardPaths build systems but if we
could also improve QStandardPaths itself in one of the above mentioned
solutions that could possibly help make it easier to port applications and
libraries from one of Qt's platforms to another.

Thoughts, opinions, counterarguments, suggestions?


[1] https://codereview.qt-project.org/#/c/103277/
[2] https://bugreports.qt.io/browse/QTBUG-44473
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20150223/eb570912/attachment.html>

More information about the Development mailing list