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
@@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
styles::{GLOW_STYLE, LINK_STYLE},
|
||||
AppBuilder, BuildId, BuildMode, BuilderUpdate, Platform, Result, ServeArgs, TraceController,
|
||||
AppBuilder, BuildId, BuildMode, BuilderUpdate, BundleFormat, Result, ServeArgs,
|
||||
TraceController,
|
||||
};
|
||||
|
||||
mod ansi_buffer;
|
||||
@@ -122,15 +123,15 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
|
||||
// Received a message from the devtools server - currently we only use this for
|
||||
// logging, so we just forward it the tui
|
||||
ServeUpdate::WsMessage { msg, platform } => {
|
||||
screen.push_ws_message(platform, &msg);
|
||||
ServeUpdate::WsMessage { msg, bundle } => {
|
||||
screen.push_ws_message(bundle, &msg);
|
||||
}
|
||||
|
||||
// Wait for logs from the build engine
|
||||
// These will cause us to update the screen
|
||||
// We also can check the status of the builds here in case we have multiple ongoing builds
|
||||
ServeUpdate::BuilderUpdate { id, update } => {
|
||||
let platform = builder.get_build(id).unwrap().build.platform;
|
||||
let bundle_format = builder.get_build(id).unwrap().build.bundle;
|
||||
|
||||
// Queue any logs to be printed if need be
|
||||
screen.new_build_update(&update);
|
||||
@@ -147,14 +148,14 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
stage: BuildStage::Failed,
|
||||
} => {
|
||||
if exit_on_error {
|
||||
bail!("Build failed for platform: {platform}");
|
||||
bail!("Build failed for platform: {bundle_format}");
|
||||
}
|
||||
}
|
||||
BuilderUpdate::Progress {
|
||||
stage: BuildStage::Aborted,
|
||||
} => {
|
||||
if exit_on_error {
|
||||
bail!("Build aborted for platform: {platform}");
|
||||
bail!("Build aborted for platform: {bundle_format}");
|
||||
}
|
||||
}
|
||||
BuilderUpdate::Progress { .. } => {}
|
||||
@@ -206,22 +207,24 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
}
|
||||
},
|
||||
BuilderUpdate::StdoutReceived { msg } => {
|
||||
screen.push_stdio(platform, msg, tracing::Level::INFO);
|
||||
screen.push_stdio(bundle_format, msg, tracing::Level::INFO);
|
||||
}
|
||||
BuilderUpdate::StderrReceived { msg } => {
|
||||
screen.push_stdio(platform, msg, tracing::Level::ERROR);
|
||||
screen.push_stdio(bundle_format, msg, tracing::Level::ERROR);
|
||||
}
|
||||
BuilderUpdate::ProcessExited { status } => {
|
||||
if status.success() {
|
||||
tracing::info!(
|
||||
r#"Application [{platform}] exited gracefully.
|
||||
r#"Application [{bundle_format}] exited gracefully.
|
||||
• To restart the app, press `r` to rebuild or `o` to open
|
||||
• To exit the server, press `ctrl+c`"#
|
||||
);
|
||||
} else {
|
||||
tracing::error!("Application [{platform}] exited with error: {status}");
|
||||
tracing::error!(
|
||||
"Application [{bundle_format}] exited with error: {status}"
|
||||
);
|
||||
if exit_on_error {
|
||||
bail!("Application [{platform}] exited with error: {status}");
|
||||
bail!("Application [{bundle_format}] exited with error: {status}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,7 +244,7 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
}
|
||||
|
||||
ServeUpdate::OpenApp => match builder.use_hotpatch_engine {
|
||||
true if !matches!(builder.client.build.platform, Platform::Web) => {
|
||||
true if !matches!(builder.client.build.bundle, BundleFormat::Web) => {
|
||||
tracing::warn!(
|
||||
"Opening a native app with hotpatching enabled requires a full rebuild..."
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
serve::{ansi_buffer::ansi_string_to_line, ServeUpdate, WebServer},
|
||||
BuildId, BuildStage, BuilderUpdate, Platform, TraceContent, TraceMsg, TraceSrc,
|
||||
BuildId, BuildStage, BuilderUpdate, BundleFormat, TraceContent, TraceMsg, TraceSrc,
|
||||
};
|
||||
use cargo_metadata::diagnostic::Diagnostic;
|
||||
use crossterm::{
|
||||
@@ -316,12 +316,12 @@ impl Output {
|
||||
/// Add a message from stderr to the logs
|
||||
/// This will queue the stderr message as a TraceMsg and print it on the next render
|
||||
/// We'll use the `App` TraceSrc for the msg, and whatever level is provided
|
||||
pub fn push_stdio(&mut self, platform: Platform, msg: String, level: Level) {
|
||||
self.push_log(TraceMsg::text(TraceSrc::App(platform), level, msg));
|
||||
pub fn push_stdio(&mut self, bundle: BundleFormat, msg: String, level: Level) {
|
||||
self.push_log(TraceMsg::text(TraceSrc::App(bundle), level, msg));
|
||||
}
|
||||
|
||||
/// Push a message from the websocket to the logs
|
||||
pub fn push_ws_message(&mut self, platform: Platform, message: &axum::extract::ws::Message) {
|
||||
pub fn push_ws_message(&mut self, bundle: BundleFormat, message: &axum::extract::ws::Message) {
|
||||
use dioxus_devtools_types::ClientMsg;
|
||||
|
||||
// We can only handle text messages from the websocket...
|
||||
@@ -336,7 +336,7 @@ impl Output {
|
||||
let msg = match res {
|
||||
Ok(msg) => msg,
|
||||
Err(err) => {
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "Error parsing message from {}: {} -> {:?}", platform, err, text.as_str());
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "Error parsing message from {}: {} -> {:?}", bundle, err, text.as_str());
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -358,7 +358,7 @@ impl Output {
|
||||
};
|
||||
|
||||
// We don't care about logging the app's message so we directly push it instead of using tracing.
|
||||
self.push_log(TraceMsg::text(TraceSrc::App(platform), level, content));
|
||||
self.push_log(TraceMsg::text(TraceSrc::App(bundle), level, content));
|
||||
}
|
||||
|
||||
/// Change internal state based on the build engine's update
|
||||
@@ -641,7 +641,7 @@ impl Output {
|
||||
frame.render_widget(
|
||||
Paragraph::new(Line::from(vec![
|
||||
"Platform: ".gray(),
|
||||
client.build.platform.expected_name().yellow(),
|
||||
client.build.bundle.expected_name().yellow(),
|
||||
if state.runner.is_fullstack() {
|
||||
" + fullstack".yellow()
|
||||
} else {
|
||||
@@ -672,7 +672,7 @@ impl Output {
|
||||
|
||||
frame.render_widget_ref(
|
||||
Paragraph::new(Line::from(vec![
|
||||
if client.build.platform == Platform::Web {
|
||||
if client.build.bundle == BundleFormat::Web {
|
||||
"Serving at: ".gray()
|
||||
} else {
|
||||
"Server at: ".gray()
|
||||
@@ -755,7 +755,7 @@ impl Output {
|
||||
);
|
||||
|
||||
let server_address = match state.server.server_address() {
|
||||
Some(address) => format!("http://{}", address).yellow(),
|
||||
Some(address) => format!("http://{address}").yellow(),
|
||||
None => "no address".dark_gray(),
|
||||
};
|
||||
frame.render_widget(
|
||||
@@ -770,7 +770,7 @@ impl Output {
|
||||
frame.render_widget(
|
||||
Paragraph::new(Line::from(vec![
|
||||
"Read the docs: ".gray(),
|
||||
"https://dioxuslabs.com/0.6/docs".blue(),
|
||||
"https://dioxuslabs.com/learn/0.7/".blue(),
|
||||
])),
|
||||
links_list[0],
|
||||
);
|
||||
|
||||
@@ -163,8 +163,7 @@ pub(crate) fn handle_proxy_error(e: Error) -> axum::http::Response<axum::body::B
|
||||
axum::http::Response::builder()
|
||||
.status(axum::http::StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(axum::body::Body::from(format!(
|
||||
"Proxy connection failed: {:#?}",
|
||||
e
|
||||
"Proxy connection failed: {e:#?}"
|
||||
)))
|
||||
.unwrap()
|
||||
}
|
||||
@@ -229,7 +228,7 @@ mod test {
|
||||
let server_addr = setup_servers(config).await;
|
||||
|
||||
assert_eq!(
|
||||
reqwest::get(format!("http://{}/api", server_addr))
|
||||
reqwest::get(format!("http://{server_addr}/api"))
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
@@ -239,7 +238,7 @@ mod test {
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
reqwest::get(format!("http://{}/api/", server_addr))
|
||||
reqwest::get(format!("http://{server_addr}/api/"))
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::{AppBuilder, ServeUpdate, WebServer};
|
||||
use crate::{
|
||||
platform_override::CommandWithPlatformOverrides, BuildArtifacts, BuildId, BuildMode,
|
||||
BuildTargets, BuilderUpdate, HotpatchModuleCache, Platform, Result, ServeArgs, TailwindCli,
|
||||
BuildTargets, BuilderUpdate, BundleFormat, HotpatchModuleCache, Result, ServeArgs, TailwindCli,
|
||||
TraceSrc, Workspace,
|
||||
};
|
||||
use anyhow::{bail, Context};
|
||||
@@ -151,8 +151,8 @@ impl AppServer {
|
||||
// All servers will end up behind us (the devserver) but on a different port
|
||||
// This is so we can serve a loading screen as well as devtools without anything particularly fancy
|
||||
let fullstack = server.is_some();
|
||||
let should_proxy_port = match client.platform {
|
||||
Platform::Server => true,
|
||||
let should_proxy_port = match client.bundle {
|
||||
BundleFormat::Server => true,
|
||||
_ => fullstack && !ssg,
|
||||
};
|
||||
|
||||
@@ -168,7 +168,7 @@ impl AppServer {
|
||||
|
||||
// Only start Tailwind watcher for client builds that serve assets (not server builds or fullstack mode)
|
||||
// In fullstack mode, the client build's prebuild() handles Tailwind generation to avoid race conditions
|
||||
let tw_watcher = if client.build.platform != Platform::Server && !fullstack {
|
||||
let tw_watcher = if client.build.bundle != BundleFormat::Server && !fullstack {
|
||||
TailwindCli::serve(
|
||||
client.build.package_manifest_dir(),
|
||||
client.build.config.application.tailwind_input.clone(),
|
||||
@@ -536,7 +536,8 @@ impl AppServer {
|
||||
use crate::styles::NOTE_STYLE;
|
||||
tracing::info!(dx_src = ?TraceSrc::Dev, "Hotreloading: {NOTE_STYLE}{}{NOTE_STYLE:#}", file);
|
||||
|
||||
if !server.has_hotreload_sockets() && self.client.build.platform != Platform::Web {
|
||||
if !server.has_hotreload_sockets() && self.client.build.bundle != BundleFormat::Web
|
||||
{
|
||||
tracing::warn!("No clients to hotreload - try reloading the app!");
|
||||
}
|
||||
|
||||
@@ -554,8 +555,8 @@ impl AppServer {
|
||||
devserver: &mut WebServer,
|
||||
) -> Result<()> {
|
||||
// Make sure to save artifacts regardless of if we're opening the app or not
|
||||
match artifacts.platform {
|
||||
Platform::Server => {
|
||||
match artifacts.bundle {
|
||||
BundleFormat::Server => {
|
||||
if let Some(server) = self.server.as_mut() {
|
||||
server.artifacts = Some(artifacts.clone());
|
||||
}
|
||||
@@ -661,7 +662,7 @@ impl AppServer {
|
||||
|
||||
// If the client is running on Android, we need to remove the port forwarding
|
||||
// todo: use the android tools "adb"
|
||||
if matches!(self.client.build.platform, Platform::Android) {
|
||||
if matches!(self.client.build.bundle, BundleFormat::Android) {
|
||||
if let Err(err) = Command::new(&self.workspace.android_tools()?.adb)
|
||||
.arg("reverse")
|
||||
.arg("--remove")
|
||||
@@ -786,7 +787,7 @@ impl AppServer {
|
||||
BuildId::CLIENT => {
|
||||
// multiple tabs on web can cause this to be called incorrectly, and it doesn't
|
||||
// make any sense anyways
|
||||
if self.client.build.platform != Platform::Web {
|
||||
if self.client.build.bundle != BundleFormat::Web {
|
||||
if let Some(aslr_reference) = aslr_reference {
|
||||
self.client.aslr_reference = Some(aslr_reference);
|
||||
}
|
||||
@@ -804,7 +805,7 @@ impl AppServer {
|
||||
}
|
||||
|
||||
// Assign the runtime asset dir to the runner
|
||||
if self.client.build.platform == Platform::Ios {
|
||||
if self.client.build.bundle == BundleFormat::Ios {
|
||||
// xcrun simctl get_app_container booted com.dioxuslabs
|
||||
let res = Command::new("xcrun")
|
||||
.arg("simctl")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
config::WebHttpsConfig, serve::ServeUpdate, BuildId, BuildStage, BuilderUpdate, Platform,
|
||||
config::WebHttpsConfig, serve::ServeUpdate, BuildId, BuildStage, BuilderUpdate, BundleFormat,
|
||||
Result, TraceSrc,
|
||||
};
|
||||
use anyhow::{bail, Context};
|
||||
@@ -62,7 +62,7 @@ pub(crate) struct WebServer {
|
||||
new_build_status_sockets: UnboundedReceiver<ConnectedWsClient>,
|
||||
build_status: SharedStatus,
|
||||
application_name: String,
|
||||
platform: Platform,
|
||||
bundle: BundleFormat,
|
||||
}
|
||||
|
||||
pub(crate) struct ConnectedWsClient {
|
||||
@@ -128,7 +128,7 @@ impl WebServer {
|
||||
new_hot_reload_sockets: hot_reload_sockets_rx,
|
||||
new_build_status_sockets: build_status_sockets_rx,
|
||||
application_name: runner.app_name().to_string(),
|
||||
platform: runner.client.build.platform,
|
||||
bundle: runner.client.build.bundle,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ impl WebServer {
|
||||
drop(new_message);
|
||||
|
||||
// Update the socket with project info and current build status
|
||||
let project_info = SharedStatus::new(Status::ClientInit { application_name: self.application_name.clone(), platform: self.platform });
|
||||
let project_info = SharedStatus::new(Status::ClientInit { application_name: self.application_name.clone(), bundle: self.bundle });
|
||||
if project_info.send_to(&mut new_socket.socket).await.is_ok() {
|
||||
_ = self.build_status.send_to(&mut new_socket.socket).await;
|
||||
self.build_status_sockets.push(new_socket);
|
||||
@@ -175,7 +175,7 @@ impl WebServer {
|
||||
}
|
||||
Some((idx, message)) = new_message.next() => {
|
||||
match message {
|
||||
Some(Ok(msg)) => return ServeUpdate::WsMessage { msg, platform: Platform::Web },
|
||||
Some(Ok(msg)) => return ServeUpdate::WsMessage { msg, bundle: BundleFormat::Web },
|
||||
_ => {
|
||||
drop(new_message);
|
||||
_ = self.hot_reload_sockets.remove(idx);
|
||||
@@ -375,8 +375,8 @@ impl WebServer {
|
||||
}
|
||||
|
||||
pub fn server_address(&self) -> Option<SocketAddr> {
|
||||
match self.platform {
|
||||
Platform::Web | Platform::Server => Some(self.devserver_address()),
|
||||
match self.bundle {
|
||||
BundleFormat::Web | BundleFormat::Server => Some(self.devserver_address()),
|
||||
_ => self.proxied_server_address(),
|
||||
}
|
||||
}
|
||||
@@ -461,8 +461,7 @@ fn build_devserver_router(
|
||||
Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(Body::from(format!(
|
||||
"Backend connection failed. The backend is likely still starting up. Please try again in a few seconds. Error: {:#?}",
|
||||
error
|
||||
"Backend connection failed. The backend is likely still starting up. Please try again in a few seconds. Error: {error:#?}"
|
||||
)))
|
||||
.unwrap()
|
||||
},
|
||||
@@ -577,7 +576,7 @@ fn build_serve_dir(runner: &AppServer) -> axum::routing::MethodRouter {
|
||||
.handle_error(|error: Infallible| async move {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Unhandled internal error: {}", error),
|
||||
format!("Unhandled internal error: {error}"),
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -730,7 +729,7 @@ struct SharedStatus(Arc<RwLock<Status>>);
|
||||
enum Status {
|
||||
ClientInit {
|
||||
application_name: String,
|
||||
platform: Platform,
|
||||
bundle: BundleFormat,
|
||||
},
|
||||
Building {
|
||||
progress: f64,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{BuildId, BuilderUpdate, Error, Platform, TraceMsg};
|
||||
use crate::{BuildId, BuilderUpdate, BundleFormat, Error, TraceMsg};
|
||||
use axum::extract::ws::Message as WsMessage;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -13,7 +13,7 @@ pub(crate) enum ServeUpdate {
|
||||
pid: Option<u32>,
|
||||
},
|
||||
WsMessage {
|
||||
platform: Platform,
|
||||
bundle: BundleFormat,
|
||||
msg: WsMessage,
|
||||
},
|
||||
|
||||
|
||||
Reference in new issue
Block a user