diff --git a/build/filters.js b/build/filters.js index 877ccb8a17fac..c1152e8eb9142 100644 --- a/build/filters.js +++ b/build/filters.js @@ -43,6 +43,8 @@ module.exports.indentationFilter = [ '!src/vs/base/node/terminateProcess.sh', '!src/vs/base/node/cpuUsage.sh', '!test/unit/assert.js', + '!resources/linux/snap/electron-launch', + '!resources/linux/snap/hooks/configure', '!build/ext.js', // except specific folders diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js index 747bfb98a57c2..d16ee9351bf48 100644 --- a/build/gulpfile.vscode.linux.js +++ b/build/gulpfile.vscode.linux.js @@ -238,7 +238,13 @@ function prepareSnapPackage(arch) { .pipe(replace('@@ARCHITECTURE@@', arch === 'x64' ? 'amd64' : arch)) .pipe(rename('snap/snapcraft.yaml')); - const all = es.merge(desktops, icon, code, snapcraft); + const electronLaunch = gulp.src('resources/linux/snap/electron-launch', { base: '.' }) + .pipe(rename('electron-launch')); + + const hooks = gulp.src('resources/linux/snap/hooks/configure', { base: '.' }) + .pipe(rename('snap/hooks/configure')); + + const all = es.merge(desktops, icon, code, snapcraft, electronLaunch, hooks); return all.pipe(vfs.dest(destination)); }; diff --git a/resources/linux/snap/electron-launch b/resources/linux/snap/electron-launch new file mode 100755 index 0000000000000..6e00bb1fc4a90 --- /dev/null +++ b/resources/linux/snap/electron-launch @@ -0,0 +1,288 @@ +#!/usr/bin/env bash + +# On Fedora $SNAP is under /var and there is some magic to map it to /snap. +# We need to handle that case and reset $SNAP +SNAP=$(echo "$SNAP" | sed -e "s|/var/lib/snapd||g") + +# +# Exports are based on https://github.com/snapcore/snapcraft/blob/master/extensions/desktop/common/desktop-exports +# + +# ensure_dir_exists calls `mkdir -p` if the given path is not a directory. +# This speeds up execution time by avoiding unnecessary calls to mkdir. +# +# Usage: ensure_dir_exists []... +# +function ensure_dir_exists() { + [ -d "$1" ] || mkdir -p "$@" +} + +function prepend_dir() { + local -n var="$1" + local dir="$2" + # We can't check if the dir exists when the dir contains variables + if [[ "$dir" == *"\$"* || -d "$dir" ]]; then + export "${!var}=${dir}${var:+:$var}" + fi +} + +function append_dir() { + local -n var="$1" + local dir="$2" + # We can't check if the dir exists when the dir contains variables + if [[ "$dir" == *"\$"* || -d "$dir" ]]; then + export "${!var}=${var:+$var:}${dir}" + fi +} + +if [ "$SNAP_ARCH" == "amd64" ]; then + ARCH="x86_64-linux-gnu" +elif [ "$SNAP_ARCH" == "armhf" ]; then + ARCH="arm-linux-gnueabihf" +elif [ "$SNAP_ARCH" == "arm64" ]; then + ARCH="aarch64-linux-gnu" +else + ARCH="$SNAP_ARCH-linux-gnu" +fi + +source "$SNAP_USER_DATA/.last_revision" 2>/dev/null || true +if [ "$SNAP_DESKTOP_LAST_REVISION" = "$SNAP_REVISION" ]; then + needs_update=false +else + needs_update=true + echo "SNAP_DESKTOP_LAST_REVISION=$SNAP_REVISION" > "$SNAP_USER_DATA/.last_revision" +fi + +# Set $REALHOME to the users real home directory +REALHOME=$(getent passwd $UID | cut -d ':' -f 6) + +# Set config folder to local path +export XDG_CONFIG_HOME="$SNAP_USER_DATA/.config" +ensure_dir_exists "$XDG_CONFIG_HOME" +chmod 700 "$XDG_CONFIG_HOME" + +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/lib/$ARCH" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/lib" +append_dir PATH "$SNAP_DESKTOP_RUNTIME/usr/bin" + +# XKB config +export XKB_CONFIG_ROOT="$SNAP_DESKTOP_RUNTIME/usr/share/X11/xkb" + +# Give XOpenIM a chance to locate locale data. +# This is required for text input to work in SDL2 games. +export XLOCALEDIR="$SNAP_DESKTOP_RUNTIME/usr/share/X11/locale" + +# Set XCursors path +export XCURSOR_PATH="$SNAP_DESKTOP_RUNTIME/usr/share/icons" +prepend_dir XCURSOR_PATH "$SNAP/data-dir/icons" + +# Mesa Libs for OpenGL support +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/mesa" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/mesa-egl" + +# Tell libGL and libva where to find the drivers +export LIBGL_DRIVERS_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/dri" +append_dir LD_LIBRARY_PATH "$LIBGL_DRIVERS_PATH" +export LIBVA_DRIVERS_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/dri" + +# Set where the VDPAU drivers are located +export VDPAU_DRIVER_PATH="/usr/lib/$ARCH/vdpau/" +if [ -e "/var/lib/snapd/lib/gl/vdpau/libvdpau_nvidia.so" ]; then + export VDPAU_DRIVER_PATH="/var/lib/snapd/lib/gl/vdpau" + # Prevent picking VA-API (Intel/AMD) over NVIDIA VDPAU; on PRIME systems for example + unset LIBVA_DRIVERS_PATH +fi + +# Workaround in snapd for proprietary nVidia drivers mounts the drivers in +# /var/lib/snapd/lib/gl that needs to be in LD_LIBRARY_PATH +# Without that OpenGL using apps do not work with the nVidia drivers. +# Ref.: https://bugs.launchpad.net/snappy/+bug/1588192 +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl" +append_dir LD_LIBRARY_PATH "/var/lib/snapd/lib/gl/vdpau" + +# Unity7 export (workaround for https://launchpad.net/bugs/1638405) +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/libunity" + +# Pulseaudio export +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/pulseaudio" + +# EGL vendor files on glvnd enabled systems +prepend_dir __EGL_VENDOR_LIBRARY_DIRS "/var/lib/snapd/lib/glvnd/egl_vendor.d" +append_dir __EGL_VENDOR_LIBRARY_DIRS "$SNAP_DESKTOP_RUNTIME/usr/share/glvnd/egl_vendor.d" + +# XDG Config +prepend_dir XDG_CONFIG_DIRS "$SNAP_DESKTOP_RUNTIME/etc/xdg" +prepend_dir XDG_CONFIG_DIRS "$SNAP/etc/xdg" + +# Define snaps' own data dir +prepend_dir XDG_DATA_DIRS "$SNAP_DESKTOP_RUNTIME/usr/share" +prepend_dir XDG_DATA_DIRS "$SNAP/usr/share" +prepend_dir XDG_DATA_DIRS "$SNAP/share" +prepend_dir XDG_DATA_DIRS "$SNAP/data-dir" +prepend_dir XDG_DATA_DIRS "$SNAP_USER_DATA" + +# Set XDG_DATA_HOME to local path +export XDG_DATA_HOME="$SNAP_USER_DATA/.local/share" +ensure_dir_exists "$XDG_DATA_HOME" + +# Workaround for GLib < 2.53.2 not searching for schemas in $XDG_DATA_HOME: +# https://bugzilla.gnome.org/show_bug.cgi?id=741335 +prepend_dir XDG_DATA_DIRS "$XDG_DATA_HOME" + +# Set cache folder to local path +export XDG_CACHE_HOME="$SNAP_USER_COMMON/.cache" +if [[ -d "$SNAP_USER_DATA/.cache" && ! -e "$XDG_CACHE_HOME" ]]; then + # the .cache directory used to be stored under $SNAP_USER_DATA, migrate it + mv "$SNAP_USER_DATA/.cache" "$SNAP_USER_COMMON/" +fi +ensure_dir_exists "$XDG_CACHE_HOME" + +# Ensure the app finds locale definitions (requires locales-all to be installed) +append_dir LOCPATH "$SNAP_DESKTOP_RUNTIME/usr/lib/locale" + +# Keep an array of data dirs, for looping through them +IFS=':' read -r -a data_dirs_array <<< "$XDG_DATA_DIRS" + +# Setup compiled gsettings schema +GS_SCHEMA_DIR="$XDG_DATA_HOME/glib-2.0/schemas" +function compile_schemas { + if [ -f "$1" ]; then + rm -rf "$GS_SCHEMA_DIR" + ensure_dir_exists "$GS_SCHEMA_DIR" + for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do + schema_dir="${data_dirs_array[$i]}/glib-2.0/schemas" + if [ -f "$schema_dir/gschemas.compiled" ]; then + # This directory already has compiled schemas + continue + fi + if [ -n "$(ls -A "$schema_dir"/*.xml 2>/dev/null)" ]; then + ln -s "$schema_dir"/*.xml "$GS_SCHEMA_DIR" + fi + if [ -n "$(ls -A "$schema_dir"/*.override 2>/dev/null)" ]; then + ln -s "$schema_dir"/*.override "$GS_SCHEMA_DIR" + fi + done + # Only compile schemas if we copied anything + if [ -n "$(ls -A "$GS_SCHEMA_DIR"/*.xml "$GS_SCHEMA_DIR"/*.override 2>/dev/null)" ]; then + "$1" "$GS_SCHEMA_DIR" + fi + fi +} +if [ "$needs_update" = true ]; then + compile_schemas "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/glib-2.0/glib-compile-schemas" +fi + +# Gdk-pixbuf loaders +export GDK_PIXBUF_MODULE_FILE="$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache" +export GDK_PIXBUF_MODULEDIR="$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders" +if [ -f "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" ]; then + "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" > "$GDK_PIXBUF_MODULE_FILE" +fi + +# Font Config and themes +export FONTCONFIG_PATH="$SNAP_DESKTOP_RUNTIME/etc/fonts" +export FONTCONFIG_FILE="$SNAP_DESKTOP_RUNTIME/etc/fonts/fonts.conf" + +function make_user_fontconfig { + echo "" + if [ -d "$REALHOME/.local/share/fonts" ]; then + echo " $REALHOME/.local/share/fonts" + fi + if [ -d "$REALHOME/.fonts" ]; then + echo " $REALHOME/.fonts" + fi + for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do + if [ -d "${data_dirs_array[$i]}/fonts" ]; then + echo " ${data_dirs_array[$i]}/fonts" + fi + done + # We need to include a user-writable cachedir first to support + # caching of per-user fonts. + echo ' fontconfig' + echo " $SNAP_COMMON/fontconfig" + echo "" +} + +if [ "$needs_update" = true ]; then + rm -rf "$XDG_DATA_HOME"/{fontconfig,fonts,fonts-*,themes,.themes} + + # This fontconfig fragment is installed in a location that is + # included by the system fontconfig configuration: namely the + # etc/fonts/conf.d/50-user.conf file. + ensure_dir_exists "$XDG_CONFIG_HOME/fontconfig" + make_user_fontconfig > "$XDG_CONFIG_HOME/fontconfig/fonts.conf" + + # the themes symlink are needed for GTK 3.18 when the prefix isn't changed + # GTK 3.20 looks into XDG_DATA_DIRS which has connected themes. + if [ -d "$SNAP/data-dir/themes" ]; then + ln -sf "$SNAP/data-dir/themes" "$XDG_DATA_HOME" + ln -sfn "$SNAP/data-dir/themes" "$SNAP_USER_DATA/.themes" + elif [ -d "$SNAP_DESKTOP_RUNTIME/usr/share/themes" ]; then + ln -sf "$SNAP_DESKTOP_RUNTIME/usr/share/themes" "$XDG_DATA_HOME" + ln -sfn "$SNAP_DESKTOP_RUNTIME/usr/share/themes" "$SNAP_USER_DATA/.themes" + fi +fi + +# Build mime.cache +# needed for gtk and qt icon +if [ "$needs_update" = true ]; then + rm -rf "$XDG_DATA_HOME/mime" + if [ ! -f "$SNAP_DESKTOP_RUNTIME/usr/share/mime/mime.cache" ]; then + if command -v update-mime-database >/dev/null; then + cp --preserve=timestamps -dR "$SNAP_DESKTOP_RUNTIME/usr/share/mime" "$XDG_DATA_HOME" + update-mime-database "$XDG_DATA_HOME/mime" + fi + fi +fi + +# Gio modules and cache (including gsettings module) +export GIO_MODULE_DIR="$XDG_CACHE_HOME/gio-modules" +function compile_giomodules { + if [ -f "$1/glib-2.0/gio-querymodules" ]; then + rm -rf "$GIO_MODULE_DIR" + ensure_dir_exists "$GIO_MODULE_DIR" + ln -s "$1"/gio/modules/*.so "$GIO_MODULE_DIR" + "$1/glib-2.0/gio-querymodules" "$GIO_MODULE_DIR" + fi +} +if [ "$needs_update" = true ]; then + compile_giomodules "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH" +fi + + +# Create $XDG_RUNTIME_DIR if not exists (to be removed when https://pad.lv/1656340 is fixed) +[ -n "$XDG_RUNTIME_DIR" ] && mkdir -p "$XDG_RUNTIME_DIR" -m 700 + +# create symbolic link to ibus socket path for ibus to look up its socket files +# (see comments #3 and #6 on https://launchpad.net/bugs/1580463) +IBUS_CONFIG_PATH="$XDG_CONFIG_HOME/ibus" +ensure_dir_exists "$IBUS_CONFIG_PATH" +[ -d "$IBUS_CONFIG_PATH/bus" ] && rm -rf "$IBUS_CONFIG_PATH/bus" +ln -sfn "$REALHOME/.config/ibus/bus" "$IBUS_CONFIG_PATH" + +# ibus and fcitx integration +GTK_IM_MODULE_DIR="$XDG_CACHE_HOME/immodules" +export GTK_IM_MODULE_FILE="$GTK_IM_MODULE_DIR/immodules.cache" +if [ "$needs_update" = true ]; then + rm -rf "$GTK_IM_MODULE_DIR" + ensure_dir_exists "$GTK_IM_MODULE_DIR" + ln -s "$SNAP_DESKTOP_RUNTIME"/usr/lib/"$ARCH"/gtk-3.0/3.0.0/immodules/*.so "$GTK_IM_MODULE_DIR" + "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/libgtk-3-0/gtk-query-immodules-3.0" > "$GTK_IM_MODULE_FILE" +fi + +# GTK theme and behavior modifier +# Those can impact the theme engine used by Qt as well +gtk_configs=(gtk-3.0/settings.ini gtk-3.0/bookmarks gtk-2.0/gtkfilechooser.ini) +for f in "${gtk_configs[@]}"; do + dest="$XDG_CONFIG_HOME/$f" + if [ ! -L "$dest" ]; then + ensure_dir_exists "$(dirname "$dest")" + ln -s "$REALHOME/.config/$f" "$dest" + fi +done + +append_dir GTK_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH/gtk-3.0" + +exec "$@" diff --git a/resources/linux/snap/hooks/configure b/resources/linux/snap/hooks/configure new file mode 100755 index 0000000000000..e410e8d128f31 --- /dev/null +++ b/resources/linux/snap/hooks/configure @@ -0,0 +1,43 @@ +#!/bin/bash + +set -e + +[ ! -d "${SNAP_COMMON}/fontconfig" ] && mkdir -p "${SNAP_COMMON}/fontconfig" + +function append_dir() { + local -n var="$1" + local dir="$2" + # We can't check if the dir exists when the dir contains variables + if [[ "$dir" == *"\$"* || -d "$dir" ]]; then + export "${!var}=${var:+$var:}${dir}" + fi +} + +if [ "$SNAP_ARCH" = "amd64" ]; then + ARCH="x86_64-linux-gnu" +elif [ "$SNAP_ARCH" = "armhf" ]; then + ARCH="arm-linux-gnueabihf" +elif [ "$SNAP_ARCH" = "arm64" ]; then + ARCH="aarch64-linux-gnu" +else + ARCH="$SNAP_ARCH-linux-gnu" +fi + +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/lib/$ARCH" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$ARCH" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib" +append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/lib" +append_dir PATH "$SNAP_DESKTOP_RUNTIME/usr/bin" + +cat > "${SNAP_COMMON}/fontconfig/fonts.conf" < + ${SNAP_COMMON}/fontconfig + /etc/fonts/fonts.conf + +EOF + +export FONTCONFIG_FILE="${SNAP_COMMON}/fontconfig/fonts.conf" + +"${SNAP_DESKTOP_RUNTIME}/usr/bin/fc-cache" --force --system-only --verbose || echo "configure hook: font generation failed" + +exec "$@" diff --git a/resources/linux/snap/snapcraft.yaml b/resources/linux/snap/snapcraft.yaml index 83ac1e5c23a0b..3e43a493cb977 100644 --- a/resources/linux/snap/snapcraft.yaml +++ b/resources/linux/snap/snapcraft.yaml @@ -61,49 +61,20 @@ parts: apps: @@NAME@@: - command: $SNAP/usr/share/@@NAME@@/bin/@@NAME@@ --no-sandbox + command: electron-launch $SNAP/usr/share/@@NAME@@/bin/@@NAME@@ --no-sandbox common-id: @@NAME@@.desktop - command-chain: - - snap/command-chain/desktop-launch - plugs: - - desktop - - desktop-legacy - - gsettings - - opengl - - wayland - - x11 environment: GTK_USE_PORTAL: 1 DISABLE_WAYLAND: 1 SNAP_DESKTOP_RUNTIME: $SNAP/gnome-platform url-handler: - command: $SNAP/usr/share/@@NAME@@/bin/@@NAME@@ --open-url --no-sandbox - command-chain: - - snap/command-chain/desktop-launch - plugs: - - desktop - - desktop-legacy - - gsettings - - opengl - - wayland - - x11 + command: electron-launch $SNAP/usr/share/@@NAME@@/bin/@@NAME@@ --open-url --no-sandbox environment: GTK_USE_PORTAL: 1 DISABLE_WAYLAND: 1 SNAP_DESKTOP_RUNTIME: $SNAP/gnome-platform -plugs: - desktop: - mount-host-font-cache: false - -hooks: - configure: - command-chain: - - snap/command-chain/hooks-configure-desktop - plugs: - - desktop - layout: /usr/lib/$SNAPCRAFT_ARCH_TRIPLET/webkit2gtk-4.0: bind: $SNAP/gnome-platform/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/webkit2gtk-4.0