diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d07d8678..cefad78a 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,11 +1,16 @@
name: Build
on:
+ push:
+ branches:
+ - main
+ - pv/mac
pull_request:
branches:
- main
types:
- ready_for_review
+ workflow_dispatch:
jobs:
flatpak:
@@ -50,7 +55,7 @@ jobs:
# flatpak run org.p2panda.aardvark
macos:
- name: macOS
+ name: macOS (${{ matrix.arch }})
runs-on: macos-latest
strategy:
fail-fast: false
@@ -63,6 +68,9 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: moonrepo/setup-rust@v1
+ with:
+ targets: ${{ matrix.target }}
+ channel: nightly
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -72,8 +80,9 @@ jobs:
path: |
~/Library/Caches/Homebrew
/usr/local/Homebrew
- /opt/homebrew
- key: ${{ runner.os }}-${{ matrix.arch }}-brew-${{ hashFiles('.github/workflows/build.yml') }}
+ # FIXME: Cache action is not allowed to cache x86_64 Homebrew directory
+ # /opt/homebrew
+ key: ${{ runner.os }}-${{ matrix.arch }}-brew-${{ hashFiles('**/Brewfile', '.github/workflows/build.yml') }}
restore-keys: |
${{ runner.os }}-${{ matrix.arch }}-brew-
@@ -84,150 +93,30 @@ jobs:
sudo mkdir -p /usr/local
sudo chown -R $(whoami) /usr/local
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- eval "$(/usr/local/bin/brew shellenv)"
- echo "PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/opt/pango/lib/pkgconfig:/usr/local/opt/cairo/lib/pkgconfig:/usr/local/opt/gdk-pixbuf/lib/pkgconfig:/usr/local/opt/graphene/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig:/usr/local/opt/gtk4/lib/pkgconfig:/usr/local/opt/libadwaita/lib/pkgconfig" >> $GITHUB_ENV
-
- - name: Install pkg-config (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install pkg-config || echo ERROR
-
- - name: Install GDK-Pixbuf (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install gdk-pixbuf || echo ERROR
-
- - name: Install Cairo (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install cairo || echo ERROR
-
- - name: Install Pango (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install pango || echo ERROR
-
- - name: Install AT-SPI2-Core (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install at-spi2-core || echo ERROR
-
- - name: Install Graphene (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install graphene || echo ERROR
- - name: Install GTK4 (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install gtk4 || echo ERROR
-
- - name: Install GtkSourceView5 (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install gtksourceview5 || echo ERROR
-
- - name: Install Libadwaita (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install -v libadwaita
-
- - name: Install dylibbundler (x86_64)
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install -v dylibbundler
-
- - name: Install dylibbundler ARM64
- if: matrix.arch == 'arm64'
- run: brew install -v dylibbundler
-
- - name: Verify and link x86_64 packages
- if: matrix.arch == 'x86_64'
- run: |
- # Verify installations
- arch -x86_64 /usr/local/bin/brew list pango
- arch -x86_64 /usr/local/bin/brew list cairo
- arch -x86_64 /usr/local/bin/brew list gdk-pixbuf
- arch -x86_64 /usr/local/bin/brew list gtk4
- arch -x86_64 /usr/local/bin/brew list gtksourceview5
- arch -x86_64 /usr/local/bin/brew list libadwaita
-
- # Link packages individually with error handling
- for package in pango cairo gdk-pixbuf gtk4 gtksourceview5 libadwaita; do
- arch -x86_64 /usr/local/bin/brew link --force $package || true
- done
-
- - name: Install ARM64 dependencies
- if: matrix.arch == 'arm64'
- run: |
- brew install pkg-config gtk4 pango cairo gdk-pixbuf at-spi2-core graphene libadwaita gtksourceview5 || true
- brew upgrade pkg-config gtk4 pango cairo gdk-pixbuf at-spi2-core graphene libadwaita gtksourceview5 || true
-
- - name: Finalize ARM64 setup
- if: matrix.arch == 'arm64'
+ - name: Run macOS Build Script
run: |
- echo "PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig" >> $GITHUB_ENV
- echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV
- - name: Add target ${{ matrix.target }}
- run: rustup target add ${{ matrix.target }}
- - name: Build
+ if [ "${{ matrix.arch }}" = "x86_64" ]; then
+ eval "$(/usr/local/bin/brew shellenv)"
+ echo "Homebrew prefix: $HOMEBREW_PREFIX"
+ export PKG_CONFIG_PATH="$HOMEBREW_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"
+ chmod +x scripts/build_macos.sh
+ ./scripts/build_macos.sh --release --app-bundle --dmg --arch x86_64
+ else
+ chmod +x scripts/build_macos.sh
+ ./scripts/build_macos.sh --release --app-bundle --dmg
+ fi
env:
PKG_CONFIG_ALLOW_CROSS: "1"
- CFLAGS: "-I/usr/local/include -I/usr/local/include/gtk-4.0 -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include"
- LDFLAGS: "-L/usr/local/lib -framework Cocoa -framework Security"
MACOSX_DEPLOYMENT_TARGET: "10.15"
- PKG_CONFIG_SYSROOT_DIR: ""
- PKG_CONFIG_PATH: "${{ env.PKG_CONFIG_PATH }}"
- run: cargo build --release --target ${{ matrix.target }}
- - name: Install glib-compile-resources
- if: matrix.arch == 'x86_64'
- run: arch -x86_64 /usr/local/bin/brew install glib || echo ERROR
-
- - name: Install glib-compile-resources ARM64
- if: matrix.arch == 'arm64'
- run: brew install glib || echo ERROR
- - name: Compile GResource
- run: |
- mkdir -p target/${{ matrix.target }}/release/
- glib-compile-resources --sourcedir aardvark-app/src --target target/${{ matrix.target }}/release/aardvark.gresource aardvark-app/src/aardvark.gresource.xml
-
- - name: Create App Bundle
- run: |
- mkdir -p Aardvark.app/Contents/{MacOS,Resources}/share/aardvark
- cp target/${{ matrix.target }}/release/aardvark Aardvark.app/Contents/MacOS/
- cp target/${{ matrix.target }}/release/aardvark.gresource Aardvark.app/Contents/Resources/share/aardvark/
-
- # Create Info.plist
- cat > Aardvark.app/Contents/Info.plist << EOF
-
-
-
-
- CFBundleExecutable
- aardvark
- CFBundleIdentifier
- org.p2panda.aardvark
- CFBundleName
- Aardvark
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- 0.1.0
- LSMinimumSystemVersion
- 10.15
- CFBundleSupportedPlatforms
-
- MacOSX
-
-
-
- EOF
-
- # Bundle dependencies
- - name: Bundle dependencies
- run: |
- dylibbundler -od -b -x Aardvark.app/Contents/MacOS/aardvark \
- -d Aardvark.app/Contents/Frameworks/ \
- -p @executable_path/../Frameworks/
- # Create DMG
- - name: Create DMG
- run: hdiutil create -volname "Aardvark" -srcfolder Aardvark.app -ov -format UDZO aardvark-${{ matrix.arch }}.dmg
- name: Upload Artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
+ # Build script creates artifacts in the current directory
name: aardvark-macos-${{ matrix.arch }}
path: aardvark-${{ matrix.arch }}.dmg
+
- name: Smoke test the artifact
env:
RUST_BACKTRACE: "full"
diff --git a/.gitignore b/.gitignore
index a9003d09..a1158fc8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,8 @@
target
.flatpak-builder
aardvark-app/src/config.rs
+
+# Build artifacts
+Aardvark.app/
+install/
+aardvark*.dmg
\ No newline at end of file
diff --git a/Brewfile b/Brewfile
new file mode 100644
index 00000000..010a131f
--- /dev/null
+++ b/Brewfile
@@ -0,0 +1,31 @@
+# Build tools
+brew "meson"
+brew "ninja"
+brew "pkg-config"
+
+# Rust toolchain (if not already installed)
+brew "rustup-init"
+
+# Core GTK4 and GNOME dependencies
+brew "gtk4"
+brew "libadwaita"
+brew "gtksourceview5"
+brew "glib"
+
+# Graphics and text rendering
+brew "cairo"
+brew "pango"
+brew "gdk-pixbuf"
+brew "graphene"
+
+# Accessibility
+brew "at-spi2-core"
+
+# Desktop file utilities (for update-desktop-database)
+brew "desktop-file-utils"
+
+# App bundling for macOS
+brew "dylibbundler"
+
+# Optional: For creating DMG files
+brew "create-dmg"
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index 9e73fc6b..f6b56a0d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -9,9 +9,11 @@ dependencies = [
"aardvark-doc",
"aardvark-node",
"ashpd 0.9.2",
+ "base64 0.21.7",
"futures-util",
"gettext-rs",
"gtk4",
+ "keyring",
"libadwaita",
"oo7",
"sourceview5",
@@ -82,6 +84,17 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "aes"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
+dependencies = [
+ "cfg-if",
+ "cipher",
+ "cpufeatures",
+]
+
[[package]]
name = "ahash"
version = "0.8.11"
@@ -170,7 +183,7 @@ version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d43c03d9e36dd40cab48435be0b09646da362c278223ca535493877b2c1dee9"
dependencies = [
- "async-fs",
+ "async-fs 2.1.2",
"async-net",
"enumflags2",
"futures-channel",
@@ -189,7 +202,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df"
dependencies = [
- "async-fs",
+ "async-fs 2.1.2",
"async-net",
"enumflags2",
"futures-channel",
@@ -199,7 +212,7 @@ dependencies = [
"serde_repr",
"tracing",
"url",
- "zbus 5.6.0",
+ "zbus 5.7.1",
]
[[package]]
@@ -241,13 +254,23 @@ dependencies = [
"syn 2.0.100",
]
+[[package]]
+name = "async-broadcast"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b"
+dependencies = [
+ "event-listener 2.5.3",
+ "futures-core",
+]
+
[[package]]
name = "async-broadcast"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
dependencies = [
- "event-listener",
+ "event-listener 5.4.0",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
@@ -273,20 +296,52 @@ checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec"
dependencies = [
"async-task",
"concurrent-queue",
- "fastrand",
- "futures-lite",
+ "fastrand 2.3.0",
+ "futures-lite 2.6.0",
"slab",
]
+[[package]]
+name = "async-fs"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
+dependencies = [
+ "async-lock 2.8.0",
+ "autocfg",
+ "blocking",
+ "futures-lite 1.13.0",
+]
+
[[package]]
name = "async-fs"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
dependencies = [
- "async-lock",
+ "async-lock 3.4.0",
"blocking",
- "futures-lite",
+ "futures-lite 2.6.0",
+]
+
+[[package]]
+name = "async-io"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
+dependencies = [
+ "async-lock 2.8.0",
+ "autocfg",
+ "cfg-if",
+ "concurrent-queue",
+ "futures-lite 1.13.0",
+ "log",
+ "parking",
+ "polling 2.8.0",
+ "rustix 0.37.28",
+ "slab",
+ "socket2 0.4.10",
+ "waker-fn",
]
[[package]]
@@ -295,26 +350,35 @@ version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059"
dependencies = [
- "async-lock",
+ "async-lock 3.4.0",
"cfg-if",
"concurrent-queue",
"futures-io",
- "futures-lite",
+ "futures-lite 2.6.0",
"parking",
- "polling",
+ "polling 3.7.4",
"rustix 0.38.44",
"slab",
"tracing",
"windows-sys 0.59.0",
]
+[[package]]
+name = "async-lock"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
+dependencies = [
+ "event-listener 2.5.3",
+]
+
[[package]]
name = "async-lock"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
dependencies = [
- "event-listener",
+ "event-listener 5.4.0",
"event-listener-strategy",
"pin-project-lite",
]
@@ -325,9 +389,26 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
dependencies = [
- "async-io",
+ "async-io 2.4.0",
"blocking",
- "futures-lite",
+ "futures-lite 2.6.0",
+]
+
+[[package]]
+name = "async-process"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88"
+dependencies = [
+ "async-io 1.13.0",
+ "async-lock 2.8.0",
+ "async-signal",
+ "blocking",
+ "cfg-if",
+ "event-listener 3.1.0",
+ "futures-lite 1.13.0",
+ "rustix 0.38.44",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -337,14 +418,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb"
dependencies = [
"async-channel",
- "async-io",
- "async-lock",
+ "async-io 2.4.0",
+ "async-lock 3.4.0",
"async-signal",
"async-task",
"blocking",
"cfg-if",
- "event-listener",
- "futures-lite",
+ "event-listener 5.4.0",
+ "futures-lite 2.6.0",
"rustix 0.38.44",
"tracing",
]
@@ -366,8 +447,8 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3"
dependencies = [
- "async-io",
- "async-lock",
+ "async-io 2.4.0",
+ "async-lock 3.4.0",
"atomic-waker",
"cfg-if",
"futures-core",
@@ -442,7 +523,7 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd0b50b1b78dbadd44ab18b3c794e496f3a139abb9fbc27d9c94c4eebbb96496"
dependencies = [
- "fastrand",
+ "fastrand 2.3.0",
"gloo-timers",
"tokio",
]
@@ -474,6 +555,12 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076"
+[[package]]
+name = "base64"
+version = "0.21.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
+
[[package]]
name = "base64"
version = "0.22.1"
@@ -538,6 +625,15 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "block-padding"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
+dependencies = [
+ "generic-array",
+]
+
[[package]]
name = "blocking"
version = "1.6.1"
@@ -547,7 +643,7 @@ dependencies = [
"async-channel",
"async-task",
"futures-io",
- "futures-lite",
+ "futures-lite 2.6.0",
"piper",
]
@@ -601,6 +697,15 @@ dependencies = [
"system-deps",
]
+[[package]]
+name = "cbc"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
+dependencies = [
+ "cipher",
+]
+
[[package]]
name = "cc"
version = "1.2.16"
@@ -1003,6 +1108,17 @@ dependencies = [
"powerfmt",
]
+[[package]]
+name = "derivative"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
[[package]]
name = "derive_arbitrary"
version = "1.4.1"
@@ -1254,6 +1370,23 @@ dependencies = [
"windows-sys 0.48.0",
]
+[[package]]
+name = "event-listener"
+version = "2.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
+[[package]]
+name = "event-listener"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2"
+dependencies = [
+ "concurrent-queue",
+ "parking",
+ "pin-project-lite",
+]
+
[[package]]
name = "event-listener"
version = "5.4.0"
@@ -1271,7 +1404,7 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2"
dependencies = [
- "event-listener",
+ "event-listener 5.4.0",
"pin-project-lite",
]
@@ -1281,6 +1414,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
[[package]]
name = "fastrand"
version = "2.3.0"
@@ -1299,7 +1441,7 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
dependencies = [
- "memoffset",
+ "memoffset 0.9.1",
"rustc_version",
]
@@ -1404,7 +1546,7 @@ dependencies = [
"fixedbitset",
"futures-buffered",
"futures-core",
- "futures-lite",
+ "futures-lite 2.6.0",
"pin-project",
"slab",
"smallvec",
@@ -1444,13 +1586,28 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
+[[package]]
+name = "futures-lite"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
+dependencies = [
+ "fastrand 1.9.0",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking",
+ "pin-project-lite",
+ "waker-fn",
+]
+
[[package]]
name = "futures-lite"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
dependencies = [
- "fastrand",
+ "fastrand 2.3.0",
"futures-core",
"futures-io",
"parking",
@@ -1724,7 +1881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715601f8f02e71baef9c1f94a657a9a77c192aea6097cf9ae7e5e177cd8cde68"
dependencies = [
"heck 0.5.0",
- "proc-macro-crate",
+ "proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
"syn 2.0.100",
@@ -1850,7 +2007,7 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed1786c4703dd196baf7e103525ce0cf579b3a63a0570fe653b7ee6bac33999"
dependencies = [
- "proc-macro-crate",
+ "proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
"syn 2.0.100",
@@ -1984,6 +2141,12 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
[[package]]
name = "hermit-abi"
version = "0.4.0"
@@ -2214,7 +2377,7 @@ dependencies = [
"http-body",
"hyper",
"pin-project-lite",
- "socket2",
+ "socket2 0.5.9",
"tokio",
"tower-service",
"tracing",
@@ -2440,6 +2603,7 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
dependencies = [
+ "block-padding",
"generic-array",
]
@@ -2455,13 +2619,24 @@ dependencies = [
"web-sys",
]
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi 0.3.9",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "ipconfig"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f"
dependencies = [
- "socket2",
+ "socket2 0.5.9",
"widestring",
"windows-sys 0.48.0",
"winreg",
@@ -2574,7 +2749,7 @@ dependencies = [
"derive_more",
"ed25519-dalek",
"futures-concurrency",
- "futures-lite",
+ "futures-lite 2.6.0",
"futures-util",
"hex",
"indexmap",
@@ -2620,7 +2795,7 @@ dependencies = [
"pin-project-lite",
"rustc-hash",
"rustls",
- "socket2",
+ "socket2 0.5.9",
"thiserror 2.0.12",
"tokio",
"tracing",
@@ -2657,7 +2832,7 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
- "socket2",
+ "socket2 0.5.9",
"tracing",
"windows-sys 0.59.0",
]
@@ -2762,6 +2937,20 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "keyring"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "363387f0019d714aa60cc30ab4fe501a747f4c08fc58f069dd14be971bd495a0"
+dependencies = [
+ "byteorder",
+ "lazy_static",
+ "linux-keyutils",
+ "secret-service",
+ "security-framework 2.11.1",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "lazy_static"
version = "1.5.0"
@@ -2831,6 +3020,22 @@ dependencies = [
"vcpkg",
]
+[[package]]
+name = "linux-keyutils"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e"
+dependencies = [
+ "bitflags 2.9.0",
+ "libc",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
@@ -3105,6 +3310,15 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+[[package]]
+name = "memoffset"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+dependencies = [
+ "autocfg",
+]
+
[[package]]
name = "memoffset"
version = "0.9.1"
@@ -3174,7 +3388,7 @@ dependencies = [
"cfg_aliases",
"derive_more",
"futures-buffered",
- "futures-lite",
+ "futures-lite 2.6.0",
"futures-util",
"js-sys",
"pin-project",
@@ -3311,7 +3525,7 @@ dependencies = [
"rtnetlink 0.13.1",
"rtnetlink 0.14.1",
"serde",
- "socket2",
+ "socket2 0.5.9",
"thiserror 2.0.12",
"time",
"tokio",
@@ -3332,6 +3546,7 @@ dependencies = [
"bitflags 1.3.2",
"cfg-if",
"libc",
+ "memoffset 0.7.1",
]
[[package]]
@@ -3355,7 +3570,20 @@ dependencies = [
"cfg-if",
"cfg_aliases",
"libc",
- "memoffset",
+ "memoffset 0.9.1",
+]
+
+[[package]]
+name = "nix"
+version = "0.30.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
+dependencies = [
+ "bitflags 2.9.0",
+ "cfg-if",
+ "cfg_aliases",
+ "libc",
+ "memoffset 0.9.1",
]
[[package]]
@@ -3503,7 +3731,7 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
dependencies = [
- "proc-macro-crate",
+ "proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
"syn 2.0.100",
@@ -3573,12 +3801,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cb23d3ec3527d65a83be1c1795cb883c52cfa57147d42acc797127df56fc489"
dependencies = [
"ashpd 0.11.0",
- "async-fs",
- "async-io",
- "async-lock",
+ "async-fs 2.1.2",
+ "async-io 2.4.0",
+ "async-lock 3.4.0",
"blocking",
"endi",
- "futures-lite",
+ "futures-lite 2.6.0",
"futures-util",
"getrandom 0.3.1",
"num",
@@ -3587,10 +3815,10 @@ dependencies = [
"rand 0.9.0",
"serde",
"tracing",
- "zbus 5.6.0",
- "zbus_macros 5.6.0",
+ "zbus 5.7.1",
+ "zbus_macros 5.7.1",
"zeroize",
- "zvariant 5.5.1",
+ "zvariant 5.5.3",
]
[[package]]
@@ -3601,9 +3829,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "openssl"
-version = "0.10.72"
+version = "0.10.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
+checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
dependencies = [
"bitflags 2.9.0",
"cfg-if",
@@ -3633,9 +3861,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-sys"
-version = "0.9.108"
+version = "0.9.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
+checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
dependencies = [
"cc",
"libc",
@@ -3662,7 +3890,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "p2panda-core"
version = "0.3.1"
-source = "git+https://github.com/p2panda/p2panda?rev=5e3816cc63af30ea5a8f3745e73ada265e700cf9#5e3816cc63af30ea5a8f3745e73ada265e700cf9"
+source = "git+https://github.com/p2panda/p2panda?rev=085a57206aeae70142176c0777ed2febc7b98664#085a57206aeae70142176c0777ed2febc7b98664"
dependencies = [
"blake3",
"ciborium",
@@ -3677,18 +3905,18 @@ dependencies = [
[[package]]
name = "p2panda-discovery"
version = "0.3.1"
-source = "git+https://github.com/p2panda/p2panda?rev=5e3816cc63af30ea5a8f3745e73ada265e700cf9#5e3816cc63af30ea5a8f3745e73ada265e700cf9"
+source = "git+https://github.com/p2panda/p2panda?rev=085a57206aeae70142176c0777ed2febc7b98664#085a57206aeae70142176c0777ed2febc7b98664"
dependencies = [
"anyhow",
"base32",
"flume",
"futures-buffered",
- "futures-lite",
+ "futures-lite 2.6.0",
"hickory-proto",
"iroh",
"iroh-base",
"netwatch",
- "socket2",
+ "socket2 0.5.9",
"tokio",
"tokio-util",
"tracing",
@@ -3697,12 +3925,12 @@ dependencies = [
[[package]]
name = "p2panda-net"
version = "0.3.1"
-source = "git+https://github.com/p2panda/p2panda?rev=5e3816cc63af30ea5a8f3745e73ada265e700cf9#5e3816cc63af30ea5a8f3745e73ada265e700cf9"
+source = "git+https://github.com/p2panda/p2panda?rev=085a57206aeae70142176c0777ed2febc7b98664#085a57206aeae70142176c0777ed2febc7b98664"
dependencies = [
"anyhow",
"async-trait",
"ciborium",
- "futures-lite",
+ "futures-lite 2.6.0",
"futures-util",
"iroh",
"iroh-base",
@@ -3724,7 +3952,7 @@ dependencies = [
[[package]]
name = "p2panda-store"
version = "0.3.1"
-source = "git+https://github.com/p2panda/p2panda?rev=5e3816cc63af30ea5a8f3745e73ada265e700cf9#5e3816cc63af30ea5a8f3745e73ada265e700cf9"
+source = "git+https://github.com/p2panda/p2panda?rev=085a57206aeae70142176c0777ed2febc7b98664#085a57206aeae70142176c0777ed2febc7b98664"
dependencies = [
"ciborium",
"hex",
@@ -3737,7 +3965,7 @@ dependencies = [
[[package]]
name = "p2panda-stream"
version = "0.3.1"
-source = "git+https://github.com/p2panda/p2panda?rev=5e3816cc63af30ea5a8f3745e73ada265e700cf9#5e3816cc63af30ea5a8f3745e73ada265e700cf9"
+source = "git+https://github.com/p2panda/p2panda?rev=085a57206aeae70142176c0777ed2febc7b98664#085a57206aeae70142176c0777ed2febc7b98664"
dependencies = [
"ciborium",
"futures-channel",
@@ -3752,7 +3980,7 @@ dependencies = [
[[package]]
name = "p2panda-sync"
version = "0.3.1"
-source = "git+https://github.com/p2panda/p2panda?rev=5e3816cc63af30ea5a8f3745e73ada265e700cf9#5e3816cc63af30ea5a8f3745e73ada265e700cf9"
+source = "git+https://github.com/p2panda/p2panda?rev=085a57206aeae70142176c0777ed2febc7b98664#085a57206aeae70142176c0777ed2febc7b98664"
dependencies = [
"async-trait",
"futures",
@@ -3829,7 +4057,7 @@ version = "3.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3"
dependencies = [
- "base64",
+ "base64 0.22.1",
"serde",
]
@@ -3932,7 +4160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
dependencies = [
"atomic-waker",
- "fastrand",
+ "fastrand 2.3.0",
"futures-io",
]
@@ -4029,6 +4257,22 @@ dependencies = [
"pnet_macros_support",
]
+[[package]]
+name = "polling"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
+dependencies = [
+ "autocfg",
+ "bitflags 1.3.2",
+ "cfg-if",
+ "concurrent-queue",
+ "libc",
+ "log",
+ "pin-project-lite",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "polling"
version = "3.7.4"
@@ -4037,7 +4281,7 @@ checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
dependencies = [
"cfg-if",
"concurrent-queue",
- "hermit-abi",
+ "hermit-abi 0.4.0",
"pin-project-lite",
"rustix 0.38.44",
"tracing",
@@ -4067,10 +4311,10 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "247dcb75747c53cc433d6d8963a064187eec4a676ba13ea33143f1c9100e754f"
dependencies = [
- "base64",
+ "base64 0.22.1",
"bytes",
"derive_more",
- "futures-lite",
+ "futures-lite 2.6.0",
"futures-util",
"igd-next",
"iroh-metrics",
@@ -4080,7 +4324,7 @@ dependencies = [
"rand 0.8.5",
"serde",
"smallvec",
- "socket2",
+ "socket2 0.5.9",
"thiserror 2.0.12",
"time",
"tokio",
@@ -4173,13 +4417,23 @@ dependencies = [
"yansi",
]
+[[package]]
+name = "proc-macro-crate"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
+dependencies = [
+ "once_cell",
+ "toml_edit 0.19.15",
+]
+
[[package]]
name = "proc-macro-crate"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
dependencies = [
- "toml_edit",
+ "toml_edit 0.22.24",
]
[[package]]
@@ -4215,7 +4469,7 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls",
- "socket2",
+ "socket2 0.5.9",
"thiserror 2.0.12",
"tokio",
"tracing",
@@ -4250,7 +4504,7 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
- "socket2",
+ "socket2 0.5.9",
"tracing",
"windows-sys 0.59.0",
]
@@ -4421,7 +4675,7 @@ version = "0.12.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989e327e510263980e231de548a33e63d34962d29ae61b467389a1a09627a254"
dependencies = [
- "base64",
+ "base64 0.22.1",
"bytes",
"futures-core",
"futures-util",
@@ -4569,6 +4823,20 @@ dependencies = [
"nom",
]
+[[package]]
+name = "rustix"
+version = "0.37.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6"
+dependencies = [
+ "bitflags 1.3.2",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys 0.3.8",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "rustix"
version = "0.38.44"
@@ -4619,7 +4887,7 @@ dependencies = [
"openssl-probe",
"rustls-pki-types",
"schannel",
- "security-framework",
+ "security-framework 3.2.0",
]
[[package]]
@@ -4655,7 +4923,7 @@ dependencies = [
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
- "security-framework",
+ "security-framework 3.2.0",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.52.0",
@@ -4729,6 +4997,38 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+[[package]]
+name = "secret-service"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5204d39df37f06d1944935232fd2dfe05008def7ca599bf28c0800366c8a8f9"
+dependencies = [
+ "aes",
+ "cbc",
+ "futures-util",
+ "generic-array",
+ "hkdf",
+ "num",
+ "once_cell",
+ "rand 0.8.5",
+ "serde",
+ "sha2",
+ "zbus 3.15.2",
+]
+
+[[package]]
+name = "security-framework"
+version = "2.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
+dependencies = [
+ "bitflags 2.9.0",
+ "core-foundation 0.9.4",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
[[package]]
name = "security-framework"
version = "3.2.0"
@@ -4980,6 +5280,16 @@ dependencies = [
"serde",
]
+[[package]]
+name = "socket2"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
[[package]]
name = "socket2"
version = "0.5.9"
@@ -5063,13 +5373,13 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f743f2a3cea30a58cd479013f75550e879009e3a02f616f18ca699335aa248c3"
dependencies = [
- "base64",
+ "base64 0.22.1",
"bytes",
"chrono",
"crc",
"crossbeam-queue",
"either",
- "event-listener",
+ "event-listener 5.4.0",
"futures-core",
"futures-intrusive",
"futures-io",
@@ -5138,7 +5448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0afdd3aa7a629683c2d750c2df343025545087081ab5942593a5288855b1b7a7"
dependencies = [
"atoi",
- "base64",
+ "base64 0.22.1",
"bitflags 2.9.0",
"byteorder",
"bytes",
@@ -5181,7 +5491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0bedbe1bbb5e2615ef347a5e9d8cd7680fb63e77d9dafc0f29be15e53f1ebe6"
dependencies = [
"atoi",
- "base64",
+ "base64 0.22.1",
"bitflags 2.9.0",
"byteorder",
"chrono",
@@ -5323,7 +5633,7 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6a47cab181e04277c2ceebe9d4ae102f6a50049b1855fd64546923581665492"
dependencies = [
- "base64",
+ "base64 0.22.1",
"bounded-integer",
"byteorder",
"crc",
@@ -5357,7 +5667,7 @@ dependencies = [
"parking_lot",
"pnet_packet",
"rand 0.9.0",
- "socket2",
+ "socket2 0.5.9",
"thiserror 1.0.69",
"tokio",
"tracing",
@@ -5463,7 +5773,7 @@ version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
dependencies = [
- "fastrand",
+ "fastrand 2.3.0",
"getrandom 0.3.1",
"once_cell",
"rustix 1.0.3",
@@ -5589,7 +5899,7 @@ dependencies = [
"mio",
"pin-project-lite",
"signal-hook-registry",
- "socket2",
+ "socket2 0.5.9",
"tokio-macros",
"windows-sys 0.52.0",
]
@@ -5682,7 +5992,7 @@ dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
- "toml_edit",
+ "toml_edit 0.22.24",
]
[[package]]
@@ -5694,6 +6004,17 @@ dependencies = [
"serde",
]
+[[package]]
+name = "toml_edit"
+version = "0.19.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
+dependencies = [
+ "indexmap",
+ "toml_datetime",
+ "winnow 0.5.40",
+]
+
[[package]]
name = "toml_edit"
version = "0.22.24"
@@ -5704,7 +6025,7 @@ dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
- "winnow",
+ "winnow 0.7.4",
]
[[package]]
@@ -5868,7 +6189,7 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9"
dependencies = [
- "memoffset",
+ "memoffset 0.9.1",
"tempfile",
"winapi",
]
@@ -5928,7 +6249,7 @@ version = "2.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
dependencies = [
- "base64",
+ "base64 0.22.1",
"log",
"once_cell",
"rustls",
@@ -6000,6 +6321,12 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+[[package]]
+name = "waker-fn"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7"
+
[[package]]
name = "walkdir"
version = "2.5.0"
@@ -6659,6 +6986,15 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
+[[package]]
+name = "winnow"
+version = "0.5.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "winnow"
version = "0.7.4"
@@ -6807,24 +7143,65 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2164e798d9e3d84ee2c91139ace54638059a3b23e361f5c11781c2c6459bde0f"
+[[package]]
+name = "zbus"
+version = "3.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6"
+dependencies = [
+ "async-broadcast 0.5.1",
+ "async-executor",
+ "async-fs 1.6.0",
+ "async-io 1.13.0",
+ "async-lock 2.8.0",
+ "async-process 1.8.1",
+ "async-recursion",
+ "async-task",
+ "async-trait",
+ "blocking",
+ "byteorder",
+ "derivative",
+ "enumflags2",
+ "event-listener 2.5.3",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "hex",
+ "nix 0.26.4",
+ "once_cell",
+ "ordered-stream",
+ "rand 0.8.5",
+ "serde",
+ "serde_repr",
+ "sha1",
+ "static_assertions",
+ "tracing",
+ "uds_windows",
+ "winapi",
+ "xdg-home",
+ "zbus_macros 3.15.2",
+ "zbus_names 2.6.1",
+ "zvariant 3.15.2",
+]
+
[[package]]
name = "zbus"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725"
dependencies = [
- "async-broadcast",
+ "async-broadcast 0.7.2",
"async-executor",
- "async-fs",
- "async-io",
- "async-lock",
- "async-process",
+ "async-fs 2.1.2",
+ "async-io 2.4.0",
+ "async-lock 3.4.0",
+ "async-process 2.3.0",
"async-recursion",
"async-task",
"async-trait",
"blocking",
"enumflags2",
- "event-listener",
+ "event-listener 5.4.0",
"futures-core",
"futures-sink",
"futures-util",
@@ -6847,35 +7224,49 @@ dependencies = [
[[package]]
name = "zbus"
-version = "5.6.0"
+version = "5.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2522b82023923eecb0b366da727ec883ace092e7887b61d3da5139f26b44da58"
+checksum = "d3a7c7cee313d044fca3f48fa782cb750c79e4ca76ba7bc7718cd4024cdf6f68"
dependencies = [
- "async-broadcast",
+ "async-broadcast 0.7.2",
"async-executor",
- "async-io",
- "async-lock",
- "async-process",
+ "async-io 2.4.0",
+ "async-lock 3.4.0",
+ "async-process 2.3.0",
"async-recursion",
"async-task",
"async-trait",
"blocking",
"enumflags2",
- "event-listener",
+ "event-listener 5.4.0",
"futures-core",
- "futures-lite",
+ "futures-lite 2.6.0",
"hex",
- "nix 0.29.0",
+ "nix 0.30.1",
"ordered-stream",
"serde",
"serde_repr",
"tracing",
"uds_windows",
"windows-sys 0.59.0",
- "winnow",
- "zbus_macros 5.6.0",
+ "winnow 0.7.4",
+ "zbus_macros 5.7.1",
"zbus_names 4.2.0",
- "zvariant 5.5.1",
+ "zvariant 5.5.3",
+]
+
+[[package]]
+name = "zbus_macros"
+version = "3.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5"
+dependencies = [
+ "proc-macro-crate 1.3.1",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "syn 1.0.109",
+ "zvariant_utils 1.0.1",
]
[[package]]
@@ -6884,7 +7275,7 @@ version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e"
dependencies = [
- "proc-macro-crate",
+ "proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
"syn 2.0.100",
@@ -6893,19 +7284,30 @@ dependencies = [
[[package]]
name = "zbus_macros"
-version = "5.6.0"
+version = "5.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05d2e12843c75108c00c618c2e8ef9675b50b6ec095b36dc965f2e5aed463c15"
+checksum = "a17e7e5eec1550f747e71a058df81a9a83813ba0f6a95f39c4e218bdc7ba366a"
dependencies = [
- "proc-macro-crate",
+ "proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
"syn 2.0.100",
"zbus_names 4.2.0",
- "zvariant 5.5.1",
+ "zvariant 5.5.3",
"zvariant_utils 3.2.0",
]
+[[package]]
+name = "zbus_names"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d"
+dependencies = [
+ "serde",
+ "static_assertions",
+ "zvariant 3.15.2",
+]
+
[[package]]
name = "zbus_names"
version = "3.0.0"
@@ -6925,8 +7327,8 @@ checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97"
dependencies = [
"serde",
"static_assertions",
- "winnow",
- "zvariant 5.5.1",
+ "winnow 0.7.4",
+ "zvariant 5.5.3",
]
[[package]]
@@ -7032,6 +7434,20 @@ dependencies = [
"syn 2.0.100",
]
+[[package]]
+name = "zvariant"
+version = "3.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db"
+dependencies = [
+ "byteorder",
+ "enumflags2",
+ "libc",
+ "serde",
+ "static_assertions",
+ "zvariant_derive 3.15.2",
+]
+
[[package]]
name = "zvariant"
version = "4.2.0"
@@ -7048,26 +7464,39 @@ dependencies = [
[[package]]
name = "zvariant"
-version = "5.5.1"
+version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "557e89d54880377a507c94cd5452f20e35d14325faf9d2958ebeadce0966c1b2"
+checksum = "9d30786f75e393ee63a21de4f9074d4c038d52c5b1bb4471f955db249f9dffb1"
dependencies = [
"endi",
"enumflags2",
"serde",
"url",
- "winnow",
- "zvariant_derive 5.5.1",
+ "winnow 0.7.4",
+ "zvariant_derive 5.5.3",
"zvariant_utils 3.2.0",
]
+[[package]]
+name = "zvariant_derive"
+version = "3.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9"
+dependencies = [
+ "proc-macro-crate 1.3.1",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "zvariant_utils 1.0.1",
+]
+
[[package]]
name = "zvariant_derive"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449"
dependencies = [
- "proc-macro-crate",
+ "proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
"syn 2.0.100",
@@ -7076,17 +7505,28 @@ dependencies = [
[[package]]
name = "zvariant_derive"
-version = "5.5.1"
+version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "757779842a0d242061d24c28be589ce392e45350dfb9186dfd7a042a2e19870c"
+checksum = "75fda702cd42d735ccd48117b1630432219c0e9616bf6cb0f8350844ee4d9580"
dependencies = [
- "proc-macro-crate",
+ "proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
"syn 2.0.100",
"zvariant_utils 3.2.0",
]
+[[package]]
+name = "zvariant_utils"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
[[package]]
name = "zvariant_utils"
version = "2.1.0"
@@ -7109,5 +7549,5 @@ dependencies = [
"serde",
"static_assertions",
"syn 2.0.100",
- "winnow",
+ "winnow 0.7.4",
]
diff --git a/aardvark-app/Cargo.toml b/aardvark-app/Cargo.toml
index 9d787829..5ccc6caa 100644
--- a/aardvark-app/Cargo.toml
+++ b/aardvark-app/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
authors = [
"adz ",
"sandreae ",
- "Julian Sparber "
+ "Julian Sparber ",
]
[dependencies]
@@ -16,16 +16,25 @@ gtk = { version = "0.9", package = "gtk4", features = ["gnome_47"] }
sourceview = { package = "sourceview5", version = "0.9" }
tracing = "0.1"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
-ashpd = { version = "0.9", default-features = false, features = ["tracing", "async-std"] }
thiserror = { version = "2.0" }
futures-util = "0.3"
-oo7 = { version = "0.4", default-features = false, features = [
- "openssl_crypto",
- "async-std",
- "tracing",
-] }
[dependencies.adw]
package = "libadwaita"
version = "0.7"
-features = ["v1_6"]
\ No newline at end of file
+features = ["v1_6"]
+
+[target.'cfg(target_os = "linux")'.dependencies]
+oo7 = { version = "0.4", default-features = false, features = [
+ "openssl_crypto",
+ "async-std",
+ "tracing",
+] }
+ashpd = { version = "0.9", default-features = false, features = [
+ "tracing",
+ "async-std",
+] }
+
+[target.'cfg(target_os = "macos")'.dependencies]
+keyring = "2.0"
+base64 = "0.21"
diff --git a/aardvark-app/src/config.rs.in b/aardvark-app/src/config.rs.in
index 0e057e17..bcb5941e 100644
--- a/aardvark-app/src/config.rs.in
+++ b/aardvark-app/src/config.rs.in
@@ -2,6 +2,4 @@ pub const APP_ID: &str = @APP_ID@;
pub const VERSION: &str = @VERSION@;
pub const GETTEXT_PACKAGE: &str = @GETTEXT_PACKAGE@;
pub const LOCALEDIR: &str = @LOCALEDIR@;
-pub const PKGDATADIR: &str = @PKGDATADIR@;
-pub const RESOURCES_FILE: &str = concat!(@PKGDATADIR@, "/resources.gresource");
-pub const UI_RESOURCES_FILE: &str = concat!(@PKGDATADIR@, "/ui-resources.gresource");
\ No newline at end of file
+pub const PKGDATADIR: &str = @PKGDATADIR@;
\ No newline at end of file
diff --git a/aardvark-app/src/main.rs b/aardvark-app/src/main.rs
index 7b56ba1d..48fa38cb 100644
--- a/aardvark-app/src/main.rs
+++ b/aardvark-app/src/main.rs
@@ -32,6 +32,7 @@ mod window;
use gettextrs::{bind_textdomain_codeset, bindtextdomain, textdomain};
use gtk::prelude::*;
use gtk::{gio, glib};
+use std::path::PathBuf;
use tracing::info;
use tracing_subscriber::EnvFilter;
use tracing_subscriber::prelude::*;
@@ -47,18 +48,7 @@ pub use self::config::APP_ID;
fn main() -> glib::ExitCode {
setup_logging();
-
- // Set up gettext translations
- bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR).expect("Unable to bind the text domain");
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8")
- .expect("Unable to set the text domain encoding");
- textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain");
-
- // Load resources
- let res = gio::Resource::load(RESOURCES_FILE).expect("Could not load gresource file");
- gio::resources_register(&res);
- let ui_res = gio::Resource::load(UI_RESOURCES_FILE).expect("Could not load UI gresource file");
- gio::resources_register(&ui_res);
+ load_resources();
// Create a new GtkApplication. The application manages our main loop,
// application windows, integration with the window manager/compositor, and
@@ -83,3 +73,42 @@ fn setup_logging() {
.try_init()
.ok();
}
+
+fn load_resources() {
+ // Used for macOS app bundle
+ let mut base_bundle_path =
+ std::env::current_exe().expect("Failed to get current executable path.");
+ base_bundle_path.pop(); // -> Aardvark.app/Contents/MacOS/
+ base_bundle_path.pop(); // -> Aardvark.app/Contents/
+
+ let local_dir_path = if cfg!(target_os = "macos") {
+ base_bundle_path.join(LOCALEDIR)
+ } else {
+ PathBuf::from(LOCALEDIR)
+ };
+
+ let resources_dir_path = if cfg!(target_os = "macos") {
+ base_bundle_path.join(PKGDATADIR)
+ } else {
+ PathBuf::from(PKGDATADIR)
+ };
+
+ bindtextdomain(
+ GETTEXT_PACKAGE,
+ local_dir_path
+ .to_str()
+ .expect("Locale path is not valid UTF-8"),
+ )
+ .expect("Unable to bind the text domain");
+ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8")
+ .expect("Unable to set the text domain encoding");
+ textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain");
+
+ let res = gio::Resource::load(resources_dir_path.join("resources.gresource"))
+ .expect("Could not load gresource file");
+ gio::resources_register(&res);
+
+ let ui_res = gio::Resource::load(resources_dir_path.join("ui-resources.gresource"))
+ .expect("Could not load UI gresource file");
+ gio::resources_register(&ui_res);
+}
diff --git a/aardvark-app/src/meson.build b/aardvark-app/src/meson.build
index 3d6c6024..94841115 100644
--- a/aardvark-app/src/meson.build
+++ b/aardvark-app/src/meson.build
@@ -7,12 +7,24 @@ gnome.compile_resources('ui-resources',
install_dir: pkgdatadir,
)
+# Detect if we're building for a macOS app bundle
+is_macos_bundle = get_option('macos_bundle')
+
conf = configuration_data()
conf.set_quoted('APP_ID', application_id)
conf.set_quoted('VERSION', meson.project_version())
conf.set_quoted('GETTEXT_PACKAGE', 'aardvark')
-conf.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir'))
-conf.set_quoted('PKGDATADIR', pkgdatadir)
+
+# Set paths based on whether we're building for macOS app bundle or not
+if is_macos_bundle
+ # For macOS app bundles, use relative paths that will be resolved at runtime
+ conf.set_quoted('LOCALEDIR', 'Resources/share/locale')
+ conf.set_quoted('PKGDATADIR', 'Resources/share/aardvark')
+else
+ # For Flatpak and other installations, use absolute paths
+ conf.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir'))
+ conf.set_quoted('PKGDATADIR', pkgdatadir)
+endif
configure_file(
input: 'config.rs.in',
diff --git a/aardvark-app/src/secret.rs b/aardvark-app/src/secret.rs
index f81e03d4..ec4f93f1 100644
--- a/aardvark-app/src/secret.rs
+++ b/aardvark-app/src/secret.rs
@@ -16,23 +16,37 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
+#[cfg(target_os = "linux")]
use std::collections::HashMap;
use thiserror::Error;
use tracing::info;
+#[cfg(target_os = "linux")]
use crate::APP_ID;
use aardvark_doc::identity::{IdentityError, PrivateKey};
+#[cfg(target_os = "linux")]
const XDG_SCHEMA: &'static str = "xdg:schema";
+#[cfg(target_os = "linux")]
fn attributes() -> HashMap<&'static str, String> {
HashMap::from([(XDG_SCHEMA, APP_ID.to_owned())])
}
+#[cfg(target_os = "macos")]
+use base64::engine::general_purpose::STANDARD as Base64Engine;
+
+#[cfg(target_os = "macos")]
+use base64::Engine as _;
+
#[derive(Debug, Error)]
pub enum Error {
+ #[cfg(target_os = "linux")]
#[error("Secret Service error: {0}")]
Service(oo7::Error),
+ #[cfg(target_os = "macos")]
+ #[error("Keyring error: {0}")]
+ Service(keyring::Error),
#[error("Format error: {0}")]
Format(IdentityError),
}
@@ -43,12 +57,14 @@ impl From for Error {
}
}
+#[cfg(target_os = "linux")]
impl From for Error {
fn from(value: oo7::Error) -> Self {
Error::Service(value)
}
}
+#[cfg(target_os = "linux")]
pub async fn get_or_create_identity() -> Result {
let keyring = oo7::Keyring::new().await?;
@@ -76,3 +92,35 @@ pub async fn get_or_create_identity() -> Result {
Ok(private_key)
}
+
+#[cfg(target_os = "macos")]
+pub async fn get_or_create_identity() -> Result {
+ let entry = keyring::Entry::new("Aardvark Identity", "default user").map_err(Error::Service)?;
+
+ let private_key: PrivateKey = match entry.get_password() {
+ Ok(password) => {
+ let private_key = PrivateKey::try_from(
+ Base64Engine
+ .decode(password)
+ .expect("Failed to decode base64 secret from keyring")
+ .as_slice(),
+ )?;
+ info!("Found existing identity: {}", private_key.public_key());
+ private_key
+ }
+ Err(keyring::Error::NoEntry) => {
+ let private_key = PrivateKey::new();
+ entry
+ .set_password(&Base64Engine.encode(private_key.as_bytes()))
+ .map_err(Error::Service)?;
+ info!(
+ "No existing identity found. Create new identity: {}",
+ private_key.public_key()
+ );
+ private_key
+ }
+ Err(e) => return Err(Error::Service(e)),
+ };
+
+ Ok(private_key)
+}
diff --git a/aardvark-app/src/system_settings.rs b/aardvark-app/src/system_settings.rs
index 9e79f5dc..f42e476e 100644
--- a/aardvark-app/src/system_settings.rs
+++ b/aardvark-app/src/system_settings.rs
@@ -20,14 +20,21 @@
use adw::prelude::*;
use adw::subclass::prelude::*;
+#[cfg(target_os = "linux")]
use ashpd::{desktop::settings::Settings as SettingsProxy, zvariant};
+#[cfg(target_os = "linux")]
use futures_util::stream::StreamExt;
use gtk::{glib, glib::Properties, glib::clone, pango};
use std::cell::{Cell, RefCell};
use tracing::error;
+#[cfg(target_os = "linux")]
const GNOME_DESKTOP_NAMESPACE: &str = "org.gnome.desktop.interface";
+
+#[cfg(target_os = "linux")]
const CLOCK_FORMAT_KEY: &str = "clock-format";
+
+#[cfg(target_os = "linux")]
const MONOSPACE_FONT_NAME_KEY: &str = "monospace-font-name";
/// The clock format setting.
@@ -89,7 +96,11 @@ mod imp {
self,
async move {
if let Err(error) = this.init().await {
+ #[cfg(target_os = "linux")]
error!("Unable to read system settings: {error}");
+
+ #[cfg(target_os = "macos")]
+ let _ = error;
}
}
));
@@ -97,6 +108,7 @@ mod imp {
}
impl SystemSettings {
+ #[cfg(target_os = "linux")]
async fn init(&self) -> Result<(), ashpd::Error> {
let proxy = SettingsProxy::new().await?;
let settings = proxy.read_all(&[GNOME_DESKTOP_NAMESPACE]).await?;
@@ -175,6 +187,13 @@ mod imp {
Ok(())
}
+ #[cfg(target_os = "macos")]
+ async fn init(&self) -> Result<(), ()> {
+ // TODO: Implement reading macOS system settings
+ Ok(())
+ }
+
+ #[cfg(target_os = "linux")]
fn set_clock_format(&self, clock_format: ClockFormat) {
if self.obj().clock_format() == clock_format {
return;
@@ -184,6 +203,7 @@ mod imp {
self.obj().notify_clock_format();
}
+ #[cfg(target_os = "linux")]
fn set_monospace_font_name(&self, font_name: Option) {
if self.obj().monospace_font_name() == font_name {
return;
@@ -211,6 +231,7 @@ impl Default for SystemSettings {
}
}
+#[cfg(target_os = "linux")]
impl TryFrom<&zvariant::OwnedValue> for ClockFormat {
type Error = zvariant::Error;
@@ -229,6 +250,7 @@ impl TryFrom<&zvariant::OwnedValue> for ClockFormat {
}
}
+#[cfg(target_os = "linux")]
impl TryFrom for ClockFormat {
type Error = zvariant::Error;
diff --git a/aardvark-doc/Cargo.toml b/aardvark-doc/Cargo.toml
index 8d67583b..9426057b 100644
--- a/aardvark-doc/Cargo.toml
+++ b/aardvark-doc/Cargo.toml
@@ -14,6 +14,6 @@ async-channel = "2.3.1"
glib = "0.20"
gio = "0.20"
loro = "1.5"
-p2panda-core = { git = "https://github.com/p2panda/p2panda", rev = "5e3816cc63af30ea5a8f3745e73ada265e700cf9", default-features = false }
+p2panda-core = { git = "https://github.com/p2panda/p2panda", rev = "085a57206aeae70142176c0777ed2febc7b98664", default-features = false }
thiserror = "2.0.11"
tracing = "0.1"
diff --git a/aardvark-node/Cargo.toml b/aardvark-node/Cargo.toml
index 0296b85b..aaf625fb 100644
--- a/aardvark-node/Cargo.toml
+++ b/aardvark-node/Cargo.toml
@@ -13,12 +13,12 @@ anyhow = "1.0.94"
async-trait = "0.1.83"
chrono = "0.4.40"
ciborium = "0.2.2"
-p2panda-core = { git = "https://github.com/p2panda/p2panda", rev = "5e3816cc63af30ea5a8f3745e73ada265e700cf9" }
-p2panda-discovery = { git = "https://github.com/p2panda/p2panda", rev = "5e3816cc63af30ea5a8f3745e73ada265e700cf9", features = ["mdns"] }
-p2panda-net = { git = "https://github.com/p2panda/p2panda", rev = "5e3816cc63af30ea5a8f3745e73ada265e700cf9" }
-p2panda-store = { git = "https://github.com/p2panda/p2panda", rev = "5e3816cc63af30ea5a8f3745e73ada265e700cf9", features = ["sqlite"], default-features = false}
-p2panda-stream = { git = "https://github.com/p2panda/p2panda", rev = "5e3816cc63af30ea5a8f3745e73ada265e700cf9" }
-p2panda-sync = { git = "https://github.com/p2panda/p2panda", rev = "5e3816cc63af30ea5a8f3745e73ada265e700cf9", features = ["log-sync"] }
+p2panda-core = { git = "https://github.com/p2panda/p2panda", rev = "085a57206aeae70142176c0777ed2febc7b98664" }
+p2panda-discovery = { git = "https://github.com/p2panda/p2panda", rev = "085a57206aeae70142176c0777ed2febc7b98664", features = ["mdns"] }
+p2panda-net = { git = "https://github.com/p2panda/p2panda", rev = "085a57206aeae70142176c0777ed2febc7b98664" }
+p2panda-store = { git = "https://github.com/p2panda/p2panda", rev = "085a57206aeae70142176c0777ed2febc7b98664", features = ["sqlite"], default-features = false}
+p2panda-stream = { git = "https://github.com/p2panda/p2panda", rev = "085a57206aeae70142176c0777ed2febc7b98664" }
+p2panda-sync = { git = "https://github.com/p2panda/p2panda", rev = "085a57206aeae70142176c0777ed2febc7b98664", features = ["log-sync"] }
serde = { version = "1.0.215", features = ["derive"] }
sqlx = { version = "0.8.5", features = ["runtime-tokio", "sqlite", "chrono"], default-features = false}
tokio = { version = "1.44.2", features = ["rt", "sync"] }
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 00000000..1b03a140
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,4 @@
+option('macos_bundle',
+ type: 'boolean',
+ value: false,
+ description: 'Build for macOS app bundle with relative resource paths')
\ No newline at end of file
diff --git a/scripts/build_macos.sh b/scripts/build_macos.sh
new file mode 100755
index 00000000..c995b907
--- /dev/null
+++ b/scripts/build_macos.sh
@@ -0,0 +1,252 @@
+#!/bin/bash
+
+# Copyright 2024 The Aardvark Developers
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+set -e
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+echo -e "${GREEN}๐๏ธ Aardvark Build Script${NC}"
+
+command_exists() {
+ command -v "$1" >/dev/null 2>&1
+}
+
+# Initialize flags
+CREATE_APP_BUNDLE=false
+CREATE_DMG=false
+CREATE_CLEAN=false
+BUILD_TYPE="debug"
+ARCH=$(uname -m)
+# Parse command line arguments
+while [[ "$#" -gt 0 ]]; do
+ case $1 in
+ --help|-h)
+ echo "Usage: $0 [options]"
+ echo "Options:"
+ echo " --app-bundle Create macOS .app bundle"
+ echo " --dmg Create DMG installer"
+ echo " --clean Clean build directory before building"
+ echo " --release Build in release mode"
+ echo " --arch ARCH Target architecture (default: $(uname -m))"
+ echo " --help, -h Show this help message"
+ exit 0
+ ;;
+ --app-bundle) CREATE_APP_BUNDLE=true ;;
+ --dmg) CREATE_DMG=true ;;
+ --clean) CREATE_CLEAN=true ;;
+ --release) BUILD_TYPE="release" ;;
+ --arch) ARCH="$2"; shift ;;
+ *) echo "Unknown parameter passed: $1"; exit 1 ;;
+ esac
+ shift
+done
+
+# Determine if we need to cross-compile based on target architecture
+if [ "$ARCH" != "$(uname -m)" ]; then
+ CROSS_COMPILE=true
+ echo -e "${YELLOW}๐ฝ Cross-compiling for $ARCH architecture${NC}"
+else
+ CROSS_COMPILE=false
+fi
+
+
+# Ask before installing dependencies unless in CI
+if [ -z "$CI" ]; then
+ read -p "Please confirm you want to install dependencies, build and install Aardvark (y/n) " -n 1 -r
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ echo -e "${RED}โ Aborting...${NC}"
+ exit 1
+ fi
+fi
+
+# Check if Homebrew is installed
+if ! command_exists brew; then
+ echo -e "${RED}โ Homebrew not found. Please install it first.${NC}"
+ exit 1
+fi
+
+if [ "$CROSS_COMPILE" = true ]; then
+ BREW_ARCH_CMD="arch -$ARCH brew"
+else
+ BREW_ARCH_CMD="brew"
+fi
+
+# Install dependencies
+echo -e "${BLUE}๐ฆ Installing/updating dependencies...${NC}"
+if ! $BREW_ARCH_CMD bundle; then
+ echo -e "${YELLOW}โ ๏ธ brew bundle failed, attempting to resolve Python linking conflicts...${NC}"
+
+ # Try to force link python if it exists but isn't linked
+ if brew list python@3.13 &> /dev/null; then
+ echo -e "${YELLOW}๐ Force linking Python...${NC}"
+ $BREW_ARCH_CMD link --overwrite python@3.13 || true
+ fi
+
+ # Retry brew bundle
+ echo -e "${YELLOW}๐ Retrying brew bundle...${NC}"
+ if ! $BREW_ARCH_CMD bundle; then
+ echo -e "${RED}โ brew bundle failed again. Please check the dependencies.${NC}"
+ exit 1
+ fi
+fi
+
+# Set up environment for system libraries
+export PKG_CONFIG_PATH="$HOMEBREW_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"
+export GETTEXT_SYSTEM=1
+export GETTEXT_DIR="$HOMEBREW_PREFIX"
+export GETTEXT_LIB_DIR="$HOMEBREW_PREFIX/lib"
+export GETTEXT_INCLUDE_DIR="$HOMEBREW_PREFIX/include"
+
+echo -e "${BLUE}โ๏ธ Configuring build with Meson...${NC}"
+
+# Only remove builddir if explicitly requested
+if [ "$CREATE_CLEAN" = true ]; then
+ echo -e "${YELLOW}๐งน Clean build requested, removing builddir...${NC}"
+ rm -rf builddir
+fi
+
+if [ ! -d "builddir" ]; then
+ BUILD_ARGS=(
+ --buildtype=$BUILD_TYPE \
+ --prefix="$(pwd)/install" \
+ -Dmacos_bundle=true
+ )
+ if [ "$CROSS_COMPILE" = true ]; then
+ BUILD_ARGS+=(--cross-file="$(pwd)/$ARCH-darwin-cross.txt")
+ fi
+ meson setup builddir "${BUILD_ARGS[@]}"
+else
+ echo -e "${YELLOW}๐ Using existing builddir (use --clean for clean build)${NC}"
+fi
+
+# Build the project
+echo -e "${BLUE}๐จ Building Aardvark...${NC}"
+meson compile -C builddir
+
+# Install to local directory
+echo -e "${BLUE}๐ฆ Installing to local directory...${NC}"
+meson install -C builddir
+
+echo -e "${GREEN}โ
Build completed successfully!${NC}"
+
+echo -e "${GREEN}๐ Built for: $ARCH${NC}"
+
+# Optional: Create macOS app bundle
+if [ "$CREATE_APP_BUNDLE" = true ]; then
+ echo -e "${BLUE}๐ฑ Creating app bundle...${NC}"
+
+ # Find the installed binary
+ BINARY_PATH="install/bin/aardvark"
+ if [ ! -f "$BINARY_PATH" ]; then
+ echo -e "${RED}โ Binary not found at $BINARY_PATH${NC}"
+ exit 1
+ fi
+
+ # Create app bundle structure
+ rm -rf Aardvark.app
+ mkdir -p Aardvark.app/Contents/{MacOS,Resources,Frameworks}
+
+ # Copy binary
+ cp "$BINARY_PATH" Aardvark.app/Contents/MacOS/
+
+ # Copy resources if they exist
+ if [ -d "install/share" ]; then
+ cp -r install/share Aardvark.app/Contents/Resources/
+ fi
+
+ # Create Info.plist
+ cat > Aardvark.app/Contents/Info.plist << 'EOF'
+
+
+
+
+ CFBundleExecutable
+ aardvark
+ CFBundleIdentifier
+ org.p2panda.aardvark
+ CFBundleName
+ Aardvark
+ CFBundleDisplayName
+ Aardvark
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 0.1.0
+ CFBundleVersion
+ 1
+ LSMinimumSystemVersion
+ 10.15
+ CFBundleSupportedPlatforms
+
+ MacOSX
+
+ NSHighResolutionCapable
+
+
+
+EOF
+
+ # Bundle dependencies
+ echo -e "${BLUE}๐ Bundling dependencies...${NC}"
+ dylibbundler -od -b -x Aardvark.app/Contents/MacOS/aardvark \
+ -d Aardvark.app/Contents/Frameworks/ \
+ -p @executable_path/../Frameworks/ > /dev/null 2>&1 || echo -e "${YELLOW}โ ๏ธ Some libraries may not be bundled${NC}"
+
+ echo -e "${GREEN}โ
App bundle created: Aardvark.app${NC}"
+
+ # Optional: Create DMG
+ if [ "$CREATE_DMG" = true ]; then
+ if command_exists create-dmg; then
+ echo -e "${BLUE}๐ฟ Creating DMG...${NC}"
+ rm -f "aardvark-$ARCH.dmg"
+ create-dmg \
+ --volname "Aardvark" \
+ --window-pos 200 120 \
+ --window-size 600 400 \
+ --icon-size 100 \
+ --icon "Aardvark.app" 175 120 \
+ --hide-extension "Aardvark.app" \
+ --app-drop-link 425 120 \
+ "aardvark-$ARCH.dmg" \
+ "Aardvark.app"
+ echo -e "${GREEN}โ
DMG created: aardvark-$ARCH.dmg${NC}"
+ else
+ echo -e "${YELLOW}โ ๏ธ create-dmg command not found. Skipping DMG creation.${NC}"
+ fi
+ fi
+fi
+
+echo -e " Direct: ${BLUE}./install/bin/aardvark${NC}"
+
+if [ "$CREATE_APP_BUNDLE" = true ]; then
+ if [ -d "Aardvark.app" ]; then
+ echo -e " App bundle: ${BLUE}open Aardvark.app${NC}"
+ fi
+fi
+
+if [ "$CREATE_DMG" = true ]; then
+ if [ -f "aardvark-$ARCH.dmg" ]; then
+ echo -e " DMG: ${BLUE}open \"aardvark-$ARCH.dmg\"${NC}"
+ fi
+fi
\ No newline at end of file
diff --git a/x86_64-darwin-cross.txt b/x86_64-darwin-cross.txt
new file mode 100644
index 00000000..86ab85eb
--- /dev/null
+++ b/x86_64-darwin-cross.txt
@@ -0,0 +1,11 @@
+[binaries]
+c = ['clang', '-target', 'x86_64-apple-darwin']
+cpp = ['clang++', '-target', 'x86_64-apple-darwin']
+rust = ['rustc', '--target', 'x86_64-apple-darwin']
+pkgconfig = 'pkg-config'
+
+[host_machine]
+system = 'darwin'
+cpu_family = 'x86_64'
+cpu = 'x86_64'
+endian = 'little'