final 0.7 fixes: xcode 15/16 hybrid, auto openssldir for android, include_*! tracking hotpatch, fix /assets/ brick at high opt levels, windows linker file, etc (#4376)
* wip: openssl autodetection * add voltaile read inside of asset fn * support xcode 15 for --device * vendor openssl on android * Smaller width TUI * switch to anyhow for the entire CLI * add backtrace and print double printing of cargo_metadata errors * add some padding to multi-line anyhow error * check semvers * don't open if not interactive * set the tailwind current_dir so it doesn't twitch * get the oboe demo working * copy the c++ library on android * cleanup env vars * add depinfo watcher * fix stale hotpatches and crate count * add musl support * remove outdated autofmt test * update scanner app * add hotdog app and bundle to ci * upload dx on every branch * collapse mobile into desktop * `dx doctor` command * windows command files * no pipe on doctor * fix ci? * fix links * fix ci * use main instead of nightly * bump node * build cli for host * cargo doc * prep dog_app for bundle * package hotdog * no bundle or nightly cli * comment out nightly cli * add quotes to linker files
This commit is contained in:
1 parent
97947b169b
commit
727752a965
78 files changed
+2270
-817
No files matched your search
@@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
styles::{GLOW_STYLE, LINK_STYLE},
|
||||
AppBuilder, BuildId, BuildMode, BuilderUpdate, Error, Platform, Result, ServeArgs,
|
||||
TraceController,
|
||||
AppBuilder, BuildId, BuildMode, BuilderUpdate, Platform, Result, ServeArgs, TraceController,
|
||||
};
|
||||
|
||||
mod ansi_buffer;
|
||||
@@ -12,6 +11,7 @@ mod runner;
|
||||
mod server;
|
||||
mod update;
|
||||
|
||||
use anyhow::bail;
|
||||
use dioxus_dx_wire_format::BuildStage;
|
||||
pub(crate) use output::*;
|
||||
pub(crate) use runner::*;
|
||||
@@ -41,7 +41,7 @@ pub(crate) use update::*;
|
||||
pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) -> Result<()> {
|
||||
// Load the args into a plan, resolving all tooling, build dirs, arguments, decoding the multi-target, etc
|
||||
let exit_on_error = args.exit_on_error;
|
||||
let mut builder = AppServer::start(args).await?;
|
||||
let mut builder = AppServer::new(args).await?;
|
||||
let mut devserver = WebServer::start(&builder)?;
|
||||
let mut screen = Output::start(builder.interactive).await?;
|
||||
|
||||
@@ -66,6 +66,8 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
}
|
||||
);
|
||||
|
||||
builder.initialize();
|
||||
|
||||
loop {
|
||||
// Draw the state of the server to the screen
|
||||
screen.render(&builder, &devserver);
|
||||
@@ -145,18 +147,14 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
stage: BuildStage::Failed,
|
||||
} => {
|
||||
if exit_on_error {
|
||||
return Err(Error::Cargo(format!(
|
||||
"Build failed for platform: {platform}"
|
||||
)));
|
||||
bail!("Build failed for platform: {platform}");
|
||||
}
|
||||
}
|
||||
BuilderUpdate::Progress {
|
||||
stage: BuildStage::Aborted,
|
||||
} => {
|
||||
if exit_on_error {
|
||||
return Err(Error::Cargo(format!(
|
||||
"Build aborted for platform: {platform}"
|
||||
)));
|
||||
bail!("Build aborted for platform: {platform}");
|
||||
}
|
||||
}
|
||||
BuilderUpdate::Progress { .. } => {}
|
||||
@@ -164,7 +162,12 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
screen.push_cargo_log(message);
|
||||
}
|
||||
BuilderUpdate::BuildFailed { err } => {
|
||||
tracing::error!("Build failed: {}", err);
|
||||
tracing::error!(
|
||||
"{ERROR_STYLE}Build failed{ERROR_STYLE:#}: {}",
|
||||
crate::error::log_stacktrace(&err, 15),
|
||||
ERROR_STYLE = crate::styles::ERROR_STYLE,
|
||||
);
|
||||
|
||||
if exit_on_error {
|
||||
return Err(err);
|
||||
}
|
||||
@@ -184,7 +187,9 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to hot-patch app: {err}");
|
||||
|
||||
if matches!(err, crate::Error::PatchingFailed(_)) {
|
||||
if let Some(_patching) =
|
||||
err.downcast_ref::<crate::build::PatchError>()
|
||||
{
|
||||
tracing::info!("Starting full rebuild: {err}");
|
||||
builder.full_rebuild().await;
|
||||
devserver.send_reload_start().await;
|
||||
@@ -216,9 +221,7 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
} else {
|
||||
tracing::error!("Application [{platform}] exited with error: {status}");
|
||||
if exit_on_error {
|
||||
return Err(Error::Runtime(format!(
|
||||
"Application [{platform}] exited with error: {status}"
|
||||
)));
|
||||
bail!("Application [{platform}] exited with error: {status}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,7 +251,10 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
}
|
||||
_ => {
|
||||
if let Err(err) = builder.open_all(&devserver, true).await {
|
||||
tracing::error!("Failed to open app: {err}")
|
||||
tracing::error!(
|
||||
"Failed to open app: {}",
|
||||
crate::error::log_stacktrace(&err, 15)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -278,7 +284,7 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) ->
|
||||
_ = devserver.shutdown().await;
|
||||
|
||||
match error {
|
||||
Some(err) => return Err(anyhow::anyhow!("{}", err).into()),
|
||||
Some(err) => return Err(err),
|
||||
None => return Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ use tracing::Level;
|
||||
use super::AppServer;
|
||||
|
||||
const TICK_RATE_MS: u64 = 100;
|
||||
const VIEWPORT_MAX_WIDTH: u16 = 100;
|
||||
const VIEWPORT_MAX_WIDTH: u16 = 90;
|
||||
const VIEWPORT_HEIGHT_SMALL: u16 = 5;
|
||||
const VIEWPORT_HEIGHT_BIG: u16 = 13;
|
||||
|
||||
@@ -204,7 +204,7 @@ impl Output {
|
||||
Ok(Some(update)) => return update,
|
||||
Err(ee) => {
|
||||
return ServeUpdate::Exit {
|
||||
error: Some(Box::new(ee)),
|
||||
error: Some(anyhow::anyhow!(ee)),
|
||||
}
|
||||
}
|
||||
Ok(None) => {}
|
||||
@@ -675,7 +675,7 @@ impl Output {
|
||||
if client.build.platform == Platform::Web {
|
||||
"Serving at: ".gray()
|
||||
} else {
|
||||
"ServerFns at: ".gray()
|
||||
"Server at: ".gray()
|
||||
},
|
||||
address,
|
||||
])),
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::config::WebProxyConfig;
|
||||
use crate::TraceSrc;
|
||||
use crate::{Error, Result};
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
use anyhow::{bail, Context};
|
||||
use axum::body::Body;
|
||||
use axum::http::request::Parts;
|
||||
use axum::{body::Body as MyBody, response::IntoResponse};
|
||||
@@ -47,7 +47,7 @@ impl ProxyClient {
|
||||
self.inner
|
||||
.request(req)
|
||||
.await
|
||||
.map_err(|err| crate::error::Error::Other(anyhow!(err)))
|
||||
.context("Failed to send proxy request")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,11 +64,11 @@ pub(crate) fn add_proxy(mut router: Router, proxy: &WebProxyConfig) -> Result<Ro
|
||||
let trimmed_path = path.trim_start_matches('/');
|
||||
|
||||
if trimmed_path.is_empty() {
|
||||
return Err(crate::Error::ProxySetup(format!(
|
||||
bail!(
|
||||
"Proxy backend URL must have a non-empty path, e.g. {}/api instead of {}",
|
||||
proxy.backend.trim_end_matches('/'),
|
||||
proxy.backend
|
||||
)));
|
||||
);
|
||||
}
|
||||
|
||||
let method_router = proxy_to(url, false, handle_proxy_error);
|
||||
@@ -268,21 +268,4 @@ mod test {
|
||||
async fn add_proxy_trailing_slash() {
|
||||
test_proxy_requests("/api/".to_string()).await;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_proxy_empty_path() {
|
||||
let config = WebProxyConfig {
|
||||
backend: "http://localhost:8000".to_string(),
|
||||
};
|
||||
let router = super::add_proxy(Router::new(), &config);
|
||||
match router.unwrap_err() {
|
||||
crate::Error::ProxySetup(e) => {
|
||||
assert_eq!(
|
||||
e,
|
||||
"Proxy backend URL must have a non-empty path, e.g. http://localhost:8000/api instead of http://localhost:8000"
|
||||
);
|
||||
}
|
||||
e => panic!("Unexpected error type: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
use super::{AppBuilder, ServeUpdate, WebServer};
|
||||
use crate::{
|
||||
platform_override::CommandWithPlatformOverrides, BuildArtifacts, BuildId, BuildMode,
|
||||
BuildTargets, BuilderUpdate, Error, HotpatchModuleCache, Platform, Result, ServeArgs,
|
||||
TailwindCli, TraceSrc, Workspace,
|
||||
BuildTargets, BuilderUpdate, HotpatchModuleCache, Platform, Result, ServeArgs, TailwindCli,
|
||||
TraceSrc, Workspace,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use anyhow::{bail, Context};
|
||||
use dioxus_core::internal::{
|
||||
HotReloadTemplateWithLocation, HotReloadedTemplate, TemplateGlobalKey,
|
||||
};
|
||||
@@ -92,7 +92,7 @@ pub(crate) struct CachedFile {
|
||||
|
||||
impl AppServer {
|
||||
/// Create the AppRunner and then initialize the filemap with the crate directory.
|
||||
pub(crate) async fn start(args: ServeArgs) -> Result<Self> {
|
||||
pub(crate) async fn new(args: ServeArgs) -> Result<Self> {
|
||||
let workspace = Workspace::current().await?;
|
||||
|
||||
// Resolve the simpler args
|
||||
@@ -115,7 +115,8 @@ impl AppServer {
|
||||
|
||||
let open_browser = args
|
||||
.open
|
||||
.unwrap_or_else(|| workspace.settings.always_open_browser.unwrap_or_default());
|
||||
.unwrap_or_else(|| workspace.settings.always_open_browser.unwrap_or(true))
|
||||
&& interactive;
|
||||
|
||||
let wsl_file_poll_interval = args
|
||||
.wsl_file_poll_interval
|
||||
@@ -161,15 +162,9 @@ impl AppServer {
|
||||
|
||||
let watch_fs = args.watch.unwrap_or(true);
|
||||
let use_hotpatch_engine = args.hot_patch;
|
||||
let build_mode = match use_hotpatch_engine {
|
||||
true => BuildMode::Fat,
|
||||
false => BuildMode::Base,
|
||||
};
|
||||
|
||||
let client = AppBuilder::start(&client, build_mode.clone())?;
|
||||
let server = server
|
||||
.map(|server| AppBuilder::start(&server, build_mode))
|
||||
.transpose()?;
|
||||
let client = AppBuilder::new(&client)?;
|
||||
let server = server.map(|server| AppBuilder::new(&server)).transpose()?;
|
||||
|
||||
let tw_watcher = TailwindCli::serve(
|
||||
client.build.package_manifest_dir(),
|
||||
@@ -229,6 +224,18 @@ impl AppServer {
|
||||
Ok(runner)
|
||||
}
|
||||
|
||||
pub(crate) fn initialize(&mut self) {
|
||||
let build_mode = match self.use_hotpatch_engine {
|
||||
true => BuildMode::Fat,
|
||||
false => BuildMode::Base,
|
||||
};
|
||||
|
||||
self.client.start(build_mode.clone());
|
||||
if let Some(server) = self.server.as_mut() {
|
||||
server.start(build_mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn rebuild_ssg(&mut self, devserver: &WebServer) {
|
||||
if self.client.stage != BuildStage::Success {
|
||||
return;
|
||||
@@ -355,9 +362,10 @@ impl AppServer {
|
||||
for path in files {
|
||||
// for various assets that might be linked in, we just try to hotreloading them forcefully
|
||||
// That is, unless they appear in an include! macro, in which case we need to a full rebuild....
|
||||
let Some(ext) = path.extension().and_then(|v| v.to_str()) else {
|
||||
continue;
|
||||
};
|
||||
let ext = path
|
||||
.extension()
|
||||
.and_then(|v| v.to_str())
|
||||
.unwrap_or_default();
|
||||
|
||||
// If it's an asset, we want to hotreload it
|
||||
// todo(jon): don't hardcode this here
|
||||
@@ -458,6 +466,21 @@ impl AppServer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If it's not a rust file, then it might be depended on via include! or similar
|
||||
if ext != "rs" {
|
||||
if let Some(artifacts) = self.client.artifacts.as_ref() {
|
||||
if artifacts.depinfo.files.contains(path) {
|
||||
needs_full_rebuild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the client is in a failed state, any changes to rsx should trigger a rebuild/hotpatch
|
||||
if self.client.stage == BuildStage::Failed && !templates.is_empty() {
|
||||
needs_full_rebuild = true
|
||||
}
|
||||
|
||||
// todo - we need to distinguish between hotpatchable rebuilds and true full rebuilds.
|
||||
@@ -685,7 +708,7 @@ impl AppServer {
|
||||
.hotpatch(res, cache)
|
||||
.await
|
||||
}
|
||||
_ => return Err(Error::Runtime("Invalid build id".into())),
|
||||
_ => bail!("Invalid build id"),
|
||||
}?;
|
||||
|
||||
if id == BuildId::CLIENT {
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::{
|
||||
config::WebHttpsConfig, serve::ServeUpdate, BuildId, BuildStage, BuilderUpdate, Platform,
|
||||
Result, TraceSrc,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use anyhow::{bail, Context};
|
||||
use axum::{
|
||||
body::Body,
|
||||
extract::{
|
||||
@@ -635,8 +635,7 @@ async fn get_rustls(web_config: &WebHttpsConfig) -> Result<(String, String)> {
|
||||
{
|
||||
return Ok((cert, key));
|
||||
} else {
|
||||
// missing cert or key
|
||||
return Err("https is enabled but cert or key path is missing".into());
|
||||
bail!("https is enabled but cert or key path is missing");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -682,7 +681,7 @@ async fn get_rustls(web_config: &WebHttpsConfig) -> Result<(String, String)> {
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "An error occurred while generating mkcert certificates: {}", e.to_string())
|
||||
}
|
||||
};
|
||||
return Err("failed to generate mkcert certificates".into());
|
||||
bail!("failed to generate mkcert certificates");
|
||||
}
|
||||
Ok(mut cmd) => {
|
||||
cmd.wait().await?;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{BuildId, BuilderUpdate, Platform, TraceMsg};
|
||||
use crate::{BuildId, BuilderUpdate, Error, Platform, TraceMsg};
|
||||
use axum::extract::ws::Message as WsMessage;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -44,6 +44,6 @@ pub(crate) enum ServeUpdate {
|
||||
},
|
||||
|
||||
Exit {
|
||||
error: Option<Box<dyn std::error::Error + Send + Sync>>,
|
||||
error: Option<Error>,
|
||||
},
|
||||
}
|
||||
Reference in new issue
Block a user