Skip to content

Instantly share code, notes, and snippets.

@arifd
Created October 1, 2020 21:48
Show Gist options
  • Save arifd/fb4ebd4d9995ddf02bc6016690a225b6 to your computer and use it in GitHub Desktop.
Save arifd/fb4ebd4d9995ddf02bc6016690a225b6 to your computer and use it in GitHub Desktop.
Miniquad, Rust, WASM, Web, build script
#!/bin/bash
#===========================================================================================#
# Miniquad WASM/Web Builder #
# #
# Put this script at the base of your cargo project and run it to quickly build and test #
# your miniquad project in a WASM/Web environment. #
# #
# It creates and pulls in all the necessary files into a directory called 'www/' leaving #
# the originals intact. Just delete the www folder to undo its effect. #
# #
# Default mode (without arguments) is debug. Pass in --release for release mode. #
# #
# If your project runs in the browser in debug but not in release, it's likely due to #
# an incompatible optimisation. Head over to that section and comment out the culprit. #
# #
# This script uses Python3 for the Web Server. #
#===========================================================================================#
### Setup ###
bold=$(tput bold)
normal=$(tput sgr0)
### Check supplied arguments ###
if [[ "$1" == "--release" ]] ; then
MODE="release"
else
MODE="debug"
fi
### Check build configurations ###
grep -q "lto = true" Cargo.toml || echo "hint: add ${bold}lto = true${normal} under ${bold}[profile.release]${normal} for futher optimisation"
# grep -q "debug = true" Cargo.toml || echo "hint: wasm-snip needs debug symbols to effectively stnip dead-code. Add ${bold}debug = true${normal} under ${bold}[profile.release]${normal} for futher optimisation"
### Get name of project ###
NAME=$(grep "name =" Cargo.toml | cut -d' ' -f3- | tr -d '"')
if [[ -z "$NAME" ]] ; then
echo "Abort! Can't deduce name from Cargo.toml file"
exit 1
fi
### Build your WASM file ###
if [[ "$MODE" == "release" ]] ; then
cargo build --release --target wasm32-unknown-unknown || exit 1
else
cargo build --target wasm32-unknown-unknown || exit 1
fi
### Create www dir with necessary files (if not already present) ###
if [ ! -d www ]; then
HTML=$(awk '/~HTML~/{flag=1; i++; next}/~END~/{flag=0}flag && i > 1' $0 | sed "s/~NAME~/$NAME/g")
PYSERVER=$(awk '/~PYSERVER~/{flag=1; i++; next}/~END~/{flag=0}flag && i > 1' $0)
mkdir www
echo "$HTML" > www/index.html
echo "$PYSERVER" > www/server.py
fi
### Check and copy any files detected in source code ###
ASSETS=($(grep -Erho --include \*.rs '"(.*?)"' src/ | grep "/" | grep "." | tr -d '"'))
for ASSET in ${ASSETS[@]}; do
cp --parents $ASSET www/
done
### Copy WASM file over ###
cp "target/wasm32-unknown-unknown/$MODE/$NAME.wasm" www/.
### Optimisations ###
if [[ "$MODE" == "release" ]] ; then
NUM_OPTS=4
# If you're using std heavy code. It's possible that wasm-snip could break your WASM file.
wasm-snip "www/$NAME.wasm" --snip-rust-fmt-code --snip-rust-panicking-code -o "www/$NAME.wasm" || NUM_OPTS=$((NUM_OPTS-1))
wasm-gc "www/$NAME.wasm" || NUM_OPTS=$((NUM_OPTS-1))
wasm-strip "www/$NAME.wasm" || NUM_OPTS=$((NUM_OPTS-1))
wasm-opt "www/$NAME.wasm" -O4 -o "www/$NAME.wasm" || NUM_OPTS=$((NUM_OPTS-1))
else
NUM_OPTS=0
fi
### display results ###
echo "==========================="
echo "$NUM_OPTS / 4 OPTIMISATIONS ENGAGED"
echo "==========================="
echo "Final file sizes:"
ls -lh www/
### serve ###
python3 www/server.py
############################################################################
exit 0 # END OF SCRIPT. EVERYTHING BELOW IS DATA NEEDED FOR THE ABOVE SCRIPT
############################################################################
~HTML~
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>TITLE</title>
<style>
html,
body,
canvas {
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
background: black;
z-index: 0;
}
</style>
</head>
<body>
<canvas id="glcanvas" tabindex='1'></canvas>
<!-- Minified and statically hosted version of https://github.com/not-fl3/miniquad/blob/master/native/sapp-wasm/js/gl.js -->
<script src="https://not-fl3.github.io/miniquad-samples/gl.js"></script>
<script>load("~NAME~.wasm");</script> <!-- Your compiled wasm file -->
</body>
</html>
~END~
~PYSERVER~
import http.server
import socketserver
import os
PORT = 8000
os.chdir(os.path.dirname(__file__))
Handler = http.server.SimpleHTTPRequestHandler
Handler.extensions_map.update({
'.wasm': 'application/wasm',
})
socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(("", PORT), Handler) as httpd:
httpd.allow_reuse_address = True
print("serving at port", PORT)
httpd.serve_forever()
~END~
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment