Use Manganis Linker System (#2561)

* feat: new manganis linker

* revision: fmt, clippy, cleanup

* revision: link subcommand

* fix: async runtime

* revision: remove working dir arg

* revision: switch dep source

* fix: matrix, playwright

* fix: fullstack manganis
This commit is contained in:
Miles Murgaw authored and GitHub committed 2024-07-02 21:36:44 -07:00
1 parent 90c46afd12
commit 2ef406982e
15 files changed
+330 -170

No files matched your search

+4 -4
View File
@@ -222,7 +222,7 @@ jobs:
- { - {
target: x86_64-pc-windows-msvc, target: x86_64-pc-windows-msvc,
os: windows-latest, os: windows-latest,
toolchain: "1.75.0", toolchain: "1.76.0",
cross: false, cross: false,
command: "test", command: "test",
args: "--all --tests", args: "--all --tests",
@@ -230,7 +230,7 @@ jobs:
- { - {
target: x86_64-apple-darwin, target: x86_64-apple-darwin,
os: macos-latest, os: macos-latest,
toolchain: "1.75.0", toolchain: "1.76.0",
cross: false, cross: false,
command: "test", command: "test",
args: "--all --tests", args: "--all --tests",
@@ -238,7 +238,7 @@ jobs:
- { - {
target: aarch64-apple-ios, target: aarch64-apple-ios,
os: macos-latest, os: macos-latest,
toolchain: "1.75.0", toolchain: "1.76.0",
cross: false, cross: false,
command: "build", command: "build",
args: "--package dioxus-mobile", args: "--package dioxus-mobile",
@@ -246,7 +246,7 @@ jobs:
- { - {
target: aarch64-linux-android, target: aarch64-linux-android,
os: ubuntu-latest, os: ubuntu-latest,
toolchain: "1.75.0", toolchain: "1.76.0",
cross: true, cross: true,
command: "build", command: "build",
args: "--package dioxus-mobile", args: "--package dioxus-mobile",
Generated
+66 -7
View File
@@ -906,7 +906,7 @@ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"miniz_oxide", "miniz_oxide",
"object", "object 0.32.2",
"rustc-demangle", "rustc-demangle",
] ]
@@ -1936,7 +1936,7 @@ dependencies = [
"cssparser-macros", "cssparser-macros",
"dtoa-short", "dtoa-short",
"itoa 1.0.11", "itoa 1.0.11",
"phf 0.11.2", "phf 0.8.0",
"smallvec", "smallvec",
] ]
@@ -5918,8 +5918,7 @@ dependencies = [
[[package]] [[package]]
name = "manganis-cli-support" name = "manganis-cli-support"
version = "0.2.4" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/DogeDark/dioxus-collect-assets/#6b6077150c854af6497d8b96d3a070635ab9b6c4"
checksum = "6d502b0db0ef8c880fecff174903815efedfacbcd5ea9a8bef96752f1e0d7eb6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cargo-lock", "cargo-lock",
@@ -5928,8 +5927,9 @@ dependencies = [
"image 0.25.1", "image 0.25.1",
"imagequant", "imagequant",
"lightningcss", "lightningcss",
"manganis-common", "manganis-common 0.2.4 (git+https://github.com/DogeDark/dioxus-collect-assets/)",
"mozjpeg", "mozjpeg",
"object 0.36.0",
"petgraph", "petgraph",
"png", "png",
"railwind", "railwind",
@@ -5938,6 +5938,7 @@ dependencies = [
"reqwest 0.11.27", "reqwest 0.11.27",
"rustc-hash", "rustc-hash",
"serde", "serde",
"serde_json",
"toml 0.7.8", "toml 0.7.8",
"tracing", "tracing",
"url", "url",
@@ -5960,13 +5961,29 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "manganis-common"
version = "0.2.4"
source = "git+https://github.com/DogeDark/dioxus-collect-assets/#6b6077150c854af6497d8b96d3a070635ab9b6c4"
dependencies = [
"anyhow",
"base64 0.21.7",
"home",
"infer 0.11.0",
"reqwest",
"serde",
"toml 0.7.8",
"tracing",
"url",
]
[[package]] [[package]]
name = "manganis-macro" name = "manganis-macro"
version = "0.2.2" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "704a0123ac90fa630b21a04fde56c29dfd5a7665c5e8f3639567989daa2d29d1" checksum = "704a0123ac90fa630b21a04fde56c29dfd5a7665c5e8f3639567989daa2d29d1"
dependencies = [ dependencies = [
"manganis-common", "manganis-common 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.60", "syn 2.0.60",
@@ -6554,6 +6571,18 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "object"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
dependencies = [
"flate2",
"memchr",
"ruzstd",
"wasmparser 0.208.1",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.19.0" version = "1.19.0"
@@ -8117,6 +8146,17 @@ version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]]
name = "ruzstd"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
dependencies = [
"byteorder",
"derive_more",
"twox-hash",
]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.17" version = "1.0.17"
@@ -9899,6 +9939,16 @@ dependencies = [
"utf-8", "utf-8",
] ]
[[package]]
name = "twox-hash"
version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
dependencies = [
"cfg-if",
"static_assertions",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.17.0" version = "1.17.0"
@@ -10132,7 +10182,7 @@ dependencies = [
"log", "log",
"walrus-macro", "walrus-macro",
"wasm-encoder", "wasm-encoder",
"wasmparser", "wasmparser 0.80.2",
] ]
[[package]] [[package]]
@@ -10419,6 +10469,15 @@ version = "0.80.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b" checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b"
[[package]]
name = "wasmparser"
version = "0.208.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd921789c9dcc495f589cb37d200155dee65b4a4beeb853323b5e24e0a5f9c58"
dependencies = [
"bitflags 2.5.0",
]
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.69" version = "0.3.69"
+1 -1
View File
@@ -98,7 +98,7 @@ wasm-bindgen-futures = "0.4.42"
html_parser = "0.7.0" html_parser = "0.7.0"
thiserror = "1.0.40" thiserror = "1.0.40"
prettyplease = { version = "0.2.16", features = ["verbatim"] } prettyplease = { version = "0.2.16", features = ["verbatim"] }
manganis-cli-support = { version = "0.2.1", features = ["html"] } manganis-cli-support = { git = "https://github.com/DogeDark/dioxus-collect-assets/", features = ["html"] }
manganis = { version = "0.2.1" } manganis = { version = "0.2.1" }
interprocess = { version = "1.2.2", package = "interprocess-docfix" } interprocess = { version = "1.2.2", package = "interprocess-docfix" }
+11 -6
View File
@@ -1,4 +1,5 @@
use brotli::enc::BrotliEncoderParams; use brotli::enc::BrotliEncoderParams;
use std::fs;
use std::path::Path; use std::path::Path;
use std::{ffi::OsString, path::PathBuf}; use std::{ffi::OsString, path::PathBuf};
use walkdir::WalkDir; use walkdir::WalkDir;
@@ -10,12 +11,16 @@ use dioxus_cli_config::CrateConfig;
use dioxus_cli_config::Platform; use dioxus_cli_config::Platform;
use manganis_cli_support::{AssetManifest, AssetManifestExt}; use manganis_cli_support::{AssetManifest, AssetManifestExt};
pub fn asset_manifest(bin: Option<&str>, crate_config: &CrateConfig) -> AssetManifest { /// The temp file name for passing manganis json from linker to current exec.
AssetManifest::load_from_path( pub const MG_JSON_OUT: &str = "mg-out";
bin,
crate_config.crate_dir.join("Cargo.toml"), pub fn asset_manifest(config: &CrateConfig) -> AssetManifest {
crate_config.workspace_dir.join("Cargo.lock"), let file_path = config.out_dir().join(MG_JSON_OUT);
) let read = fs::read_to_string(&file_path).unwrap();
_ = fs::remove_file(file_path);
let json: Vec<String> = serde_json::from_str(&read).unwrap();
AssetManifest::load(json)
} }
/// Create a head file that contains all of the imports for assets that the user project uses /// Create a head file that contains all of the imports for assets that the user project uses
+89 -43
View File
@@ -4,6 +4,7 @@ use crate::{
AssetConfigDropGuard, AssetConfigDropGuard,
}, },
error::{Error, Result}, error::{Error, Result},
link::LinkCommand,
tools::Tool, tools::Tool,
}; };
use anyhow::Context; use anyhow::Context;
@@ -83,13 +84,12 @@ pub fn build_web(
let CrateConfig { let CrateConfig {
crate_dir, crate_dir,
target_dir, target_dir,
executable,
dioxus_config, dioxus_config,
.. ..
} = config; } = config;
let out_dir = config.out_dir(); let out_dir = config.out_dir();
let _guard = AssetConfigDropGuard::new(); let _asset_guard = AssetConfigDropGuard::new();
let _manganis_support = ManganisSupportGuard::default(); let _manganis_support = ManganisSupportGuard::default();
// start to build the assets // start to build the assets
@@ -114,54 +114,76 @@ pub fn build_web(
} }
} }
let cmd = subprocess::Exec::cmd("cargo") let mut cargo_args = vec!["--target".to_string(), "wasm32-unknown-unknown".to_string()];
let mut cmd = subprocess::Exec::cmd("cargo")
.set_rust_flags(rust_flags) .set_rust_flags(rust_flags)
.env("CARGO_TARGET_DIR", target_dir) .env("CARGO_TARGET_DIR", target_dir)
.cwd(crate_dir) .cwd(crate_dir)
.arg("build") .arg("build")
.arg("--target")
.arg("wasm32-unknown-unknown")
.arg("--message-format=json-render-diagnostics"); .arg("--message-format=json-render-diagnostics");
// TODO: make the initial variable mutable to simplify all the expressions // TODO: make the initial variable mutable to simplify all the expressions
// below. Look inside the `build_desktop()` as an example. // below. Look inside the `build_desktop()` as an example.
let cmd = if config.release { if config.release {
cmd.arg("--release") cargo_args.push("--release".to_string());
}
if config.verbose {
cargo_args.push("--verbose".to_string());
} else { } else {
cmd cargo_args.push("--quiet".to_string());
}; }
let cmd = if config.verbose {
cmd.arg("--verbose")
} else {
cmd.arg("--quiet")
};
let cmd = if config.custom_profile.is_some() { if config.custom_profile.is_some() {
let custom_profile = config.custom_profile.as_ref().unwrap(); let custom_profile = config.custom_profile.as_ref().unwrap();
cmd.arg("--profile").arg(custom_profile) cargo_args.push("--profile".to_string());
} else { cargo_args.push(custom_profile.to_string());
cmd }
};
let cmd = if config.features.is_some() { if config.features.is_some() {
let features_str = config.features.as_ref().unwrap().join(" "); let features_str = config.features.as_ref().unwrap().join(" ");
cmd.arg("--features").arg(features_str) cargo_args.push("--features".to_string());
} else { cargo_args.push(features_str);
cmd }
};
let cmd = cmd.args(&config.cargo_args); if let Some(target) = &config.target {
cargo_args.push("--target".to_string());
cargo_args.push(target.clone());
}
let cmd = match executable { cargo_args.append(&mut config.cargo_args.clone());
ExecutableType::Binary(name) => cmd.arg("--bin").arg(name),
ExecutableType::Lib(name) => cmd.arg("--lib").arg(name), match &config.executable {
ExecutableType::Example(name) => cmd.arg("--example").arg(name), ExecutableType::Binary(name) => {
cargo_args.push("--bin".to_string());
cargo_args.push(name.to_string());
}
ExecutableType::Lib(name) => {
cargo_args.push("--lib".to_string());
cargo_args.push(name.to_string());
}
ExecutableType::Example(name) => {
cargo_args.push("--example".to_string());
cargo_args.push(name.to_string());
}
}; };
cmd = cmd.args(&cargo_args);
let CargoBuildResult { let CargoBuildResult {
warnings, warnings,
output_location, output_location,
} = prettier_build(cmd)?; } = prettier_build(cmd)?;
// Start Manganis linker intercept.
let linker_args = vec![format!("{}", config.out_dir().display())];
manganis_cli_support::start_linker_intercept(
&LinkCommand::command_name(),
cargo_args,
Some(linker_args),
)
.unwrap();
let output_location = output_location.context("No output location found")?; let output_location = output_location.context("No output location found")?;
// [2] Establish the output directory structure // [2] Establish the output directory structure
@@ -277,7 +299,7 @@ pub fn build_web(
let assets = if !skip_assets { let assets = if !skip_assets {
tracing::info!("Processing assets"); tracing::info!("Processing assets");
let assets = asset_manifest(executable.executable(), config); let assets = asset_manifest(config);
process_assets(config, &assets)?; process_assets(config, &assets)?;
Some(assets) Some(assets)
} else { } else {
@@ -337,7 +359,9 @@ pub fn build_desktop(
build_assets(config)?; build_assets(config)?;
let _guard = dioxus_cli_config::__private::save_config(config); let _guard = dioxus_cli_config::__private::save_config(config);
let _manganis_support = ManganisSupportGuard::default(); let _manganis_support = ManganisSupportGuard::default();
let _guard = AssetConfigDropGuard::new(); let _asset_guard = AssetConfigDropGuard::new();
let mut cargo_args = Vec::new();
let mut cmd = subprocess::Exec::cmd("cargo") let mut cmd = subprocess::Exec::cmd("cargo")
.set_rust_flags(rust_flags) .set_rust_flags(rust_flags)
@@ -347,38 +371,60 @@ pub fn build_desktop(
.arg("--message-format=json-render-diagnostics"); .arg("--message-format=json-render-diagnostics");
if config.release { if config.release {
cmd = cmd.arg("--release"); cargo_args.push("--release".to_string());
} }
if config.verbose { if config.verbose {
cmd = cmd.arg("--verbose"); cargo_args.push("--verbose".to_string());
} else { } else {
cmd = cmd.arg("--quiet"); cargo_args.push("--quiet".to_string());
} }
if config.custom_profile.is_some() { if config.custom_profile.is_some() {
let custom_profile = config.custom_profile.as_ref().unwrap(); let custom_profile = config.custom_profile.as_ref().unwrap();
cmd = cmd.arg("--profile").arg(custom_profile); cargo_args.push("--profile".to_string());
cargo_args.push(custom_profile.to_string());
} }
if config.features.is_some() { if config.features.is_some() {
let features_str = config.features.as_ref().unwrap().join(" "); let features_str = config.features.as_ref().unwrap().join(" ");
cmd = cmd.arg("--features").arg(features_str); cargo_args.push("--features".to_string());
cargo_args.push(features_str);
} }
if let Some(target) = &config.target { if let Some(target) = &config.target {
cmd = cmd.arg("--target").arg(target); cargo_args.push("--target".to_string());
cargo_args.push(target.clone());
} }
cmd = cmd.args(&config.cargo_args); cargo_args.append(&mut config.cargo_args.clone());
let cmd = match &config.executable { match &config.executable {
ExecutableType::Binary(name) => cmd.arg("--bin").arg(name), ExecutableType::Binary(name) => {
ExecutableType::Lib(name) => cmd.arg("--lib").arg(name), cargo_args.push("--bin".to_string());
ExecutableType::Example(name) => cmd.arg("--example").arg(name), cargo_args.push(name.to_string());
}
ExecutableType::Lib(name) => {
cargo_args.push("--lib".to_string());
cargo_args.push(name.to_string());
}
ExecutableType::Example(name) => {
cargo_args.push("--example".to_string());
cargo_args.push(name.to_string());
}
}; };
cmd = cmd.args(&cargo_args);
let warning_messages = prettier_build(cmd)?; let warning_messages = prettier_build(cmd)?;
// Start Manganis linker intercept.
let linker_args = vec![format!("{}", config.out_dir().display())];
manganis_cli_support::start_linker_intercept(
&LinkCommand::command_name(),
cargo_args,
Some(linker_args),
)?;
let file_name: String = config.executable.executable().unwrap().to_string(); let file_name: String = config.executable.executable().unwrap().to_string();
let target_file = if cfg!(windows) { let target_file = if cfg!(windows) {
@@ -399,7 +445,7 @@ pub fn build_desktop(
let assets = if !skip_assets { let assets = if !skip_assets {
tracing::info!("Processing assets"); tracing::info!("Processing assets");
let assets = asset_manifest(config.executable.executable(), config); let assets = asset_manifest(config);
// Collect assets // Collect assets
process_assets(config, &assets)?; process_assets(config, &assets)?;
// Create the __assets_head.html file for bundling // Create the __assets_head.html file for bundling
+18 -14
View File
@@ -16,22 +16,26 @@ pub struct Check {
impl Check { impl Check {
// Todo: check the entire crate // Todo: check the entire crate
pub async fn check(self) -> Result<()> { pub fn check(self) -> Result<()> {
match self.file { let rt = tokio::runtime::Runtime::new().unwrap();
// Default to checking the project
None => { rt.block_on(async move {
if let Err(e) = check_project_and_report().await { match self.file {
eprintln!("error checking project: {}", e); // Default to checking the project
exit(1); None => {
if let Err(e) = check_project_and_report().await {
eprintln!("error checking project: {}", e);
exit(1);
}
}
Some(file) => {
if let Err(e) = check_file_and_report(file).await {
eprintln!("failed to check file: {}", e);
exit(1);
}
} }
} }
Some(file) => { });
if let Err(e) = check_file_and_report(file).await {
eprintln!("failed to check file: {}", e);
exit(1);
}
}
}
Ok(()) Ok(())
} }
+39
View File
@@ -0,0 +1,39 @@
use crate::{assets, error::Result};
use clap::Parser;
use std::{fs, path::PathBuf};
#[derive(Clone, Debug, Parser)]
#[clap(name = "link", hide = true)]
pub struct LinkCommand {
// Allow us to accept any argument after `dx link`
#[clap(trailing_var_arg = true, allow_hyphen_values = true)]
pub args: Vec<String>,
}
impl LinkCommand {
pub fn link(self) -> Result<()> {
let Some((link_args, object_files)) = manganis_cli_support::linker_intercept(self.args)
else {
tracing::warn!("Invalid linker arguments.");
return Ok(());
};
// Parse object files, deserialize JSON, & create a file to propogate JSON.
let json = manganis_cli_support::get_json_from_object_files(object_files);
let parsed = serde_json::to_string(&json).unwrap();
let out_dir = PathBuf::from(link_args.first().unwrap());
fs::create_dir_all(&out_dir).unwrap();
let path = out_dir.join(assets::MG_JSON_OUT);
fs::write(path, parsed).unwrap();
Ok(())
}
/// We need to pass the subcommand name to Manganis so this
/// helps centralize where we set the subcommand "name".
pub fn command_name() -> String {
"link".to_string()
}
}
+6
View File
@@ -7,6 +7,7 @@ pub mod clean;
pub mod config; pub mod config;
pub mod create; pub mod create;
pub mod init; pub mod init;
pub mod link;
pub mod plugin; pub mod plugin;
pub mod serve; pub mod serve;
pub mod translate; pub mod translate;
@@ -85,6 +86,10 @@ pub enum Commands {
#[cfg(feature = "plugin")] #[cfg(feature = "plugin")]
#[clap(subcommand)] #[clap(subcommand)]
Plugin(plugin::Plugin), Plugin(plugin::Plugin),
/// Handles parsing of linker arguments for linker-based systems
/// such as Manganis and binary patching.
Link(link::LinkCommand),
} }
impl Display for Commands { impl Display for Commands {
@@ -100,6 +105,7 @@ impl Display for Commands {
Commands::Autoformat(_) => write!(f, "fmt"), Commands::Autoformat(_) => write!(f, "fmt"),
Commands::Check(_) => write!(f, "check"), Commands::Check(_) => write!(f, "check"),
Commands::Bundle(_) => write!(f, "bundle"), Commands::Bundle(_) => write!(f, "bundle"),
Commands::Link(_) => write!(f, "link"),
#[cfg(feature = "plugin")] #[cfg(feature = "plugin")]
Commands::Plugin(_) => write!(f, "plugin"), Commands::Plugin(_) => write!(f, "plugin"),
+1 -1
View File
@@ -15,7 +15,7 @@ pub enum Plugin {
} }
impl Plugin { impl Plugin {
pub async fn plugin(self) -> Result<()> { pub fn plugin(self) -> Result<()> {
match self { match self {
Plugin::List {} => { Plugin::List {} => {
for item in crate::plugin::PluginManager::plugin_list() { for item in crate::plugin::PluginManager::plugin_list() {
+4 -4
View File
@@ -14,7 +14,7 @@ pub struct Serve {
} }
impl Serve { impl Serve {
pub async fn serve(self, bin: Option<PathBuf>) -> Result<()> { pub fn serve(self, bin: Option<PathBuf>) -> Result<()> {
let mut crate_config = dioxus_cli_config::CrateConfig::new(bin)?; let mut crate_config = dioxus_cli_config::CrateConfig::new(bin)?;
let serve_cfg = self.serve.clone(); let serve_cfg = self.serve.clone();
@@ -65,10 +65,10 @@ impl Serve {
// start the develop server // start the develop server
use server::{desktop, fullstack, web}; use server::{desktop, fullstack, web};
match platform { match platform {
Platform::Web => web::startup(crate_config.clone(), &serve_cfg).await?, Platform::Web => web::startup(crate_config.clone(), &serve_cfg)?,
Platform::Desktop => desktop::startup(crate_config.clone(), &serve_cfg).await?, Platform::Desktop => desktop::startup(crate_config.clone(), &serve_cfg)?,
Platform::Fullstack | Platform::StaticGeneration => { Platform::Fullstack | Platform::StaticGeneration => {
fullstack::startup(crate_config.clone(), &serve_cfg).await? fullstack::startup(crate_config.clone(), &serve_cfg)?
} }
_ => unreachable!(), _ => unreachable!(),
} }
+1 -1
View File
@@ -2,7 +2,7 @@
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")] #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")] #![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
mod assets; pub mod assets;
pub mod builder; pub mod builder;
pub mod server; pub mod server;
pub mod tools; pub mod tools;
+7 -11
View File
@@ -10,8 +10,7 @@ use Commands::*;
const LOG_ENV: &str = "DIOXUS_LOG"; const LOG_ENV: &str = "DIOXUS_LOG";
#[tokio::main] fn main() -> anyhow::Result<()> {
async fn main() -> anyhow::Result<()> {
let args = Cli::parse(); let args = Cli::parse();
// If {LOG_ENV} is set, default to env, otherwise filter to cli // If {LOG_ENV} is set, default to env, otherwise filter to cli
@@ -40,19 +39,17 @@ async fn main() -> anyhow::Result<()> {
.context(error_wrapper("Configuring new project failed")), .context(error_wrapper("Configuring new project failed")),
#[cfg(feature = "plugin")] #[cfg(feature = "plugin")]
Plugin(opts) => opts Plugin(opts) => opts.plugin().context(error_wrapper("Error with plugin")),
.plugin()
.await
.context(error_wrapper("Error with plugin")),
Autoformat(opts) => opts Autoformat(opts) => opts
.autoformat() .autoformat()
.context(error_wrapper("Error autoformatting RSX")), .context(error_wrapper("Error autoformatting RSX")),
Check(opts) => opts Check(opts) => opts.check().context(error_wrapper("Error checking RSX")),
.check()
.await Link(opts) => opts
.context(error_wrapper("Error checking RSX")), .link()
.context(error_wrapper("Error with linker passthrough")),
action => { action => {
let bin = get_bin(args.bin)?; let bin = get_bin(args.bin)?;
@@ -81,7 +78,6 @@ async fn main() -> anyhow::Result<()> {
Serve(opts) => opts Serve(opts) => opts
.serve(Some(bin.clone())) .serve(Some(bin.clone()))
.await
.context(error_wrapper("Serving project failed")), .context(error_wrapper("Serving project failed")),
Bundle(opts) => opts Bundle(opts) => opts
+44 -42
View File
@@ -23,11 +23,11 @@ use crate::plugin::PluginManager;
use super::HotReloadState; use super::HotReloadState;
pub async fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> { pub fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> {
startup_with_platform::<DesktopPlatform>(config, serve).await startup_with_platform::<DesktopPlatform>(config, serve)
} }
pub(crate) async fn startup_with_platform<P: Platform + Send + 'static>( pub(crate) fn startup_with_platform<P: Platform + Send + 'static>(
config: CrateConfig, config: CrateConfig,
serve_cfg: &ConfigOptsServe, serve_cfg: &ConfigOptsServe,
) -> Result<()> { ) -> Result<()> {
@@ -54,7 +54,7 @@ pub(crate) async fn startup_with_platform<P: Platform + Send + 'static>(
file_map, file_map,
}; };
serve::<P>(config, serve_cfg, hot_reload_state).await?; serve::<P>(config, serve_cfg, hot_reload_state)?;
Ok(()) Ok(())
} }
@@ -70,53 +70,55 @@ fn set_ctrl_c(config: &CrateConfig) {
} }
/// Start the server without hot reload /// Start the server without hot reload
async fn serve<P: Platform + Send + 'static>( fn serve<P: Platform + Send + 'static>(
config: CrateConfig, config: CrateConfig,
serve: &ConfigOptsServe, serve: &ConfigOptsServe,
hot_reload_state: HotReloadState, hot_reload_state: HotReloadState,
) -> Result<()> { ) -> Result<()> {
let hot_reload: tokio::task::JoinHandle<Result<()>> = tokio::spawn({
let hot_reload_state = hot_reload_state.clone();
async move {
match hot_reload_state.file_map.clone() {
Some(file_map) => {
// The open interprocess sockets
start_desktop_hot_reload(hot_reload_state, file_map).await?;
}
None => {
std::future::pending::<()>().await;
}
}
Ok(())
}
});
let platform = RwLock::new(P::start(&config, serve, Vec::new())?); let platform = RwLock::new(P::start(&config, serve, Vec::new())?);
tracing::info!("🚀 Starting development server..."); let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async move {
// We got to own watcher so that it exists for the duration of serve let hot_reload: tokio::task::JoinHandle<Result<()>> = tokio::spawn({
// Otherwise full reload won't work. let hot_reload_state = hot_reload_state.clone();
let _watcher = setup_file_watcher( async move {
{ match hot_reload_state.file_map.clone() {
let config = config.clone(); Some(file_map) => {
let serve = serve.clone(); // The open interprocess sockets
move || { start_desktop_hot_reload(hot_reload_state, file_map).await?;
platform }
.write() None => {
.unwrap() std::future::pending::<()>().await;
.rebuild(&config, &serve, Vec::new()) }
}
Ok(())
} }
}, });
&config,
None,
hot_reload_state,
)
.await?;
hot_reload.await.unwrap()?; tracing::info!("🚀 Starting development server...");
Ok(()) // We got to own watcher so that it exists for the duration of serve
// Otherwise full reload won't work.
let _watcher = setup_file_watcher(
{
let config = config.clone();
let serve = serve.clone();
move || {
platform
.write()
.unwrap()
.rebuild(&config, &serve, Vec::new())
}
},
&config,
None,
hot_reload_state,
)
.await?;
hot_reload.await.unwrap()?;
Ok(())
})
} }
async fn start_desktop_hot_reload( async fn start_desktop_hot_reload(
+2 -2
View File
@@ -36,8 +36,8 @@ pub fn server_rust_flags(build: &ConfigOptsBuild) -> String {
rust_flags(build, SERVER_RUST_FLAGS) rust_flags(build, SERVER_RUST_FLAGS)
} }
pub async fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> { pub fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> {
desktop::startup_with_platform::<FullstackPlatform>(config, serve).await desktop::startup_with_platform::<FullstackPlatform>(config, serve)
} }
fn start_web_build_thread( fn start_web_build_thread(
+37 -34
View File
@@ -22,7 +22,7 @@ use server::*;
use super::HotReloadState; use super::HotReloadState;
pub async fn startup(config: CrateConfig, serve_cfg: &ConfigOptsServe) -> Result<()> { pub fn startup(config: CrateConfig, serve_cfg: &ConfigOptsServe) -> Result<()> {
set_ctrlc_handler(&config); set_ctrlc_handler(&config);
let ip = serve_cfg let ip = serve_cfg
@@ -33,11 +33,11 @@ pub async fn startup(config: CrateConfig, serve_cfg: &ConfigOptsServe) -> Result
let hot_reload_state = build_hotreload_filemap(&config); let hot_reload_state = build_hotreload_filemap(&config);
serve(ip, config, hot_reload_state, serve_cfg).await serve(ip, config, hot_reload_state, serve_cfg)
} }
/// Start the server without hot reload /// Start the server without hot reload
pub async fn serve( pub fn serve(
ip: IpAddr, ip: IpAddr,
config: CrateConfig, config: CrateConfig,
hot_reload_state: HotReloadState, hot_reload_state: HotReloadState,
@@ -55,42 +55,45 @@ pub async fn serve(
tracing::info!("🚀 Starting development server..."); tracing::info!("🚀 Starting development server...");
// We got to own watcher so that it exists for the duration of serve let rt = tokio::runtime::Runtime::new().unwrap();
// Otherwise full reload won't work. rt.block_on(async move {
let _watcher = setup_file_watcher( // We got to own watcher so that it exists for the duration of serve
{ // Otherwise full reload won't work.
let config = config.clone(); let _watcher = setup_file_watcher(
let hot_reload_state = hot_reload_state.clone(); {
move || build(&config, &hot_reload_state, skip_assets) let config = config.clone();
}, let hot_reload_state = hot_reload_state.clone();
&config, move || build(&config, &hot_reload_state, skip_assets)
Some(WebServerInfo { ip, port }), },
hot_reload_state.clone(), &config,
) Some(WebServerInfo { ip, port }),
.await?; hot_reload_state.clone(),
)
.await?;
// HTTPS // HTTPS
// Before console info so it can stop if mkcert isn't installed or fails // Before console info so it can stop if mkcert isn't installed or fails
let rustls_config = get_rustls(&config).await?; let rustls_config = get_rustls(&config).await?;
// Print serve info // Print serve info
print_console_info( print_console_info(
&config, &config,
PrettierOptions { PrettierOptions {
changed: vec![], changed: vec![],
warnings: first_build_result.warnings, warnings: first_build_result.warnings,
elapsed_time: first_build_result.elapsed_time, elapsed_time: first_build_result.elapsed_time,
}, },
Some(WebServerInfo { ip, port }), Some(WebServerInfo { ip, port }),
); );
// Router // Router
let router = setup_router(config.clone(), hot_reload_state).await?; let router = setup_router(config.clone(), hot_reload_state).await?;
// Start server // Start server
start_server(ip, port, router, opts.open, rustls_config, &config).await?; start_server(ip, port, router, opts.open, rustls_config, &config).await?;
Ok(()) Ok(())
})
} }
/// Starts dx serve with no hot reload /// Starts dx serve with no hot reload