Merge pull request #814 from omacom/slack-desktop-aarch64
Add slack-desktop for aarch64 on a native Electron runtime
This commit is contained in:
7 files changed
+278
No files matched your search
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"source": "local",
|
||||||
|
"upstream": {
|
||||||
|
"watch": {
|
||||||
|
"json": "https://slack.com/api/desktop.latestRelease?arch=x64&variant=deb",
|
||||||
|
"path": "version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
# Maintainer: Ryan Hughes <ryan@omarchy.org>
|
||||||
|
|
||||||
|
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=$(<slack/usr/lib/slack/version)
|
||||||
|
if [[ $slack_electron != "$_electronver" ]]; then
|
||||||
|
error "Slack $pkgver ships Electron $slack_electron, but _electronver is $_electronver."
|
||||||
|
plain "Set _electronver=$slack_electron and update its checksum."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Electron loads resources/app ahead of app.asar, so the extracted tree can
|
||||||
|
# carry the replacement modules without repacking the archive.
|
||||||
|
asar extract slack/usr/lib/slack/resources/app.asar app
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
local lib="$pkgdir/usr/lib/slack"
|
||||||
|
local app="$lib/resources/app"
|
||||||
|
|
||||||
|
install -d "$lib"
|
||||||
|
cp -a --no-preserve=ownership electron/. "$lib/"
|
||||||
|
mv "$lib/electron" "$lib/slack"
|
||||||
|
rm -f "$lib/resources/default_app.asar" "$lib/LICENSE"
|
||||||
|
find slack/usr/lib/slack/resources -maxdepth 1 -type f ! -name app.asar \
|
||||||
|
-exec cp --no-preserve=ownership -t "$lib/resources" {} +
|
||||||
|
cp -a --no-preserve=ownership app "$app"
|
||||||
|
|
||||||
|
local shim target
|
||||||
|
for shim in \
|
||||||
|
'slack-desktop-utils.js:@tinyspeck/slack-desktop-utils/lib/index.js' \
|
||||||
|
'file-handler-info.js:file-handler-info/index.js' \
|
||||||
|
'electron-native-auth.js:electron-native-auth/index.js'; do
|
||||||
|
target="$app/node_modules/${shim#*:}"
|
||||||
|
if [[ ! -f $target ]]; then
|
||||||
|
error "Slack $pkgver no longer ships ${shim#*:}; review the replacement modules."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
install -m644 "$srcdir/${shim%%:*}" "$target"
|
||||||
|
done
|
||||||
|
|
||||||
|
local addon
|
||||||
|
for addon in "${_x86_addons[@]}"; do
|
||||||
|
rm -f "$app/node_modules/$addon"
|
||||||
|
done
|
||||||
|
|
||||||
|
local file machine
|
||||||
|
while IFS= read -r -d '' file; do
|
||||||
|
machine=$(readelf -h "$file" 2>/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"
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
@@ -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;
|
||||||
@@ -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 };
|
||||||
|
};
|
||||||
@@ -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;
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -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;
|
||||||
Reference in new issue
Block a user