1
0

builder.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. use crate::{
  2. cli::BuildOptions,
  3. config::{Config, ExecutableType},
  4. error::Result,
  5. };
  6. use log::{info, warn};
  7. use std::{io::Write, process::Command};
  8. use wasm_bindgen_cli_support::Bindgen;
  9. pub struct BuildConfig {}
  10. impl Into<BuildConfig> for BuildOptions {
  11. fn into(self) -> BuildConfig {
  12. BuildConfig {}
  13. }
  14. }
  15. impl Default for BuildConfig {
  16. fn default() -> Self {
  17. Self {}
  18. }
  19. }
  20. pub fn build(config: &Config, _build_config: &BuildConfig) -> Result<()> {
  21. /*
  22. [1] Build the project with cargo, generating a wasm32-unknown-unknown target (is there a more specific, better target to leverage?)
  23. [2] Generate the appropriate build folders
  24. [3] Wasm-bindgen the .wasm fiile, and move it into the {builddir}/modules/xxxx/xxxx_bg.wasm
  25. [4] Wasm-opt the .wasm file with whatever optimizations need to be done
  26. [5] Link up the html page to the wasm module
  27. */
  28. let Config {
  29. out_dir,
  30. crate_dir,
  31. target_dir,
  32. static_dir,
  33. executable,
  34. ..
  35. } = config;
  36. let t_start = std::time::Instant::now();
  37. // [1] Build the .wasm module
  38. info!("Running build commands...");
  39. let mut cmd = Command::new("cargo");
  40. cmd.current_dir(&crate_dir)
  41. .arg("build")
  42. .arg("--target")
  43. .arg("wasm32-unknown-unknown")
  44. .stdout(std::process::Stdio::piped())
  45. .stderr(std::process::Stdio::piped());
  46. if config.release {
  47. cmd.arg("--release");
  48. }
  49. match executable {
  50. ExecutableType::Binary(name) => cmd.arg("--bin").arg(name),
  51. ExecutableType::Lib(name) => cmd.arg("--lib").arg(name),
  52. ExecutableType::Example(name) => cmd.arg("--example").arg(name),
  53. };
  54. let mut child = cmd.spawn()?;
  55. let _err_code = child.wait()?;
  56. // [2] Establish the output directory structure
  57. let bindgen_outdir = out_dir.join("wasm");
  58. // [3] Bindgen the final binary for use easy linking
  59. let mut bindgen_builder = Bindgen::new();
  60. let input_path = match executable {
  61. ExecutableType::Binary(name) | ExecutableType::Lib(name) => target_dir
  62. // .join("wasm32-unknown-unknown/release")
  63. .join("wasm32-unknown-unknown/debug")
  64. .join(format!("{}.wasm", name)),
  65. ExecutableType::Example(name) => target_dir
  66. // .join("wasm32-unknown-unknown/release/examples")
  67. .join("wasm32-unknown-unknown/debug/examples")
  68. .join(format!("{}.wasm", name)),
  69. };
  70. bindgen_builder
  71. .input_path(input_path)
  72. .web(true)?
  73. .debug(true)
  74. .demangle(true)
  75. .keep_debug(true)
  76. .remove_name_section(false)
  77. .remove_producers_section(false)
  78. .out_name("module")
  79. .generate(&bindgen_outdir)?;
  80. // [4]
  81. // TODO: wasm-opt
  82. // [5] Generate the html file with the module name
  83. // TODO: support names via options
  84. info!("Writing to '{:#?}' directory...", out_dir);
  85. let mut file = std::fs::File::create(out_dir.join("index.html"))?;
  86. file.write_all(gen_page("./wasm/module.js").as_str().as_bytes())?;
  87. let copy_options = fs_extra::dir::CopyOptions::new();
  88. match fs_extra::dir::copy(static_dir, out_dir, &copy_options) {
  89. Ok(_) => {}
  90. Err(_e) => {
  91. warn!("Error copying dir");
  92. }
  93. }
  94. let t_end = std::time::Instant::now();
  95. log::info!("Done in {}ms! 🎉", (t_end - t_start).as_millis());
  96. Ok(())
  97. }
  98. fn gen_page(module: &str) -> String {
  99. format!(
  100. r#"
  101. <html>
  102. <head>
  103. <meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
  104. <meta charset="UTF-8" />
  105. <link
  106. href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css"
  107. rel="stylesheet"
  108. />
  109. </head>
  110. <body>
  111. <!-- Note the usage of `type=module` here as this is an ES6 module -->
  112. <script type="module">
  113. import init from "{}";
  114. init();
  115. </script>
  116. </body>
  117. </html>
  118. "#,
  119. module
  120. )
  121. }