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}