From 418a48bef68afd849efa25358732bfa850890773 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Mon, 5 Oct 2026 12:26:23 -0400 Subject: [PATCH] Add slack-desktop for aarch64 on a native Electron runtime Slack only publishes an x86_64 Linux build, so the AUR recipe produces an aarch64 package full of x86_64 binaries that cannot start. Run Slack's application code on the AArch64 build of the Electron release it ships with, replace the three native addons Slack requires at boot with JavaScript equivalents, and drop the x86_64 addons it can do without. --- pkgbuilds/slack-desktop/.omarchy/package.json | 9 + pkgbuilds/slack-desktop/PKGBUILD | 160 ++++++++++++++++++ pkgbuilds/slack-desktop/README.md | 22 +++ .../slack-desktop/electron-native-auth.js | 14 ++ pkgbuilds/slack-desktop/file-handler-info.js | 9 + .../slack-desktop/slack-desktop-utils.js | 53 ++++++ pkgbuilds/slack-desktop/slack.desktop | 11 ++ 7 files changed, 278 insertions(+) create mode 100644 pkgbuilds/slack-desktop/.omarchy/package.json create mode 100644 pkgbuilds/slack-desktop/PKGBUILD create mode 100644 pkgbuilds/slack-desktop/README.md create mode 100644 pkgbuilds/slack-desktop/electron-native-auth.js create mode 100644 pkgbuilds/slack-desktop/file-handler-info.js create mode 100644 pkgbuilds/slack-desktop/slack-desktop-utils.js create mode 100644 pkgbuilds/slack-desktop/slack.desktop diff --git a/pkgbuilds/slack-desktop/.omarchy/package.json b/pkgbuilds/slack-desktop/.omarchy/package.json new file mode 100644 index 0000000..0eca1ed --- /dev/null +++ b/pkgbuilds/slack-desktop/.omarchy/package.json @@ -0,0 +1,9 @@ +{ + "source": "local", + "upstream": { + "watch": { + "json": "https://slack.com/api/desktop.latestRelease?arch=x64&variant=deb", + "path": "version" + } + } +} diff --git a/pkgbuilds/slack-desktop/PKGBUILD b/pkgbuilds/slack-desktop/PKGBUILD new file mode 100644 index 0000000..2d8a089 --- /dev/null +++ b/pkgbuilds/slack-desktop/PKGBUILD @@ -0,0 +1,160 @@ +# Maintainer: Ryan Hughes + +pkgname=slack-desktop +pkgver=4.52.171 +pkgrel=1 +# Slack publishes Linux builds for x86_64 only. Its application code runs +# unchanged on the AArch64 build of the Electron release it ships with; see +# README.md for the native modules that are replaced or dropped. +_electronver=44.4.5 +pkgdesc='Slack Desktop for Linux on a native AArch64 Electron runtime' +arch=('aarch64') +url='https://slack.com/downloads' +license=('custom') +depends=( + 'alsa-lib' + 'at-spi2-core' + 'cairo' + 'dbus' + 'expat' + 'fontconfig' + 'gcc-libs' + 'glib2' + 'glibc' + 'gtk3' + 'libcups' + 'libnotify' + 'libsecret' + 'libx11' + 'libxcb' + 'libxcomposite' + 'libxdamage' + 'libxext' + 'libxfixes' + 'libxkbcommon' + 'libxrandr' + 'mesa' + 'nspr' + 'nss' + 'pango' + 'systemd-libs' + 'xdg-utils' +) +optdepends=( + 'libappindicator-gtk3: Systray indicator support' + 'org.freedesktop.secrets: Keyring password store support' +) +makedepends=('asar') +options=('!debug' '!strip') +source=( + "slack-desktop-${pkgver}-amd64.deb::https://downloads.slack-edge.com/desktop-releases/linux/x64/${pkgver}/slack-desktop-${pkgver}-amd64.deb" + "electron-v${_electronver}-linux-arm64.zip::https://github.com/electron/electron/releases/download/v${_electronver}/electron-v${_electronver}-linux-arm64.zip" + 'slack.desktop' + 'slack-desktop-utils.js' + 'file-handler-info.js' + 'electron-native-auth.js' +) +noextract=( + "slack-desktop-${pkgver}-amd64.deb" + "electron-v${_electronver}-linux-arm64.zip" +) +sha256sums=('c6199816e6d842289869a9e84a05042af6e0de68959df7a15e7273873b86dc36' + '3bf0acab49c4ea3c9283cdb86bf3dd7204bd52a6fba6c8ae51101bdba2adae0e' + 'e438e78265f3e566990300946afb4ea5d09bcd8c426738ab8f486ae9ddb86c0f' + '6de40409af5a04605c3287cb3c661132eb55a4f636f7cd9bbfd456f4adf41971' + 'a2a8fd45daa4f493ad4487da9f01477233feecfef360ed366bfb0a58f804890a' + '9cd53c84fdc407c83f2ca6e9485916296f3712b2742dcc0acf22fda5195ead50') + +# x86_64 addons in Slack's app that can never load on AArch64. The three that +# Slack requires on Linux are replaced by the JavaScript files above; the rest +# are Windows/macOS helpers or degrade on failure (native-keymap). Any other +# foreign binary fails the build so a new native module gets reviewed. +_x86_addons=( + '@tinyspeck/slack-desktop-utils/lib/binding/napi-v8/slackdesktoputils.node' + 'file-handler-info/build/Release/file_handler_info.node' + 'electron-native-auth/build/Release/electron_native_auth.node' + '@tinyspeck/native-keymap/build/Release/keymapping.node' + 'cf-prefs/build/Release/cf-prefs.node' + 'macos-notification-state/build/Release/notificationstate.node' + 'registry-js/build/Release/registry.node' + 'windows-focus-assist/build/Release/focusassist.node' +) + +prepare() { + rm -rf slack electron app + mkdir slack electron + bsdtar -O -xf "slack-desktop-${pkgver}-amd64.deb" 'data.tar.*' | bsdtar -C slack -xf - + bsdtar -C electron -xf "electron-v${_electronver}-linux-arm64.zip" + + local slack_electron + slack_electron=$(/dev/null | + sed -n 's/^[[:space:]]*Machine:[[:space:]]*//p') + case "$machine" in + '' | AArch64) ;; + *) error "Unexpected ${machine} binary: ${file#"$pkgdir"}"; return 1 ;; + esac + done < <(find "$lib" -type f -print0) + + find "$lib" -type d -exec chmod 755 {} + + find "$lib" -type f -exec chmod 644 {} + + # Chromium sandboxes through unprivileged user namespaces, which Arch-family + # kernels allow; a setuid-root helper is not needed. + chmod 755 "$lib/slack" "$lib/chrome_crashpad_handler" "$lib/chrome-sandbox" + + install -d "$pkgdir/usr/bin" + ln -s /usr/lib/slack/slack "$pkgdir/usr/bin/slack" + install -Dm644 slack.desktop "$pkgdir/usr/share/applications/slack.desktop" + install -Dm644 slack/usr/share/pixmaps/slack.png \ + "$pkgdir/usr/share/icons/hicolor/512x512/apps/slack.png" + + local licenses="$pkgdir/usr/share/licenses/$pkgname" + install -Dm644 slack/usr/lib/slack/LICENSE "$licenses/LICENSE" + install -Dm644 slack/usr/share/doc/slack-desktop/OPEN_SOURCE_LICENSE_ATTRIBUTIONS \ + "$licenses/OPEN_SOURCE_LICENSE_ATTRIBUTIONS" + install -Dm644 electron/LICENSE "$licenses/LICENSE.electron.txt" + install -Dm644 electron/LICENSES.chromium.html "$licenses/LICENSES.chromium.html" +} diff --git a/pkgbuilds/slack-desktop/README.md b/pkgbuilds/slack-desktop/README.md new file mode 100644 index 0000000..b186dbe --- /dev/null +++ b/pkgbuilds/slack-desktop/README.md @@ -0,0 +1,22 @@ +# Slack on ARM + +Slack publishes Linux builds for x86_64 only, and the AUR `slack-desktop` recipe repackages that `.deb`. This package runs the same application code on the AArch64 build of the Electron release Slack ships with, so `yay -S slack-desktop` on an ARM Omarchy install resolves to a working package. + +## Electron version + +`_electronver` must equal the Electron version inside Slack's `.deb` (`usr/lib/slack/version`). `prepare()` refuses to build when they differ and prints the version to set. A Slack release that moves to a new Electron therefore fails its sync PR build until `_electronver` and the Electron checksum are updated; the upstream watch only tracks Slack's version. + +## Native modules + +Slack's app carries eight x86_64 Node addons. None can load on AArch64, so they are removed, and the build fails on any other foreign binary so a new native module is reviewed before it ships. + +Three are required while Slack boots on Linux and are replaced by JavaScript: + +- `file-handler-info` and `electron-native-auth` are MIT-licensed and their Linux builds compile no-op implementations (`impl_none.cc`, `addon_none.cc`). The replacements return the same results. +- `@tinyspeck/slack-desktop-utils` is closed source. Its replacement throws `Method not implemented` from every native call, which is the error Slack's own wrapper uses for methods a platform lacks. Slack catches it, so these Linux features are unavailable: double-press and combo global shortcuts, the huddle screen-share border overlay, audio device detail lookups, clipboard set-and-paste, and haptics. + +`@tinyspeck/native-keymap` already catches a missing addon and returns defaults, so keyboard layout detection reports `unknown`. The other four addons are Windows/macOS helpers that Slack does not use on Linux. + +## Validation + +Installed and used on an aarch64 Omarchy machine (N1x). Features listed above as unavailable were not expected to work and were not checked. diff --git a/pkgbuilds/slack-desktop/electron-native-auth.js b/pkgbuilds/slack-desktop/electron-native-auth.js new file mode 100644 index 0000000..db163c4 --- /dev/null +++ b/pkgbuilds/slack-desktop/electron-native-auth.js @@ -0,0 +1,14 @@ +// Linux builds of electron-native-auth (github.com/clavin/electron-native-auth) +// compile src/addon_none.cc: native auth sessions are unavailable and +// constructing a request throws. This is the same facade in JavaScript. +class AuthRequest { + static isAvailable() { + return false; + } + + constructor() { + throw new Error('this function is not implemented for this platform'); + } +} + +exports.AuthRequest = AuthRequest; diff --git a/pkgbuilds/slack-desktop/file-handler-info.js b/pkgbuilds/slack-desktop/file-handler-info.js new file mode 100644 index 0000000..fabea00 --- /dev/null +++ b/pkgbuilds/slack-desktop/file-handler-info.js @@ -0,0 +1,9 @@ +// Linux builds of file-handler-info (github.com/clavin/node-file-handler-info) +// compile src/impl_none.cc, which finds no handler. This is the same result +// without an architecture-specific addon. +exports.getHandlerInfo = (filePath) => { + if (typeof filePath !== 'string') { + throw new TypeError('Expected 1st argument to be string'); + } + return { handlerPath: null, friendlyName: null }; +}; diff --git a/pkgbuilds/slack-desktop/slack-desktop-utils.js b/pkgbuilds/slack-desktop/slack-desktop-utils.js new file mode 100644 index 0000000..350dc67 --- /dev/null +++ b/pkgbuilds/slack-desktop/slack-desktop-utils.js @@ -0,0 +1,53 @@ +// Stand-in for Slack's closed-source native helpers, which ship no aarch64 +// build. Slack's main bundle requires this module while booting, so a missing +// addon stops the window from ever opening. Every native call throws the same +// error the vendor wrapper uses for methods a platform lacks, and Slack's call +// sites already catch it and fall back. +const unavailable = () => { + throw new Error('Method not implemented'); +}; + +const namespace = new Proxy( + {}, + { + get: (_, key) => + typeof key === 'symbol' || key === 'then' ? undefined : unavailable, + }, +); + +const constants = { + AppRestartFlags: { NoCrash: 1, NoHang: 2, NoPatch: 4, NoReboot: 8 }, + WindowsNotifierState: { + NotificationPlatformUnavailable: -2, + Error: -1, + Enabled: 0, + DisabledForApplication: 1, + DisabledForUser: 2, + DisabledByGroupPolicy: 3, + DisabledByManifest: 4, + }, + StartupTaskState: { + Error: -1, + Disabled: 0, + DisabledByUser: 1, + Enabled: 2, + DisabledByPolicy: 3, + EnabledByPolicy: 4, + }, + ActivationType: { Error: -1, StartupTask: 1020 }, +}; + +module.exports = new Proxy(constants, { + get: (target, key) => { + if (key in target) return target[key]; + if ( + typeof key === 'symbol' || + key === '__esModule' || + key === 'default' || + key === 'then' + ) { + return undefined; + } + return namespace; + }, +}); diff --git a/pkgbuilds/slack-desktop/slack.desktop b/pkgbuilds/slack-desktop/slack.desktop new file mode 100644 index 0000000..3567251 --- /dev/null +++ b/pkgbuilds/slack-desktop/slack.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Slack +StartupWMClass=Slack +Comment=Slack Desktop +GenericName=Slack Client for Linux +Exec=/usr/bin/slack %U +Icon=slack +Type=Application +StartupNotify=true +Categories=GNOME;GTK;Network;InstantMessaging; +MimeType=x-scheme-handler/slack;