Skip to content

Commit f1889f6

Browse files
committed
Update macOS build configuration
1 parent 044a43f commit f1889f6

8 files changed

Lines changed: 220 additions & 89 deletions

File tree

.cargo/config.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,12 @@
11
[env]
22
MACOSX_DEPLOYMENT_TARGET = "13.0"
3+
4+
[target.'cfg(all())']
5+
rustflags = [
6+
"-Wclippy::all",
7+
"-Wclippy::pedantic",
8+
"-Wclippy::nursery",
9+
"-Wclippy::unwrap_used",
10+
"-Aclippy::module_name_repetitions",
11+
"-Aclippy::missing_errors_doc",
12+
]

build.rs

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn main() {
3434
.unwrap_or_default()
3535
.contains("android")
3636
{
37-
let properties_content = format!("enablePushNotifications={}", enable_push);
37+
let properties_content = format!("enablePushNotifications={enable_push}");
3838
std::fs::write("android/build.properties", properties_content)
3939
.expect("Failed to write build.properties");
4040
}
@@ -73,6 +73,10 @@ fn main() {
7373
{
7474
// Only run macOS-specific build steps when building for macOS
7575
if std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default() == "macos" {
76+
// Rebuild when target architecture or deployment target changes
77+
println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_ARCH");
78+
println!("cargo:rerun-if-env-changed=MACOSX_DEPLOYMENT_TARGET");
79+
7680
let bridges = vec!["src/macos.rs"];
7781
for path in &bridges {
7882
println!("cargo:rerun-if-changed={path}");
@@ -99,18 +103,22 @@ fn main() {
99103
#[cfg(target_os = "macos")]
100104
fn compile_swift() {
101105
let swift_package_dir = manifest_dir().join("macos");
106+
let target_triple = swift_target_triple();
102107

103108
let mut cmd = Command::new("swift");
104109

105-
cmd.current_dir(swift_package_dir).arg("build").args([
106-
"-Xswiftc",
107-
"-import-objc-header",
108-
"-Xswiftc",
109-
swift_source_dir()
110-
.join("bridging-header.h")
111-
.to_str()
112-
.expect("Bridging header path must be valid UTF-8"),
113-
]);
110+
cmd.current_dir(&swift_package_dir)
111+
.arg("build")
112+
.args(["--triple", &target_triple])
113+
.args([
114+
"-Xswiftc",
115+
"-import-objc-header",
116+
"-Xswiftc",
117+
swift_source_dir()
118+
.join("bridging-header.h")
119+
.to_str()
120+
.expect("Bridging header path must be valid UTF-8"),
121+
]);
114122

115123
if is_release_build() {
116124
cmd.args(["-c", "release"]);
@@ -122,16 +130,17 @@ fn compile_swift() {
122130
.wait_with_output()
123131
.expect("Failed to wait for swift build output");
124132

125-
if !exit_status.status.success() {
126-
panic!(
127-
r#"
133+
assert!(
134+
exit_status.status.success(),
135+
r"
136+
Swift build failed for target: {}
128137
Stderr: {}
129138
Stdout: {}
130-
"#,
131-
String::from_utf8(exit_status.stderr).expect("Stderr must be valid UTF-8"),
132-
String::from_utf8(exit_status.stdout).expect("Stdout must be valid UTF-8"),
133-
)
134-
}
139+
",
140+
target_triple,
141+
String::from_utf8(exit_status.stderr).expect("Stderr must be valid UTF-8"),
142+
String::from_utf8(exit_status.stdout).expect("Stdout must be valid UTF-8"),
143+
);
135144
}
136145

137146
#[cfg(target_os = "macos")]
@@ -160,6 +169,30 @@ fn generated_code_dir() -> PathBuf {
160169
swift_source_dir().join("generated")
161170
}
162171

172+
#[cfg(target_os = "macos")]
173+
fn target_arch() -> String {
174+
std::env::var("CARGO_CFG_TARGET_ARCH").expect("CARGO_CFG_TARGET_ARCH must be set")
175+
}
176+
177+
#[cfg(target_os = "macos")]
178+
fn swift_arch() -> &'static str {
179+
match target_arch().as_str() {
180+
"aarch64" => "arm64",
181+
"x86_64" => "x86_64",
182+
arch => panic!("Unsupported architecture for macOS: {arch}"),
183+
}
184+
}
185+
186+
#[cfg(target_os = "macos")]
187+
fn macos_deployment_target() -> String {
188+
std::env::var("MACOSX_DEPLOYMENT_TARGET").unwrap_or_else(|_| "13.0".to_string())
189+
}
190+
191+
#[cfg(target_os = "macos")]
192+
fn swift_target_triple() -> String {
193+
format!("{}-apple-macosx{}", swift_arch(), macos_deployment_target())
194+
}
195+
163196
#[cfg(target_os = "macos")]
164197
fn swift_library_static_lib_dir() -> PathBuf {
165198
let debug_or_release = if is_release_build() {
@@ -168,5 +201,6 @@ fn swift_library_static_lib_dir() -> PathBuf {
168201
"debug"
169202
};
170203

171-
manifest_dir().join(format!("macos/.build/{debug_or_release}"))
204+
let arch_dir = format!("{}-apple-macosx", swift_arch());
205+
manifest_dir().join(format!("macos/.build/{arch_dir}/{debug_or_release}"))
172206
}

src/commands.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1+
// Tauri command handlers must take owned values: `State<'_, _>` is the framework's
2+
// preferred wrapper, and serde-deserialized payloads (Vec, String, ...) cannot be borrowed.
3+
#![allow(clippy::needless_pass_by_value)]
4+
15
use serde::Deserialize;
26
use tauri::{command, plugin::PermissionState, AppHandle, Runtime, State};
37

48
use crate::{NotificationData, Notifications, Result};
59

610
#[derive(Debug, Deserialize)]
711
#[allow(dead_code)]
8-
pub(crate) struct NotificationIdentifier {
12+
pub struct NotificationIdentifier {
913
pub id: i32,
1014
#[allow(dead_code)]
1115
pub tag: Option<String>,
1216
}
1317

1418
#[command]
15-
pub(crate) async fn is_permission_granted<R: Runtime>(
19+
pub async fn is_permission_granted<R: Runtime>(
1620
_app: AppHandle<R>,
1721
notification: State<'_, Notifications<R>>,
1822
) -> Result<Option<bool>> {
@@ -25,31 +29,31 @@ pub(crate) async fn is_permission_granted<R: Runtime>(
2529
}
2630

2731
#[command]
28-
pub(crate) async fn request_permission<R: Runtime>(
32+
pub async fn request_permission<R: Runtime>(
2933
_app: AppHandle<R>,
3034
notification: State<'_, Notifications<R>>,
3135
) -> Result<PermissionState> {
3236
notification.request_permission().await
3337
}
3438

3539
#[command]
36-
pub(crate) async fn register_for_push_notifications<R: Runtime>(
40+
pub async fn register_for_push_notifications<R: Runtime>(
3741
_app: AppHandle<R>,
3842
notification: State<'_, Notifications<R>>,
3943
) -> Result<String> {
4044
notification.register_for_push_notifications().await
4145
}
4246

4347
#[command]
44-
pub(crate) async fn unregister_for_push_notifications<R: Runtime>(
48+
pub async fn unregister_for_push_notifications<R: Runtime>(
4549
_app: AppHandle<R>,
4650
notification: State<'_, Notifications<R>>,
4751
) -> Result<()> {
4852
notification.unregister_for_push_notifications()
4953
}
5054

5155
#[command]
52-
pub(crate) async fn notify<R: Runtime>(
56+
pub async fn notify<R: Runtime>(
5357
_app: AppHandle<R>,
5458
notification: State<'_, Notifications<R>>,
5559
options: NotificationData,
@@ -60,7 +64,7 @@ pub(crate) async fn notify<R: Runtime>(
6064
}
6165

6266
#[command]
63-
pub(crate) async fn register_action_types<R: Runtime>(
67+
pub async fn register_action_types<R: Runtime>(
6468
_app: AppHandle<R>,
6569
notification: State<'_, Notifications<R>>,
6670
types: Vec<crate::ActionType>,
@@ -69,23 +73,23 @@ pub(crate) async fn register_action_types<R: Runtime>(
6973
}
7074

7175
#[command]
72-
pub(crate) async fn get_pending<R: Runtime>(
76+
pub async fn get_pending<R: Runtime>(
7377
_app: AppHandle<R>,
7478
notification: State<'_, Notifications<R>>,
7579
) -> Result<Vec<crate::PendingNotification>> {
7680
notification.pending().await
7781
}
7882

7983
#[command]
80-
pub(crate) async fn get_active<R: Runtime>(
84+
pub async fn get_active<R: Runtime>(
8185
_app: AppHandle<R>,
8286
notification: State<'_, Notifications<R>>,
8387
) -> Result<Vec<crate::ActiveNotification>> {
8488
notification.active().await
8589
}
8690

8791
#[command]
88-
pub(crate) fn set_click_listener_active<R: Runtime>(
92+
pub fn set_click_listener_active<R: Runtime>(
8993
_app: AppHandle<R>,
9094
notification: State<'_, Notifications<R>>,
9195
active: bool,
@@ -94,7 +98,7 @@ pub(crate) fn set_click_listener_active<R: Runtime>(
9498
}
9599

96100
#[command]
97-
pub(crate) fn remove_active<R: Runtime>(
101+
pub fn remove_active<R: Runtime>(
98102
_app: AppHandle<R>,
99103
notification: State<'_, Notifications<R>>,
100104
notifications: Vec<NotificationIdentifier>,
@@ -104,7 +108,7 @@ pub(crate) fn remove_active<R: Runtime>(
104108
}
105109

106110
#[command]
107-
pub(crate) fn cancel<R: Runtime>(
111+
pub fn cancel<R: Runtime>(
108112
_app: AppHandle<R>,
109113
notification: State<'_, Notifications<R>>,
110114
notifications: Vec<i32>,
@@ -113,15 +117,15 @@ pub(crate) fn cancel<R: Runtime>(
113117
}
114118

115119
#[command]
116-
pub(crate) fn cancel_all<R: Runtime>(
120+
pub fn cancel_all<R: Runtime>(
117121
_app: AppHandle<R>,
118122
notification: State<'_, Notifications<R>>,
119123
) -> Result<()> {
120124
notification.cancel_all()
121125
}
122126

123127
#[command]
124-
pub(crate) fn create_channel<R: Runtime>(
128+
pub fn create_channel<R: Runtime>(
125129
_app: AppHandle<R>,
126130
notification: State<'_, Notifications<R>>,
127131
channel: crate::Channel,
@@ -130,7 +134,7 @@ pub(crate) fn create_channel<R: Runtime>(
130134
}
131135

132136
#[command]
133-
pub(crate) fn delete_channel<R: Runtime>(
137+
pub fn delete_channel<R: Runtime>(
134138
_app: AppHandle<R>,
135139
notification: State<'_, Notifications<R>>,
136140
id: String,
@@ -139,7 +143,7 @@ pub(crate) fn delete_channel<R: Runtime>(
139143
}
140144

141145
#[command]
142-
pub(crate) fn list_channels<R: Runtime>(
146+
pub fn list_channels<R: Runtime>(
143147
_app: AppHandle<R>,
144148
notification: State<'_, Notifications<R>>,
145149
) -> Result<Vec<crate::Channel>> {

src/desktop.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use tauri::{
66

77
use crate::NotificationsBuilder;
88

9+
// Signature must match the iOS/Android `init` so the cfg-gated call sites in `lib.rs::init` compile uniformly.
10+
#[allow(clippy::unnecessary_wraps)]
911
pub fn init<R: Runtime, C: DeserializeOwned>(
1012
app: &AppHandle<R>,
1113
_api: PluginApi<R, C>,
@@ -18,6 +20,8 @@ pub fn init<R: Runtime, C: DeserializeOwned>(
1820
/// You can get an instance of this type via [`NotificationsExt`](crate::NotificationsExt)
1921
pub struct Notifications<R: Runtime>(AppHandle<R>);
2022

23+
// `async` and `Result` mirror the mobile/macOS plugin API so callers can `.await` and `?` uniformly.
24+
#[allow(clippy::unused_async, clippy::unnecessary_wraps)]
2125
impl<R: Runtime> crate::NotificationsBuilder<R> {
2226
pub async fn show(self) -> crate::Result<()> {
2327
let mut notification = imp::Notification::new(self.app.config().identifier.clone());
@@ -42,6 +46,8 @@ impl<R: Runtime> crate::NotificationsBuilder<R> {
4246
}
4347
}
4448

49+
// `async` mirrors the mobile/macOS plugin API so callers can `.await` uniformly.
50+
#[allow(clippy::unused_async)]
4551
impl<R: Runtime> Notifications<R> {
4652
pub fn builder(&self) -> NotificationsBuilder<R> {
4753
NotificationsBuilder::new(self.0.clone())
@@ -181,6 +187,8 @@ mod imp {
181187
}
182188

183189
/// Shows the notification.
190+
// `current_exe()?` returns Result on Windows; Result is kept for that branch.
191+
#[allow(clippy::unnecessary_wraps)]
184192
pub fn show(self) -> crate::Result<()> {
185193
let mut notification = notify_rust::Notification::new();
186194
if let Some(body) = self.body {

src/error.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use serde::{ser::Serializer, Serialize};
22

33
pub type Result<T> = std::result::Result<T, Error>;
44

5-
/// Replica of the tauri::plugin::mobile::ErrorResponse for desktop platforms.
5+
/// Replica of the [`tauri::plugin::mobile::ErrorResponse`] for desktop platforms.
66
#[cfg(desktop)]
77
#[derive(Debug, thiserror::Error, Clone, serde::Deserialize)]
88
pub struct ErrorResponse<T = ()> {
@@ -31,7 +31,7 @@ impl<T> std::fmt::Display for ErrorResponse<T> {
3131
}
3232
}
3333

34-
/// Replica of the tauri::plugin::mobile::PluginInvokeError for desktop platforms.
34+
/// Replica of the [`tauri::plugin::mobile::PluginInvokeError`] for desktop platforms.
3535
#[cfg(desktop)]
3636
#[derive(Debug, thiserror::Error)]
3737
pub enum PluginInvokeError {
@@ -91,7 +91,7 @@ mod tests {
9191
fn test_io_error_display() {
9292
let io_err = io::Error::new(io::ErrorKind::NotFound, "test error");
9393
let err = Error::Io(io_err);
94-
let display_str = format!("{}", err);
94+
let display_str = format!("{err}");
9595
assert!(display_str.contains("test error"));
9696
}
9797

0 commit comments

Comments
 (0)