Skip to content

Commit 0a0d91b

Browse files
mrledapoorvkhfeschber
authored
Include libadwaita and other dependencies in the app bundle on macOS (#271)
* Include libadwaita and other dependencies in the app bundle on macOS * Fix missing pipes * Use recent bash for associative array support (declare -A) * Use correct path for homebrew bash on Intel macOS * Get homebrew path from the brew command * Simplify copy-macos-dylib and convert to POSIX sh Remove need for recent bash altogether * Fix permissions nit * Update macOS dylib copy script path in release workflow * fix a few typos * fix script invocation in pre-release.yml --------- Co-authored-by: Apoorv Khandelwal <[email protected]> Co-authored-by: Ferdinand Schober <[email protected]>
1 parent 94e6372 commit 0a0d91b

File tree

6 files changed

+133
-8
lines changed

6 files changed

+133
-8
lines changed

.github/workflows/pre-release.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ jobs:
9494
- name: Install cargo bundle
9595
run: cargo install cargo-bundle
9696
- name: Bundle
97-
run: cargo bundle --release
97+
run: |
98+
cargo bundle --release
99+
scripts/copy-macos-dylib.sh "target/release/bundle/osx/Lan Mouse.app/Contents/MacOS/lan-mouse"
98100
- name: Zip bundle
99101
run: |
100102
cd target/release/bundle/osx
@@ -120,7 +122,9 @@ jobs:
120122
- name: Install cargo bundle
121123
run: cargo install cargo-bundle
122124
- name: Bundle
123-
run: cargo bundle --release
125+
run: |
126+
cargo bundle --release
127+
scripts/copy-macos-dylib.sh "target/release/bundle/osx/Lan Mouse.app/Contents/MacOS/lan-mouse"
124128
- name: Zip bundle
125129
run: |
126130
cd target/release/bundle/osx

.github/workflows/rust.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ jobs:
112112
- name: Install cargo bundle
113113
run: cargo install cargo-bundle
114114
- name: Bundle
115-
run: cargo bundle
115+
run: |
116+
cargo bundle
117+
scripts/copy-macos-dylib.sh
116118
- name: Zip bundle
117119
run: |
118120
cd target/debug/bundle/osx
@@ -142,7 +144,9 @@ jobs:
142144
- name: Install cargo bundle
143145
run: cargo install cargo-bundle
144146
- name: Bundle
145-
run: cargo bundle
147+
run: |
148+
cargo bundle
149+
scripts/copy-macos-dylib.sh
146150
- name: Zip bundle
147151
run: |
148152
cd target/debug/bundle/osx

.github/workflows/tagged-release.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ jobs:
9090
- name: Install cargo bundle
9191
run: cargo install cargo-bundle
9292
- name: Bundle
93-
run: cargo bundle --release
93+
run: |
94+
cargo bundle --release
95+
scripts/copy-macos-dylib.sh "target/release/bundle/osx/Lan Mouse.app/Contents/MacOS/lan-mouse"
9496
- name: Zip bundle
9597
run: |
9698
cd target/release/bundle/osx
@@ -116,7 +118,9 @@ jobs:
116118
- name: Install cargo bundle
117119
run: cargo install cargo-bundle
118120
- name: Bundle
119-
run: cargo bundle --release
121+
run: |
122+
cargo bundle --release
123+
scripts/copy-macos-dylib.sh "target/release/bundle/osx/Lan Mouse.app/Contents/MacOS/lan-mouse"
120124
- name: Zip bundle
121125
run: |
122126
cd target/release/bundle/osx

README.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ paru -S lan-mouse-git
8383

8484
<details>
8585
<summary>Fedora</summary>
86-
8786
You can install Lan Mouse from the [Terra Repository](https://terra.fyralabs.com).
8887

8988

@@ -94,6 +93,18 @@ dnf install lan-mouse
9493
```
9594
</details>
9695

96+
<details>
97+
<summary>MacOS</summary>
98+
99+
- Download the package for your Mac (Intel or ARM) from the releases page
100+
- Unzip it
101+
- Remove the quarantine with `xattr -rd com.apple.quarantine "Lan Mouse.app"`
102+
- Launch the app
103+
- Grant accessibility permissions in System Preferences
104+
105+
</details>
106+
107+
97108
<details>
98109
<summary>Manual Installation</summary>
99110

@@ -172,7 +183,15 @@ For a detailed list of available features, checkout the [Cargo.toml](./Cargo.tom
172183
<summary>MacOS</summary>
173184

174185
```sh
175-
brew install libadwaita pkg-config
186+
# Install dependencies
187+
brew install libadwaita pkg-config imagemagick
188+
cargo install cargo-bundle
189+
# Create the macOS icon file
190+
scripts/makeicns.sh
191+
# Create the .app bundle
192+
cargo bundle
193+
# Copy all dynamic libraries into the bundle, and update the bundle to find them there
194+
scripts/copy-macos-dylib.sh
176195
```
177196
</details>
178197

dylibs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*

scripts/copy-macos-dylib.sh

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/bin/sh
2+
set -eu
3+
4+
homebrew_path=""
5+
exec_path="target/debug/bundle/osx/Lan Mouse.app/Contents/MacOS/lan-mouse"
6+
7+
usage() {
8+
cat <<EOF
9+
$0: Copy all Homebrew libraries into the macOS app bundle.
10+
USAGE: $0 [-h] [-b homebrew_path] [exec_path]
11+
12+
OPTIONS:
13+
-h, --help Show this help message and exit
14+
-b Path to Homebrew installation (default: $homebrew_path)
15+
exec_path Path to the main executable in the app bundle
16+
(default: get from `brew --prefix`)
17+
18+
When macOS apps are linked to dynamic libraries (.dylib files),
19+
the fully qualified path to the library is embedded in the binary.
20+
If the libraries come from Homebrew, that means that Homebrew must be present
21+
and the libraries must be installed in the same location on the user's machine.
22+
23+
This script copies all of the Homebrew libraries that an executable links to into the app bundle
24+
and tells all the binaries in the bundle to look for them there.
25+
EOF
26+
}
27+
28+
# Gather command-line arguments
29+
while test $# -gt 0; do
30+
case "$1" in
31+
-h | --help ) usage; exit 0;;
32+
-b | --homebrew ) homebrew_path="$1"; shift 2;;
33+
* ) exec_path="$1"; shift;;
34+
esac
35+
done
36+
37+
if [ -z "$homebrew_path" ]; then
38+
homebrew_path="$(brew --prefix)"
39+
fi
40+
41+
# Path to the .app bundle
42+
bundle_path=$(dirname "$(dirname "$(dirname "$exec_path")")")
43+
# Path to the Frameworks directory
44+
fwks_path="$bundle_path/Contents/Frameworks"
45+
mkdir -p "$fwks_path"
46+
47+
# Copy and fix references for a binary (executable or dylib)
48+
#
49+
# This function will:
50+
# - Copy any referenced dylibs from /opt/homebrew to the Frameworks directory
51+
# - Update the binary to reference the local copy instead
52+
# - Add the Frameworks directory to the binary's RPATH
53+
# - Recursively process the copied dylibs
54+
fix_references() {
55+
local bin="$1"
56+
57+
# Get all Homebrew libraries referenced by the binary
58+
libs=$(otool -L "$bin" | awk -v homebrew="$homebrew_path" '$0 ~ homebrew {print $1}')
59+
60+
echo "$libs" | while IFS= read -r old_path; do
61+
local base_name="$(basename "$old_path")"
62+
local dest="$fwks_path/$base_name"
63+
64+
if [ ! -e "$dest" ]; then
65+
echo "Copying $old_path -> $dest"
66+
cp -f "$old_path" "$dest"
67+
# Ensure the copied dylib is writable so that xattr -rd /path/to/Lan\ Mouse.app works.
68+
chmod 644 "$dest"
69+
70+
echo "Updating $dest to have install_name of @rpath/$base_name..."
71+
install_name_tool -id "@rpath/$base_name" "$dest"
72+
73+
# Recursively process this dylib
74+
fix_references "$dest"
75+
fi
76+
77+
echo "Updating $bin to reference @rpath/$base_name..."
78+
install_name_tool -change "$old_path" "@rpath/$base_name" "$bin"
79+
done
80+
}
81+
82+
fix_references "$exec_path"
83+
84+
# Ensure the main executable has our Frameworks path in its RPATH
85+
if ! otool -l "$exec_path" | grep -q "@executable_path/../Frameworks"; then
86+
echo "Adding RPATH to $exec_path"
87+
install_name_tool -add_rpath "@executable_path/../Frameworks" "$exec_path"
88+
fi
89+
90+
# Se-sign the .app
91+
codesign --force --deep --sign - "$bundle_path"
92+
93+
echo "Done!"

0 commit comments

Comments
 (0)