1
0
Эх сурвалжийг харах

Add --renderer argument to the CLI

Signed-off-by: Nico Burns <nico@nicoburns.com>
Nico Burns 3 өдөр өмнө
parent
commit
7d8c23e5a9

+ 0 - 1
Cargo.toml

@@ -441,7 +441,6 @@ openssl = { version = "0.10", features = ["vendored"] }
 # To make most examples faster to compile, we split out assets and http-related stuff
 # This trims off like 270 dependencies, leading to a significant speedup in compilation time
 [features]
-default = ["desktop"]
 desktop = ["dioxus/desktop"]
 native = ["dioxus/native"]
 liveview = ["dioxus/liveview"]

+ 25 - 11
packages/cli/src/build/request.rs

@@ -316,8 +316,8 @@
 //! - xbuild: <https://github.com/rust-mobile/xbuild/blob/master/xbuild/src/command/build.rs>
 
 use crate::{
-    AndroidTools, BuildContext, DioxusConfig, Error, LinkAction, LinkerFlavor, Platform, Result,
-    RustcArgs, TargetArgs, TraceSrc, WasmBindgen, WasmOptConfig, Workspace,
+    AndroidTools, BuildContext, ClientRenderer, DioxusConfig, Error, LinkAction, LinkerFlavor,
+    Platform, Result, RustcArgs, TargetArgs, TraceSrc, WasmBindgen, WasmOptConfig, Workspace,
     DX_RUSTC_WRAPPER_ENV_VAR,
 };
 use anyhow::Context;
@@ -553,20 +553,25 @@ impl BuildRequest {
         let mut no_default_features = args.no_default_features;
 
         let platform: Platform = match args.platform {
-            Some(platform) => match enabled_platforms.len() {
-                0 => platform,
+            Some(platform_arg) => match enabled_platforms.len() {
+                0 => Platform::from(platform_arg),
 
                 // The user passed --platform XYZ but already has `default = ["ABC"]` in their Cargo.toml or dioxus = { features = ["abc"] }
                 // We want to strip out the default platform and use the one they passed, setting no-default-features
                 _ => {
                     features.extend(Self::platformless_features(main_package));
                     no_default_features = true;
-                    platform
+                    Platform::from(platform_arg)
                 }
             },
-            None if !using_dioxus_explicitly => Platform::autodetect_from_cargo_feature("desktop").unwrap(),
+            None if !using_dioxus_explicitly => Platform::TARGET_PLATFORM.unwrap(),
             None => match enabled_platforms.len() {
-                0 => return Err(anyhow::anyhow!("No platform specified and no platform marked as default in Cargo.toml. Try specifying a platform with `--platform`").into()),
+                0 => match args.renderer {
+                    Some(_) => Platform::TARGET_PLATFORM.unwrap(),
+                    None => Platform::TARGET_PLATFORM.unwrap(),
+                    // TODO: should we always have a default
+                    // None => return Err(anyhow::anyhow!("No platform specified and no platform marked as default in Cargo.toml. Try specifying a platform with `--platform`").into()),
+                },
                 1 => enabled_platforms[0],
                 _ => {
                     return Err(anyhow::anyhow!(
@@ -579,7 +584,11 @@ impl BuildRequest {
 
         // Add any features required to turn on the client
         if using_dioxus_explicitly {
-            features.push(Self::feature_for_platform(main_package, platform));
+            features.push(Self::feature_for_platform_and_renderer(
+                main_package,
+                platform,
+                args.renderer,
+            ));
         }
 
         // Set the profile of the build if it's not already set
@@ -2824,9 +2833,13 @@ impl BuildRequest {
     }
 
     /// Get the features required to build for the given platform
-    fn feature_for_platform(package: &krates::cm::Package, platform: Platform) -> String {
+    fn feature_for_platform_and_renderer(
+        package: &krates::cm::Package,
+        platform: Platform,
+        renderer: Option<ClientRenderer>,
+    ) -> String {
         // Try to find the feature that activates the dioxus feature for the given platform
-        let dioxus_feature = platform.feature_name();
+        let dioxus_feature = platform.feature_name(renderer);
 
         let res = package.features.iter().find_map(|(key, features)| {
             // if the feature is just the name of the platform, we use that
@@ -2852,7 +2865,7 @@ impl BuildRequest {
         });
 
         res.unwrap_or_else(|| {
-            let fallback = format!("dioxus/{}", platform.feature_name()) ;
+            let fallback = format!("dioxus/{}", dioxus_feature) ;
             tracing::debug!(
                 "Could not find explicit feature for platform {platform}, passing `fallback` instead"
             );
@@ -2910,6 +2923,7 @@ impl BuildRequest {
         };
 
         // we only trace features 1 level deep..
+        // TODO: trace all enabled features, not just default features
         for feature in default.iter() {
             // If the user directly specified a platform we can just use that.
             if feature.starts_with("dioxus/") {

+ 2 - 2
packages/cli/src/cli/build.rs

@@ -1,5 +1,5 @@
 use crate::{cli::*, AppBuilder, BuildRequest, Workspace};
-use crate::{BuildMode, Platform};
+use crate::{BuildMode, Platform, PlatformArg};
 
 use super::target::TargetArgs;
 
@@ -120,7 +120,7 @@ impl CommandWithPlatformOverrides<BuildArgs> {
             let main_target = client.main_target.clone();
             let mut server_args = server_args.clone();
             // The platform in the server build is always set to Server
-            server_args.platform = Some(Platform::Server);
+            server_args.platform = Some(PlatformArg::Server);
             server =
                 Some(BuildRequest::new(&server_args, Some(main_target), workspace.clone()).await?);
         }

+ 7 - 2
packages/cli/src/cli/target.rs

@@ -1,5 +1,6 @@
 use crate::cli::*;
-use crate::Platform;
+use crate::ClientRenderer;
+use crate::PlatformArg;
 use target_lexicon::Triple;
 
 /// A single target to build for
@@ -7,7 +8,11 @@ use target_lexicon::Triple;
 pub(crate) struct TargetArgs {
     /// Build platform: support Web & Desktop [default: "default_platform"]
     #[clap(long, value_enum)]
-    pub(crate) platform: Option<Platform>,
+    pub(crate) platform: Option<PlatformArg>,
+
+    /// Build renderer: support Webview and Native [default: "webview"]
+    #[clap(long, value_enum)]
+    pub(crate) renderer: Option<ClientRenderer>,
 
     /// Build in release mode [default: false]
     #[clap(long, short)]

+ 118 - 40
packages/cli/src/platform.rs

@@ -17,56 +17,118 @@ use std::str::FromStr;
     clap::ValueEnum,
 )]
 #[non_exhaustive]
-pub(crate) enum Platform {
+pub(crate) enum PlatformArg {
     /// Targeting the web platform using WASM
     #[clap(name = "web")]
-    #[serde(rename = "web")]
     #[default]
     Web,
 
     /// Targeting macos desktop
-    /// When running on macos, you can also use `--platform desktop` to build for the desktop
-    #[cfg_attr(target_os = "macos", clap(alias = "desktop"))]
     #[clap(name = "macos")]
-    #[serde(rename = "macos")]
     MacOS,
 
     /// Targeting windows desktop
-    /// When running on windows, you can also use `--platform desktop` to build for the desktop
-    #[cfg_attr(target_os = "windows", clap(alias = "desktop"))]
     #[clap(name = "windows")]
-    #[serde(rename = "windows")]
     Windows,
 
     /// Targeting linux desktop
-    /// When running on linux, you can also use `--platform desktop` to build for the desktop
-    #[cfg_attr(target_os = "linux", clap(alias = "desktop"))]
     #[clap(name = "linux")]
-    #[serde(rename = "linux")]
     Linux,
 
     /// Targeting the ios platform
     ///
     /// Can't work properly if you're not building from an Apple device.
     #[clap(name = "ios")]
-    #[serde(rename = "ios")]
     Ios,
 
     /// Targeting the android platform
     #[clap(name = "android")]
-    #[serde(rename = "android")]
     Android,
 
+    /// Targeting the current platform with the "desktop" renderer
+    #[clap(name = "desktop")]
+    Desktop,
+
+    /// Targeting the current platform with the "native" renderer
+    #[clap(name = "native")]
+    Native,
+
     /// Targeting the server platform using Axum and Dioxus-Fullstack
     ///
     /// This is implicitly passed if `fullstack` is enabled as a feature. Using this variant simply
     /// means you're only building the server variant without the `.wasm` to serve.
     #[clap(name = "server")]
-    #[serde(rename = "server")]
     Server,
 
     /// Targeting the static generation platform using SSR and Dioxus-Fullstack
     #[clap(name = "liveview")]
+    Liveview,
+}
+
+#[derive(
+    Copy,
+    Clone,
+    Hash,
+    PartialEq,
+    Eq,
+    PartialOrd,
+    Ord,
+    Serialize,
+    Deserialize,
+    Debug,
+    clap::ValueEnum,
+)]
+#[non_exhaustive]
+pub(crate) enum ClientRenderer {
+    /// Targeting webview renderer
+    #[serde(rename = "webview")]
+    Webview,
+
+    /// Targeting native renderer
+    #[serde(rename = "native")]
+    Native,
+}
+
+#[derive(
+    Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug, Default,
+)]
+#[non_exhaustive]
+pub(crate) enum Platform {
+    /// Targeting the web platform using WASM
+    #[serde(rename = "web")]
+    #[default]
+    Web,
+
+    /// Targeting macos desktop
+    #[serde(rename = "macos")]
+    MacOS,
+
+    /// Targeting windows desktop
+    #[serde(rename = "windows")]
+    Windows,
+
+    /// Targeting linux desktop
+    #[serde(rename = "linux")]
+    Linux,
+
+    /// Targeting the ios platform
+    ///
+    /// Can't work properly if you're not building from an Apple device.
+    #[serde(rename = "ios")]
+    Ios,
+
+    /// Targeting the android platform
+    #[serde(rename = "android")]
+    Android,
+
+    /// Targeting the server platform using Axum and Dioxus-Fullstack
+    ///
+    /// This is implicitly passed if `fullstack` is enabled as a feature. Using this variant simply
+    /// means you're only building the server variant without the `.wasm` to serve.
+    #[serde(rename = "server")]
+    Server,
+
+    /// Targeting the static generation platform using SSR and Dioxus-Fullstack
     #[serde(rename = "liveview")]
     Liveview,
 }
@@ -113,18 +175,51 @@ impl Display for Platform {
     }
 }
 
+impl From<PlatformArg> for Platform {
+    fn from(value: PlatformArg) -> Self {
+        match value {
+            // Most values map 1:1
+            PlatformArg::Web => Platform::Web,
+            PlatformArg::MacOS => Platform::MacOS,
+            PlatformArg::Windows => Platform::Windows,
+            PlatformArg::Linux => Platform::Linux,
+            PlatformArg::Ios => Platform::Ios,
+            PlatformArg::Android => Platform::Android,
+            PlatformArg::Server => Platform::Server,
+            PlatformArg::Liveview => Platform::Liveview,
+
+            // The alias arguments
+            PlatformArg::Desktop | PlatformArg::Native => {
+                Platform::TARGET_PLATFORM.unwrap()
+            }
+        }
+    }
+}
+
 impl Platform {
-    /// Get the feature name for the platform in the dioxus crate
-    pub(crate) fn feature_name(&self) -> &str {
+    #[cfg(target_os = "macos")]
+    pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Platform::MacOS);
+    #[cfg(target_os = "windows")]
+    pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Platform::Windows);
+    #[cfg(target_os = "linux")]
+    pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Platform::Linux);
+    #[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
+    pub(crate) const TARGET_PLATFORM: Option<Self> = None;
+
+    // /// Get the feature name for the platform in the dioxus crate
+    pub(crate) fn feature_name(&self, renderer: Option<ClientRenderer>) -> &str {
         match self {
             Platform::Web => "web",
-            Platform::MacOS => "desktop",
-            Platform::Windows => "desktop",
-            Platform::Linux => "desktop",
+            Platform::MacOS | Platform::Windows | Platform::Linux => match renderer {
+                None | Some(ClientRenderer::Webview) => "desktop",
+                Some(ClientRenderer::Native) => "native",
+            },
+            Platform::Ios | Platform::Android => match renderer {
+                None | Some(ClientRenderer::Webview) => "mobile",
+                Some(ClientRenderer::Native) => "native",
+            },
             Platform::Server => "server",
             Platform::Liveview => "liveview",
-            Platform::Ios => "mobile",
-            Platform::Android => "mobile",
         }
     }
 
@@ -160,25 +255,7 @@ impl Platform {
     pub(crate) fn autodetect_from_cargo_feature(feature: &str) -> Option<Self> {
         match feature {
             "web" => Some(Platform::Web),
-            "desktop" | "native" => {
-                #[cfg(target_os = "macos")]
-                {
-                    Some(Platform::MacOS)
-                }
-                #[cfg(target_os = "windows")]
-                {
-                    Some(Platform::Windows)
-                }
-                #[cfg(target_os = "linux")]
-                {
-                    Some(Platform::Linux)
-                }
-                // Possibly need a something for freebsd? Maybe default to Linux?
-                #[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
-                {
-                    None
-                }
-            }
+            "desktop" | "native" => Platform::TARGET_PLATFORM,
             "mobile" => None,
             "liveview" => Some(Platform::Liveview),
             "server" => Some(Platform::Server),
@@ -188,6 +265,7 @@ impl Platform {
 
     pub(crate) fn profile_name(&self, release: bool) -> String {
         let base_profile = match self {
+            // TODO: add native profile?
             Platform::MacOS | Platform::Windows | Platform::Linux => "desktop",
             Platform::Web => "web",
             Platform::Ios => "ios",