CLI: add --renderer argument (#4320)
* Add --renderer argument to the CLI Signed-off-by: Nico Burns <nico@nicoburns.com> * Make `--platform native` work Signed-off-by: Nico Burns <nico@nicoburns.com> * Emit `krates` error when cargo metadata fails * Reinstate default "desktop" feature for examples * Remove commented 'no platform specified' error Signed-off-by: Nico Burns <nico@nicoburns.com> * use the target tripple and bundle format as the source of truth for the build * resolve renderer and bundle format * add shorthand flags * add headings to the help for shorthands * resolve the renderer from the target triple if it isn't passed * make value after --fullstack optional * convert desktop -> mobile when targeting mobile webview * use the new shorthand flags in the playwright tests * fix clippy * merge fix * cleanup merge conflicts * fix clippy * remove nit * restore platform as a legacy argument * improve help message * vendor openssl on native, pin server_fn * print build errors as warnings * add --desktop arg compat * adjust cli headings * prefer self.is_wasm_or_wasi() --------- Signed-off-by: Nico Burns <nico@nicoburns.com> Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com> Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
This commit is contained in:
28 files changed
+998
-549
No files matched your search
+507
-143
@@ -1,6 +1,484 @@
|
||||
use anyhow::{Context, Result};
|
||||
use clap::{arg, ArgMatches, Args, FromArgMatches};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Display;
|
||||
use std::str::FromStr;
|
||||
use target_lexicon::{Architecture, Environment, OperatingSystem, Triple};
|
||||
|
||||
use crate::Workspace;
|
||||
|
||||
#[derive(
|
||||
Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug, Default,
|
||||
)]
|
||||
#[non_exhaustive]
|
||||
pub(crate) enum TargetAlias {
|
||||
/// Targeting the WASM architecture
|
||||
Wasm,
|
||||
|
||||
/// Targeting macos desktop
|
||||
MacOS,
|
||||
|
||||
/// Targeting windows desktop
|
||||
Windows,
|
||||
|
||||
/// Targeting linux desktop
|
||||
Linux,
|
||||
|
||||
/// Targeting the ios platform
|
||||
///
|
||||
/// Can't work properly if you're not building from an Apple device.
|
||||
Ios,
|
||||
|
||||
/// Targeting the android platform
|
||||
Android,
|
||||
|
||||
/// Targeting the current target
|
||||
Host,
|
||||
|
||||
/// An unknown target platform
|
||||
#[default]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl Args for TargetAlias {
|
||||
fn augment_args(cmd: clap::Command) -> clap::Command {
|
||||
const HELP_HEADING: &str = "Target Alias";
|
||||
cmd.arg(arg!(--wasm "Target the wasm triple").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--macos "Target the macos triple").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--windows "Target the windows triple").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--linux "Target the linux triple").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--ios "Target the ios triple").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--android "Target the android triple").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--host "Target the host triple").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--desktop "Target the host triple").help_heading(HELP_HEADING))
|
||||
.group(
|
||||
clap::ArgGroup::new("target_alias")
|
||||
.args([
|
||||
"wasm", "macos", "windows", "linux", "ios", "android", "host", "host",
|
||||
])
|
||||
.multiple(false)
|
||||
.required(false),
|
||||
)
|
||||
}
|
||||
|
||||
fn augment_args_for_update(cmd: clap::Command) -> clap::Command {
|
||||
Self::augment_args(cmd)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromArgMatches for TargetAlias {
|
||||
fn from_arg_matches(matches: &ArgMatches) -> Result<Self, clap::Error> {
|
||||
if let Some(platform) = matches.get_one::<clap::Id>("target_alias") {
|
||||
match platform.as_str() {
|
||||
"wasm" => Ok(Self::Wasm),
|
||||
"macos" => Ok(Self::MacOS),
|
||||
"windows" => Ok(Self::Windows),
|
||||
"linux" => Ok(Self::Linux),
|
||||
"ios" => Ok(Self::Ios),
|
||||
"android" => Ok(Self::Android),
|
||||
"host" => Ok(Self::Host),
|
||||
_ => Err(clap::Error::raw(
|
||||
clap::error::ErrorKind::InvalidValue,
|
||||
format!("Unknown target alias: {platform}"),
|
||||
)),
|
||||
}
|
||||
} else {
|
||||
Ok(Self::Unknown)
|
||||
}
|
||||
}
|
||||
fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), clap::Error> {
|
||||
*self = Self::from_arg_matches(matches)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TargetAlias {
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Self::MacOS);
|
||||
#[cfg(target_os = "windows")]
|
||||
pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Self::Windows);
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Self::Linux);
|
||||
#[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
|
||||
pub(crate) const TARGET_PLATFORM: Option<Self> = None;
|
||||
|
||||
pub(crate) async fn into_target(self, device: bool, workspace: &Workspace) -> Result<Triple> {
|
||||
match self {
|
||||
// Generally just use the host's triple for native executables unless specified otherwise
|
||||
Self::MacOS | Self::Windows | Self::Linux | Self::Host | Self::Unknown => {
|
||||
Ok(Triple::host())
|
||||
}
|
||||
|
||||
// We currently assume unknown-unknown for web, but we might want to eventually
|
||||
// support emscripten
|
||||
Self::Wasm => Ok("wasm32-unknown-unknown".parse()?),
|
||||
|
||||
// For iOS we should prefer the actual architecture for the simulator, but in lieu of actually
|
||||
// figuring that out, we'll assume aarch64 on m-series and x86_64 otherwise
|
||||
Self::Ios => {
|
||||
// use the host's architecture and sim if --device is passed
|
||||
use target_lexicon::{Architecture, HOST};
|
||||
let triple_str = match HOST.architecture {
|
||||
Architecture::Aarch64(_) if device => "aarch64-apple-ios",
|
||||
Architecture::Aarch64(_) => "aarch64-apple-ios-sim",
|
||||
_ if device => "x86_64-apple-ios",
|
||||
_ => "x86_64-apple-ios",
|
||||
};
|
||||
Ok(triple_str.parse()?)
|
||||
}
|
||||
|
||||
// Same idea with android but we figure out the connected device using adb
|
||||
Self::Android => Ok(workspace
|
||||
.android_tools()?
|
||||
.autodetect_android_device_triple()
|
||||
.await),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn or(self, other: Self) -> Self {
|
||||
if self == Self::Unknown {
|
||||
other
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug, Default,
|
||||
)]
|
||||
pub(crate) struct RendererArg {
|
||||
pub(crate) renderer: Option<Renderer>,
|
||||
}
|
||||
|
||||
impl Args for RendererArg {
|
||||
fn augment_args(cmd: clap::Command) -> clap::Command {
|
||||
const HELP_HEADING: &str = "Renderer";
|
||||
cmd.arg(arg!(--web "Enable the dioxus web renderer").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--webview "Enable the dioxus webview renderer").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--native "Enable the dioxus native renderer").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--server "Enable the dioxus server renderer").help_heading(HELP_HEADING))
|
||||
.arg(arg!(--liveview "Enable the dioxus liveview renderer").help_heading(HELP_HEADING))
|
||||
.group(
|
||||
clap::ArgGroup::new("renderer")
|
||||
.args(["web", "webview", "native", "server", "liveview"])
|
||||
.multiple(false)
|
||||
.required(false),
|
||||
)
|
||||
}
|
||||
|
||||
fn augment_args_for_update(cmd: clap::Command) -> clap::Command {
|
||||
Self::augment_args(cmd)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromArgMatches for RendererArg {
|
||||
fn from_arg_matches(matches: &ArgMatches) -> Result<Self, clap::Error> {
|
||||
if let Some(renderer) = matches.get_one::<clap::Id>("renderer") {
|
||||
match renderer.as_str() {
|
||||
"web" => Ok(Self {
|
||||
renderer: Some(Renderer::Web),
|
||||
}),
|
||||
"webview" => Ok(Self {
|
||||
renderer: Some(Renderer::Webview),
|
||||
}),
|
||||
"native" => Ok(Self {
|
||||
renderer: Some(Renderer::Native),
|
||||
}),
|
||||
"server" => Ok(Self {
|
||||
renderer: Some(Renderer::Server),
|
||||
}),
|
||||
"liveview" => Ok(Self {
|
||||
renderer: Some(Renderer::Liveview),
|
||||
}),
|
||||
_ => Err(clap::Error::raw(
|
||||
clap::error::ErrorKind::InvalidValue,
|
||||
format!("Unknown platform: {renderer}"),
|
||||
)),
|
||||
}
|
||||
} else {
|
||||
Ok(Self { renderer: None })
|
||||
}
|
||||
}
|
||||
|
||||
fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), clap::Error> {
|
||||
*self = Self::from_arg_matches(matches)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RendererArg> for Option<Renderer> {
|
||||
fn from(val: RendererArg) -> Self {
|
||||
val.renderer
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub(crate) enum Renderer {
|
||||
/// Targeting webview renderer
|
||||
Webview,
|
||||
|
||||
/// Targeting native renderer
|
||||
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.
|
||||
Server,
|
||||
|
||||
/// Targeting the static generation platform using SSR and Dioxus-Fullstack
|
||||
Liveview,
|
||||
|
||||
/// Targeting the web renderer
|
||||
Web,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
/// Get the feature name for the platform in the dioxus crate
|
||||
pub(crate) fn feature_name(&self, target: &Triple) -> &str {
|
||||
match self {
|
||||
Renderer::Webview => match (target.environment, target.operating_system) {
|
||||
(Environment::Android, _) | (_, OperatingSystem::IOS(_)) => "mobile",
|
||||
_ => "desktop",
|
||||
},
|
||||
Renderer::Native => "native",
|
||||
Renderer::Server => "server",
|
||||
Renderer::Liveview => "liveview",
|
||||
Renderer::Web => "web",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn autodetect_from_cargo_feature(feature: &str) -> Option<Self> {
|
||||
match feature {
|
||||
"web" => Some(Self::Web),
|
||||
"desktop" | "mobile" => Some(Self::Webview),
|
||||
"native" => Some(Self::Native),
|
||||
"liveview" => Some(Self::Liveview),
|
||||
"server" => Some(Self::Server),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn default_platform(&self) -> TargetAlias {
|
||||
match self {
|
||||
Renderer::Webview | Renderer::Native | Renderer::Server | Renderer::Liveview => {
|
||||
TargetAlias::TARGET_PLATFORM.unwrap()
|
||||
}
|
||||
Renderer::Web => TargetAlias::Wasm,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_target(triple: &Triple) -> Self {
|
||||
match triple.architecture {
|
||||
// Assume any wasm32 or wasm64 target is a web target
|
||||
Architecture::Wasm32 | Architecture::Wasm64 => Self::Web,
|
||||
// Otherwise, assume webview for native targets
|
||||
_ => Self::Webview,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct UnknownRendererError;
|
||||
|
||||
impl std::error::Error for UnknownRendererError {}
|
||||
|
||||
impl std::fmt::Display for UnknownRendererError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Unknown renderer")
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Renderer {
|
||||
type Err = UnknownRendererError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"webview" => Ok(Self::Webview),
|
||||
"native" => Ok(Self::Native),
|
||||
"server" => Ok(Self::Server),
|
||||
"liveview" => Ok(Self::Liveview),
|
||||
"web" => Ok(Self::Web),
|
||||
_ => Err(UnknownRendererError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Renderer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(match self {
|
||||
Renderer::Webview => "webview",
|
||||
Renderer::Native => "native",
|
||||
Renderer::Server => "server",
|
||||
Renderer::Liveview => "liveview",
|
||||
Renderer::Web => "web",
|
||||
})
|
||||
}
|
||||
}
|
||||
#[derive(
|
||||
Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug, Default,
|
||||
)]
|
||||
#[non_exhaustive]
|
||||
pub(crate) enum BundleFormat {
|
||||
/// Targeting the web bundle structure
|
||||
#[serde(rename = "web")]
|
||||
#[default]
|
||||
Web,
|
||||
|
||||
/// Targeting the macos desktop bundle structure
|
||||
#[cfg_attr(target_os = "macos", serde(alias = "desktop"))]
|
||||
#[serde(rename = "macos")]
|
||||
MacOS,
|
||||
|
||||
/// Targeting the windows desktop bundle structure
|
||||
#[cfg_attr(target_os = "windows", serde(alias = "desktop"))]
|
||||
#[serde(rename = "windows")]
|
||||
Windows,
|
||||
|
||||
/// Targeting the linux desktop bundle structure
|
||||
#[cfg_attr(target_os = "linux", serde(alias = "desktop"))]
|
||||
#[serde(rename = "linux")]
|
||||
Linux,
|
||||
|
||||
/// Targeting the server bundle structure (a single binary placed next to the web build)
|
||||
#[serde(rename = "server")]
|
||||
Server,
|
||||
|
||||
/// Targeting the ios bundle structure
|
||||
///
|
||||
/// Can't work properly if you're not building from an Apple device.
|
||||
#[serde(rename = "ios")]
|
||||
Ios,
|
||||
|
||||
/// Targeting the android bundle structure
|
||||
#[serde(rename = "android")]
|
||||
Android,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct UnknownBundleFormatError;
|
||||
|
||||
impl std::error::Error for UnknownBundleFormatError {}
|
||||
|
||||
impl std::fmt::Display for UnknownBundleFormatError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Unknown bundle format")
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for BundleFormat {
|
||||
type Err = UnknownBundleFormatError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"web" => Ok(Self::Web),
|
||||
"macos" => Ok(Self::MacOS),
|
||||
"windows" => Ok(Self::Windows),
|
||||
"linux" => Ok(Self::Linux),
|
||||
"server" => Ok(Self::Server),
|
||||
"ios" => Ok(Self::Ios),
|
||||
"android" => Ok(Self::Android),
|
||||
_ => Err(UnknownBundleFormatError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BundleFormat {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(match self {
|
||||
BundleFormat::Web => "web",
|
||||
BundleFormat::MacOS => "macos",
|
||||
BundleFormat::Windows => "windows",
|
||||
BundleFormat::Linux => "linux",
|
||||
BundleFormat::Server => "server",
|
||||
BundleFormat::Ios => "ios",
|
||||
BundleFormat::Android => "android",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl BundleFormat {
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Self::MacOS);
|
||||
#[cfg(target_os = "windows")]
|
||||
pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Self::Windows);
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) const TARGET_PLATFORM: Option<Self> = Some(Self::Linux);
|
||||
#[cfg(not(any(target_os = "linux", target_os = "windows", target_os = "macos")))]
|
||||
pub(crate) const TARGET_PLATFORM: Option<Self> = None;
|
||||
|
||||
/// Get the name of the folder we need to generate for this platform
|
||||
///
|
||||
/// Note that web and server share the same platform folder since we'll export the web folder as a bundle on its own
|
||||
pub(crate) fn build_folder_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Web => "web",
|
||||
Self::Server => "web",
|
||||
Self::Ios => "ios",
|
||||
Self::Android => "android",
|
||||
Self::Windows => "windows",
|
||||
Self::Linux => "linux",
|
||||
Self::MacOS => "macos",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn profile_name(&self, release: bool) -> String {
|
||||
let base_profile = match self {
|
||||
Self::MacOS | Self::Windows | Self::Linux => "desktop",
|
||||
Self::Web => "wasm",
|
||||
Self::Ios => "ios",
|
||||
Self::Android => "android",
|
||||
Self::Server => "server",
|
||||
};
|
||||
|
||||
let opt_level = if release { "release" } else { "dev" };
|
||||
|
||||
format!("{base_profile}-{opt_level}")
|
||||
}
|
||||
|
||||
pub(crate) fn expected_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Web => "Web",
|
||||
Self::MacOS => "MacOS",
|
||||
Self::Windows => "Windows",
|
||||
Self::Linux => "Linux",
|
||||
Self::Ios => "iOS",
|
||||
Self::Android => "Android",
|
||||
Self::Server => "Server",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_target(target: &Triple, renderer: Option<Renderer>) -> Result<BundleFormat> {
|
||||
match (
|
||||
renderer,
|
||||
target.architecture,
|
||||
target.environment,
|
||||
target.operating_system,
|
||||
) {
|
||||
// The server always uses the server bundle format
|
||||
(Some(Renderer::Server), _, _, _) => Ok(BundleFormat::Server),
|
||||
// The web renderer always uses the web bundle format
|
||||
(Some(Renderer::Web), _, _, _) => Ok(BundleFormat::Web),
|
||||
// Otherwise, guess it based on the target
|
||||
// Assume any wasm32 or wasm64 target is a web target
|
||||
(_, Architecture::Wasm32 | Architecture::Wasm64, _, _) => Ok(BundleFormat::Web),
|
||||
// For native targets, we need to determine the bundle format based on the OS
|
||||
(_, _, Environment::Android, _) => Ok(BundleFormat::Android),
|
||||
(_, _, _, OperatingSystem::IOS(_)) => Ok(BundleFormat::Ios),
|
||||
(_, _, _, OperatingSystem::MacOSX(_) | OperatingSystem::Darwin(_)) => {
|
||||
Ok(BundleFormat::MacOS)
|
||||
}
|
||||
(_, _, _, OperatingSystem::Linux) => Ok(BundleFormat::Linux),
|
||||
(_, _, _, OperatingSystem::Windows) => Ok(BundleFormat::Windows),
|
||||
// If we don't recognize the target, default to desktop
|
||||
_ => BundleFormat::TARGET_PLATFORM.context(
|
||||
"failed to determine bundle format. Try setting the `--bundle` flag manually",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
@@ -18,188 +496,74 @@ use std::str::FromStr;
|
||||
)]
|
||||
#[non_exhaustive]
|
||||
pub(crate) enum Platform {
|
||||
/// Targeting the web platform using WASM
|
||||
/// Alias for `--wasm --web --bundle-format web`
|
||||
#[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
|
||||
/// Alias for `--macos --webview --bundle-format macos`
|
||||
#[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
|
||||
/// Alias for `--windows --webview --bundle-format windows`
|
||||
#[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
|
||||
/// Alias for `--linux --webview --bundle-format linux`
|
||||
#[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.
|
||||
/// Alias for `--ios --webview --bundle-format ios`
|
||||
#[clap(name = "ios")]
|
||||
#[serde(rename = "ios")]
|
||||
Ios,
|
||||
|
||||
/// Targeting the android platform
|
||||
/// Alias for `--android --webview --bundle-format android`
|
||||
#[clap(name = "android")]
|
||||
#[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.
|
||||
/// Alias for `--host --server --bundle-format server`
|
||||
#[clap(name = "server")]
|
||||
#[serde(rename = "server")]
|
||||
Server,
|
||||
|
||||
/// Targeting the static generation platform using SSR and Dioxus-Fullstack
|
||||
/// Alias for `--host --liveview --bundle-format host`
|
||||
#[clap(name = "liveview")]
|
||||
#[serde(rename = "liveview")]
|
||||
Liveview,
|
||||
}
|
||||
|
||||
/// An error that occurs when a platform is not recognized
|
||||
pub(crate) struct UnknownPlatformError;
|
||||
|
||||
impl std::fmt::Display for UnknownPlatformError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Unknown platform")
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Platform {
|
||||
type Err = UnknownPlatformError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"web" => Ok(Self::Web),
|
||||
"macos" => Ok(Self::MacOS),
|
||||
"windows" => Ok(Self::Windows),
|
||||
"linux" => Ok(Self::Linux),
|
||||
"liveview" => Ok(Self::Liveview),
|
||||
"server" => Ok(Self::Server),
|
||||
"ios" => Ok(Self::Ios),
|
||||
"android" => Ok(Self::Android),
|
||||
_ => Err(UnknownPlatformError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Platform {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(match self {
|
||||
Platform::Web => "web",
|
||||
Platform::MacOS => "macos",
|
||||
Platform::Windows => "windows",
|
||||
Platform::Linux => "linux",
|
||||
Platform::Ios => "ios",
|
||||
Platform::Android => "android",
|
||||
Platform::Server => "server",
|
||||
Platform::Liveview => "liveview",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Platform {
|
||||
/// Get the feature name for the platform in the dioxus crate
|
||||
pub(crate) fn feature_name(&self) -> &str {
|
||||
pub(crate) fn into_triple(self) -> (TargetAlias, Renderer, BundleFormat) {
|
||||
match self {
|
||||
Platform::Web => "web",
|
||||
Platform::MacOS => "desktop",
|
||||
Platform::Windows => "desktop",
|
||||
Platform::Linux => "desktop",
|
||||
Platform::Server => "server",
|
||||
Platform::Liveview => "liveview",
|
||||
Platform::Ios => "mobile",
|
||||
Platform::Android => "mobile",
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the name of the folder we need to generate for this platform
|
||||
///
|
||||
/// Note that web and server share the same platform folder since we'll export the web folder as a bundle on its own
|
||||
pub(crate) fn build_folder_name(&self) -> &'static str {
|
||||
match self {
|
||||
Platform::Web => "web",
|
||||
Platform::Server => "web",
|
||||
Platform::Liveview => "liveview",
|
||||
Platform::Ios => "ios",
|
||||
Platform::Android => "android",
|
||||
Platform::Windows => "windows",
|
||||
Platform::Linux => "linux",
|
||||
Platform::MacOS => "macos",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn expected_name(&self) -> &'static str {
|
||||
match self {
|
||||
Platform::Web => "Web",
|
||||
Platform::MacOS => "Desktop MacOS",
|
||||
Platform::Windows => "Desktop Windows",
|
||||
Platform::Linux => "Desktop Linux",
|
||||
Platform::Ios => "Mobile iOS",
|
||||
Platform::Android => "Mobile Android",
|
||||
Platform::Server => "Server",
|
||||
Platform::Liveview => "Liveview",
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
"mobile" => None,
|
||||
"liveview" => Some(Platform::Liveview),
|
||||
"server" => Some(Platform::Server),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn profile_name(&self, release: bool) -> String {
|
||||
let base_profile = match self {
|
||||
Platform::MacOS | Platform::Windows | Platform::Linux => "desktop",
|
||||
Platform::Web => "web",
|
||||
Platform::Ios => "ios",
|
||||
Platform::Android => "android",
|
||||
Platform::Server => "server",
|
||||
Platform::Liveview => "liveview",
|
||||
};
|
||||
|
||||
if release {
|
||||
format!("{}-release", base_profile)
|
||||
} else {
|
||||
format!("{}-dev", base_profile)
|
||||
Platform::Web => (TargetAlias::Wasm, Renderer::Web, BundleFormat::Web),
|
||||
Platform::MacOS => (TargetAlias::MacOS, Renderer::Webview, BundleFormat::MacOS),
|
||||
Platform::Windows => (
|
||||
TargetAlias::Windows,
|
||||
Renderer::Webview,
|
||||
BundleFormat::Windows,
|
||||
),
|
||||
Platform::Linux => (TargetAlias::Linux, Renderer::Webview, BundleFormat::Linux),
|
||||
Platform::Ios => (TargetAlias::Ios, Renderer::Webview, BundleFormat::Ios),
|
||||
Platform::Android => (
|
||||
TargetAlias::Android,
|
||||
Renderer::Webview,
|
||||
BundleFormat::Android,
|
||||
),
|
||||
Platform::Server => (TargetAlias::Host, Renderer::Server, BundleFormat::Server),
|
||||
Platform::Liveview => (
|
||||
TargetAlias::Host,
|
||||
Renderer::Liveview,
|
||||
BundleFormat::TARGET_PLATFORM.unwrap(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user