diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..35049cbc --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +xtask = "run --package xtask --" diff --git a/Cargo.lock b/Cargo.lock index 0020ff1b..a061c458 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -863,6 +863,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.28" @@ -1985,16 +1991,6 @@ dependencies = [ "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "num_enum" version = "0.5.11" @@ -2331,9 +2327,9 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "rayon" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -2341,14 +2337,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -3447,6 +3441,21 @@ dependencies = [ "nom", ] +[[package]] +name = "xflags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9e15fbb3de55454b0106e314b28e671279009b363e6f1d8e39fdc3bf048944" +dependencies = [ + "xflags-macros", +] + +[[package]] +name = "xflags-macros" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155" + [[package]] name = "xi-unicode" version = "0.3.0" @@ -3465,6 +3474,15 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd" +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "flate2", + "fs_extra", + "xflags", +] + [[package]] name = "zerocopy" version = "0.7.32" diff --git a/Cargo.toml b/Cargo.toml index 6b1082eb..eacb6a46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,10 @@ readme = "README.md" description = "A simple portable multimedia layer to create apps or games easily" [workspace] -members = ["crates/*"] +members = [ + "crates/*", + "xtask" +] [workspace.package] version = "0.12.1" diff --git a/scripts/build_docs.ps1 b/scripts/build_docs.ps1 deleted file mode 100644 index 2d5805f0..00000000 --- a/scripts/build_docs.ps1 +++ /dev/null @@ -1 +0,0 @@ -Start-Process cargo -ArgumentList "doc --all-features" -NoNewWindow -Wait diff --git a/scripts/build_docs.sh b/scripts/build_docs.sh deleted file mode 100755 index 0f362426..00000000 --- a/scripts/build_docs.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cargo doc --all-features - diff --git a/scripts/build_msvc_examples.ps1 b/scripts/build_msvc_examples.ps1 deleted file mode 100644 index 85d31b8f..00000000 --- a/scripts/build_msvc_examples.ps1 +++ /dev/null @@ -1,19 +0,0 @@ -# Create directory if it doesn't exist -[void](New-Item -ItemType Directory -Path ".\docs\msvc_examples\examples\assets" -ErrorAction SilentlyContinue) - -# Copy assets to docs/examples directory -Copy-Item -Path ".\examples\assets" -Destination ".\docs\msvc_examples" -Recurse -ErrorAction SilentlyContinue - -# Function to compile each example -function Compile { - param ( - [string]$example - ) - - .\scripts\msvc_example.ps1 $example --release --no-assets -} - -# Loop through each .rs file in examples directory -Get-ChildItem -Path ".\examples\*.rs" | ForEach-Object { - Compile $_.Basename -} diff --git a/scripts/build_web_examples.ps1 b/scripts/build_web_examples.ps1 deleted file mode 100644 index 0277f17c..00000000 --- a/scripts/build_web_examples.ps1 +++ /dev/null @@ -1,36 +0,0 @@ -# Create directory if it doesn't exist -[void](New-Item -ItemType Directory -Path ".\docs\examples\assets" -ErrorAction SilentlyContinue) - -# Copy assets to docs/examples directory -Copy-Item -Path ".\examples\assets" -Destination ".\docs\examples" -Recurse -ErrorAction SilentlyContinue - -# Initialize document body -$doc_body = "" - -# Copy docs.html to index.html and replace body placeholder -Copy-Item -Path ".\scripts\docs.html" -Destination ".\docs\index.html" -$index = (Get-Content ".\scripts\docs.html") -replace "{{ BODY }}", $doc_body -$index | Set-Content -Path ".\docs\index.html" diff --git a/scripts/build_web_examples.sh b/scripts/build_web_examples.sh index 1a9102e4..ed6ae5b3 100755 --- a/scripts/build_web_examples.sh +++ b/scripts/build_web_examples.sh @@ -1,27 +1 @@ -#!/bin/bash -mkdir -p ./docs/examples/assets -cp -R ./examples/assets ./docs/examples - -doc_body="" -cp ./scripts/docs.html ./docs/index.html -index=$(sed "s#{{ BODY }}#${doc_body}#g" "./scripts/docs.html") -echo "${index}" > ./docs/index.html +cargo xtask examples web --release \ No newline at end of file diff --git a/scripts/msvc_example.ps1 b/scripts/msvc_example.ps1 deleted file mode 100644 index 88e656f9..00000000 --- a/scripts/msvc_example.ps1 +++ /dev/null @@ -1,22 +0,0 @@ -param( - [string]$1, - [string]$2, - [string]$3 -) - -$features = "glyph,egui,text,extra,audio,links,drop_files,clipboard,save_file,texture_to_file" -if ($2 -eq "--release") { - # Build release version - cargo build --target x86_64-pc-windows-msvc --release --example $1 --features=$features - Copy-Item .\target\x86_64-pc-windows-msvc\release\examples\$1.exe .\docs\msvc_examples\$1.exe -} -else { - # Build debug version - cargo build --target x86_64-pc-windows-msvc --example $1 --features=$features - Copy-Item .\target\x86_64-pc-windows-msvc\debug\examples\$1.exe .\docs\msvc_examples\$1.exe -} - -if ($3 -ne "--no-assets") { - # Copy assets folder - Copy-Item .\examples\assets .\docs\msvc_examples -Recurse -Force -} diff --git a/scripts/web_example.ps1 b/scripts/web_example.ps1 deleted file mode 100644 index f14f284d..00000000 --- a/scripts/web_example.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -param( - [string]$1, - [string]$2, - [string]$3 -) - -[void](New-Item -ItemType Directory -Path ".\docs\examples\$1" -Force) - -$env:RUSTFLAGS = "--cfg=web_sys_unstable_apis" -$features = "glyph,egui,text,extra,audio,links,drop_files,clipboard,save_file,texture_to_file" - -if ($2 -eq "--release") { - # Build release version - cargo build --target wasm32-unknown-unknown --release --example $1 --features=$features - wasm-bindgen .\target\wasm32-unknown-unknown\release\examples\$1.wasm --out-dir .\docs\examples\$1 --no-modules --browser - wasm-opt -O -o .\docs\examples\$1\${1}_bg.wasm .\docs\examples\$1\${1}_bg.wasm - - if ($3 -eq "--gzip") { - # Gzip the wasm files - Compress-Archive -Path ".\docs\examples\$1\$1_bg.wasm" -DestinationPath ".\docs\examples\$1\$1_bg.wasm.gz" -Force - Compress-Archive -Path ".\docs\examples\$1\$1.js" -DestinationPath ".\docs\examples\$1\$1.js.gz" -Force - } -} -else { - # Build debug version - cargo build --target wasm32-unknown-unknown --example $1 --features=$features - wasm-bindgen .\target\wasm32-unknown-unknown\debug\examples\$1.wasm --out-dir .\docs\examples\$1 --no-modules --browser --keep-debug --debug -} - -# Copy example.html and replace placeholder with example name -Copy-Item .\scripts\example.html .\docs\examples\$1.html -Force -$index = Get-Content .\scripts\example.html | ForEach-Object { $_ -replace '{{ EXAMPLE }}', $1 } -$index | Set-Content .\docs\examples\$1.html -Force - -if ($3 -ne "--no-assets") { - # Copy assets folder - Copy-Item .\examples\assets .\docs\examples -Recurse -Force -} diff --git a/scripts/web_example.sh b/scripts/web_example.sh deleted file mode 100755 index 5e880618..00000000 --- a/scripts/web_example.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -mkdir -p ./docs/examples/$1 - -# web_sys_unstable_apis is required to enable the web_sys clipboard API -# https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Clipboard.html -export RUSTFLAGS=--cfg=web_sys_unstable_apis -features=glyph,egui,text,extra,audio,links,drop_files,clipboard,save_file,texture_to_file - -if [[ $2 == '--release' ]]; -then - cargo build --target wasm32-unknown-unknown --release --example $1 --features=$features - wasm-bindgen ./target/wasm32-unknown-unknown/release/examples/$1.wasm --out-dir ./docs/examples/$1 --no-modules --browser - wasm-opt -O -o ./docs/examples/$1/$1_bg.wasm ./docs/examples/$1/$1_bg.wasm - - if [[ $3 == '--gzip' ]]; - then - gzip -f ./docs/examples/$1/$1_bg.wasm - gzip -f ./docs/examples/$1/$1.js - fi - -else - cargo build --target wasm32-unknown-unknown --example $1 --features=$features - wasm-bindgen ./target/wasm32-unknown-unknown/debug/examples/$1.wasm --out-dir ./docs/examples/$1 --no-modules --browser --keep-debug --debug -fi - -cp ./scripts/example.html ./docs/examples/$1.html -index=$(sed "s/{{ EXAMPLE }}/${1}/g" "./scripts/example.html") -echo "${index}" > ./docs/examples/$1.html - -if [[ $3 != '--no-assets' ]]; -then - cp -R ./examples/assets ./docs/examples -fi diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 00000000..0cab6a08 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "xtask" +version = "0.1.0" +publish = false +authors.workspace = true +edition.workspace = true +homepage.workspace = true +repository.workspace = true +license.workspace = true +readme = "README.md" +description = "" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +flate2 = "1.0" +fs_extra = "1.3.0" +xflags = "0.3.2" diff --git a/xtask/README.md b/xtask/README.md new file mode 100644 index 00000000..09cb263a --- /dev/null +++ b/xtask/README.md @@ -0,0 +1,4 @@ +xtask +=== + +Adds useful development commands using xtask. Use the command `cargo xtask` to show the help. diff --git a/scripts/docs.html b/xtask/res/docs.html similarity index 100% rename from scripts/docs.html rename to xtask/res/docs.html diff --git a/scripts/example.html b/xtask/res/example.html similarity index 100% rename from scripts/example.html rename to xtask/res/example.html diff --git a/xtask/src/cli.rs b/xtask/src/cli.rs new file mode 100644 index 00000000..e95c17c5 --- /dev/null +++ b/xtask/src/cli.rs @@ -0,0 +1,98 @@ +#![allow(unreachable_pub)] + +use std::str::FromStr; + +xflags::xflags! { + src "./src/cli.rs" + + cmd cli { + cmd docs {} + cmd example { + required name: String + required target: TargetType + + optional --release + optional --no-assets + optional --gzip + } + + cmd examples { + required target: TargetType + + optional --release + optional --gzip + } + } +} + +// generated start +// The following code is generated by `xflags` macro. +// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate. +#[derive(Debug)] +pub struct Cli { + pub subcommand: CliCmd, +} + +#[derive(Debug)] +pub enum CliCmd { + Docs(Docs), + Example(Example), + Examples(Examples), +} + +#[derive(Debug)] +pub struct Docs; + +#[derive(Debug)] +pub struct Example { + pub name: String, + pub target: TargetType, + + pub release: bool, + pub no_assets: bool, + pub gzip: bool, +} + +#[derive(Debug)] +pub struct Examples { + pub target: TargetType, + + pub release: bool, + pub gzip: bool, +} + +impl Cli { + #[allow(dead_code)] + pub fn from_env_or_exit() -> Self { + Self::from_env_or_exit_() + } + + #[allow(dead_code)] + pub fn from_env() -> xflags::Result { + Self::from_env_() + } + + #[allow(dead_code)] + pub fn from_vec(args: Vec) -> xflags::Result { + Self::from_vec_(args) + } +} +// generated end + +#[derive(Copy, Clone, Debug, Default)] +pub enum TargetType { + #[default] + Msvc, + Web, +} + +impl FromStr for TargetType { + type Err = String; + fn from_str(s: &str) -> Result { + match s { + "msvc" => Ok(Self::Msvc), + "web" => Ok(Self::Web), + _ => Err("Invalid option".to_owned()), + } + } +} diff --git a/xtask/src/cli_docs.rs b/xtask/src/cli_docs.rs new file mode 100644 index 00000000..e36b282a --- /dev/null +++ b/xtask/src/cli_docs.rs @@ -0,0 +1,40 @@ +use std::path::PathBuf; +use std::process::Command; +use std::{env, fs}; + +use crate::cli::Docs; +use crate::{project_root, DynError}; + +impl Docs { + pub(crate) fn run(self) -> Result<(), DynError> { + docs_clean()?; + docs_run()?; + + Ok(()) + } +} + +fn docs_clean() -> Result<(), DynError> { + let _ = fs::remove_dir_all(dist_doc_dir()); + fs::create_dir_all(dist_doc_dir())?; + + Ok(()) +} + +fn docs_run() -> Result<(), DynError> { + let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); + let status = Command::new(cargo) + .current_dir(project_root()) + .args(["doc", "--all-features"]) + .status()?; + + if !status.success() { + Err("Command 'cargo doc --all-features' failed")?; + } + + Ok(()) +} + +fn dist_doc_dir() -> PathBuf { + project_root().join("target/doc") +} diff --git a/xtask/src/cli_example.rs b/xtask/src/cli_example.rs new file mode 100644 index 00000000..68102af7 --- /dev/null +++ b/xtask/src/cli_example.rs @@ -0,0 +1,13 @@ +use crate::cli::{Example, TargetType}; +use crate::DynError; + +impl Example { + pub(crate) fn run(self) -> Result<(), DynError> { + match self.target { + TargetType::Msvc => self.run_msvc()?, + TargetType::Web => self.run_web()?, + } + + Ok(()) + } +} diff --git a/xtask/src/cli_example_msvc.rs b/xtask/src/cli_example_msvc.rs new file mode 100644 index 00000000..8df06234 --- /dev/null +++ b/xtask/src/cli_example_msvc.rs @@ -0,0 +1,52 @@ +use std::fs; +use std::path::PathBuf; + +use crate::cli::{Example, TargetType}; +use crate::{cargo_build, copy_assets, project_root, DynError}; + +impl Example { + pub(crate) fn run_msvc(self) -> Result<(), DynError> { + let status = match self.release { + true => cargo_build(TargetType::Msvc, "release", self.name.as_str())?, + false => cargo_build(TargetType::Msvc, "dev", self.name.as_str())?, + }; + + if !status.success() { + Err("Command 'cargo build' failed")?; + } + + let name_str = self.name.as_str(); + let executable = format!("{name_str}.exe"); + + fs::create_dir_all(docs_msvc_dir(self.release))?; + let _ = fs::copy( + dist_msvc_dir(self.release).join(executable.as_str()), + docs_msvc_dir(self.release).join(executable.as_str()), + ); + + if !self.no_assets { + copy_assets(docs_msvc_dir(self.release)); + } + + Ok(()) + } +} + +pub fn docs_msvc_dir(release: bool) -> PathBuf { + project_root() + .join("docs/msvc_examples/") + .join(match release { + true => "release", + false => "debug", + }) +} + +fn dist_msvc_dir(release: bool) -> PathBuf { + project_root() + .join("target/x86_64-pc-windows-msvc") + .join(match release { + true => "release", + false => "debug", + }) + .join("examples") +} diff --git a/xtask/src/cli_example_web.rs b/xtask/src/cli_example_web.rs new file mode 100644 index 00000000..4064f491 --- /dev/null +++ b/xtask/src/cli_example_web.rs @@ -0,0 +1,109 @@ +use std::fs::File; +use std::io::{BufRead, BufReader, Write}; +use std::path::PathBuf; + +use crate::cli::{Example, TargetType}; +use crate::{cargo_build, copy_assets, gz_file, project_root, wasm_bindgen, wasm_opt, DynError}; + +impl Example { + pub(crate) fn run_web(self) -> Result<(), DynError> { + let status = match self.release { + true => cargo_build(TargetType::Web, "release", self.name.as_str())?, + false => cargo_build(TargetType::Web, "dev", self.name.as_str())?, + }; + + if !status.success() { + Err("Command 'cargo build' failed")?; + } + + let name_str = self.name.as_str(); + let wasm = format!("{name_str}.wasm"); + + let input = dist_web_dir(self.release) + .join(wasm.as_str()) + .to_string_lossy() + .into_owned(); + let output = docs_web_dir(name_str).to_string_lossy().into_owned(); + + let status = wasm_bindgen(input.as_str(), output.as_str(), !self.release)?; + if !status.success() { + Err("Command 'wasm-bindgen' failed")?; + } + + if self.release { + let wasm_file = format!("{name_str}_bg.wasm"); + let inout = docs_web_dir(name_str) + .join(wasm_file.as_str()) + .to_string_lossy() + .into_owned(); + + let status = wasm_opt(inout.as_str(), inout.as_str())?; + if !status.success() { + Err("Command 'wasm-opt' failed")?; + } + + if self.gzip { + let wasm_gz = format!("{wasm_file}.gz"); + let wasm_gz_output = docs_web_dir(name_str) + .join(wasm_gz) + .to_string_lossy() + .into_owned(); + + let js_gz_input = docs_web_dir(name_str) + .join(format!("{name_str}.js")) + .to_string_lossy() + .into_owned(); + let js_gz_output = docs_web_dir(name_str) + .join(format!("{name_str}.js.gz")) + .to_string_lossy() + .into_owned(); + + gz_file(inout.as_str(), wasm_gz_output.as_str()); + gz_file(js_gz_input.as_str(), js_gz_output.as_str()); + } + } + + let example_file = format!("{name_str}.html"); + + let file_in = File::open(res_dir().join("example.html"))?; + let reader = BufReader::new(file_in); + + let mut output_lines = Vec::new(); + for line in reader.lines() { + let mut line = line?; + + line = line.replace("{{ EXAMPLE }}", self.name.as_str()); + output_lines.push(line); + } + + let mut file_out = File::create(docs_web_dir("").join(example_file.as_str()))?; + + for line in &output_lines { + writeln!(file_out, "{}", line)?; + } + + if !self.no_assets { + copy_assets(docs_web_dir("")) + } + + Ok(()) + } +} + +pub fn docs_web_dir(name: &str) -> PathBuf { + project_root().join("docs").join("examples").join(name) +} + +fn dist_web_dir(release: bool) -> PathBuf { + project_root() + .join("target/wasm32-unknown-unknown") + .join(match release { + true => "release", + false => "debug", + }) + .join("examples") +} + +pub fn res_dir() -> PathBuf { + project_root().join("xtask/res") +} diff --git a/xtask/src/cli_examples.rs b/xtask/src/cli_examples.rs new file mode 100644 index 00000000..4c1893de --- /dev/null +++ b/xtask/src/cli_examples.rs @@ -0,0 +1,41 @@ +use std::fs; +use std::path::PathBuf; + +use crate::cli::{Examples, TargetType}; +use crate::DynError; + +impl Examples { + pub(crate) fn run(self) -> Result<(), DynError> { + match self.target { + TargetType::Msvc => self.run_msvc()?, + TargetType::Web => self.run_web()?, + } + + Ok(()) + } + + pub(crate) fn list_files(self, path: &str) -> Result, DynError> { + let entries = fs::read_dir(path)?; + let dir_entries: Vec<_> = entries + .filter_map(Result::ok) + .filter_map(|entry| { + let metadata = entry.metadata().ok()?; + let is_file = metadata.is_file(); + let is_hidden = entry + .file_name() + .to_str() + .map(|name| name.starts_with('.')) + .unwrap_or_default(); + let is_valid = is_file && !is_hidden; + if is_valid { + Some(entry) + } else { + None + } + }) + .map(|entry| entry.path()) + .collect(); + + Ok(dir_entries.into_iter()) + } +} diff --git a/xtask/src/cli_examples_msvc.rs b/xtask/src/cli_examples_msvc.rs new file mode 100644 index 00000000..44629cf0 --- /dev/null +++ b/xtask/src/cli_examples_msvc.rs @@ -0,0 +1,35 @@ +use crate::cli::{Example, Examples}; +use crate::cli_example_msvc::docs_msvc_dir; +use crate::{copy_assets, project_root, DynError}; + +impl Examples { + pub(crate) fn run_msvc(self) -> Result<(), DynError> { + copy_assets(docs_msvc_dir(self.release).join("assets")); + + let examples_path = project_root() + .join("examples") + .to_string_lossy() + .into_owned(); + + let target = self.target; + let release = self.release; + let gzip = self.gzip; + + self.list_files(examples_path.as_str())? + .for_each(|example| { + let name = example.file_stem().unwrap().to_str().unwrap().to_owned(); + // eprintln!("{}", name); + let example = Example { + name, + target, + release, + no_assets: true, + gzip, + }; + + let _ = example.run(); + }); + + Ok(()) + } +} diff --git a/xtask/src/cli_examples_web.rs b/xtask/src/cli_examples_web.rs new file mode 100644 index 00000000..e43b0ddc --- /dev/null +++ b/xtask/src/cli_examples_web.rs @@ -0,0 +1,66 @@ +use std::fs::File; +use std::io::{BufRead, BufReader, Write}; + +use crate::cli::{Example, Examples}; +use crate::cli_example_web::docs_web_dir; +use crate::{copy_assets, project_root, DynError}; + +impl Examples { + pub(crate) fn run_web(self) -> Result<(), DynError> { + copy_assets(docs_web_dir("assets")); + + let mut doc_body = String::from("
    \n"); + + let examples_path = project_root() + .join("examples") + .to_string_lossy() + .into_owned(); + + let target = self.target; + let release = self.release; + let gzip = self.gzip; + + self.list_files(examples_path.as_str())? + .for_each(|example| { + let name = example.file_stem().unwrap().to_str().unwrap().to_owned(); + let name_str = name.as_str().to_owned(); + + let example = Example { + name, + target, + release, + no_assets: true, + gzip, + }; + + let _ = example.run(); + + let url = format!("examples/{name_str}.html"); + let image = format!("examples/images/{name_str}.jpg"); + let tmp = format!("\n
  • \"{name_str}\"
    {name_str}
  • "); + + doc_body.push_str(tmp.as_str()); + }); + + doc_body.push_str("\n
"); + + let file_in = File::open(crate::cli_example_web::res_dir().join("docs.html"))?; + let reader = BufReader::new(file_in); + + let mut output_lines = Vec::new(); + for line in reader.lines() { + let mut line = line?; + + line = line.replace("{{ BODY }}", doc_body.as_str()); + output_lines.push(line); + } + + let mut file_out = File::create(docs_web_dir("../").join("index.html"))?; + + for line in &output_lines { + writeln!(file_out, "{}", line)?; + } + + Ok(()) + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 00000000..ca579a94 --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,133 @@ +mod cli; + +mod cli_docs; +mod cli_example; +mod cli_example_msvc; +mod cli_example_web; +mod cli_examples; +mod cli_examples_msvc; +mod cli_examples_web; + +use crate::cli::TargetType; +use cli::{Cli, CliCmd}; +use flate2::write::GzEncoder; +use flate2::Compression; +use std::env; +use std::fs::File; +use std::io::{copy, BufReader, Error}; +use std::path::PathBuf; +use std::process::{Command, ExitStatus}; + +type DynError = Box; + +fn main() { + if let Err(e) = try_main() { + eprintln!("{}", e); + std::process::exit(-1); + } +} + +fn try_main() -> Result<(), DynError> { + let flags = Cli::from_env_or_exit(); + + match flags.subcommand { + CliCmd::Docs(cmd) => cmd.run()?, + CliCmd::Example(cmd) => cmd.run()?, + CliCmd::Examples(cmd) => cmd.run()?, + } + + Ok(()) +} + +fn project_root() -> PathBuf { + let dir = + env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()); + + PathBuf::from(dir).parent().unwrap().to_owned() +} + +fn assets_dir() -> PathBuf { + project_root().join("examples/assets") +} + +fn copy_assets(to: PathBuf) { + let options = fs_extra::dir::CopyOptions::new() + .overwrite(true) + .copy_inside(true); + + let paths = vec![assets_dir().as_path().to_owned()]; + let _ = fs_extra::copy_items(&paths, to, &options); +} + +fn cargo_build(target: TargetType, profile: &str, name: &str) -> Result { + let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); + + // We want this to be configurable? + let features = + "glyph,egui,text,extra,audio,links,drop_files,clipboard,save_file,texture_to_file"; + let features_arg = format!("--features={features}"); + + match target { + TargetType::Msvc => Command::new(cargo) + .current_dir(project_root()) + .args([ + "build", + "--target", + "x86_64-pc-windows-msvc", + "--profile", + profile, + "--example", + name, + features_arg.as_str(), + ]) + .status(), + + TargetType::Web => Command::new(cargo) + .current_dir(project_root()) + .env("RUSTFLAGS", "--cfg=web_sys_unstable_apis") + .args([ + "build", + "--target", + "wasm32-unknown-unknown", + "--profile", + profile, + "--example", + name, + features_arg.as_str(), + ]) + .status(), + } +} + +fn wasm_bindgen(input: &str, output: &str, debug: bool) -> Result { + Command::new("wasm-bindgen") + .current_dir(project_root()) + .args( + &[ + [input, "--out-dir", output, "--no-modules", "--browser"].as_slice(), + match debug { + true => ["--keep-debug", "--debug"].as_slice(), + false => [].as_slice(), + }, + ] + .concat(), + ) + .status() +} + +fn wasm_opt(input: &str, output: &str) -> Result { + Command::new("wasm-opt") + .current_dir(project_root()) + .args(["-O", "-o", input, output]) + .status() +} + +fn gz_file(input: &str, output: &str) { + let mut input_wasm = BufReader::new(File::open(input).unwrap()); + let output_wasm = File::create(output).unwrap(); + + let mut encoder_wasm = GzEncoder::new(output_wasm, Compression::default()); + + copy(&mut input_wasm, &mut encoder_wasm).unwrap(); + encoder_wasm.finish().unwrap(); +}