waterui_cli/platform.rs
1//! Platform abstraction for `WaterUI` CLI
2
3use std::path::PathBuf;
4
5use color_eyre::eyre;
6use target_lexicon::Triple;
7
8use crate::{
9 build::BuildOptions,
10 device::{Artifact, Device},
11 project::Project,
12 toolchain::Toolchain,
13};
14
15/// Build options for the platform
16#[derive(Debug, Clone)]
17/// Configuration options for packaging the application.
18///
19/// This struct contains settings that control how the application
20/// is packaged for distribution across different platforms.
21pub struct PackageOptions {
22 /// Whether to prepare the package for store distribution.
23 ///
24 /// When `true`, the package will be configured for submission to
25 /// official app stores (App Store for iOS/macOS or Play Store for Android).
26 ///
27 /// When `false`, the package will be prepared for direct distribution
28 /// or development purposes.
29 ///
30 /// # Warning
31 ///
32 /// Enable this option only change your packaging format, it does not change your build configuration.
33 /// For a real world distribution build, you may also want to disable `debug` in `BuildOptions`.
34 distribution: bool,
35
36 /// Whether to enable debug mode in the packaged application.
37 ///
38 /// When `true`, the application will include additional debug information
39 /// and logging capabilities to facilitate troubleshooting during development.
40 ///
41 /// When `false`, the application will be optimized for release with
42 /// minimal debug information.
43 ///
44 /// This flag is not conflict with `distribution`, since `distribution` decide the package format,
45 /// while `debug` decide the build configuration.
46 debug: bool,
47}
48
49impl PackageOptions {
50 /// Create new package options
51 #[must_use]
52 pub const fn new(distribution: bool, debug: bool) -> Self {
53 Self {
54 distribution,
55 debug,
56 }
57 }
58
59 /// Whether to package in distribution mode
60 #[must_use]
61 pub const fn is_distribution(&self) -> bool {
62 self.distribution
63 }
64
65 /// Whether to package in debug mode
66 #[must_use]
67 pub const fn is_debug(&self) -> bool {
68 self.debug
69 }
70}
71
72/// Trait representing a specific platform (e.g., Android, iOS, etc.)
73///
74/// Note: `Platform` would never check toolchain since it is the responsibility of the `Toolchain`.
75/// We assume the toolchain is already set up correctly when calling methods of this trait.
76pub trait Platform: Send + Sync {
77 /// The associated toolchain type for this platform.
78 type Toolchain: Toolchain;
79 /// The associated device type for this platform.
80 type Device: Device;
81
82 /// Clean build artifacts for this platform (not include rust build artifacts)
83 fn clean(&self, project: &Project) -> impl Future<Output = eyre::Result<()>> + Send;
84
85 /// Package the project for this platform
86 ///
87 /// Return the path to the packaged file
88 ///
89 /// # Warnings
90 /// You should call `build` before calling this method to ensure the project is built for the platform.
91 fn package(
92 &self,
93 project: &Project,
94 options: PackageOptions,
95 ) -> impl Future<Output = eyre::Result<Artifact>> + Send;
96
97 /// Get the toolchain for this platform
98 fn toolchain(&self) -> Self::Toolchain;
99
100 /// Scan for connected devices for this platform
101 fn scan(&self) -> impl Future<Output = eyre::Result<Vec<Self::Device>>> + Send;
102
103 /// Get the target triple for this platform
104 fn triple(&self) -> Triple;
105
106 /// Build the Rust library for this platform
107 ///
108 /// Warning: This method would build and copy the built library to the appropriate location in the project directory.
109 /// However, it does not handle hot reload library building or management.
110 ///
111 /// Return the target directory path where the built library is located.
112 fn build(
113 &self,
114 project: &Project,
115 options: BuildOptions,
116 ) -> impl Future<Output = eyre::Result<PathBuf>> + Send;
117}