Skip to content

build: conditionally compile media capture permission for macOS deplo… - #1776

Closed
JakiChen wants to merge 1 commit into
tauri-apps:devfrom
JakiChen:compat/macos-media-permission-conditional
Closed

build: conditionally compile media capture permission for macOS deplo…#1776
JakiChen wants to merge 1 commit into
tauri-apps:devfrom
JakiChen:compat/macos-media-permission-conditional

Conversation

@JakiChen

Copy link
Copy Markdown

Motivation

When building wry with a macOS deployment target lower than 12.0 (e.g. 10.15 or 11.0), compilation fails because the delegate method requestMediaCapturePermissionForOrigin:initiatedByFrame:type:decisionHandler: is only available on macOS 12.0+. This forces downstream users to maintain forks or manually patch wry.

Solution

  • In build.rs, read the MACOSX_DEPLOYMENT_TARGET environment variable and set custom cfg flags macos_12_or_later / macos_11_or_earlier.
  • Guard the entire requestMediaCapturePermissionForOrigin method with #[cfg(macos_12_or_later)].
  • On older deployment targets the method is excluded, so the system default permission flow takes over (no functional loss).

The recently added custom permission_handler logic is fully preserved when compiling for macOS ≥ 12.

Testing

  • Built a Tauri 2 project using this branch with MACOSX_DEPLOYMENT_TARGET=11.0: compilation succeeds (previously failed).
  • Built with MACOSX_DEPLOYMENT_TARGET=12.0: compilation succeeds and the permission handler works as expected.

Impact

  • No behavioral change for macOS 12+ builds.
  • Removes the need for downstream patches when targeting older macOS versions.

@JakiChen
JakiChen requested a review from a team as a code owner July 21, 2026 01:50
@JakiChen
JakiChen force-pushed the compat/macos-media-permission-conditional branch from 1f4c61d to e5d1755 Compare July 21, 2026 02:17
@FabianLars

Copy link
Copy Markdown
Member

do you have an error log or something for the compilation failure?

@JakiChen

Copy link
Copy Markdown
Author

@FabianLars Thanks for the review.

Below is the full error log for this patch not being applied. This log was compiled on my macOS 11.7.11 system, MACOSX_DEPLOYMENT_TARGET=11.0 (this issue should not occur on newer versions of macOS):

Error log
JakiChen@MacBook-Pro-15 tauri2 % pnpm tauri dev
$ tauri dev
     Running BeforeDevCommand (`pnpm dev`)
        Warn Waiting for your frontend dev server to start on http://localhost:1420/...
$ vite

  VITE v6.4.3  ready in 2978 ms

  ➜  Local:   http://localhost:1420/
     Running DevCommand (`cargo  run --no-default-features --color always --`)
        Info Watching /Users/JakiChen/Developer/tauri2/src-tauri for changes...
     Locking 1 package to latest compatible version
      Adding wry v0.55.1
   Compiling wry v0.55.1
   Compiling tauri-runtime-wry v2.11.4
   Compiling tauri v2.11.5
   Compiling tauri-plugin-opener v2.5.4
   Compiling OnTrack v0.1.0 (/Users/JakiChen/Developer/tauri2/src-tauri)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 46s
     Running `target/debug/OnTrack`

thread 'main' (499554) panicked at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/__macro_helpers/define_class.rs:416:21:
failed overriding protocol method -[WKUIDelegate webView:requestMediaCapturePermissionForOrigin:initiatedByFrame:type:decisionHandler:]: method not found
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

thread 'main' (499554) panicked at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:225:5:
panic in a function that cannot unwind
stack backtrace:
   0:        0x1082678a8 - std[b33743bf75a7d9fc]::backtrace_rs::backtrace::libunwind::trace
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/../../backtrace/src/backtrace/libunwind.rs:117:9
   1:        0x1082678a8 - std[b33743bf75a7d9fc]::backtrace_rs::backtrace::trace_unsynchronized::<std[b33743bf75a7d9fc]::sys::backtrace::_print_fmt::{closure#1}>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/../../backtrace/src/backtrace/mod.rs:66:14
   2:        0x1082678a8 - std[b33743bf75a7d9fc]::sys::backtrace::_print_fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:74:9
   3:        0x1082678a8 - <<std[b33743bf75a7d9fc]::sys::backtrace::BacktraceLock>::print::DisplayBacktrace as core[2691a9036f58a443]::fmt::Display>::fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:44:26
   4:        0x10827c547 - <core[2691a9036f58a443]::fmt::rt::Argument>::fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/fmt/rt.rs:152:76
   5:        0x10827c547 - core[2691a9036f58a443]::fmt::write
   6:        0x10826bd51 - std[b33743bf75a7d9fc]::io::default_write_fmt::<std[b33743bf75a7d9fc]::sys::stdio::unix::Stderr>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/io/mod.rs:639:11
   7:        0x10826bd51 - <std[b33743bf75a7d9fc]::sys::stdio::unix::Stderr as std[b33743bf75a7d9fc]::io::Write>::write_fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/io/mod.rs:1994:13
   8:        0x108249205 - <std[b33743bf75a7d9fc]::sys::backtrace::BacktraceLock>::print
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:47:9
   9:        0x108249205 - std[b33743bf75a7d9fc]::panicking::default_hook::{closure#0}
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:292:27
  10:        0x1082602b7 - std[b33743bf75a7d9fc]::panicking::default_hook
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:319:9
  11:        0x108260636 - std[b33743bf75a7d9fc]::panicking::panic_with_hook
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:825:13
  12:        0x108249308 - std[b33743bf75a7d9fc]::panicking::panic_handler::{closure#0}
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:691:13
  13:        0x10823a959 - std[b33743bf75a7d9fc]::sys::backtrace::__rust_end_short_backtrace::<std[b33743bf75a7d9fc]::panicking::panic_handler::{closure#0}, !>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:182:18
  14:        0x108249a74 - __rustc[b7974e8690430dd9]::rust_begin_unwind
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:689:5
  15:        0x1082afeec - core[2691a9036f58a443]::panicking::panic_nounwind_fmt::runtime
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:122:22
  16:        0x1082afeec - core[2691a9036f58a443]::panicking::panic_nounwind_fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/intrinsics/mod.rs:2447:9
  17:        0x1082afe57 - core[2691a9036f58a443]::panicking::panic_nounwind
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:225:5
  18:        0x1082afff2 - core[2691a9036f58a443]::panicking::panic_cannot_unwind
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:337:5
  19:        0x107d47ac9 - tao::platform_impl::platform::app_delegate::did_finish_launching::hc21ee4ddd6f6a79e
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tao-0.35.3/src/platform_impl/macos/app_delegate.rs:125:1
  20:     0x7fff20616463 - <unknown>
  21:     0x7fff206b1ed9 - <unknown>
  22:     0x7fff206b1e54 - <unknown>
  23:     0x7fff205e76ce - <unknown>
  24:     0x7fff2135ac18 - <unknown>
  25:     0x7fff22e31d80 - <unknown>
  26:     0x7fff22e31ad2 - <unknown>
  27:     0x7fff22e2ec71 - <unknown>
  28:     0x7fff22e2e8c7 - <unknown>
  29:     0x7fff21386366 - <unknown>
  30:     0x7fff213861d6 - <unknown>
  31:     0x7fff26403853 - <unknown>
  32:     0x7fff26402f6e - <unknown>
  33:     0x7fff263fbcd3 - <unknown>
  34:     0x7fff2887b012 - <unknown>
  35:     0x7fff22e28f70 - <unknown>
  36:     0x7fff22e272a5 - <unknown>
  37:     0x7fff22e195c9 - <unknown>
  38:        0x107e8ca90 - <() as objc2::encode::EncodeArguments>::__invoke::hfbd1295069e9d7de
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/encode.rs:433:26
  39:        0x107e90e80 - objc2::runtime::message_receiver::msg_send_primitive::send::hefa04ed9e5c4ac17
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/runtime/message_receiver.rs:172:18
  40:        0x107e820f0 - objc2::runtime::message_receiver::MessageReceiver::send_message::h80708214df4f9304
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/runtime/message_receiver.rs:432:38
  41:        0x107970b87 - <MethodFamily as objc2::__macro_helpers::msg_send_retained::MsgSend<Receiver,Return>>::send_message::hfbc289b054314dcb
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/__macro_helpers/msg_send_retained.rs:35:28
  42:        0x10785daf0 - tao::platform_impl::platform::event_loop::EventLoop<T>::run_return::h0f2ada7a0b595030
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tao-0.35.3/src/platform_impl/macos/event_loop.rs:234:16
  43:        0x10785e0dd - tao::platform_impl::platform::event_loop::EventLoop<T>::run::he619712e59400f5f
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tao-0.35.3/src/platform_impl/macos/event_loop.rs:201:26
  44:        0x10773c9d4 - tao::event_loop::EventLoop<T>::run::hdeb5161e67b67ec0
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tao-0.35.3/src/event_loop.rs:224:21
  45:        0x1078bbccf - <tauri_runtime_wry::Wry<T> as tauri_runtime::Runtime<T>>::run::hcbc13a458fa56cec
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tauri-runtime-wry-2.11.4/src/lib.rs:3241:21
  46:        0x107aa7a57 - tauri::app::App<R>::run::h1f4963525e8f2872
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tauri-2.11.5/src/app.rs:1373:8
  47:        0x107aa8136 - tauri::app::Builder<R>::run::hbb0a856065026ea0
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tauri-2.11.5/src/app.rs:2450:26
  48:        0x107b53ab1 - OnTrack::main::hb63f4b191c558f21
                               at /Users/JakiChen/Developer/tauri2/src-tauri/src/main.rs:41:10
  49:        0x1079930ae - core::ops::function::FnOnce::call_once::h2c23e300f4b86dc3
                               at /Users/JakiChen/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
  50:        0x1078ec981 - std::sys::backtrace::__rust_begin_short_backtrace::h4bac9a5de200d602
                               at /Users/JakiChen/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs:166:18
  51:        0x107b14664 - std::rt::lang_start::{{closure}}::h0650c671a76a2756
                               at /Users/JakiChen/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:206:18
  52:        0x10825ef8b - <&dyn core[2691a9036f58a443]::ops::function::Fn<(), Output = i32> + core[2691a9036f58a443]::marker::Sync + core[2691a9036f58a443]::panic::unwind_safe::RefUnwindSafe as core[2691a9036f58a443]::ops::function::FnOnce<()>>::call_once
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/ops/function.rs:287:21
  53:        0x10825ef8b - std[b33743bf75a7d9fc]::panicking::catch_unwind::do_call::<&dyn core[2691a9036f58a443]::ops::function::Fn<(), Output = i32> + core[2691a9036f58a443]::marker::Sync + core[2691a9036f58a443]::panic::unwind_safe::RefUnwindSafe, i32>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:581:40
  54:        0x10825ef8b - std[b33743bf75a7d9fc]::panicking::catch_unwind::<i32, &dyn core[2691a9036f58a443]::ops::function::Fn<(), Output = i32> + core[2691a9036f58a443]::marker::Sync + core[2691a9036f58a443]::panic::unwind_safe::RefUnwindSafe>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:544:19
  55:        0x10825ef8b - std[b33743bf75a7d9fc]::panic::catch_unwind::<&dyn core[2691a9036f58a443]::ops::function::Fn<(), Output = i32> + core[2691a9036f58a443]::marker::Sync + core[2691a9036f58a443]::panic::unwind_safe::RefUnwindSafe, i32>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panic.rs:359:14
  56:        0x10825ef8b - std[b33743bf75a7d9fc]::rt::lang_start_internal::{closure#0}
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/rt.rs:175:24
  57:        0x10825ef8b - std[b33743bf75a7d9fc]::panicking::catch_unwind::do_call::<std[b33743bf75a7d9fc]::rt::lang_start_internal::{closure#0}, isize>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:581:40
  58:        0x10825ef8b - std[b33743bf75a7d9fc]::panicking::catch_unwind::<isize, std[b33743bf75a7d9fc]::rt::lang_start_internal::{closure#0}>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:544:19
  59:        0x10825ef8b - std[b33743bf75a7d9fc]::panic::catch_unwind::<std[b33743bf75a7d9fc]::rt::lang_start_internal::{closure#0}, isize>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panic.rs:359:14
  60:        0x10825ef8b - std[b33743bf75a7d9fc]::rt::lang_start_internal
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/rt.rs:171:5
  61:        0x107b14647 - std::rt::lang_start::h2009ba0a7673ceee
                               at /Users/JakiChen/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:205:5
  62:        0x107b53b58 - _main
thread caused non-unwinding panic. aborting.

Additionally, I've verified the fix locally by applying this patch to my Cargo.toml:

[patch.crates-io]
wry = { path = "../wry" }  # Points to my local branch with this PR changes

With this patch, the project compiles successfully under the same deployment target.

Regarding the fix itself: I'm fully open to alternative implementations. If you think there's a cleaner or more comprehensive solution (e.g., adjusting the cfg attributes, using a different type, or even a different approach to maintain backward compatibility), I'd be happy to update this PR or close it in favor of your preferred approach. My main goal is to ensure that users on older macOS versions can compile wry without trouble.

@FabianLars

Copy link
Copy Markdown
Member

alright thanks. so it's another case of madsmtm/objc2#645 :/

Can you check if this happens in release as well? (tauri build or tauri dev --release)
If so then we can put this behind a debug_assertion check because this approach would really suck for production apps (though i can't think of a better one right now either)

@JakiChen

Copy link
Copy Markdown
Author

@FabianLars I think we're on the same page about the root cause (objc2#645), but I'd like to clarify why I believe the deployment-target-based conditional compilation is the right long-term fix.


The Problem

The panic occurs because requestMediaCapturePermissionForOrigin doesn't exist on macOS < 12.0. This is not a runtime issue — it's a compile-time issue because objc2 tries to generate a method override for a protocol method that doesn't exist on older SDKs.


Why debug_assertions is a temporary workaround, not a fix

Scenario debug_assertions approach My PR (based on MACOSX_DEPLOYMENT_TARGET)
tauri dev (Debug) ✅ Works (skips the method) ✅ Works
tauri build --release (Release) Panic on macOS 11 (method still compiled) No panic (method excluded based on deployment target)
User configurable ❌ No — hardcoded to build mode ✅ Yes — via minimumSystemVersion in tauri.conf.json
Supports multiple distributions ❌ Can't produce a macOS 11-compatible release build ✅ Yes — set minimumSystemVersion: "11.0" and get a working app

The User Experience After This PR

  1. Developer sets minimumSystemVersion: "11.0" in tauri.conf.json.
  2. Tauri passes MACOSX_DEPLOYMENT_TARGET=11.0 to wry.
  3. wry's build.rs reads it and sets #[cfg(macos_11_or_earlier)].
  4. The requestMediaCapturePermissionForOrigin method is excluded from the binary.
  5. On macOS 11, WebKit uses system default permission handling — no crash, getUserMedia still works.
  6. The developer can also choose to publish a macOS 12+ version with full custom permission UI by setting minimumSystemVersion: "12.0".

One Question for You

Do you think we should also provide a runtime fallback (e.g., checking NSAppKitVersion at runtime) instead of compile-time? That would allow a single binary to work on both macOS 11 and 12+, but it would still require conditionally excluding the method at compile time (since the method doesn't exist on macOS 11). So the #[cfg] is unavoidable.


My Test Results (for reference)

On my macOS 11.7.11 system (where MACOSX_DEPLOYMENT_TARGET defaults to 10.13):

Command Result Note
pnpm tauri dev ❌ Panic objc2 assertion fails
pnpm tauri build ✅ Passes Release mode disables the assertion
pnpm tauri dev --release ✅ Passes But very slow for daily development (minutes per Rust change)

So currently, developers targeting older macOS are forced to use --release mode just to avoid the panic — which hurts development velocity significantly.


I believe this PR is a practical solution to restore normal development experience for users on older macOS, while keeping production builds functional.

Please let me know if you need any additional information (logs, more test results, etc.) — I'm happy to provide whatever helps move this forward. 🙏

@FabianLars

Copy link
Copy Markdown
Member

So the thing here is: the way you implemented it, it is also applied to release builds which means if you build an app on macos 11, endusers on 12+ will not have this method working.
There should be no reason to do this though, the panic should be only from objc2's internal checks (that only happen in debug mode), macOS itself should not care if you register delegate methods that it doesn't know about.

So ideally, if you build the release app on 11, register the delegate method, when running the app it should be ignored on 11, and actually do what it's supposed to on 12+.

@JakiChen

Copy link
Copy Markdown
Author

@FabianLars , I also realized there was a logical problem in the submitted PR code; the default value should be 12 to better reflect the intended value.

  println!("cargo::rustc-check-cfg=cfg(macos_12_or_later)");
  println!("cargo::rustc-check-cfg=cfg(macos_11_or_earlier)");

  let deployment_target =
    std::env::var("MACOSX_DEPLOYMENT_TARGET").unwrap_or_else(|_| "12".to_string());
  let major: u32 = deployment_target
    .split('.')
    .next()
    .unwrap_or("10")
    .parse()
    .unwrap_or(12);

  if major >= 12 {
    println!("cargo:rustc-cfg=macos_12_or_later");
  } else {
    println!("cargo:rustc-cfg=macos_11_or_earlier");
  }

The script below reads bundle.macOS.minimumSystemVersion from tauri.conf.json and sets MACOSX_DEPLOYMENT_TARGET exactly to that value (no hardcoded mapping).
It also includes an optional --clean flag to force a rebuild of wry when switching targets.

Script (tauri-env.sh)

#!/bin/bash
set -e

MODE="${1:-dev}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

# Locate tauri.conf.json
CONF_FILE="$SCRIPT_DIR/src-tauri/tauri.conf.json"
[ -f "$CONF_FILE" ] || CONF_FILE="$SCRIPT_DIR/tauri.conf.json"
if [ ! -f "$CONF_FILE" ]; then
  echo "❌ tauri.conf.json not found. Run from project root or src-tauri directory."
  exit 1
fi

# Read minimumSystemVersion
MIN_VER=$(node -e "
  const fs = require('fs');
  const conf = JSON.parse(fs.readFileSync('$CONF_FILE', 'utf8'));
  const ver = conf?.bundle?.macOS?.minimumSystemVersion || '10.13';
  console.log(ver);
")

echo "📋 minimumSystemVersion from tauri.conf.json = $MIN_VER"
export MACOSX_DEPLOYMENT_TARGET="$MIN_VER"

# Optional clean
if [[ "$*" == *--clean* ]]; then
  echo "🧹 Cleaning wry cache..."
  (cd "$(dirname "$CONF_FILE")" && cargo clean -p wry 2>/dev/null || true)
fi

cd "$(dirname "$CONF_FILE")"

if [ "$MODE" = "build" ]; then
  echo "🚀 Starting Tauri build..."
  pnpm tauri build
else
  echo "🚀 Starting Tauri dev server..."
  pnpm tauri dev
fi

How to build for different macOS versions

  1. Set the desired deployment target in tauri.conf.json:
"bundle": {
  "macOS": {
    "minimumSystemVersion": "11.0"   // or "10.13", "12.0", etc.
  }
}
  1. Run the script (it will pick up the value automatically):
chmod +x tauri-env.sh
./tauri-env.sh              # dev mode
./tauri-env.sh build        # production build
./tauri-env.sh --clean      # force wry rebuild when switching

The above ideas are for reference only, and I am not certain about them.

This is my first attempt to quickly validate a product prototype using Tauri. I feel exhausted from investing so much time and energy in it. (Perhaps patching and script control is currently the optimal solution for me.) However, local builds take up too much disk space. And I can't synchronize with the latest Wry from the official website (which is a real shame).

@JakiChen

JakiChen commented Jul 22, 2026

Copy link
Copy Markdown
Author

Heyyyyyy, @FabianLars

I realized my previous script had a bug — cargo clean -p wry must run before export MACOSX_DEPLOYMENT_TARGET, otherwise wry won't recompile with the new target.

This updated version reads minimumSystemVersion from tauri.conf.json, maps it to the desired deployment target (10.13 → 10.13, ≥12 → 12.0, otherwise 11.0), cleans wry cache, and then exports the variable for pnpm tauri dev/build.

It solves the need to build different macOS versions without manual setup.

#!/bin/bash
set -e

# Usage instructions
usage() {
  cat <<EOF
Usage: $0 <MODE>

Automatically reads the macOS minimum system version from tauri.conf.json,
cleans wry cache to ensure the deployment target takes effect, sets
MACOSX_DEPLOYMENT_TARGET accordingly, and runs the Tauri command.

MODE:
  dev        Start the development server
  build      Build the application

Options:
  --help     Show this help message

Examples:
  ./tauri-env.sh dev
  ./tauri-env.sh build
EOF
  exit 0
}

# Show help if no argument or --help is given
if [ $# -eq 0 ] || [ "$1" = "--help" ]; then
  usage
fi

MODE="$1"
if [ "$MODE" != "dev" ] && [ "$MODE" != "build" ]; then
  echo "❌ Invalid mode: $MODE"
  usage
fi

# Find the project directory (assumes script is in project root)
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

# Locate tauri.conf.json (usually inside src-tauri)
CONF_FILE="$SCRIPT_DIR/src-tauri/tauri.conf.json"
if [ ! -f "$CONF_FILE" ]; then
  CONF_FILE="$SCRIPT_DIR/tauri.conf.json"
fi
if [ ! -f "$CONF_FILE" ]; then
  echo "❌ Could not find tauri.conf.json. Please run this script from a Tauri project root."
  exit 1
fi

# Enter the directory containing tauri.conf.json (src-tauri)
TAURI_DIR="$(dirname "$CONF_FILE")"
cd "$TAURI_DIR"

# Read minimumSystemVersion from tauri.conf.json
MIN_VER=$(node -e "
  const fs = require('fs');
  const conf = JSON.parse(fs.readFileSync('tauri.conf.json', 'utf8'));
  const ver = conf?.bundle?.macOS?.minimumSystemVersion || '10.13';
  console.log(ver);
")
echo "📋 Read minimumSystemVersion: $MIN_VER"

# Map minimum system version to deployment target
if [ "$MIN_VER" = "10.13" ]; then
  TARGET="10.13"
else
  MAJOR=$(echo "$MIN_VER" | cut -d. -f1)
  if [ "$MAJOR" -ge 12 ]; then
    TARGET="12.0"
  else
    TARGET="11.0"
  fi
fi

# Clean wry cache to force recompilation with the new target
echo "🧹 Cleaning wry cache to apply deployment target..."
cargo clean -p wry

# Set the deployment target for this process and its children
export MACOSX_DEPLOYMENT_TARGET="$TARGET"
echo "🔧 MACOSX_DEPLOYMENT_TARGET set to $TARGET"

# Execute Tauri command
if [ "$MODE" = "build" ]; then
  echo "🚀 Building Tauri application..."
  pnpm tauri build
else
  echo "🚀 Starting Tauri dev server..."
  pnpm tauri dev
fi
Error Log ("minimumSystemVersion": "12.0")
JakiChen@MacBook-Pro-15 tauri2 % ./tauri-env.sh dev
📋 Read minimumSystemVersion: 12.0
🧹 Cleaning wry cache to apply deployment target...
     Removed 538 files, 47.7MiB total
🔧 MACOSX_DEPLOYMENT_TARGET set to 12.0
🚀 Starting Tauri dev server...
$ tauri dev
     Running BeforeDevCommand (`pnpm dev`)
        Warn Waiting for your frontend dev server to start on http://localhost:1420/...
$ vite

  VITE v6.4.3  ready in 2748 ms

  ➜  Local:   http://localhost:1420/
     Running DevCommand (`cargo  run --no-default-features --color always --`)
        Info Watching /Users/JakiChen/Developer/tauri2/src-tauri for changes...
   Compiling objc2-exception-helper v0.1.1
   Compiling wry v0.55.1 (/Users/JakiChen/Developer/tauri2/wry)
   Compiling libsqlite3-sys v0.30.1
   Compiling OnTrack v0.1.0 (/Users/JakiChen/Developer/tauri2/src-tauri)
   Compiling objc2 v0.6.4
warning: wry@0.55.1: MAJOR_VERSION_FROM_ENV = 12
   Compiling block2 v0.6.2
   Compiling objc2-core-foundation v0.3.2
   Compiling dispatch2 v0.3.1
   Compiling objc2-foundation v0.3.2
   Compiling rusqlite v0.32.1
   Compiling objc2-app-kit v0.3.2
   Compiling objc2-web-kit v0.3.2
   Compiling tao v0.35.3
   Compiling window-vibrancy v0.6.0
   Compiling muda v0.19.3
   Compiling tauri-runtime v2.11.3
warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:11:54
   |
11 | use objc2_app_kit::{NSDragOperation, NSDraggingInfo, NSFilenamesPboardType};
   |                                                      ^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(deprecated)]` on by default

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:21:40
   |
21 |   let types = NSArray::arrayWithObject(NSFilenamesPboardType);
   |                                        ^^^^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:24:40
   |
24 |     let paths = pb.propertyListForType(NSFilenamesPboardType).unwrap();
   |                                        ^^^^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSAlternateKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:3
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEventType, NSShiftKeyMask,
  |   ^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSCommandKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:23
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEventType, NSShiftKeyMask,
  |                       ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSControlKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:41
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEventType, NSShiftKeyMask,
  |                                         ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSShiftKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:81
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEventType, NSShiftKeyMask,
  |                                                                                 ^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSControlKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:116:36
    |
116 |     ctrl_key = mods_flags.contains(NSControlKeyMask),
    |                                    ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSAlternateKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:117:35
    |
117 |     alt_key = mods_flags.contains(NSAlternateKeyMask),
    |                                   ^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSShiftKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:118:37
    |
118 |     shift_key = mods_flags.contains(NSShiftKeyMask),
    |                                     ^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSCommandKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:119:36
    |
119 |     meta_key = mods_flags.contains(NSCommandKeyMask),
    |                                    ^^^^^^^^^^^^^^^^

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:40:21
   |
40 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
   |                     ^^^^^^ unnecessary `unsafe` block
   |
   = note: `#[warn(unused_unsafe)]` (part of `#[warn(unused)]`) on by default

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:57:21
   |
57 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
   |                     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:85:21
   |
85 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
   |                     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_parent.rs:33:7
   |
33 |       unsafe {
   |       ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:43:5
   |
43 |     unsafe {
   |     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
    --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/mod.rs:1350:22
     |
1350 |   let absolute_url = unsafe { url_obj.absoluteString().unwrap() };
     |                      ^^^^^^ unnecessary `unsafe` block

   Compiling tauri-runtime-wry v2.11.4
   Compiling tauri v2.11.5
warning: `wry` (lib) generated 17 warnings
   Compiling tauri-plugin-opener v2.5.4
    Building [=======================> ] 365/369: tauri-plugin-opener, tauri                             Building [=======================> ] 366/369: tauri                                                  Building [=======================> ] 367/369: OnTrack                                                Building [=======================> ] 368/369: OnTrack(bin)                                           Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 20s
     Running `target/debug/OnTrack`

thread 'main' (169822) panicked at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/__macro_helpers/define_class.rs:416:21:
failed overriding protocol method -[WKUIDelegate webView:requestMediaCapturePermissionForOrigin:initiatedByFrame:type:decisionHandler:]: method not found
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

thread 'main' (169822) panicked at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:225:5:
panic in a function that cannot unwind
stack backtrace:
   0:        0x1086ce3e8 - std[b33743bf75a7d9fc]::backtrace_rs::backtrace::libunwind::trace
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/../../backtrace/src/backtrace/libunwind.rs:117:9
   1:        0x1086ce3e8 - std[b33743bf75a7d9fc]::backtrace_rs::backtrace::trace_unsynchronized::<std[b33743bf75a7d9fc]::sys::backtrace::_print_fmt::{closure#1}>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/../../backtrace/src/backtrace/mod.rs:66:14
   2:        0x1086ce3e8 - std[b33743bf75a7d9fc]::sys::backtrace::_print_fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:74:9
   3:        0x1086ce3e8 - <<std[b33743bf75a7d9fc]::sys::backtrace::BacktraceLock>::print::DisplayBacktrace as core[2691a9036f58a443]::fmt::Display>::fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:44:26
   4:        0x1086e3087 - <core[2691a9036f58a443]::fmt::rt::Argument>::fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/fmt/rt.rs:152:76
   5:        0x1086e3087 - core[2691a9036f58a443]::fmt::write
   6:        0x1086d2891 - std[b33743bf75a7d9fc]::io::default_write_fmt::<std[b33743bf75a7d9fc]::sys::stdio::unix::Stderr>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/io/mod.rs:639:11
   7:        0x1086d2891 - <std[b33743bf75a7d9fc]::sys::stdio::unix::Stderr as std[b33743bf75a7d9fc]::io::Write>::write_fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/io/mod.rs:1994:13
   8:        0x1086afd45 - <std[b33743bf75a7d9fc]::sys::backtrace::BacktraceLock>::print
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:47:9
   9:        0x1086afd45 - std[b33743bf75a7d9fc]::panicking::default_hook::{closure#0}
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:292:27
  10:        0x1086c6df7 - std[b33743bf75a7d9fc]::panicking::default_hook
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:319:9
  11:        0x1086c7176 - std[b33743bf75a7d9fc]::panicking::panic_with_hook
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:825:13
  12:        0x1086afe48 - std[b33743bf75a7d9fc]::panicking::panic_handler::{closure#0}
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:691:13
  13:        0x1086a1499 - std[b33743bf75a7d9fc]::sys::backtrace::__rust_end_short_backtrace::<std[b33743bf75a7d9fc]::panicking::panic_handler::{closure#0}, !>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:182:18
  14:        0x1086b05b4 - __rustc[b7974e8690430dd9]::rust_begin_unwind
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:689:5
  15:        0x108716a2c - core[2691a9036f58a443]::panicking::panic_nounwind_fmt::runtime
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:122:22
  16:        0x108716a2c - core[2691a9036f58a443]::panicking::panic_nounwind_fmt
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/intrinsics/mod.rs:2447:9
  17:        0x108716997 - core[2691a9036f58a443]::panicking::panic_nounwind
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:225:5
  18:        0x108716b32 - core[2691a9036f58a443]::panicking::panic_cannot_unwind
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:337:5
  19:        0x1081ade79 - tao::platform_impl::platform::app_delegate::did_finish_launching::hc21ee4ddd6f6a79e
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tao-0.35.3/src/platform_impl/macos/app_delegate.rs:125:1
  20:     0x7fff2089a463 - <unknown>
  21:     0x7fff20935ed9 - <unknown>
  22:     0x7fff20935e54 - <unknown>
  23:     0x7fff2086b6ce - <unknown>
  24:     0x7fff215dec18 - <unknown>
  25:     0x7fff230b5d80 - <unknown>
  26:     0x7fff230b5ad2 - <unknown>
  27:     0x7fff230b2c71 - <unknown>
  28:     0x7fff230b28c7 - <unknown>
  29:     0x7fff2160a366 - <unknown>
  30:     0x7fff2160a1d6 - <unknown>
  31:     0x7fff26687853 - <unknown>
  32:     0x7fff26686f6e - <unknown>
  33:     0x7fff2667fcd3 - <unknown>
  34:     0x7fff28aff012 - <unknown>
  35:     0x7fff230acf70 - <unknown>
  36:     0x7fff230ab2a5 - <unknown>
  37:     0x7fff2309d5c9 - <unknown>
  38:        0x1082f2e90 - <() as objc2::encode::EncodeArguments>::__invoke::hfbd1295069e9d7de
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/encode.rs:433:26
  39:        0x1082f7280 - objc2::runtime::message_receiver::msg_send_primitive::send::hefa04ed9e5c4ac17
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/runtime/message_receiver.rs:172:18
  40:        0x1082e84f0 - objc2::runtime::message_receiver::MessageReceiver::send_message::h80708214df4f9304
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/runtime/message_receiver.rs:432:38
  41:        0x107f503e7 - <MethodFamily as objc2::__macro_helpers::msg_send_retained::MsgSend<Receiver,Return>>::send_message::hcd728eff02bbf0fe
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/objc2-0.6.4/src/__macro_helpers/msg_send_retained.rs:35:28
  42:        0x107f94490 - tao::platform_impl::platform::event_loop::EventLoop<T>::run_return::haaea605de73f932e
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tao-0.35.3/src/platform_impl/macos/event_loop.rs:234:16
  43:        0x107f94a7d - tao::platform_impl::platform::event_loop::EventLoop<T>::run::hf9fa83aa62dea8c3
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tao-0.35.3/src/platform_impl/macos/event_loop.rs:201:26
  44:        0x107d70a74 - tao::event_loop::EventLoop<T>::run::hf10f81bf14998c82
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tao-0.35.3/src/event_loop.rs:224:21
  45:        0x107d87d9f - <tauri_runtime_wry::Wry<T> as tauri_runtime::Runtime<T>>::run::h263f923a8e10424d
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tauri-runtime-wry-2.11.4/src/lib.rs:3241:21
  46:        0x107eab3c7 - tauri::app::App<R>::run::hebf5ac20f3282b3d
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tauri-2.11.5/src/app.rs:1373:8
  47:        0x107eabaa6 - tauri::app::Builder<R>::run::h9191d0dcd62cfb91
                               at /Users/JakiChen/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tauri-2.11.5/src/app.rs:2450:26
  48:        0x107f72e71 - OnTrack::main::h07d4414c148b49e1
                               at /Users/JakiChen/Developer/tauri2/src-tauri/src/main.rs:41:10
  49:        0x107ebee5e - core::ops::function::FnOnce::call_once::hf97d24bcc3d4ba2e
                               at /Users/JakiChen/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
  50:        0x107e11191 - std::sys::backtrace::__rust_begin_short_backtrace::h97350fd7bcac20ec
                               at /Users/JakiChen/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs:166:18
  51:        0x107f18e04 - std::rt::lang_start::{{closure}}::hbc34b943a35e9909
                               at /Users/JakiChen/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:206:18
  52:        0x1086c5acb - <&dyn core[2691a9036f58a443]::ops::function::Fn<(), Output = i32> + core[2691a9036f58a443]::marker::Sync + core[2691a9036f58a443]::panic::unwind_safe::RefUnwindSafe as core[2691a9036f58a443]::ops::function::FnOnce<()>>::call_once
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/ops/function.rs:287:21
  53:        0x1086c5acb - std[b33743bf75a7d9fc]::panicking::catch_unwind::do_call::<&dyn core[2691a9036f58a443]::ops::function::Fn<(), Output = i32> + core[2691a9036f58a443]::marker::Sync + core[2691a9036f58a443]::panic::unwind_safe::RefUnwindSafe, i32>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:581:40
  54:        0x1086c5acb - std[b33743bf75a7d9fc]::panicking::catch_unwind::<i32, &dyn core[2691a9036f58a443]::ops::function::Fn<(), Output = i32> + core[2691a9036f58a443]::marker::Sync + core[2691a9036f58a443]::panic::unwind_safe::RefUnwindSafe>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:544:19
  55:        0x1086c5acb - std[b33743bf75a7d9fc]::panic::catch_unwind::<&dyn core[2691a9036f58a443]::ops::function::Fn<(), Output = i32> + core[2691a9036f58a443]::marker::Sync + core[2691a9036f58a443]::panic::unwind_safe::RefUnwindSafe, i32>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panic.rs:359:14
  56:        0x1086c5acb - std[b33743bf75a7d9fc]::rt::lang_start_internal::{closure#0}
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/rt.rs:175:24
  57:        0x1086c5acb - std[b33743bf75a7d9fc]::panicking::catch_unwind::do_call::<std[b33743bf75a7d9fc]::rt::lang_start_internal::{closure#0}, isize>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:581:40
  58:        0x1086c5acb - std[b33743bf75a7d9fc]::panicking::catch_unwind::<isize, std[b33743bf75a7d9fc]::rt::lang_start_internal::{closure#0}>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:544:19
  59:        0x1086c5acb - std[b33743bf75a7d9fc]::panic::catch_unwind::<std[b33743bf75a7d9fc]::rt::lang_start_internal::{closure#0}, isize>
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panic.rs:359:14
  60:        0x1086c5acb - std[b33743bf75a7d9fc]::rt::lang_start_internal
                               at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/rt.rs:171:5
  61:        0x107f18de7 - std::rt::lang_start::hc21547e8c9585c63
                               at /Users/JakiChen/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/std/src/rt.rs:205:5
  62:        0x107f72f08 - _main
thread caused non-unwinding panic. aborting.
JakiChen@MacBook-Pro-15 tauri2 % 
Pass Log("minimumSystemVersion": "11.0")
Last login: Wed Jul 22 07:36:02 on ttys002
JakiChen@MacBook-Pro-15 tauri2 % ./tauri-env.sh dev            
📋 Read minimumSystemVersion: 11.0
🧹 Cleaning wry cache to apply deployment target...
     Removed 538 files, 48.0MiB total
🔧 MACOSX_DEPLOYMENT_TARGET set to 11.0
🚀 Starting Tauri dev server...
$ tauri dev
     Running BeforeDevCommand (`pnpm dev`)
        Warn Waiting for your frontend dev server to start on http://localhost:1420/...
$ vite

  VITE v6.4.3  ready in 2554 ms

  ➜  Local:   http://localhost:1420/
     Running DevCommand (`cargo  run --no-default-features --color always --`)
        Info Watching /Users/JakiChen/Developer/tauri2/src-tauri for changes...
   Compiling objc2-exception-helper v0.1.1
   Compiling wry v0.55.1 (/Users/JakiChen/Developer/tauri2/wry)
   Compiling libsqlite3-sys v0.30.1
   Compiling OnTrack v0.1.0 (/Users/JakiChen/Developer/tauri2/src-tauri)
   Compiling objc2 v0.6.4
warning: wry@0.55.1: MAJOR_VERSION_FROM_ENV = 11
   Compiling objc2-core-foundation v0.3.2
   Compiling block2 v0.6.2
   Compiling dispatch2 v0.3.1
   Compiling objc2-foundation v0.3.2
   Compiling rusqlite v0.32.1
   Compiling objc2-app-kit v0.3.2
   Compiling objc2-web-kit v0.3.2
   Compiling tao v0.35.3
   Compiling muda v0.19.3
   Compiling window-vibrancy v0.6.0
   Compiling tauri-runtime v2.11.3
warning: unused import: `block2::Block`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:8:5
  |
8 | use block2::Block;
  |     ^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default

warning: unused imports: `WKMediaCaptureType`, `WKPermissionDecision`, and `WKSecurityOrigin`
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:21:16
   |
21 |   WKFrameInfo, WKMediaCaptureType, WKPermissionDecision, WKSecurityOrigin, WKUIDelegate,
   |                ^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:11:54
   |
11 | use objc2_app_kit::{NSDragOperation, NSDraggingInfo, NSFilenamesPboardType};
   |                                                      ^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(deprecated)]` on by default

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:21:40
   |
21 |   let types = NSArray::arrayWithObject(NSFilenamesPboardType);
   |                                        ^^^^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:24:40
   |
24 |     let paths = pb.propertyListForType(NSFilenamesPboardType).unwrap();
   |                                        ^^^^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSAlternateKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:3
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEventType, NSShiftKeyMask,
  |   ^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSCommandKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:23
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEventType, NSShiftKeyMask,
  |                       ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSControlKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:41
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEventType, NSShiftKeyMask,
  |                                         ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSShiftKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:81
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEventType, NSShiftKeyMask,
  |                                                                                 ^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSControlKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:116:36
    |
116 |     ctrl_key = mods_flags.contains(NSControlKeyMask),
    |                                    ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSAlternateKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:117:35
    |
117 |     alt_key = mods_flags.contains(NSAlternateKeyMask),
    |                                   ^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSShiftKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:118:37
    |
118 |     shift_key = mods_flags.contains(NSShiftKeyMask),
    |                                     ^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSCommandKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:119:36
    |
119 |     meta_key = mods_flags.contains(NSCommandKeyMask),
    |                                    ^^^^^^^^^^^^^^^^

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:40:21
   |
40 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
   |                     ^^^^^^ unnecessary `unsafe` block
   |
   = note: `#[warn(unused_unsafe)]` (part of `#[warn(unused)]`) on by default

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:57:21
   |
57 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
   |                     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:85:21
   |
85 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
   |                     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_parent.rs:33:7
   |
33 |       unsafe {
   |       ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:43:5
   |
43 |     unsafe {
   |     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
    --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/mod.rs:1350:22
     |
1350 |   let absolute_url = unsafe { url_obj.absoluteString().unwrap() };
     |                      ^^^^^^ unnecessary `unsafe` block

   Compiling tauri-runtime-wry v2.11.4
   Compiling tauri v2.11.5
warning: `wry` (lib) generated 19 warnings (run `cargo fix --lib -p wry` to apply 2 suggestions)
   Compiling tauri-plugin-opener v2.5.4
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 3m 17s
     Running `target/debug/OnTrack`

@FabianLars

Copy link
Copy Markdown
Member

i don't have a macos 11 machine available rn (and can't make the vm working anymore for some reason), can you test this branch? https://github.com/tauri-apps/wry/tree/macos-availability
Requires rust/cargo 1.93 or newer

@JakiChen

JakiChen commented Jul 22, 2026

Copy link
Copy Markdown
Author

The branch builds and all tests pass on my end (macOS 11.7.11). I noticed the source has availability checks gating for macOS 12(#[cfg(not(macos_12_unavailable))]) — looks good.

Pass Log(`pnpm tauri dev`)
JakiChen@MacBook-Pro-15 tauri2 % cd wry
JakiChen@MacBook-Pro-15 wry % git fetch origin macos-availability
From https://github.com/tauri-apps/wry
 * branch            macos-availability -> FETCH_HEAD
JakiChen@MacBook-Pro-15 wry % git checkout macos-availability
Branch 'macos-availability' set up to track remote branch 'macos-availability' from 'origin'.
Switched to a new branch 'macos-availability'
JakiChen@MacBook-Pro-15 wry % cd ../src-tauri
JakiChen@MacBook-Pro-15 src-tauri % pnpm tauri dev
$ tauri dev
     Running BeforeDevCommand (`pnpm dev`)
        Warn Waiting for your frontend dev server to start on http://localhost:1420/...
        Warn Waiting for your frontend dev server to start on http://localhost:1420/...
$ vite

  VITE v6.4.3  ready in 3311 ms

  ➜  Local:   http://localhost:1420/
     Running DevCommand (`cargo  run --no-default-features --color always --`)
        Info Watching /Users/JakiChen/Developer/tauri2/src-tauri for changes...
     Locking 1 package to latest compatible version
      Adding wry v0.55.1 (/Users/JakiChen/Developer/tauri2/wry)
   Compiling bitflags v2.13.1
   Compiling objc2 v0.6.4
   Compiling selectors v0.36.1
   Compiling dom_query v0.27.0
   Compiling objc2-foundation v0.3.2
   Compiling wry v0.55.1 (/Users/JakiChen/Developer/tauri2/wry)
   Compiling tauri-utils v2.9.3
warning: unused import: `block2::Block`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:8:5
  |
8 | use block2::Block;
  |     ^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default

warning: unused imports: `WKMediaCaptureType`, `WKPermissionDecision`, and `WKSecurityOrigin`
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:21:16
   |
21 | ...nfo, WKMediaCaptureType, WKPermissionDecision, WKSecurityOrigin, WKUI...
   |         ^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^

warning: unexpected `cfg` condition name: `macos_12_unavailable`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:129:15
    |
129 |     #[cfg(not(macos_12_unavailable))]
    |               ^^^^^^^^^^^^^^^^^^^^
    |
    = help: expected names are: `docsrs`, `feature`, `gtk`, `linux`, and `test` and 31 more
    = help: consider using a Cargo feature instead
    = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
             [lints.rust]
             unexpected_cfgs = { level = "warn", check-cfg = ['cfg(macos_12_unavailable)'] }
    = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(macos_12_unavailable)");` to the top of the `build.rs`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
    = note: requested on the command line with `-W unexpected-cfgs`

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:11:54
   |
11 | ...ration, NSDraggingInfo, NSFilenamesPboardType};
   |                            ^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(deprecated)]` on by default

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:21:40
   |
21 |   let types = NSArray::arrayWithObject(NSFilenamesPboardType);
   |                                        ^^^^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:24:40
   |
24 |     let paths = pb.propertyListForType(NSFilenamesPboardType).unwrap();
   |                                        ^^^^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSAlternateKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:3
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEven...
  |   ^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSCommandKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:23
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEven...
  |                       ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSControlKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:41
  |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEven...
  |                                         ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSShiftKeyMask`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:81
  |
2 | ...Mask, NSEvent, NSEventType, NSShiftKeyMask,
  |                                ^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSControlKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:116:36
    |
116 |     ctrl_key = mods_flags.contains(NSControlKeyMask),
    |                                    ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSAlternateKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:117:35
    |
117 |     alt_key = mods_flags.contains(NSAlternateKeyMask),
    |                                   ^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSShiftKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:118:37
    |
118 |     shift_key = mods_flags.contains(NSShiftKeyMask),
    |                                     ^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSCommandKeyMask`
   --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:119:36
    |
119 |     meta_key = mods_flags.contains(NSCommandKeyMask),
    |                                    ^^^^^^^^^^^^^^^^

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:40:21
   |
40 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
   |                     ^^^^^^ unnecessary `unsafe` block
   |
   = note: `#[warn(unused_unsafe)]` (part of `#[warn(unused)]`) on by default

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:57:21
   |
57 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
   |                     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:85:21
   |
85 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
   |                     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_parent.rs:33:7
   |
33 |       unsafe {
   |       ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:43:5
   |
43 |     unsafe {
   |     ^^^^^^ unnecessary `unsafe` block

warning: field `permission_handler` is never read
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:87:3
   |
82 | pub struct WryWebViewUIDelegateIvars {
   |            ------------------------- field in this struct
...
87 |   permission_handler: Option<Box<dyn Fn(PermissionKind) -> PermissionRes...
   |   ^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default

   Compiling tauri-runtime-wry v2.11.4
warning: `wry` (lib) generated 20 warnings (run `cargo fix --lib -p wry` to apply 2 suggestions)
   Compiling tauri-build v2.6.3
   Compiling tauri-plugin v2.6.3
   Compiling tauri-codegen v2.6.3
   Compiling tauri v2.11.5
   Compiling tauri-plugin-opener v2.5.4
   Compiling tauri-macros v2.6.3
   Compiling OnTrack v0.1.0 (/Users/JakiChen/Developer/tauri2/src-tauri)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 5m 25s
     Running `target/debug/OnTrack`
Pass Log(`pnm tauri build`)
JakiChen@MacBook-Pro-15 src-tauri % pnpm tauri build
$ tauri build
       Info Looking up installed tauri packages to check mismatched versions...
    Running beforeBuildCommand `pnpm build`
$ tsc && vite build
vite v6.4.3 building for production...
✓ 630 modules transformed.
dist/index.html                   0.86 kB │ gzip:   0.50 kB
dist/assets/index-94RnFMqK.css   19.02 kB │ gzip:   4.52 kB
dist/assets/index-D7jmcMzm.js   580.36 kB │ gzip: 172.85 kB

(!) Some chunks are larger than 500 kB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
✓ built in 17.41s
  Compiling proc-macro2 v1.0.107
  Compiling quote v1.0.47
  Compiling unicode-ident v1.0.24
  Compiling serde_core v1.0.229
  Compiling libc v0.2.186
  Compiling siphasher v1.0.3
  Compiling icu_properties_data v2.2.0
  Compiling icu_normalizer_data v2.2.0
  Compiling find-msvc-tools v0.1.9
  Compiling phf_shared v0.13.1
  Compiling shlex v2.0.1
  Compiling zmij v1.0.23
  Compiling fastrand v2.5.0
  Compiling cc v1.3.0
  Compiling stable_deref_trait v1.2.1
  Compiling cfg-if v1.0.4
  Compiling memchr v2.8.3
  Compiling smallvec v1.15.2
  Compiling serde v1.0.229
  Compiling phf_generator v0.13.1
  Compiling itoa v1.0.18
  Compiling typeid v1.0.3
  Compiling time-core v0.1.9
  Compiling num-conv v0.2.2
  Compiling thiserror v2.0.19
  Compiling version_check v0.9.5
  Compiling phf_codegen v0.13.1
  Compiling syn v2.0.119
  Compiling syn v3.0.1
  Compiling ident_case v1.0.1
  Compiling autocfg v1.5.1
  Compiling strsim v0.11.1
  Compiling litemap v0.8.2
  Compiling writeable v0.6.3
  Compiling thiserror v1.0.69
  Compiling erased-serde v0.4.10
  Compiling serde_json v1.0.150
  Compiling parking_lot_core v0.9.12
  Compiling utf8_iter v1.0.4
  Compiling anyhow v1.0.104
  Compiling bitflags v2.13.1
  Compiling new_debug_unreachable v1.0.6
  Compiling scopeguard v1.2.0
  Compiling lock_api v0.4.14
  Compiling string_cache_codegen v0.6.1
  Compiling getrandom v0.4.3
  Compiling precomputed-hash v0.1.1
  Compiling winnow v1.0.4
  Compiling parking_lot v0.12.5
  Compiling objc2-exception-helper v0.1.1
  Compiling ctor-proc-macro v0.0.7
  Compiling web_atoms v0.2.5
  Compiling toml_parser v1.1.2+spec-1.1.0
  Compiling toml_writer v1.1.2+spec-1.1.0
  Compiling string_cache v0.9.0
  Compiling log v0.4.33
  Compiling percent-encoding v2.3.2
  Compiling dtoa v1.0.11
  Compiling form_urlencoded v1.2.2
  Compiling dtoa-short v0.3.5
  Compiling tendril v0.5.1
  Compiling indexmap v1.9.3
  Compiling serde_spanned v1.1.1
  Compiling semver v1.0.28
  Compiling uuid v1.24.0
  Compiling toml_datetime v1.1.1+spec-1.1.0
  Compiling selectors v0.36.1
  Compiling aho-corasick v1.1.4
  Compiling alloc-no-stdlib v2.0.4
  Compiling regex-syntax v0.8.11
  Compiling unic-common v0.9.0
  Compiling camino v1.2.4
  Compiling byteorder v1.5.0
  Compiling objc2 v0.6.4
  Compiling unic-char-range v0.9.0
  Compiling unic-char-property v0.9.0
  Compiling unic-ucd-version v0.9.0
  Compiling serde_derive v1.0.229
  Compiling thiserror-impl v2.0.19
  Compiling alloc-stdlib v0.2.4
  Compiling toml v1.1.3+spec-1.1.0
  Compiling servo_arc v0.4.3
  Compiling schemars v0.8.22
  Compiling rustc-hash v2.1.3
  Compiling objc2-encode v4.1.0
  Compiling hashbrown v0.12.3
  Compiling synstructure v0.13.2
  Compiling darling_core v0.23.0
  Compiling serde_derive_internals v0.29.1
  Compiling deranged v0.5.8
  Compiling regex-automata v0.4.16
  Compiling equivalent v1.0.2
  Compiling hashbrown v0.17.1
  Compiling bit-vec v0.8.0
  Compiling fnv v1.0.7
  Compiling powerfmt v0.2.0
  Compiling cfb v0.7.3
  Compiling bit-set v0.8.0
  Compiling time v0.3.53
  Compiling indexmap v2.14.0
  Compiling zerofrom-derive v0.1.7
  Compiling yoke-derive v0.8.2
  Compiling zerovec-derive v0.11.3
  Compiling displaydoc v0.2.6
  Compiling phf_macros v0.13.1
  Compiling zerofrom v0.1.8
  Compiling yoke v0.8.3
  Compiling darling_macro v0.23.0
  Compiling zerovec v0.11.6
  Compiling zerotrie v0.2.4
  Compiling thiserror-impl v1.0.69
  Compiling darling v0.23.0
  Compiling serde_with_macros v3.21.0
  Compiling phf v0.13.1
  Compiling tinystr v0.8.3
  Compiling icu_locale_core v2.2.0
  Compiling potential_utf v0.1.5
  Compiling cssparser-macros v0.6.1
  Compiling icu_collections v2.2.0
  Compiling derive_more-impl v2.1.1
  Compiling cssparser v0.36.0
  Compiling markup5ever v0.38.0
  Compiling swift-rs v1.0.7
  Compiling jsonptr v0.6.3
  Compiling html5ever v0.38.0
  Compiling cargo-platform v0.1.9
  Compiling regex v1.13.1
  Compiling icu_provider v2.2.0
  Compiling derive_more v2.1.1
  Compiling schemars_derive v0.8.22
  Compiling icu_properties v2.2.0
  Compiling icu_normalizer v2.2.0
  Compiling brotli-decompressor v5.0.3
  Compiling unic-ucd-ident v0.9.0
  Compiling quick-xml v0.41.0
  Compiling crc32fast v1.5.0
  Compiling dunce v1.0.5
  Compiling base64 v0.22.1
  Compiling bytes v1.12.1
  Compiling same-file v1.0.6
  Compiling base64 v0.21.7
  Compiling dyn-clone v1.0.20
  Compiling foldhash v0.2.0
  Compiling walkdir v2.5.0
  Compiling dom_query v0.27.0
  Compiling plist v1.10.0
  Compiling idna_adapter v1.2.2
  Compiling idna v1.1.0
  Compiling http v1.4.2
  Compiling brotli v8.0.4
  Compiling url v2.5.8
  Compiling cargo_metadata v0.19.2
  Compiling serde-untagged v0.1.9
  Compiling json-patch v3.0.1
  Compiling urlpattern v0.3.0
  Compiling serde_with v3.21.0
  Compiling infer v0.19.0
  Compiling ctor v0.8.0
  Compiling glob v0.3.3
  Compiling block2 v0.6.2
  Compiling objc2-core-foundation v0.3.2
  Compiling rustc_version v0.4.1
  Compiling toml_datetime v0.7.5+spec-1.1.0
  Compiling generic-array v0.14.7
  Compiling option-ext v0.2.0
  Compiling core-foundation-sys v0.8.7
  Compiling once_cell v1.21.4
  Compiling winnow v0.7.15
  Compiling dirs-sys v0.5.0
  Compiling embed-resource v3.0.11
  Compiling time-macros v0.2.31
  Compiling heck v0.5.0
  Compiling objc2-foundation v0.3.2
  Compiling tauri-utils v2.9.3
  Compiling typenum v1.20.1
  Compiling simd-adler32 v0.3.10
  Compiling toml v0.9.12+spec-1.1.0
  Compiling tauri-winres v0.3.6
  Compiling dirs v6.0.0
  Compiling cargo_toml v0.22.3
  Compiling adler2 v2.0.1
  Compiling crossbeam-utils v0.8.22
  Compiling miniz_oxide v0.8.9
  Compiling dpi v0.1.2
  Compiling cookie v0.18.1
  Compiling raw-window-handle v0.6.2
  Compiling objc2-app-kit v0.3.2
  Compiling tauri-build v2.6.3
  Compiling flate2 v1.1.9
  Compiling crypto-common v0.1.7
  Compiling block-buffer v0.10.4
  Compiling fdeflate v0.3.7
  Compiling core-foundation v0.10.1
  Compiling foreign-types-macros v0.2.3
  Compiling bitflags v1.3.2
  Compiling zerocopy v0.8.54
  Compiling foreign-types-shared v0.3.1
  Compiling foreign-types v0.5.0
  Compiling objc2-web-kit v0.3.2
  Compiling png v0.17.16
  Compiling core-graphics-types v0.2.0
  Compiling digest v0.10.7
  Compiling crossbeam-channel v0.5.16
  Compiling tauri v2.11.5
  Compiling wry v0.55.1 (/Users/JakiChen/Developer/tauri2/wry)
  Compiling ahash v0.8.12
  Compiling tauri-runtime v2.11.3
  Compiling cpufeatures v0.2.17
  Compiling sha2 v0.10.9
  Compiling ico v0.5.0
  Compiling core-graphics v0.25.0
  Compiling tauri-plugin v2.6.3
  Compiling dispatch2 v0.3.1
  Compiling num-traits v0.2.19
  Compiling tauri-runtime-wry v2.11.4
  Compiling unicode-segmentation v1.13.3
  Compiling getrandom v0.3.4
  Compiling vcpkg v0.2.15
  Compiling pkg-config v0.3.33
  Compiling tao v0.35.3
  Compiling keyboard-types v0.7.0
  Compiling libsqlite3-sys v0.30.1
  Compiling png v0.18.1
  Compiling tauri-plugin-opener v2.5.4
  Compiling tauri-codegen v2.6.3
warning: unexpected `cfg` condition name: `macos_12_unavailable`
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:129:15
   |
129 |     #[cfg(not(macos_12_unavailable))]
   |               ^^^^^^^^^^^^^^^^^^^^
   |
   = help: expected names are: `docsrs`, `feature`, `gtk`, `linux`, and `test` and 31 more
   = help: consider using a Cargo feature instead
   = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
            [lints.rust]
            unexpected_cfgs = { level = "warn", check-cfg = ['cfg(macos_12_unavailable)'] }
   = help: or consider adding `println!("cargo::rustc-check-cfg=cfg(macos_12_unavailable)");` to the top of the `build.rs`
   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
   = note: requested on the command line with `-W unexpected-cfgs`

warning: unused import: `NSObject`
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/mod.rs:37:24
  |
37 |   runtime::{AnyObject, NSObject, ProtocolObject},
  |                        ^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:11:54
  |
11 | ...ration, NSDraggingInfo, NSFilenamesPboardType};
  |                            ^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(deprecated)]` on by default

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:21:40
  |
21 |   let types = NSArray::arrayWithObject(NSFilenamesPboardType);
  |                                        ^^^^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSFilenamesPboardType`: Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:24:40
  |
24 |     let paths = pb.propertyListForType(NSFilenamesPboardType).unwrap();
  |                                        ^^^^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSAlternateKeyMask`
--> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:3
 |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEven...
 |   ^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSCommandKeyMask`
--> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:23
 |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEven...
 |                       ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSControlKeyMask`
--> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:41
 |
2 |   NSAlternateKeyMask, NSCommandKeyMask, NSControlKeyMask, NSEvent, NSEven...
 |                                         ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSShiftKeyMask`
--> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:2:81
 |
2 | ...Mask, NSEvent, NSEventType, NSShiftKeyMask,
 |                                ^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSControlKeyMask`
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:116:36
   |
116 |     ctrl_key = mods_flags.contains(NSControlKeyMask),
   |                                    ^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSAlternateKeyMask`
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:117:35
   |
117 |     alt_key = mods_flags.contains(NSAlternateKeyMask),
   |                                   ^^^^^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSShiftKeyMask`
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:118:37
   |
118 |     shift_key = mods_flags.contains(NSShiftKeyMask),
   |                                     ^^^^^^^^^^^^^^

warning: use of deprecated static `objc2_app_kit::NSCommandKeyMask`
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/synthetic_mouse_events.rs:119:36
   |
119 |     meta_key = mods_flags.contains(NSCommandKeyMask),
   |                                    ^^^^^^^^^^^^^^^^

warning: unused variable: `error`
  --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/download.rs:106:3
   |
106 |   error: &NSError,
   |   ^^^^^ help: if this is intentional, prefix it with an underscore: `_error`
   |
   = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default

warning: unnecessary `unsafe` block
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:40:21
  |
40 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
  |                     ^^^^^^ unnecessary `unsafe` block
  |
  = note: `#[warn(unused_unsafe)]` (part of `#[warn(unused)]`) on by default

warning: unnecessary `unsafe` block
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:57:21
  |
57 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
  |                     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/drag_drop.rs:85:21
  |
85 |   let dl: NSPoint = unsafe { drag_info.draggingLocation() };
  |                     ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_parent.rs:33:7
  |
33 |       unsafe {
  |       ^^^^^^ unnecessary `unsafe` block

warning: unnecessary `unsafe` block
 --> /Users/JakiChen/Developer/tauri2/wry/src/wkwebview/class/wry_web_view_ui_delegate.rs:43:5
  |
43 |     unsafe {
  |     ^^^^^^ unnecessary `unsafe` block

  Compiling serialize-to-javascript-impl v0.1.2
  Compiling pin-project-lite v0.2.17
  Compiling tokio v1.53.0
  Compiling tauri-macros v2.6.3
  Compiling muda v0.19.3
  Compiling hashbrown v0.14.5
  Compiling serialize-to-javascript v0.1.2
  Compiling window-vibrancy v0.6.0
  Compiling iana-time-zone v0.1.65
  Compiling serde_repr v0.1.21
  Compiling embed_plist v1.2.2
  Compiling mime v0.3.17
  Compiling chrono v0.4.45
  Compiling hashlink v0.9.1
  Compiling OnTrack v0.1.0 (/Users/JakiChen/Developer/tauri2/src-tauri)
warning: `wry` (lib) generated 19 warnings (run `cargo fix --lib -p wry` to apply 2 suggestions)
  Compiling dirs-sys v0.4.1
  Compiling open v5.4.0
  Compiling fallible-streaming-iterator v0.1.9
  Compiling fallible-iterator v0.3.0
  Compiling dirs v5.0.1
  Compiling rusqlite v0.32.1
   Finished `release` profile [optimized] target(s) in 19m 13s
      Built application at: /Users/JakiChen/Developer/tauri2/src-tauri/target/release/OnTrack
   Bundling OnTrack.app (/Users/JakiChen/Developer/tauri2/src-tauri/target/release/bundle/macos/OnTrack.app)
   Bundling OnTrack_0.1.0_x64.dmg (/Users/JakiChen/Developer/tauri2/src-tauri/target/release/bundle/dmg/OnTrack_0.1.0_x64.dmg)
    Running bundle_dmg.sh
failed to bundle project: error running bundle_dmg.sh: `failed to run /Users/JakiChen/Developer/tauri2/src-tauri/target/release/bundle/dmg/bundle_dmg.sh`
      Error failed to bundle project: error running bundle_dmg.sh: `failed to run /Users/JakiChen/Developer/tauri2/src-tauri/target/release/bundle/dmg/bundle_dmg.sh`
[ELIFECYCLE] Command failed with exit code 1.
JakiChen@MacBook-Pro-15 src-tauri %

Heyyyyy @FabianLars , I have a question about the build.rs logic in this #1781 .

It uses operating_system_version() to set macos_12_unavailable, but only when CARGO_CFG_DEBUG_ASSERTIONS is present. In release builds, that cfg is never set, so the new API method is always included.

Doesn’t this mean we cannot produce a release binary compatible with macOS <12 from a newer CI host (e.g., macOS 14) by simply setting MACOSX_DEPLOYMENT_TARGET? Is that the intended behavior?

Just wondering if this has been considered. Thanks.

@FabianLars

Copy link
Copy Markdown
Member

This is what I was trying to explain in previous comments. The error you're getting should only happen in debug mode because it's a debug_assertion gated test inside the objc2 crate.

This isn't actually macOS itself complaining about it.

Once we update objc2 to 0.7 (not yet released) we can remove this cfg code here because objc2 will drop the check or at least change it in a way that doesn't crash like it does now.

@JakiChen

JakiChen commented Jul 22, 2026

Copy link
Copy Markdown
Author

@FabianLars

Thanks for the clarification — that really helped. Now I understand that the crash was only a debug assertion inside objc2, not macOS itself blocking anything. That makes sense.

Still, my main worry is about release binaries. If the newer API code is always compiled in when debug_assertions is off, could that lead to subtle compatibility issues down the road, even with MACOSX_DEPLOYMENT_TARGET set? My (possibly naive) expectation was that code paths not valid for the target OS version should ideally be excluded from the final binary to keep things clean and avoid future bugs.

I tried a quick local patch in build.rs that reads MACOSX_DEPLOYMENT_TARGET and sets a cfg like macos_12_or_later or macos_11_or_earlier accordingly, using that to conditionally compile the relevant code. Right now I default to 10.15 if the env var is not set, but that feels a bit arbitrary — maybe it should default to 12.0? I’m not sure about the right default, and I’m also not 100% certain my understanding of how Rust’s conditional compilation and linkage interacts with macOS deployment targets is correct. I’d really appreciate your thoughts on whether this approach makes sense.

And a more general question: would it be possible (or planned) to have the build script read minimumSystemVersion directly from tauri.conf.json and use that to drive the conditional compilation? That feels like the cleanest approach from a user’s perspective — a single source of truth that Tauri already knows about.

I hope you don’t mind these beginner questions — I’m very new to Rust and the ecosystem, and I realize there’s a lot I still need to learn. If I’m missing something fundamental or making incorrect assumptions, I truly apologize. Thanks again for your time and patience!

@FabianLars

Copy link
Copy Markdown
Member

Still, my main worry is about release binaries. If the newer API code is always compiled in when debug_assertions is off, could that lead to subtle compatibility issues down the road, even with MACOSX_DEPLOYMENT_TARGET set? My (possibly naive) expectation was that code paths not valid for the target OS version should ideally be excluded from the final binary to keep things clean and avoid future bugs.

Not in this case. Basically there are 2 different kinds of method availability we have to care about on macOS:

First, "normal" methods that we actively call, for example https://github.com/tauri-apps/wry/blob/dev/src/wkwebview/mod.rs#L382C1-L388C8
Here we want to call setElementFullscreenEnabled on WKPreferences but that method was added in macOS 12.3 so we must guard it with version checks that run at runtime on the user's system, since we want to call them on macOS 12.3+ systems but not on older macOS versions. The functionality is also not important enough to raise the Deployment Target to 12.3 (and hence making anybody with older versions unable to run your app).

Secondly, "delegate" methods that we define but are called from "outside", e.g. by macOS or other programs or other part of the same program.
When overwriting a Delegate like we do here, we can even add methods macOS never knew and will never know about and that's okay.
Let's maybe compare that with a REST API. You have an app that calls into some remote REST API. You haven't updated your app in a while but the REST API added new endpoints. Your app keeps working even though it doesn't know about the new endpoints.
The REST API represents our Delegate here and "your app" is macOS / WKWebView using the Delegate.
Now why the crash in Wry? Imagine you're working on the REST API now and want to add a new endpoint without touching the other endpoints. Now your development environment has a development-only check against your production OpenAPI/Swagger that of course doesn't know about the new endpoint yet. -> You see a warning/error in dev, but adding new endpoint to the server is actually okay.

I hope this makes even a little bit of sense, i'm not the best at explaining things, especially this stuff here as it leans heavily to the objc / ffi side instead of being a real rust question. Feel free to ask follow up questions :)

I tried a quick local patch in build.rs that reads MACOSX_DEPLOYMENT_TARGET and sets a cfg like macos_12_or_later or macos_11_or_earlier accordingly, using that to conditionally compile the relevant code. Right now I default to 10.15 if the env var is not set, but that feels a bit arbitrary — maybe it should default to 12.0? I’m not sure about the right default, and I’m also not 100% certain my understanding of how Rust’s conditional compilation and linkage interacts with macOS deployment targets is correct. I’d really appreciate your thoughts on whether this approach makes sense.

I'd say the right default is very subjective. In Tauri we use 10.13 because of technical limitations. We must use some APIs that were added in 10.13 so we can't go lower than that, but as library authors we want the minimum supported OS version as low as possible to give app developers the choice what to support. And for library authors it then also makes sense to set the default deployment target to the minimum version as well.
But if you say hey, i don't care about those 3 users still on macOS 11 or below, or you need APIs that were added in version 12, then you can go ahead and raise it to 12. (12 being an example here)

And a more general question: would it be possible (or planned) to have the build script read minimumSystemVersion directly from tauri.conf.json and use that to drive the conditional compilation? That feels like the cleanest approach from a user’s perspective — a single source of truth that Tauri already knows about.

In Wry? Probablyyy not, it isn't connected to Tauri close enough for that. Ignoring this PR we also have no real reason to check for the deployment target in Wry.
In Tauri we read the deployment target in multiple places, but had to disable it in tauri dev specifically as it caused recompilation issues. ref tauri-apps/tauri#14083 / tauri-apps/tauri#11577

@JakiChen

Copy link
Copy Markdown
Author

Thanks so much for taking the time to write all that out! I'll go ahead and close this PR.

@JakiChen JakiChen closed this Jul 23, 2026
@FabianLars FabianLars mentioned this pull request Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants