Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow optional use of XDG base or custom directories on macOS #10838

Closed
fractalcounty opened this issue Sep 27, 2024 · 4 comments
Closed

Allow optional use of XDG base or custom directories on macOS #10838

fractalcounty opened this issue Sep 27, 2024 · 4 comments

Comments

@fractalcounty
Copy link

fractalcounty commented Sep 27, 2024

Describe the project you are working on

A multi-platform game targeting both macOS and Linux with a development workflow that involves frequent switching between the two platforms

Describe the problem or limitation you are having in your project

Currently, Godot on macOS stores configuration, data, and cache files in macOS-specific directories:

Configuration and Data: ~/Library/Application Support/Godot/
Cache: ~/Library/Caches/Godot/

On Linux, Godot adheres to the XDG Base Directory specification, using:

Configuration: ~/.config/godot/
Data: ~/.local/share/godot/
Cache: ~/.cache/godot/

This makes sense, as XDG is primarily a Linux standard. So what's the problem?

A massive amount of multi-platform software uses the XDG Base Directory specification on both Linux and macOS, presumably because of their shared *nix/Unix-like design. On my machine, I utilize my ~/.config/ directory much more than the standard Application Support directory. An added benefit of this is that it allows me to seamlessly track and sync my app configurations across both macOS and Linux environments. This works like a charm for 99% of programs I use, as most at least allow the user to define a custom config directory if all else fails.

Unfortunately, aside from a few App Store applications, Godot is one of the only applications I use for development that doesn't support the optional use of XDG Base Directories (or any custom data directories) on macOS whatsoever. As a result, I have to rely on symlinks and scripting to track editor config data in my dotfiles repo.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I propose that the Linux/BSD platform's support of XDG directories (or custom data directories in general) should be extended to macOS, allowing macOS users to optionally store configuration, data, and cache files in the standard XDG locations:

Type Default path Optional XDG path
Data ~/Library/Application Support/Godot/ ~/.local/share/godot/ ($XDG_DATA_HOME)
Settings ~/Library/Application Support/Godot/ ~/.config/godot/ ($XDG_CONFIG_HOME)
Cache ~/Library/Caches/Godot/ ~/.cache/godot/ ($XDG_CACHE_HOME)

This enhancement would provide consistency between macOS and Linux for users who develop on both platforms, streamline the management of configuration files, and align Godot with the practices of other XDG-compliant cross-platform tools.

To implement this feature without disrupting existing functionality for most users, here are two general approaches I considered:

  • Explicit Setting: Allow users to enable the use of XDG Base Directories by setting a Godot-specific environment variable, such as $GODOT_HOME=~/.config/godot/ or $GODOT_USE_XDG_DIRS=1. Alternatively, provide more granular control through environment variables like $GODOT_CONFIG_DIR, $GODOT_DATA_DIR, and $GODOT_CACHE_DIR. An option in the editor settings UI could also be provided for user convenience.

  • Implicit Setting: Automatically use XDG Base Directories if certain conditions are met, such as the presence of $XDG_CONFIG_HOME, $XDG_DATA_HOME, or $XDG_CACHE_HOME environment variables, or if the user has already placed valid Godot configuration files in ~/.config/godot/ (similar to how git and openssh work)

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Below are very rough pseudocode examples for both the explicit and implicit approaches I previously outlined, inspired by how it's already handled on Unix-like platforms (i.e in os_linuxbsd.cpp). I've never touched C++ in my life, so forgive me if any of this is silly or impractical.

Explicit approach

In this approach, the use of XDG directories is enabled when the environment variable GODOT_USE_XDG_DIRS is set:

bool OS_MacOS::should_use_xdg_dirs() const {
    return has_environment("GODOT_USE_XDG_DIRS") && get_environment("GODOT_USE_XDG_DIRS") == "1";
}

String OS_MacOS::get_xdg_path(const String &p_env_var, const String &p_default_subdir) const {
    if (has_environment(p_env_var)) {
        if (get_environment(p_env_var).is_absolute_path()) {
            return get_environment(p_env_var);
        } else {
            WARN_PRINT_ONCE(vformat("`%s` is a relative path. Ignoring its value and falling back to default.", p_env_var));
        }
    }
    if (has_environment("HOME")) {
        return get_environment("HOME").path_join(p_default_subdir);
    }
    return ".";
}


String OS_MacOS::get_config_path() const {
    if (should_use_xdg_dirs()) {
        return get_xdg_path("XDG_CONFIG_HOME", ".config");
    } else {
        // Default macOS behavior
        if (has_environment("HOME")) {
            return get_environment("HOME").path_join("Library/Application Support");
        }
        return ".";
    }
}

// get_data_path, get_cache_path, etc...

For a simpler approach that only allows the user to specify an editor config directory, Godot could check if a custom path exists at $GODOT_HOME before deciding to use the macOS default path.

Alternatively, allowing users to specify each data directories (either via environment variables or in the editor itself) would allow for more advanced functionality with more flexibility, at the cost of increased complexity.

Implicit approach

In this simple example, the use of XDG directories is automatically enabled if the XDG_CONFIG_HOME environment variable is set to an absolute path on macOS.

bool OS_MacOS::should_use_xdg_dirs() const {
    return (has_environment("XDG_CONFIG_HOME") && get_environment("XDG_CONFIG_HOME").is_absolute_path()) ||;
}

String OS_MacOS::get_config_path() const {
    if (should_use_xdg_dirs()) {
        return get_xdg_path("XDG_CONFIG_HOME", ".config");
    } else {
        // Default macOS behavior
        if (has_environment("HOME")) {
            return get_environment("HOME").path_join("Library/Application Support");
        }
        return ".";
    }
}

// get_data_path, get_cache_path, etc...

On paper, this is probably the most elegant approach, but may result in unexpected behavior for users who have XDG variables set within their shell configurations. Then again, I feel it is safe to assume users who globally set XDG variables on macOS prefer them over the macOS default paths.

An alternative approach might be preferring configuration files in the $XDG_CONFIG_HOME/godot/ directory as first priority, and falling back to the default macOS data directories if the user hasn't intentionally populated the former with valid config files. This is similar to how git does things.

If this enhancement will not be used often, can it be worked around with a few lines of script?

Can it be worked around with a few lines of script? Yes, and even within a single shell command via symlinks- but this is a shoddy and error-prone workaround that is less than ideal.

In terms of whether or not this will be used often, it depends.

Strictly speaking, complying with the XDG Base Directory specification itself on macOS is far from an expected practice. However, usage of the ~/.config directory (aka $XDG_CONFIG_HOME) is very common at the very least, especially for cross-platform software like Godot. Even more common is the ability to specify a custom config directory for software development tools.

My logic for allowing use of the XDG directories is less 'because it's a standard, so comply with it' and more that it's a rare example of feature parity & compatibility between two operating systems with minimal downsides. Why not allow use of it?

Is there a reason why this should be core and not an add-on in the asset library?

This would need to be a core change.

@Calinou
Copy link
Member

Calinou commented Sep 28, 2024

For context, see godotengine/godot-docs-user-notes#106 (comment) and godotengine/godot-docs#10009.

It might make sense to support this on Windows as well, but the need is less critical as fewer apps support XDG environment variables there.

@bruvzg
Copy link
Member

bruvzg commented Oct 3, 2024

Environment variables on macOS are almost useless, .app bundle started from GUI will not see shell environment, and it's impossible to modify the default environment in any of the current macOS version. XDG variables are not part of the default environment, adding support for this will only work when the app is started from console (which you should never do, macOS GUI apps are not designed to be started from console, and it causes various issues), and result in inconsistent behavior (started from console, uses one folder, started from GUI uses another).

@fractalcounty
Copy link
Author

fractalcounty commented Oct 6, 2024

Environment variables on macOS are almost useless, .app bundle started from GUI will not see shell environment, and it's impossible to modify the default environment in any of the current macOS version.

I launch Godot and many other apps from my shell environment pretty frequently (had no idea that wasn't recommended) and just automatically assumed there had to be some way for .app bundles to read environment variables on macOS. I feel silly now because this feature request kind of hinged on the assumption that this would be dead-simple to implement.

The ability to define custom editor data directories in a way that doesn't rely on environment variables would still be an appropriate workaround. The most "compliant" solution I could think of on macOS would be storing an optional setting like EditorDataDir in the org.godotengine.godot domain.

Regardless, that's way beyond the scope of this proposal, and obviously not a popular enough feature to warrant whatever amount of effort would be required to implement it. Thank you though!

@bruvzg
Copy link
Member

bruvzg commented Oct 6, 2024

assumed there had to be some way for .app bundles to read environment variables on macOS

It is possible to workaround it, by launching a shell process and reading the environment from it, but it's not an expected default behavior - #81266

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants