Files
dioxus/packages/cli/src/build/context.rs
T
Jonathan Kelley 727752a965 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
2025-07-14 12:54:15 -07:00

184 lines
5.4 KiB
Rust

//! Report progress about the build to the user. We use channels to report progress back to the CLI.
use super::BuildMode;
use crate::{BuildArtifacts, BuildStage, Error, TraceSrc};
use cargo_metadata::diagnostic::Diagnostic;
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
use serde::{Deserialize, Serialize};
use std::{path::PathBuf, process::ExitStatus};
/// The context of the build process. While the BuildRequest is a "plan" for the build, the BuildContext
/// provides some dynamic configuration that is only known at runtime. For example, the Progress channel
/// and the BuildMode can change while serving.
///
/// The structure of this is roughly taken from cargo itself which uses a similar pattern.
#[derive(Debug, Clone)]
pub struct BuildContext {
pub tx: ProgressTx,
pub mode: BuildMode,
}
pub type ProgressTx = UnboundedSender<BuilderUpdate>;
pub type ProgressRx = UnboundedReceiver<BuilderUpdate>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
pub struct BuildId(pub(crate) usize);
impl BuildId {
pub const CLIENT: Self = Self(0);
pub const SERVER: Self = Self(1);
}
#[allow(clippy::large_enum_variant)]
pub enum BuilderUpdate {
Progress {
stage: BuildStage,
},
CompilerMessage {
message: Diagnostic,
},
BuildReady {
bundle: BuildArtifacts,
},
BuildFailed {
err: Error,
},
/// A running process has received a stdout.
/// May or may not be a complete line - do not treat it as a line. It will include a line if it is a complete line.
///
/// We will poll lines and any content in a 50ms interval
StdoutReceived {
msg: String,
},
/// A running process has received a stderr.
/// May or may not be a complete line - do not treat it as a line. It will include a line if it is a complete line.
///
/// We will poll lines and any content in a 50ms interval
StderrReceived {
msg: String,
},
ProcessExited {
status: ExitStatus,
},
/// Waiting for the process failed. This might be because it's hung or being debugged.
/// This is not the same as the process exiting, so it should just be logged but not treated as an error.
ProcessWaitFailed {
err: std::io::Error,
},
}
impl BuildContext {
pub(crate) fn status_wasm_bindgen_start(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::RunningBindgen,
});
}
pub(crate) fn status_splitting_bundle(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::SplittingBundle,
});
}
pub(crate) fn status_start_bundle(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::Bundling,
});
}
pub(crate) fn status_running_gradle(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::RunningGradle,
})
}
pub(crate) fn status_build_diagnostic(&self, message: Diagnostic) {
_ = self
.tx
.unbounded_send(BuilderUpdate::CompilerMessage { message });
}
pub(crate) fn status_build_error(&self, line: String) {
tracing::debug!(dx_src = ?TraceSrc::Cargo, "{line}");
}
pub(crate) fn status_build_message(&self, line: String) {
tracing::trace!(dx_src = ?TraceSrc::Cargo, "{line}");
}
pub(crate) fn status_build_progress(&self, count: usize, total: usize, name: String) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::Compiling {
current: count,
total,
krate: name,
},
});
}
pub(crate) fn status_starting_build(&self, crate_count: usize) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::Starting {
patch: matches!(self.mode, BuildMode::Thin { .. }),
crate_count,
},
});
}
pub(crate) fn status_starting_link(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::Linking,
});
}
pub(crate) fn status_copied_asset(
progress: &UnboundedSender<BuilderUpdate>,
current: usize,
total: usize,
path: PathBuf,
) {
_ = progress.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::CopyingAssets {
current,
total,
path,
},
});
}
pub(crate) fn status_optimizing_wasm(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::OptimizingWasm,
});
}
pub(crate) fn status_hotpatching(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::Hotpatching,
});
}
pub(crate) fn status_installing_tooling(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::InstallingTooling,
});
}
pub(crate) fn status_compressing_assets(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::CompressingAssets,
});
}
pub(crate) fn status_extracting_assets(&self) {
_ = self.tx.unbounded_send(BuilderUpdate::Progress {
stage: BuildStage::ExtractingAssets,
});
}
}