2021-07-07 20:54:14 +00:00
|
|
|
use crate::{
|
2021-12-29 17:03:18 +00:00
|
|
|
config::{CrateConfig, ExecutableType},
|
|
|
|
error::{Error, Result},
|
2022-01-23 09:35:59 +00:00
|
|
|
DioxusConfig,
|
2021-07-07 20:54:14 +00:00
|
|
|
};
|
2022-01-24 03:55:27 +00:00
|
|
|
use std::{
|
|
|
|
fs::{copy, create_dir_all, remove_dir_all},
|
|
|
|
path::PathBuf,
|
|
|
|
process::Command,
|
|
|
|
};
|
2021-07-07 20:54:14 +00:00
|
|
|
use wasm_bindgen_cli_support::Bindgen;
|
|
|
|
|
2022-01-23 09:35:59 +00:00
|
|
|
pub fn build(config: &CrateConfig) -> Result<()> {
|
2021-07-07 20:54:14 +00:00
|
|
|
/*
|
|
|
|
[1] Build the project with cargo, generating a wasm32-unknown-unknown target (is there a more specific, better target to leverage?)
|
|
|
|
[2] Generate the appropriate build folders
|
|
|
|
[3] Wasm-bindgen the .wasm fiile, and move it into the {builddir}/modules/xxxx/xxxx_bg.wasm
|
|
|
|
[4] Wasm-opt the .wasm file with whatever optimizations need to be done
|
|
|
|
[5] Link up the html page to the wasm module
|
|
|
|
*/
|
|
|
|
|
2021-12-29 17:03:18 +00:00
|
|
|
let CrateConfig {
|
2022-01-23 09:35:59 +00:00
|
|
|
out_dir,
|
2021-07-07 20:54:14 +00:00
|
|
|
crate_dir,
|
|
|
|
target_dir,
|
2022-01-23 14:50:23 +00:00
|
|
|
public_dir,
|
2021-07-07 20:54:14 +00:00
|
|
|
executable,
|
2022-01-23 09:35:59 +00:00
|
|
|
dioxus_config,
|
2021-07-07 20:54:14 +00:00
|
|
|
..
|
|
|
|
} = config;
|
|
|
|
|
|
|
|
let t_start = std::time::Instant::now();
|
|
|
|
|
|
|
|
// [1] Build the .wasm module
|
2022-01-23 02:54:24 +00:00
|
|
|
log::info!("🚅 Running build command...");
|
2021-07-07 20:54:14 +00:00
|
|
|
let mut cmd = Command::new("cargo");
|
|
|
|
cmd.current_dir(&crate_dir)
|
|
|
|
.arg("build")
|
|
|
|
.arg("--target")
|
|
|
|
.arg("wasm32-unknown-unknown")
|
2022-01-22 14:19:59 +00:00
|
|
|
.stdout(std::process::Stdio::inherit())
|
2022-01-22 17:29:36 +00:00
|
|
|
.stderr(std::process::Stdio::inherit());
|
2021-07-07 20:54:14 +00:00
|
|
|
|
|
|
|
if config.release {
|
|
|
|
cmd.arg("--release");
|
|
|
|
}
|
|
|
|
|
|
|
|
match executable {
|
|
|
|
ExecutableType::Binary(name) => cmd.arg("--bin").arg(name),
|
|
|
|
ExecutableType::Lib(name) => cmd.arg("--lib").arg(name),
|
|
|
|
ExecutableType::Example(name) => cmd.arg("--example").arg(name),
|
|
|
|
};
|
|
|
|
|
2022-01-22 14:19:59 +00:00
|
|
|
let output = cmd.output()?;
|
2022-01-22 02:02:52 +00:00
|
|
|
|
2022-01-23 04:11:17 +00:00
|
|
|
if !output.status.success() {
|
2021-12-29 17:03:18 +00:00
|
|
|
log::error!("Build failed!");
|
2022-01-22 14:19:59 +00:00
|
|
|
let reason = String::from_utf8_lossy(&output.stderr).to_string();
|
2021-12-29 17:03:18 +00:00
|
|
|
return Err(Error::BuildFailed(reason));
|
|
|
|
}
|
2022-01-23 09:35:59 +00:00
|
|
|
|
2021-07-07 20:54:14 +00:00
|
|
|
// [2] Establish the output directory structure
|
2022-01-23 14:50:23 +00:00
|
|
|
let bindgen_outdir = out_dir.join("assets").join("dioxus");
|
2021-07-07 20:54:14 +00:00
|
|
|
|
|
|
|
// [3] Bindgen the final binary for use easy linking
|
|
|
|
let mut bindgen_builder = Bindgen::new();
|
|
|
|
|
|
|
|
let release_type = match config.release {
|
|
|
|
true => "release",
|
|
|
|
false => "debug",
|
|
|
|
};
|
|
|
|
|
|
|
|
let input_path = match executable {
|
|
|
|
ExecutableType::Binary(name) | ExecutableType::Lib(name) => target_dir
|
|
|
|
.join(format!("wasm32-unknown-unknown/{}", release_type))
|
|
|
|
.join(format!("{}.wasm", name)),
|
|
|
|
|
|
|
|
ExecutableType::Example(name) => target_dir
|
|
|
|
.join(format!("wasm32-unknown-unknown/{}/examples", release_type))
|
|
|
|
.join(format!("{}.wasm", name)),
|
|
|
|
};
|
|
|
|
|
|
|
|
bindgen_builder
|
|
|
|
.input_path(input_path)
|
|
|
|
.web(true)?
|
|
|
|
.debug(true)
|
|
|
|
.demangle(true)
|
|
|
|
.keep_debug(true)
|
|
|
|
.remove_name_section(false)
|
|
|
|
.remove_producers_section(false)
|
2022-01-23 09:35:59 +00:00
|
|
|
.out_name(&dioxus_config.application.name)
|
2021-07-07 20:54:14 +00:00
|
|
|
.generate(&bindgen_outdir)?;
|
|
|
|
|
2022-01-23 14:50:23 +00:00
|
|
|
let copy_options = fs_extra::dir::CopyOptions {
|
|
|
|
overwrite: true,
|
|
|
|
skip_exist: false,
|
|
|
|
buffer_size: 64000,
|
|
|
|
copy_inside: false,
|
|
|
|
content_only: false,
|
|
|
|
depth: 0,
|
|
|
|
};
|
|
|
|
if public_dir.is_dir() {
|
|
|
|
for entry in std::fs::read_dir(&public_dir)? {
|
|
|
|
let path = entry?.path();
|
|
|
|
if path.is_file() {
|
|
|
|
std::fs::copy(&path, out_dir.join(path.file_name().unwrap()))?;
|
|
|
|
} else {
|
|
|
|
match fs_extra::dir::copy(&path, out_dir, ©_options) {
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(_e) => {
|
|
|
|
log::warn!("Error copying dir: {}", _e);
|
|
|
|
}
|
|
|
|
}
|
2022-01-22 02:02:52 +00:00
|
|
|
}
|
2021-07-07 20:54:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let t_end = std::time::Instant::now();
|
2022-01-22 14:19:59 +00:00
|
|
|
log::info!("🏁 Done in {}ms!", (t_end - t_start).as_millis());
|
2021-07-07 20:54:14 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-01-24 03:55:27 +00:00
|
|
|
pub fn build_desktop(config: &CrateConfig) -> Result<()> {
|
|
|
|
log::info!("🚅 Running build [Desktop] command...");
|
|
|
|
|
|
|
|
let mut cmd = Command::new("cargo");
|
|
|
|
cmd.current_dir(&config.crate_dir)
|
|
|
|
.arg("build")
|
|
|
|
.stdout(std::process::Stdio::inherit())
|
|
|
|
.stderr(std::process::Stdio::inherit());
|
|
|
|
|
|
|
|
if config.release {
|
|
|
|
cmd.arg("--release");
|
|
|
|
}
|
|
|
|
|
|
|
|
match &config.executable {
|
|
|
|
crate::ExecutableType::Binary(name) => cmd.arg("--bin").arg(name),
|
|
|
|
crate::ExecutableType::Lib(name) => cmd.arg("--lib").arg(name),
|
|
|
|
crate::ExecutableType::Example(name) => cmd.arg("--example").arg(name),
|
|
|
|
};
|
|
|
|
|
|
|
|
let output = cmd.output()?;
|
|
|
|
|
2022-01-27 15:06:09 +00:00
|
|
|
if !output.status.success() {
|
|
|
|
return Err(Error::BuildFailed("Program build failed.".into()));
|
|
|
|
}
|
|
|
|
|
2022-01-24 03:55:27 +00:00
|
|
|
if output.status.success() {
|
|
|
|
if config.out_dir.is_dir() {
|
|
|
|
remove_dir_all(&config.out_dir)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
let release_type = match config.release {
|
|
|
|
true => "release",
|
|
|
|
false => "debug",
|
|
|
|
};
|
|
|
|
|
|
|
|
let file_name: String;
|
|
|
|
let mut res_path = match &config.executable {
|
|
|
|
crate::ExecutableType::Binary(name) | crate::ExecutableType::Lib(name) => {
|
|
|
|
file_name = name.clone();
|
|
|
|
config
|
|
|
|
.target_dir
|
2022-01-25 04:42:27 +00:00
|
|
|
.join(release_type.to_string())
|
|
|
|
.join(name.to_string())
|
2022-01-24 03:55:27 +00:00
|
|
|
}
|
|
|
|
crate::ExecutableType::Example(name) => {
|
|
|
|
file_name = name.clone();
|
|
|
|
config
|
|
|
|
.target_dir
|
2022-01-25 04:42:27 +00:00
|
|
|
.join(release_type.to_string())
|
2022-01-24 03:55:27 +00:00
|
|
|
.join("examples")
|
2022-01-25 04:42:27 +00:00
|
|
|
.join(name.to_string())
|
2022-01-24 03:55:27 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-01-25 09:51:36 +00:00
|
|
|
let target_file = if cfg!(windows) {
|
2022-01-24 03:55:27 +00:00
|
|
|
res_path.set_extension("exe");
|
2022-01-25 09:51:36 +00:00
|
|
|
format!("{}.exe", &file_name)
|
2022-01-24 03:55:27 +00:00
|
|
|
} else {
|
2022-01-25 09:51:36 +00:00
|
|
|
file_name
|
|
|
|
};
|
|
|
|
|
2022-01-24 03:55:27 +00:00
|
|
|
create_dir_all(&config.out_dir)?;
|
|
|
|
copy(res_path, &config.out_dir.join(target_file))?;
|
|
|
|
|
|
|
|
log::info!(
|
|
|
|
"🚩 Build completed: [./{}]",
|
|
|
|
config
|
|
|
|
.dioxus_config
|
|
|
|
.application
|
|
|
|
.out_dir
|
|
|
|
.clone()
|
2022-01-25 05:52:33 +00:00
|
|
|
.unwrap_or_else(|| PathBuf::from("dist"))
|
2022-01-24 03:55:27 +00:00
|
|
|
.display()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-01-23 09:35:59 +00:00
|
|
|
pub fn gen_page(config: &DioxusConfig, serve: bool) -> String {
|
|
|
|
let mut html = String::from(include_str!("./assets/index.html"));
|
|
|
|
|
|
|
|
let resouces = config.web.resource.clone();
|
|
|
|
|
2022-01-25 04:42:27 +00:00
|
|
|
let mut style_list = resouces.style.unwrap_or_default();
|
|
|
|
let mut script_list = resouces.script.unwrap_or_default();
|
2022-01-23 09:35:59 +00:00
|
|
|
|
|
|
|
if serve {
|
2022-01-25 04:42:27 +00:00
|
|
|
let mut dev_style = resouces.dev.style.clone().unwrap_or_default();
|
|
|
|
let mut dev_script = resouces.dev.script.unwrap_or_default();
|
2022-01-23 09:35:59 +00:00
|
|
|
style_list.append(&mut dev_style);
|
|
|
|
script_list.append(&mut dev_script);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut style_str = String::new();
|
|
|
|
for style in style_list {
|
|
|
|
style_str.push_str(&format!(
|
|
|
|
"<link rel=\"stylesheet\" href=\"{}\">\n",
|
|
|
|
&style.to_str().unwrap(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
html = html.replace("{style_include}", &style_str);
|
|
|
|
|
|
|
|
let mut script_str = String::new();
|
|
|
|
for script in script_list {
|
|
|
|
script_str.push_str(&format!(
|
|
|
|
"<script src=\"{}\"></script>\n",
|
|
|
|
&script.to_str().unwrap(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
html = html.replace("{script_include}", &script_str);
|
|
|
|
|
|
|
|
if serve {
|
|
|
|
html += &format!(
|
|
|
|
"<script>{}</script>",
|
|
|
|
include_str!("./assets/autoreload.js")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
html = html.replace("{app_name}", &config.application.name);
|
|
|
|
|
2022-01-25 09:51:36 +00:00
|
|
|
let title = config
|
|
|
|
.web
|
|
|
|
.app
|
|
|
|
.title
|
|
|
|
.clone()
|
|
|
|
.unwrap_or_else(|| "dioxus | ⛺".into());
|
2022-01-23 09:35:59 +00:00
|
|
|
|
|
|
|
html.replace("{app_title}", &title)
|
2021-07-07 20:54:14 +00:00
|
|
|
}
|
2021-12-29 16:04:18 +00:00
|
|
|
|
|
|
|
// use binary_install::{Cache, Download};
|
|
|
|
|
|
|
|
// /// Attempts to find `wasm-opt` in `PATH` locally, or failing that downloads a
|
|
|
|
// /// precompiled binary.
|
|
|
|
// ///
|
|
|
|
// /// Returns `Some` if a binary was found or it was successfully downloaded.
|
|
|
|
// /// Returns `None` if a binary wasn't found in `PATH` and this platform doesn't
|
|
|
|
// /// have precompiled binaries. Returns an error if we failed to download the
|
|
|
|
// /// binary.
|
|
|
|
// pub fn find_wasm_opt(
|
|
|
|
// cache: &Cache,
|
|
|
|
// install_permitted: bool,
|
|
|
|
// ) -> Result<install::Status, failure::Error> {
|
|
|
|
// // First attempt to look up in PATH. If found assume it works.
|
|
|
|
// if let Ok(path) = which::which("wasm-opt") {
|
|
|
|
// PBAR.info(&format!("found wasm-opt at {:?}", path));
|
|
|
|
|
|
|
|
// match path.as_path().parent() {
|
|
|
|
// Some(path) => return Ok(install::Status::Found(Download::at(path))),
|
|
|
|
// None => {}
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// let version = "version_78";
|
|
|
|
// Ok(install::download_prebuilt(
|
|
|
|
// &install::Tool::WasmOpt,
|
|
|
|
// cache,
|
|
|
|
// version,
|
|
|
|
// install_permitted,
|
|
|
|
// )?)
|
|
|
|
// }
|