Make desktop fullstack work with the CLI (#2862)
* Make desktop fullstack work with the CLI * Simplify desktop fullstack example * move the profiles to the workspace
This commit is contained in:
1 parent
6a46a66c9a
commit
5a7a91323a
23 files changed
+239
-259
No files matched your search
@@ -231,7 +231,7 @@ impl BuildRequest {
|
||||
Ok(Some(assets))
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.map_err(|e| anyhow::anyhow!(e))?
|
||||
}
|
||||
|
||||
pub fn copy_assets_dir(&self) -> anyhow::Result<()> {
|
||||
@@ -257,6 +257,7 @@ impl BuildRequest {
|
||||
match self.build_arguments.platform {
|
||||
Some(Platform::Fullstack | Platform::StaticGeneration) => match self.target_platform {
|
||||
TargetPlatform::Web => out_dir.join("public"),
|
||||
TargetPlatform::Desktop => out_dir.join("desktop"),
|
||||
_ => out_dir,
|
||||
},
|
||||
_ => out_dir,
|
||||
|
||||
@@ -1,41 +1,60 @@
|
||||
use toml_edit::Item;
|
||||
|
||||
use crate::builder::Build;
|
||||
use crate::dioxus_crate::DioxusCrate;
|
||||
|
||||
use crate::builder::BuildRequest;
|
||||
use std::path::PathBuf;
|
||||
use std::io::Write;
|
||||
|
||||
use super::TargetPlatform;
|
||||
|
||||
static CLIENT_RUST_FLAGS: &[&str] = &["-Cdebuginfo=none", "-Cstrip=debuginfo"];
|
||||
static CLIENT_PROFILE: &str = "dioxus-client";
|
||||
static SERVER_PROFILE: &str = "dioxus-server";
|
||||
|
||||
// The `opt-level=2` increases build times, but can noticeably decrease time
|
||||
// between saving changes and being able to interact with an app. The "overall"
|
||||
// time difference (between having and not having the optimization) can be
|
||||
// almost imperceptible (~1 s) but also can be very noticeable (~6 s) — depends
|
||||
// on setup (hardware, OS, browser, idle load).
|
||||
static SERVER_RUST_FLAGS: &[&str] = &["-O"];
|
||||
static DEBUG_RUST_FLAG: &str = "-Cdebug-assertions";
|
||||
// Find or create the client and server profiles in the .cargo/config.toml file
|
||||
fn initialize_profiles(config: &DioxusCrate) -> crate::Result<()> {
|
||||
let config_path = config.workspace_dir().join(".cargo/config.toml");
|
||||
let mut config = match std::fs::read_to_string(&config_path) {
|
||||
Ok(config) => config.parse::<toml_edit::DocumentMut>().map_err(|e| {
|
||||
crate::Error::Other(anyhow::anyhow!("Failed to parse .cargo/config.toml: {}", e))
|
||||
})?,
|
||||
Err(_) => Default::default(),
|
||||
};
|
||||
|
||||
fn add_debug_rust_flags(build: &Build, flags: &mut Vec<String>) {
|
||||
if !build.release {
|
||||
flags.push(DEBUG_RUST_FLAG.to_string());
|
||||
}
|
||||
}
|
||||
if let Item::Table(table) = config
|
||||
.as_table_mut()
|
||||
.entry("profile")
|
||||
.or_insert(Item::Table(Default::default()))
|
||||
{
|
||||
if let toml_edit::Entry::Vacant(entry) = table.entry(CLIENT_PROFILE) {
|
||||
let mut client = toml_edit::Table::new();
|
||||
client.insert("inherits", Item::Value("dev".into()));
|
||||
client.insert("opt-level", Item::Value(2.into()));
|
||||
entry.insert(Item::Table(client));
|
||||
}
|
||||
|
||||
fn fullstack_rust_flags(build: &Build, base_flags: &[&str]) -> Vec<String> {
|
||||
// If we are forcing debug mode, don't add any debug flags
|
||||
if build.force_debug {
|
||||
return Default::default();
|
||||
if let toml_edit::Entry::Vacant(entry) = table.entry(SERVER_PROFILE) {
|
||||
let mut server = toml_edit::Table::new();
|
||||
server.insert("inherits", Item::Value("dev".into()));
|
||||
server.insert("opt-level", Item::Value(2.into()));
|
||||
entry.insert(Item::Table(server));
|
||||
}
|
||||
}
|
||||
|
||||
let mut rust_flags = base_flags.iter().map(ToString::to_string).collect();
|
||||
add_debug_rust_flags(build, &mut rust_flags);
|
||||
rust_flags
|
||||
}
|
||||
// Write the config back to the file
|
||||
if let Some(parent) = config_path.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
let file = std::fs::File::create(config_path)?;
|
||||
let mut buf_writer = std::io::BufWriter::new(file);
|
||||
write!(buf_writer, "{}", config)?;
|
||||
|
||||
// Fullstack builds run the server and client builds parallel by default
|
||||
// To make them run in parallel, we need to set up different target directories for the server and client within /.dioxus
|
||||
fn get_target_directory(build: &Build, target: PathBuf) -> Option<PathBuf> {
|
||||
(!build.force_sequential).then_some(target)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl BuildRequest {
|
||||
@@ -43,63 +62,67 @@ impl BuildRequest {
|
||||
config: DioxusCrate,
|
||||
build_arguments: Build,
|
||||
serve: bool,
|
||||
) -> Vec<Self> {
|
||||
vec![
|
||||
) -> Result<Vec<Self>, crate::Error> {
|
||||
initialize_profiles(&config)?;
|
||||
|
||||
Ok(vec![
|
||||
Self::new_client(serve, &config, &build_arguments),
|
||||
Self::new_server(serve, &config, &build_arguments),
|
||||
]
|
||||
])
|
||||
}
|
||||
|
||||
fn new_with_target_directory_rust_flags_and_features(
|
||||
serve: bool,
|
||||
config: &DioxusCrate,
|
||||
build: &Build,
|
||||
target_directory: PathBuf,
|
||||
rust_flags: &[&str],
|
||||
feature: String,
|
||||
feature: Option<String>,
|
||||
target_platform: TargetPlatform,
|
||||
) -> Self {
|
||||
let config = config.clone();
|
||||
let mut build = build.clone();
|
||||
// Set the target directory we are building the server in
|
||||
let target_dir = get_target_directory(&build, target_directory);
|
||||
// Add the server feature to the features we pass to the build
|
||||
build.target_args.features.push(feature);
|
||||
if let Some(feature) = feature {
|
||||
build.target_args.features.push(feature);
|
||||
}
|
||||
|
||||
// Add the server flags to the build arguments
|
||||
let rust_flags = fullstack_rust_flags(&build, rust_flags);
|
||||
|
||||
Self {
|
||||
serve,
|
||||
build_arguments: build.clone(),
|
||||
dioxus_crate: config,
|
||||
rust_flags,
|
||||
target_dir,
|
||||
rust_flags: Default::default(),
|
||||
target_dir: None,
|
||||
target_platform,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_server(serve: bool, config: &DioxusCrate, build: &Build) -> Self {
|
||||
let mut build = build.clone();
|
||||
if build.profile.is_none() {
|
||||
build.profile = Some(CLIENT_PROFILE.to_string());
|
||||
}
|
||||
let client_feature = build.auto_detect_server_feature(config);
|
||||
Self::new_with_target_directory_rust_flags_and_features(
|
||||
serve,
|
||||
config,
|
||||
build,
|
||||
config.server_target_dir(),
|
||||
SERVER_RUST_FLAGS,
|
||||
build.target_args.server_feature.clone(),
|
||||
&build,
|
||||
build.target_args.server_feature.clone().or(client_feature),
|
||||
TargetPlatform::Server,
|
||||
)
|
||||
}
|
||||
|
||||
fn new_client(serve: bool, config: &DioxusCrate, build: &Build) -> Self {
|
||||
let mut build = build.clone();
|
||||
if build.profile.is_none() {
|
||||
build.profile = Some(SERVER_PROFILE.to_string());
|
||||
}
|
||||
let (client_feature, client_platform) = build.auto_detect_client_platform(config);
|
||||
Self::new_with_target_directory_rust_flags_and_features(
|
||||
serve,
|
||||
config,
|
||||
build,
|
||||
config.client_target_dir(),
|
||||
CLIENT_RUST_FLAGS,
|
||||
build.target_args.client_feature.clone(),
|
||||
TargetPlatform::Web,
|
||||
&build,
|
||||
build.target_args.client_feature.clone().or(client_feature),
|
||||
client_platform,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ use dioxus_cli_config::{Platform, RuntimeCLIArguments};
|
||||
use futures_util::stream::select_all;
|
||||
use futures_util::StreamExt;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
use std::{path::PathBuf, process::Stdio};
|
||||
use tokio::process::{Child, Command};
|
||||
|
||||
@@ -29,6 +30,20 @@ pub enum TargetPlatform {
|
||||
Liveview,
|
||||
}
|
||||
|
||||
impl FromStr for TargetPlatform {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"web" => Ok(Self::Web),
|
||||
"desktop" => Ok(Self::Desktop),
|
||||
"axum" | "server" => Ok(Self::Server),
|
||||
"liveview" => Ok(Self::Liveview),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for TargetPlatform {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@@ -62,7 +77,7 @@ impl BuildRequest {
|
||||
serve: bool,
|
||||
dioxus_crate: &DioxusCrate,
|
||||
build_arguments: impl Into<Build>,
|
||||
) -> Vec<Self> {
|
||||
) -> crate::Result<Vec<Self>> {
|
||||
let build_arguments = build_arguments.into();
|
||||
let platform = build_arguments.platform();
|
||||
let single_platform = |platform| {
|
||||
@@ -76,15 +91,15 @@ impl BuildRequest {
|
||||
target_dir: Default::default(),
|
||||
}]
|
||||
};
|
||||
match platform {
|
||||
Platform::Web => single_platform(TargetPlatform::Web),
|
||||
Ok(match platform {
|
||||
Platform::Liveview => single_platform(TargetPlatform::Liveview),
|
||||
Platform::Web => single_platform(TargetPlatform::Web),
|
||||
Platform::Desktop => single_platform(TargetPlatform::Desktop),
|
||||
Platform::StaticGeneration | Platform::Fullstack => {
|
||||
Self::new_fullstack(dioxus_crate.clone(), build_arguments, serve)
|
||||
Self::new_fullstack(dioxus_crate.clone(), build_arguments, serve)?
|
||||
}
|
||||
_ => unimplemented!("Unknown platform: {platform:?}"),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) async fn build_all_parallel(
|
||||
|
||||
Reference in new issue
Block a user