Last active
April 13, 2025 18:36
-
-
Save hsandt/113d3c6698a54e378d44b5024140c2a0 to your computer and use it in GitHub Desktop.
Install Godot 3 stable or 4 beta, rc or stable and create desktop entry for Linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Desktop Entry] | |
Name=Godot Engine $VERSION $CHANNEL | |
GenericName=Libre game engine | |
Comment=Multi-platform 2D and 3D game engine with a feature-rich editor | |
Exec=godot$VERSION_$CHANNEL %f | |
Icon=$HOME/.local/share/applications/godot.png | |
Terminal=false | |
Type=Application | |
MimeType=application/x-godot-project; | |
Categories=Development;IDE; | |
Name[en_US]=Godot $VERSION $CHANNEL.desktop |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Gist: https://gist.github.com/hsandt/113d3c6698a54e378d44b5024140c2a0 | |
# CONFIG: customize to match your needs | |
base_install_folder="${HOME}/Applications/Game Engines/Godot" | |
usage() { | |
echo "Usage: install_godot_and_create_desktop_entry.sh <version> <channel> | |
Install a version of Godot for Linux in ${HOME}/Applications/Game Engines/Godot/ and | |
create a .desktop launcher for it. | |
Requirements: | |
- perl installed | |
- \"Godot template.desktop\" placed in the same directory as this script | |
- Godot icon placed at ~/.local/share/applications/godot.png | |
- jq installed (https://jqlang.org/) if using --latest option | |
ARGUMENTS | |
version Version of godot to download. Do not include channel like 'beta' here. | |
Ex: '4.0.1'. | |
channel Channel of godot to download, including number, excluding mono (see option -m instead). | |
Ex: 'beta14', 'rc1', 'stable' | |
-m, --mono Download mono build | |
-l, --latest Show latest version available on Godot repository and quit | |
-h, --help Show this help and quit | |
" | |
} | |
show_latest() { | |
# Use CLI to get latest release on GitHub: https://stackoverflow.com/questions/34899736/how-can-i-use-git-cli-to-get-the-latest-release | |
# Parsing JSON with Unix tools: https://stackoverflow.com/questions/1955505/parsing-json-with-unix-tools | |
# Requires jq (https://jqlang.org/) | |
latest_version_with_quotes=`curl -s https://api.github.com/repos/godotengine/godot/releases/latest | jq .name` | |
# Remove surrounding quotes: https://stackoverflow.com/questions/9733338/shell-script-remove-first-and-last-quote-from-a-variable | |
latest_version="${latest_version_with_quotes%\"}" | |
latest_version="${latest_version#\"}" | |
echo "$latest_version" | |
} | |
# Default arguments | |
mono=false | |
# Read arguments | |
positional_args=() | |
while [[ $# -gt 0 ]]; do | |
case $1 in | |
-h | --help ) | |
usage | |
exit 0 | |
;; | |
-l | --latest ) | |
show_latest | |
exit 0 | |
;; | |
-m | --mono ) | |
mono=true | |
shift # past argument | |
;; | |
-* ) # unknown option | |
echo "Unknown option: '$1'" | |
usage | |
exit 1 | |
;; | |
* ) # store positional argument for later | |
positional_args+=("$1") | |
shift # past argument | |
;; | |
esac | |
done | |
if ! [[ ${#positional_args[@]} -eq 2 ]]; then | |
echo "Wrong number of positional arguments: found $#, expected 2." | |
echo "Passed positional arguments: $@" | |
usage | |
exit 1 | |
fi | |
version="${positional_args[0]}" | |
channel="${positional_args[1]}" | |
parent_dir_path="$(dirname "$0")" | |
if [[ "$version" == 3* ]]; then | |
# Godot 3 was naming "X11" the Linux build | |
binary_linux_suffix="x11.64" | |
if [[ "$mono" == true ]]; then | |
zip_linux_suffix="x11_64" | |
else | |
zip_linux_suffix="x11.64" | |
fi | |
else | |
binary_linux_suffix="linux.x86_64" | |
if [[ "$mono" == true ]]; then | |
zip_linux_suffix="linux_x86_64" | |
else | |
zip_linux_suffix="linux.x86_64" | |
fi | |
fi | |
if [[ "$mono" == true ]]; then | |
full_channel="${channel}_mono" | |
else | |
full_channel="${channel}" | |
fi | |
# Non-mono build example: "Godot_v4.2.2-stable_linux_x86_64" | |
# Mono build example: "Godot_v4.2.2-stable_mono_linux_x86_64" | |
godot_zip_basename="Godot_v${version}-${full_channel}_${zip_linux_suffix}" | |
godot_zip_name="${godot_zip_basename}.zip" | |
godot_bin_name="Godot_v${version}-${full_channel}_${binary_linux_suffix}" | |
# Remove existing archive if any (in case it was previously incorrectly downloaded) | |
rm -f "$godot_zip_name" | |
if [[ "$channel" == "stable"* ]]; then | |
# Stable releases are on GitHub | |
# Note that the directory never contains "mono", so we use channel instead of full_channel | |
# but we use full_channel for the actual zip | |
download_url="https://github.com/godotengine/godot/releases/download/${version}-${channel}/${godot_zip_name}" | |
elif [[ "$channel" == "dev"* ]]; then | |
# Dev releases are on GitHub with a slightly different directory name, godot-builds | |
download_url="https://github.com/godotengine/godot-builds/releases/download/${version}-${channel}/${godot_zip_name}" | |
else | |
# Release candidates are on Tux Family | |
# Note that the directory never contains "mono", so we use channel instead of full_channel | |
download_url="https://downloads.tuxfamily.org/godotengine/${version}/${channel}/${godot_zip_name}" | |
fi | |
# Download archive for passed version in current folder | |
wget "$download_url" | |
# Unzip it | |
unzip "$godot_zip_name" | |
# Remove archive to clean up current folder | |
rm "$godot_zip_name" | |
if [[ "$mono" == true ]]; then | |
# Move the whole directory (named like zip basename), which contains binary + GodotSharp directory, under the install folder | |
binary_install_folder="$base_install_folder/$godot_zip_basename" | |
mv "$godot_zip_basename" "$binary_install_folder" | |
else | |
# Non-mono build: we should have extracted a single file named "$godot_bin_name" | |
# Move it to the target folder (overwrites any existing file) | |
binary_install_folder="$base_install_folder" | |
mv "$godot_bin_name" "$binary_install_folder" | |
fi | |
echo "Installed in ${binary_install_folder}" | |
# Create symbolic link for terminal and future Desktop entry (overwrites any existing link) | |
install_path="${binary_install_folder}/${godot_bin_name}" | |
symlink_path="${HOME}/.local/bin/godot${version}_${full_channel}" | |
ln -sf "$install_path" "$symlink_path" | |
echo "Created symbolic link at '$symlink_path'" | |
# Create Desktop entry from template (overwrites any existing file) | |
desktop_entry_path="${HOME}/.local/share/applications/Godot ${version} ${full_channel}.desktop" | |
cp "${parent_dir_path}/Godot template.desktop" "$desktop_entry_path" | |
# https://stackoverflow.com/questions/6994947/how-to-replace-a-string-in-an-existing-file-in-perl | |
perl -pi -e "s/\\\$VERSION/${version}/g" "$desktop_entry_path" | |
perl -pi -e "s/\\\$CHANNEL/${full_channel}/g" "$desktop_entry_path" | |
# https://stackoverflow.com/questions/26080096/installed-desktop-file-to-have-users-home-directory-path-inserted | |
# mind the comma separator since we deal with paths containing slashes | |
# note that "~" doesn't work with Icon=, we need full path expansion | |
perl -pi -e "s,\\\$HOME,${HOME},g" "$desktop_entry_path" | |
echo "Created desktop entry at '$desktop_entry_path'" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# The opposite operation of install_godot_and_create_desktop_entry.sh | |
# Gist: https://gist.github.com/hsandt/113d3c6698a54e378d44b5024140c2a0 | |
# CONFIG: customize to match your needs | |
base_install_folder="${HOME}/Applications/Game Engines/Godot" | |
usage() { | |
echo "Usage: uninstall_godot_and_create_desktop_entry.sh version channel | |
Uninstall a version of Godot for Linux installed in ${HOME}/Applications/Game Engines/Godot/ and | |
remove the .desktop launcher for it. | |
Requirements: | |
- perl installed | |
- the Godot version to remove must have been installed with install_godot_and_create_desktop_entry.sh | |
(or using the same path conventions) | |
ARGUMENTS | |
version Version of godot to uninstall. Do not include channel like 'beta' here. | |
Ex: '4.0.1'. | |
channel Channel of godot to uninstall, including number, excluding mono (see option -m instead). | |
Ex: 'beta14', 'rc1', 'stable' | |
-m Uninstall mono build | |
" | |
} | |
# Default arguments | |
mono=false | |
# Read arguments | |
positional_args=() | |
while [[ $# -gt 0 ]]; do | |
case $1 in | |
-h | --help ) | |
usage | |
exit 0 | |
;; | |
-m | --mono ) | |
mono=true | |
shift # past argument | |
;; | |
-* ) # unknown option | |
echo "Unknown option: '$1'" | |
usage | |
exit 1 | |
;; | |
* ) # store positional argument for later | |
positional_args+=("$1") | |
shift # past argument | |
;; | |
esac | |
done | |
if ! [[ ${#positional_args[@]} -eq 2 ]]; then | |
echo "Wrong number of positional arguments: found $#, expected 2." | |
echo "Passed positional arguments: $@" | |
usage | |
exit 1 | |
fi | |
version="${positional_args[0]}" | |
channel="${positional_args[1]}" | |
if [[ "$version" == 3* ]]; then | |
# Godot 3 was naming "X11" the Linux build | |
binary_linux_suffix="x11.64" | |
if [[ "$mono" == true ]]; then | |
zip_linux_suffix="x11_64" | |
else | |
zip_linux_suffix="x11.64" | |
fi | |
else | |
binary_linux_suffix="linux.x86_64" | |
if [[ "$mono" == true ]]; then | |
zip_linux_suffix="linux_x86_64" | |
else | |
zip_linux_suffix="linux.x86_64" | |
fi | |
fi | |
if [[ "$mono" == true ]]; then | |
full_channel="${channel}_mono" | |
else | |
full_channel="${channel}" | |
fi | |
# Non-mono build example: "Godot_v4.2.2-stable_linux_x86_64" | |
# Mono build example: "Godot_v4.2.2-stable_mono_linux_x86_64" | |
godot_zip_basename="Godot_v${version}-${full_channel}_${zip_linux_suffix}" | |
godot_bin_name="Godot_v${version}-${full_channel}_${binary_linux_suffix}" | |
if [[ "$mono" == true ]]; then | |
# Move the whole directory (named like zip basename), which contains binary + GodotSharp directory, under the install folder | |
binary_install_folder="$base_install_folder/$godot_zip_basename" | |
else | |
# Non-mono build: we should have extracted a single file named "$godot_bin_name" | |
# Move it to the target folder (overwrites any existing file) | |
binary_install_folder="$base_install_folder" | |
fi | |
install_path="${binary_install_folder}/${godot_bin_name}" | |
if [[ -f "$install_path" ]]; then | |
rm "$install_path" | |
echo "Removed Godot binary at $install_path" | |
else | |
echo "No file at '$install_path', so nothing to remove" | |
fi | |
symlink_path="${HOME}/.local/bin/godot${version}_${full_channel}" | |
if [[ -L "$symlink_path" ]]; then | |
rm "$symlink_path" | |
echo "Removed symlink at $symlink_path" | |
else | |
echo "No symlink at '$symlink_path', so nothing to remove" | |
fi | |
desktop_entry_path="${HOME}/.local/share/applications/Godot ${version} ${full_channel}.desktop" | |
if [[ -f "$desktop_entry_path" ]]; then | |
rm "$desktop_entry_path" | |
echo "Removed desktop entry at ${desktop_entry_path}" | |
else | |
echo "No file at '$desktop_entry_path', so nothing to remove" | |
fi |
I added an uninstall script to revert the operations of the install script. Convenient to remove older versions of Godot, esp. dev and rc.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I also found another script that does a similar thing but is self-contained: https://gist.github.com/hieuns/ac4f117492771a690fa06cfa47b24714
It auto-downloads the icon svg from Wikimedia and embeds the .desktop template content in the same script.
However, it takes the Godot URL argument, making it more flexible but unable to retrieve the correct URL from version+channel automatically.
It may be worth merging both methods (download icon and deduce URL, possibly embed the template too) for a simple script the user can run without extra setup.