RCF: Basedir specification for non-Linux

Simon McVittie smcv at collabora.com
Tue Apr 27 11:12:33 UTC 2021


On Mon, 26 Apr 2021 at 23:46:46 +0200, piegames wrote:
> in discussions around applications adopting the basedir specification,
> the handling of non-Linux systems (especially Windows and MacOS) is
> something that really comes up a lot.

I think the right way to think about this is Windows vs. macOS
vs. "basically Unix", rather than specifically Linux being special.

Implementations of the basedir spec on non-Linux Unix OSs like the BSD
family usually use the basedir spec as-is - there's really no reason why
Linux and, for example, FreeBSD should be different here. They're more
similar than they are different (at least from a user point of view), and
they both use something resembling traditional Unix filesystem layouts
for the OS, so they might as well both use the basedir spec for paths
in the home directory.

Windows is really outside the scope of freedesktop.org because it's
neither Free/Open Source Software nor Unix, and it has its own conventions
for where files go. A large part of the purpose of freedesktop.org is
that it gives open-source OSs our own equivalent of the conventions that
Microsoft sets for Windows developers, so that developers can target
"the Linux platform" or "the Free desktop platforms" and have things
work reasonably consistently - but on Windows we don't need that,
because there's only one Windows, and Microsoft already designed it.

macOS is technically a FreeBSD derivative, but the
traditional/conventional paths are different; it could make sense to
special-case it, like Windows, or it could make sense to just treat it
as just another Unix derivative. People who literally port open-source
software to macOS can say what's most appropriate here better than the
Linux/*BSD community can.

Similarly, Android runs on the Linux kernel, but has its own filesystem
layout that's outside the scope of freedesktop.org.

> Thus, I have the following idea: if we set the default value for
> $XDG_DATA_HOME, $XDG_CACHE_HOME and $XDG_CONFIG_HOME to the respective
> native equivalents for non-Linux platforms, it would make things easier
> to adopt on the application side.

You've described what GLib does, in its APIs that wrap the basedir spec,
and I think that makes a lot of sense. GLib's APIs separate the "user"
directory (the one you write to and the highest priority for reading) from
the "system" directories (lower-priority), but you could implement something
very similar in an API that unified them into a single list.

Pseudocode (taken from the documentation, not necessarily a 100% match for
the actual implementation):

    def g_get_user_cache_dir():
        if XDG_CACHE_HOME is set:
            return $XDG_CACHE_HOME
        else if not Windows:
            return ~/.cache
        else:
            return CSIDL_INTERNET_CACHE
            (typically C:\Users\me\Local Settings\Temporary Internet Files)
            (this is not a perfect match, but it's good enough...)

    def g_get_user_config_dir():
        if XDG_CONFIG_HOME is set:
            return $XDG_CONFIG_HOME
        else if not Windows:
            return ~/.local/share
        else:
            return CSIDL_LOCAL_APPDATA
            (typically C:\Users\me\Local Settings\Application Data)

    def g_get_system_config_dirs():
        if XDG_CONFIG_DIRS is set:
            split and return it
        else if not Windows:
            return /etc/xdg
        else:
            return CSIDL_COMMON_APPDATA
            (typically C:\Users\All Users\Application Data)

    def g_get_user_data_dir():
        if XDG_DATA_HOME is set:
            return $XDG_DATA_HOME
        else if not Windows:
            return ~/.local/share
        else:
            return CSIDL_LOCAL_APPDATA
            (typically C:\Users\me\Local Settings\Application Data)

    def g_get_system_data_dirs():
        if XDG_DATA_DIRS is set:
            split and return it
        else if not Windows:
            return /usr/local/share, /usr/share
        else:
            return CSIDL_COMMON_APPDATA, CSIDL_COMMON_DOCUMENTS,
                calling DLL's ${prefix}/share, GLib's ${prefix}/share,
                program's ${prefix}/share

Qt does something similar in QStandardPaths::standardLocations, although
the details are different on Windows. In particular, the Qt API
distinguishes between roaming and local directories, which doesn't matter
on freedesktop.org platform but does matter on Windows.

I think Qt's approach is probably necessary if you want "first-class
citizen" support for Windows - GLib's simpler API more closely resembles
the basedir spec, but it cannot capture the distinction between local
and roaming directories on Windows.

    smcv


More information about the xdg mailing list