#!/usr/bin/env bash # Compila o Plee the Bear do fredygames.com: o jogo de plataforma do projeto Plee the Bear (codigo sob a GNU # GPL; imagens, sons, musica, fases e modelos sob a CC BY-SA 3.0) e o motor Bear (GPL), em WebAssembly, com o # Emscripten 6.0.10 e as portas SDL2 2.32.10, SDL2_mixer 2.8.0 (Ogg Vorbis), FreeType, libpng e zlib dele, # mais a libclaw 1.7.4 (LGPL-2.1-or-later) compilada aqui. Este script e os patches fazem parte do # codigo-fonte publicado junto do jogo. # # source /emsdk_env.sh # emsdk install 6.0.10 && emsdk activate 6.0.10 # src/FredGames.Bundler/Builds/build-plee-the-bear.sh # # Fontes: o que o Debian empacota da versao 0.7.1 do jogo (plee-the-bear_0.7.1.orig.tar.gz), o motor Bear no # commit ad52062 (plee-the-bear_0.7.1.orig-bear.tar.gz, o mesmo do github.com/j-jorge/bear) e a libclaw 1.7.4 # (libclaw_1.7.4.orig.tar.gz mais os patches do Debian 1.7.4-6, que consertam a libclaw para compiladores # novos), todos conferidos pelo SHA-256 e guardados em artifacts/cache/plee-the-bear/ (o site hospeda os # mesmos arquivos, menos o pacote do jogo, que la vai sem as tres fontes sem licenca livre e com o nome # plee-the-bear_0.7.1.orig-pruned.tar.gz: o script baixa o original do Debian). Na pasta de fontes do site, o # script acha os demais tarballs, os patches e as fontes OFL ao lado dele. # # Sem o CMake do projeto (ele exige o jogo e o motor como bibliotecas dinamicas, carregadas por dlopen): # os mesmos arquivos .cpp que ele compila (lidos dos CMakeLists.txt), ligados de uma vez num so programa. Os # itens do jogo se registram sozinhos na fabrica (BASE_ITEM_EXPORT), entao nao ha nada a carregar. # # plee-the-bear-fredygames.patch (na arvore do jogo, com o motor em bear/; so ativo com __EMSCRIPTEN__ quando # muda o comportamento): # - compat/: no lugar de Boost.Thread e Boost.Filesystem, pequenos cabecalhos (mutex sem concorrencia, # "thread" que roda na hora, std::filesystem); o Boost.Regex e os demais sao so cabecalhos (porta do # Emscripten, Boost 1.83); # - o renderizador desenha na propria thread (como o Windows ja faz), o tamanho da janela e o da imagem, e # systime::sleep devolve a vez ao navegador (ASYNCIFY); # - os sons carregam na hora; o envio de estatisticas para o stuff-o-matic.com sai (o jogo nao usa rede); # - o lancador abre os dados em /ptb-data e nao carrega bibliotecas; # - as fontes Comic Sans, Fava e Beroga (sem licenca livre) saem; Comic Neue e Lilita One (OFL) entram; # - ajustes de C++ moderno (std::mem_fun_ref e outros removidos do libc++, em fredygames-compat/stdcompat.hpp); # - texturas com GL_CLAMP_TO_EDGE (o WebGL 1 pinta de preto textura de tamanho qualquer sem isso). # libclaw-fredygames.patch: dois consertos de C++ moderno (it_index, socket_stream). # # Os dados vao num plee-the-bear.data que o proprio Emscripten carrega (--preload-file), em /ptb-data: o que o # "make install" do projeto instala (sem as fontes de origem .xcf/.scm/.svg, a versao nao compilada das # fases/animacoes/modelos, o MIDI e o FLAC), mais as fontes OFL. Perfis e opcoes ficam em /home/web_user. # # Saida: artifacts/build/plee-the-bear-0.7.1/plee-the-bear.{js,wasm,data}, que o bundle.yaml do jogo confere # pelo SHA-256. set -euo pipefail VERSION=0.7.1 EMSCRIPTEN=6.0.10 GAME_TAR=plee-the-bear_0.7.1.orig.tar.gz GAME_SHA256=1353f37d392966e58cb976ad031af4e4aecfd032d6994d22fb08af0a219417bc BEAR_TAR=plee-the-bear_0.7.1.orig-bear.tar.gz BEAR_SHA256=c2f60cbf4a8d5a09841349494f9170bf7abc7e07bf353b974f41378cef1ceeea CLAW_TAR=libclaw_1.7.4.orig.tar.gz CLAW_SHA256=0be289da7f43b1892575f14b27860af5d1e1f6961eae11653d64e625fd7924b7 CLAWDEB_TAR=libclaw_1.7.4-6.debian.tar.xz CLAWDEB_SHA256=f3c9d253b2df7b9f52d7fa8c9078d19ff98894a6105375c29052f536ea4e43e6 FONTS_COMMIT=45e3d5269e4a17d823f6d84470bc084dc5ae46f6 COMIC_SHA256=a0ee5a37c8b27c4db0700137d928598b1e23b0089e1546a8961909176b779360 LILITA_SHA256=f5b641c45c69d772ee4eda687bc9fda411d5cad6b0b45371491da4580cbc8d59 here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" root="$(git -C "$here" rev-parse --show-toplevel 2>/dev/null || pwd)" out="$root/artifacts/build/plee-the-bear-$VERSION" cache="$root/artifacts/cache/plee-the-bear" jobs="$(sysctl -n hw.ncpu 2>/dev/null || nproc)" if ! emcc --version 2>/dev/null | head -1 | grep -q " $EMSCRIPTEN "; then echo "Precisa do Emscripten $EMSCRIPTEN no PATH (source /emsdk_env.sh)." >&2 exit 1 fi # Arquivo auxiliar: em plee-the-bear/ (repositorio) ou ao lado do script (pasta de fontes do site). aux() { if [ -f "$here/plee-the-bear/$1" ]; then echo "$here/plee-the-bear/$1"; else echo "$here/$1"; fi } # Arquivo ao lado do script, no cache ou baixado do endereco original; confere o SHA-256. fetch() { local name="$1" url="$2" sha="$3" file if [ -f "$here/$name" ]; then file="$here/$name" else file="$cache/$name" if [ ! -f "$file" ]; then mkdir -p "$cache" curl -fsSL -o "$file.part" "$url" mv "$file.part" "$file" fi fi echo "$sha $file" | shasum -a 256 -c - >&2 echo "$file" } debian=https://deb.debian.org/debian/pool/main game_tar="$(fetch "$GAME_TAR" "$debian/p/plee-the-bear/$GAME_TAR" "$GAME_SHA256")" bear_tar="$(fetch "$BEAR_TAR" "$debian/p/plee-the-bear/$BEAR_TAR" "$BEAR_SHA256")" claw_tar="$(fetch "$CLAW_TAR" "$debian/libc/libclaw/$CLAW_TAR" "$CLAW_SHA256")" clawdeb_tar="$(fetch "$CLAWDEB_TAR" "$debian/libc/libclaw/$CLAWDEB_TAR" "$CLAWDEB_SHA256")" comic="$(fetch ComicNeue-Regular.ttf \ "https://raw.githubusercontent.com/google/fonts/$FONTS_COMMIT/ofl/comicneue/ComicNeue-Regular.ttf" "$COMIC_SHA256")" lilita="$(fetch LilitaOne-Regular.ttf \ "https://raw.githubusercontent.com/google/fonts/$FONTS_COMMIT/ofl/lilitaone/LilitaOne-Regular.ttf" "$LILITA_SHA256")" rm -rf "$out" mkdir -p "$out/src" "$out/claw" "$out/clawdeb" "$out/obj" tar xzf "$game_tar" -C "$out/src" --strip-components=1 mkdir -p "$out/src/bear" tar xzf "$bear_tar" -C "$out/src/bear" --strip-components=1 tar xzf "$claw_tar" -C "$out/claw" --strip-components=1 tar xJf "$clawdeb_tar" -C "$out/clawdeb" # libclaw: os patches do Debian, na ordem do series, e o nosso. while read -r p; do case "$p" in ''|'#'*) continue ;; esac patch -d "$out/claw" -p1 --no-backup-if-mismatch -s < "$out/clawdeb/debian/patches/$p" done < "$out/clawdeb/debian/patches/series" patch -d "$out/claw" -p1 --no-backup-if-mismatch -s < "$(aux libclaw-fredygames.patch)" patch -d "$out/src" -p1 --no-backup-if-mismatch -s < "$(aux plee-the-bear-fredygames.patch)" s="$out/src" be="$s/bear/bear-engine" cflags=(-O2 -w -fexceptions -std=c++17 -DNDEBUG -ffile-prefix-map="$out/=" -D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES -D_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION -DBOOST_BIND_GLOBAL_PLACEHOLDERS -DBOOST_ALLOW_DEPRECATED_HEADERS -DBEAR_USES_FREEDESKTOP -DCLAW_PNG_SUPPORT -I"$s/fredygames-compat" -I"$out/claw" -I"$be/core/src" -I"$be/common/include" -I"$be/lib/src" -I"$s/lib/src" -I"$s/launcher/src" -DPTB_STATIC -sUSE_SDL=2 -sUSE_SDL_MIXER=2 "-sSDL2_MIXER_FORMATS=[\"ogg\"]" -sUSE_FREETYPE=1 -sUSE_BOOST_HEADERS=1 -sUSE_LIBPNG=1 -sUSE_ZLIB=1 -include boost/bind.hpp -include "$s/fredygames-compat/stdcompat.hpp") printf '%s\n' "${cflags[@]}" > "$out/cflags.txt" # Os .cpp que os CMakeLists.txt listam (sem Windows, Android e Glew), mais os da libclaw. cat > "$out/cmlist.py" <<'PY' import os, re, sys root = sys.argv[1] found = set() for dp, dn, fn in os.walk(root): if 'CMakeLists.txt' in fn: lines = open(os.path.join(dp, 'CMakeLists.txt'), errors='replace').read().split('\n') text = '\n'.join(l for l in lines if not l.strip().startswith('#')) for m in re.finditer(r'[A-Za-z0-9_./+-]+\.cpp', text): p = os.path.normpath(os.path.join(dp, m.group(0))) if os.path.exists(p): found.add(os.path.relpath(p, root)) for p in sorted(found): if not re.search(r'android|win32|system_api_windows|glew', p): print(p) PY (cd "$be/core/src" && python3 -I "$out/cmlist.py" . | sed "s|^|$be/core/src/|") > "$out/list.txt" (cd "$be/lib/src" && python3 -I "$out/cmlist.py" . | sed "s|^|$be/lib/src/|") >> "$out/list.txt" (cd "$s/lib/src" && python3 -I "$out/cmlist.py" . | sed "s|^|$s/lib/src/|") >> "$out/list.txt" (cd "$s" && ls launcher/src/code/*.cpp | sed "s|^|$s/|") >> "$out/list.txt" (cd "$out/claw" && find claw/code -name '*.cpp' | LC_ALL=C sort | sed "s|^|$out/claw/|") >> "$out/list.txt" cat > "$out/cc.sh" <<'SH' #!/usr/bin/env bash out="$1"; f="$2" flags=() while IFS= read -r line; do flags+=("$line"); done < "$out/cflags.txt" o="$out/obj/$(echo "${f#$out/}" | tr / _).o" em++ "${flags[@]}" -c "$f" -o "$o" || { echo "ERRO: $f" >&2; exit 255; } SH chmod +x "$out/cc.sh" xargs -P "$jobs" -n1 "$out/cc.sh" "$out" < "$out/list.txt" # Dados: o que o projeto instala (data/CMakeLists.txt), menos o que o navegador nao usa. d="$out/ptb-data" mkdir -p "$d" (cd "$s/data" && rsync -a \ --exclude='.svn' --exclude='*~' --exclude='*!*' --exclude='*xcf*' --exclude='*.rg' --exclude='*.tg' \ --exclude='*.mdl' --exclude='*.anim' --exclude='*.lvl' --exclude='*.mid' --exclude='*.scm' \ --exclude='*.flac' --exclude='*.gz' --exclude='*.bz2' --exclude='README' \ --exclude='*.svg' --exclude='*.ora' --exclude='*.sh' --exclude='*.yaml' \ --exclude='font/comic.ttf' --exclude='font/Fava-black.ttf' --exclude='font/beroga.ttf' \ animation font gfx level mini-game model music script sound credits.txt "$d/") cp "$comic" "$d/font/ComicNeue-Regular.ttf" cp "$lilita" "$d/font/LilitaOne-Regular.ttf" LC_ALL=C perl -pi -e 's#font/comic\.ttf#font/ComicNeue-Regular.ttf#g' "$d/credits.txt" find "$d" -type f -exec touch -t 202001010000 {} + # Ligacao: todos os objetos, em ordem fixa (os itens se registram por construtores estaticos). find "$out/obj" -name '*.o' | LC_ALL=C sort > "$out/objs.txt" ( cd "$out" em++ -O2 @objs.txt -o plee-the-bear.js -ffile-prefix-map="$out/=" \ -sUSE_SDL=2 -sUSE_SDL_MIXER=2 "-sSDL2_MIXER_FORMATS=[\"ogg\"]" -sUSE_FREETYPE=1 -sUSE_LIBPNG=1 -sUSE_ZLIB=1 \ -fexceptions -lidbfs.js -sASYNCIFY -sALLOW_MEMORY_GROWTH -sINITIAL_MEMORY=96MB -sENVIRONMENT=web \ -sEXIT_RUNTIME=1 -sFORCE_FILESYSTEM=1 -sEXPORTED_RUNTIME_METHODS=FS,addRunDependency,removeRunDependency \ -sASYNCIFY_STACK_SIZE=65536 --preload-file "ptb-data@/ptb-data" ) shasum -a 256 "$out/plee-the-bear.js" "$out/plee-the-bear.wasm" "$out/plee-the-bear.data"