platform.rs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. use serde::{Deserialize, Serialize};
  2. use std::fmt::Display;
  3. use std::str::FromStr;
  4. #[derive(
  5. Copy,
  6. Clone,
  7. Hash,
  8. PartialEq,
  9. Eq,
  10. PartialOrd,
  11. Ord,
  12. Serialize,
  13. Deserialize,
  14. Debug,
  15. Default,
  16. clap::ValueEnum,
  17. )]
  18. #[non_exhaustive]
  19. pub(crate) enum PlatformArg {
  20. /// Targeting the web platform using WASM
  21. #[clap(name = "web")]
  22. #[default]
  23. Web,
  24. /// Targeting macos desktop
  25. #[clap(name = "macos")]
  26. MacOS,
  27. /// Targeting windows desktop
  28. #[clap(name = "windows")]
  29. Windows,
  30. /// Targeting linux desktop
  31. #[clap(name = "linux")]
  32. Linux,
  33. /// Targeting the ios platform
  34. ///
  35. /// Can't work properly if you're not building from an Apple device.
  36. #[clap(name = "ios")]
  37. Ios,
  38. /// Targeting the android platform
  39. #[clap(name = "android")]
  40. Android,
  41. /// Targeting the current platform with the "desktop" renderer
  42. #[clap(name = "desktop")]
  43. Desktop,
  44. /// Targeting the current platform with the "native" renderer
  45. #[clap(name = "native")]
  46. Native,
  47. /// Targeting the server platform using Axum and Dioxus-Fullstack
  48. ///
  49. /// This is implicitly passed if `fullstack` is enabled as a feature. Using this variant simply
  50. /// means you're only building the server variant without the `.wasm` to serve.
  51. #[clap(name = "server")]
  52. Server,
  53. /// Targeting the static generation platform using SSR and Dioxus-Fullstack
  54. #[clap(name = "liveview")]
  55. Liveview,
  56. }
  57. #[derive(
  58. Copy,
  59. Clone,
  60. Hash,
  61. PartialEq,
  62. Eq,
  63. PartialOrd,
  64. Ord,
  65. Serialize,
  66. Deserialize,
  67. Debug,
  68. clap::ValueEnum,
  69. )]
  70. #[non_exhaustive]
  71. pub(crate) enum ClientRenderer {
  72. /// Targeting webview renderer
  73. #[serde(rename = "webview")]
  74. Webview,
  75. /// Targeting native renderer
  76. #[serde(rename = "native")]
  77. Native,
  78. }
  79. #[derive(
  80. Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug, Default,
  81. )]
  82. #[non_exhaustive]
  83. pub(crate) enum Platform {
  84. /// Targeting the web platform using WASM
  85. #[serde(rename = "web")]
  86. #[default]
  87. Web,
  88. /// Targeting macos desktop
  89. #[serde(rename = "macos")]
  90. MacOS,
  91. /// Targeting windows desktop
  92. #[serde(rename = "windows")]
  93. Windows,
  94. /// Targeting linux desktop
  95. #[serde(rename = "linux")]
  96. Linux,
  97. /// Targeting the ios platform
  98. ///
  99. /// Can't work properly if you're not building from an Apple device.
  100. #[serde(rename = "ios")]
  101. Ios,
  102. /// Targeting the android platform
  103. #[serde(rename = "android")]
  104. Android,
  105. /// Targeting the server platform using Axum and Dioxus-Fullstack
  106. ///
  107. /// This is implicitly passed if `fullstack` is enabled as a feature. Using this variant simply
  108. /// means you're only building the server variant without the `.wasm` to serve.
  109. #[serde(rename = "server")]
  110. Server,
  111. /// Targeting the static generation platform using SSR and Dioxus-Fullstack
  112. #[serde(rename = "liveview")]
  113. Liveview,
  114. }
  115. /// An error that occurs when a platform is not recognized
  116. pub(crate) struct UnknownPlatformError;
  117. impl std::fmt::Display for UnknownPlatformError {
  118. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  119. write!(f, "Unknown platform")
  120. }
  121. }
  122. impl FromStr for Platform {
  123. type Err = UnknownPlatformError;
  124. fn from_str(s: &str) -> Result<Self, Self::Err> {
  125. match s {
  126. "web" => Ok(Self::Web),
  127. "macos" => Ok(Self::MacOS),
  128. "windows" => Ok(Self::Windows),
  129. "linux" => Ok(Self::Linux),
  130. "liveview" => Ok(Self::Liveview),
  131. "server" => Ok(Self::Server),
  132. "ios" => Ok(Self::Ios),
  133. "android" => Ok(Self::Android),
  134. _ => Err(UnknownPlatformError),
  135. }
  136. }
  137. }
  138. impl Display for Platform {
  139. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  140. f.write_str(match self {
  141. Platform::Web => "web",
  142. Platform::MacOS => "macos",
  143. Platform::Windows => "windows",
  144. Platform::Linux => "linux",
  145. Platform::Ios => "ios",
  146. Platform::Android => "android",
  147. Platform::Server => "server",
  148. Platform::Liveview => "liveview",
  149. })
  150. }
  151. }
  152. impl From<PlatformArg> for Platform {
  153. fn from(value: PlatformArg) -> Self {
  154. match value {
  155. // Most values map 1:1
  156. PlatformArg::Web => Platform::Web,
  157. PlatformArg::MacOS => Platform::MacOS,
  158. PlatformArg::Windows => Platform::Windows,
  159. PlatformArg::Linux => Platform::Linux,
  160. PlatformArg::Ios => Platform::Ios,
  161. PlatformArg::Android => Platform::Android,
  162. PlatformArg::Server => Platform::Server,
  163. PlatformArg::Liveview => Platform::Liveview,
  164. // The alias arguments
  165. PlatformArg::Desktop | PlatformArg::Native => {
  166. Platform::TARGET_PLATFORM.unwrap()
  167. }
  168. }
  169. }
  170. }
  171. impl Platform {
  172. #[cfg(target_os = "macos")]
  173. pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Platform::MacOS);
  174. #[cfg(target_os = "windows")]
  175. pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Platform::Windows);
  176. #[cfg(target_os = "linux")]
  177. pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Platform::Linux);
  178. #[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
  179. pub(crate) const TARGET_PLATFORM: Option<Self> = None;
  180. // /// Get the feature name for the platform in the dioxus crate
  181. pub(crate) fn feature_name(&self, renderer: Option<ClientRenderer>) -> &str {
  182. match self {
  183. Platform::Web => "web",
  184. Platform::MacOS | Platform::Windows | Platform::Linux => match renderer {
  185. None | Some(ClientRenderer::Webview) => "desktop",
  186. Some(ClientRenderer::Native) => "native",
  187. },
  188. Platform::Ios | Platform::Android => match renderer {
  189. None | Some(ClientRenderer::Webview) => "mobile",
  190. Some(ClientRenderer::Native) => "native",
  191. },
  192. Platform::Server => "server",
  193. Platform::Liveview => "liveview",
  194. }
  195. }
  196. /// Get the name of the folder we need to generate for this platform
  197. ///
  198. /// Note that web and server share the same platform folder since we'll export the web folder as a bundle on its own
  199. pub(crate) fn build_folder_name(&self) -> &'static str {
  200. match self {
  201. Platform::Web => "web",
  202. Platform::Server => "web",
  203. Platform::Liveview => "liveview",
  204. Platform::Ios => "ios",
  205. Platform::Android => "android",
  206. Platform::Windows => "windows",
  207. Platform::Linux => "linux",
  208. Platform::MacOS => "macos",
  209. }
  210. }
  211. pub(crate) fn expected_name(&self) -> &'static str {
  212. match self {
  213. Platform::Web => "Web",
  214. Platform::MacOS => "Desktop MacOS",
  215. Platform::Windows => "Desktop Windows",
  216. Platform::Linux => "Desktop Linux",
  217. Platform::Ios => "Mobile iOS",
  218. Platform::Android => "Mobile Android",
  219. Platform::Server => "Server",
  220. Platform::Liveview => "Liveview",
  221. }
  222. }
  223. pub(crate) fn autodetect_from_cargo_feature(feature: &str) -> Option<Self> {
  224. match feature {
  225. "web" => Some(Platform::Web),
  226. "desktop" | "native" => Platform::TARGET_PLATFORM,
  227. "mobile" => None,
  228. "liveview" => Some(Platform::Liveview),
  229. "server" => Some(Platform::Server),
  230. _ => None,
  231. }
  232. }
  233. pub(crate) fn profile_name(&self, release: bool) -> String {
  234. let base_profile = match self {
  235. // TODO: add native profile?
  236. Platform::MacOS | Platform::Windows | Platform::Linux => "desktop",
  237. Platform::Web => "web",
  238. Platform::Ios => "ios",
  239. Platform::Android => "android",
  240. Platform::Server => "server",
  241. Platform::Liveview => "liveview",
  242. };
  243. if release {
  244. format!("{}-release", base_profile)
  245. } else {
  246. format!("{}-dev", base_profile)
  247. }
  248. }
  249. }