Skip to content

Commit 53b312e

Browse files
authored
Merge pull request #90 from OpenBrickProtocolFoundation/web-build
Web build with emscripten
2 parents 8d7b2cf + 90654f6 commit 53b312e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2404
-305
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ jobs:
8989
uses: TheMrMilchmann/setup-msvc-dev@v3
9090
with:
9191
arch: x64
92-
toolset: '14.41'
92+
toolset: '14.42'
9393

9494
- name: Setup MYSYS2 (Windows)
9595
if: matrix.config.os == 'windows' && ( matrix.config.environment == 'mingw' || matrix.config.environment == 'ucrt' )

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
tidy-checks: ''
5353
step-summary: true
5454
file-annotations: true
55-
ignore: subprojects|build|android|assets|recordings|docs|toolchains|platforms|wrapper|src/libs/core/hash-library|tests|src/lobby/curl_client.*
55+
ignore: subprojects|build|android|assets|recordings|docs|toolchains|platforms|wrapper|src/libs/core/hash-library|tests|src/helper/web_utils.*|src/lobby/web_client.*|src/lobby/curl_client.*
5656

5757
- name: Fail CI run if linter checks failed
5858
if: steps.linter.outputs.checks-failed != 0

.github/workflows/web_build.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Web CI
2+
3+
on:
4+
release:
5+
types: [published]
6+
push:
7+
branches: ['main']
8+
pull_request:
9+
workflow_dispatch:
10+
11+
jobs:
12+
web-build:
13+
name: Build for the web
14+
runs-on: ubuntu-24.04
15+
steps:
16+
- uses: actions/checkout@v4
17+
with:
18+
fetch-depth: '0'
19+
20+
# NOTE: meson has no dependencies, so --break-system-packages doesn't really break anything!
21+
- name: Setup Meson
22+
run: |
23+
pip install meson --break-system-packages
24+
25+
- name: Install dependencies
26+
run: |
27+
sudo apt-get update
28+
sudo apt-get install ninja-build pkg-config build-essential wabt -y --no-install-recommends
29+
30+
- name: Build
31+
run: |
32+
bash ./platforms/build-web.sh
33+
meson test -C build-web
34+
35+
# TODO upload page to gh-pages!
36+
- name: Upload artifacts
37+
uses: actions/upload-artifact@v4
38+
with:
39+
name: oopetris-assets
40+
path: build-web/src/executables/

.github/workflows/windows_installer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
uses: TheMrMilchmann/setup-msvc-dev@v3
2525
with:
2626
arch: x64
27-
toolset: '14.41'
27+
toolset: '14.42'
2828

2929
- name: Setup meson
3030
run: |

assets/authors/mgerhold.jpg

-49.8 KB
Binary file not shown.

assets/authors/mgerhold.png

381 KB
Loading

platforms/build-android.sh

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
set -e
44

5-
mkdir -p toolchains
5+
if [ ! -d "toolchains" ]; then
6+
mkdir -p toolchains
7+
fi
68

79
export NDK_VER_DOWNLOAD="r28-beta1"
810
export NDK_VER_DESC="r28-beta1"
@@ -291,6 +293,10 @@ for INDEX in "${ARCH_KEYS_INDEX[@]}"; do
291293
MESON_CPU_FAMILY="aarch64"
292294
fi
293295

296+
export COMPILE_FLAGS="'--sysroot=${SYS_ROOT:?}','-fPIE','-fPIC','--target=$ARM_COMPILER_TRIPLE','-DAUDIO_PREFER_MP3'"
297+
298+
export LINK_FLAGS="'-fPIE','-L$SYS_ROOT/usr/lib'"
299+
294300
cat <<EOF >"./platforms/crossbuild-android-$ARM_TARGET_ARCH.ini"
295301
[host_machine]
296302
system = 'android'
@@ -318,10 +324,11 @@ llvm-config = '$LLVM_CONFIG'
318324
[built-in options]
319325
c_std = 'gnu11'
320326
cpp_std = 'c++23'
321-
c_args = ['--sysroot=${SYS_ROOT:?}','-fPIE','-fPIC','--target=$ARM_COMPILER_TRIPLE','-DHAVE_USR_INCLUDE_MALLOC_H','-D_MALLOC_H','-D__BITNESS=$BITNESS']
322-
cpp_args = ['--sysroot=${SYS_ROOT:?}','-fPIE','-fPIC','--target=$ARM_COMPILER_TRIPLE','-D__BITNESS=$BITNESS']
323-
c_link_args = ['-fPIE','-L$SYS_ROOT/usr/lib']
324-
cpp_link_args = ['-fPIE','-L$SYS_ROOT/usr/lib']
327+
c_args = [$COMPILE_FLAGS]
328+
cpp_args = [$COMPILE_FLAGS]
329+
c_link_args = [$LINK_FLAGS]
330+
cpp_link_args = [$LINK_FLAGS]
331+
325332
prefix = '$SYS_ROOT'
326333
libdir = '$LIB_PATH'
327334
@@ -331,12 +338,14 @@ sys_root = '${SYS_ROOT}'
331338
332339
EOF
333340

334-
if [ ! -d "$PWD/subprojects/cpu-features" ]; then
335-
mkdir -p "$PWD/subprojects/cpu-features/src/"
336-
mkdir -p "$PWD/subprojects/cpu-features/include/"
337-
ln -s "$BASE_PATH/sources/android/cpufeatures/cpu-features.c" "$PWD/subprojects/cpu-features/src/cpu-features.c"
338-
ln -s "$BASE_PATH/sources/android/cpufeatures/cpu-features.h" "$PWD/subprojects/cpu-features/include/cpu-features.h"
339-
cat <<EOF >"$PWD/subprojects/cpu-features/meson.build"
341+
CPU_FUTURES_ROOT="$PWD/subprojects/cpu-features"
342+
343+
if [ ! -d "$CPU_FUTURES_ROOT" ]; then
344+
mkdir -p "$CPU_FUTURES_ROOT/src/"
345+
mkdir -p "$CPU_FUTURES_ROOT/include/"
346+
ln -s "$BASE_PATH/sources/android/cpufeatures/cpu-features.c" "$CPU_FUTURES_ROOT/src/cpu-features.c"
347+
ln -s "$BASE_PATH/sources/android/cpufeatures/cpu-features.h" "$CPU_FUTURES_ROOT/include/cpu-features.h"
348+
cat <<EOF >"$CPU_FUTURES_ROOT/meson.build"
340349
project('cpu-features','c')
341350
342351
meson.override_dependency(
@@ -367,7 +376,6 @@ EOF
367376
--cross-file "./platforms/crossbuild-android-$ARM_TARGET_ARCH.ini" \
368377
"-Dbuildtype=$BUILDTYPE" \
369378
-Dsdl2:use_hidapi=enabled \
370-
-Dcpp_args=-DAUDIO_PREFER_MP3 \
371379
-Dclang_libcpp=disabled
372380

373381
fi

platforms/build-web.sh

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
if [ ! -d "toolchains" ]; then
6+
mkdir -p toolchains
7+
fi
8+
9+
export EMSCRIPTEN_ROOT="$(pwd)/toolchains/emsdk"
10+
11+
if [ ! -d "$EMSCRIPTEN_ROOT" ]; then
12+
git clone https://github.com/emscripten-core/emsdk.git "$EMSCRIPTEN_ROOT"
13+
fi
14+
15+
"$EMSCRIPTEN_ROOT/emsdk" install latest
16+
"$EMSCRIPTEN_ROOT/emsdk" activate latest
17+
18+
EMSCRIPTEN_UPSTREAM_ROOT="$EMSCRIPTEN_ROOT/upstream/emscripten"
19+
20+
EMSCRIPTEN_PACTH_FILE="$EMSCRIPTEN_UPSTREAM_ROOT/.patched_manually.meta"
21+
22+
PATCH_DIR="platforms/emscripten"
23+
24+
if ! [ -e "$EMSCRIPTEN_PACTH_FILE" ]; then
25+
##TODO: upstream those patches
26+
# see: https://github.com/emscripten-core/emscripten/pull/18379/commits
27+
# and: https://github.com/emscripten-core/emscripten/pull/18379
28+
29+
git apply --unsafe-paths -p1 --directory="$EMSCRIPTEN_UPSTREAM_ROOT" "$PATCH_DIR/sdl2_image_port.diff"
30+
git apply --unsafe-paths -p1 --directory="$EMSCRIPTEN_UPSTREAM_ROOT" "$PATCH_DIR/sdl2_mixer_port.diff"
31+
git apply --unsafe-paths -p1 --directory="$EMSCRIPTEN_UPSTREAM_ROOT" "$PATCH_DIR/default_settings.diff"
32+
33+
touch "$EMSCRIPTEN_PACTH_FILE"
34+
fi
35+
36+
# git apply path
37+
38+
# shellcheck disable=SC1091
39+
EMSDK_QUIET=1 source "$EMSCRIPTEN_ROOT/emsdk_env.sh" >/dev/null
40+
41+
## build theneeded dependencies
42+
embuilder build sdl2-mt harfbuzz-mt freetype zlib sdl2_ttf mpg123 "sdl2_mixer:formats=mp3" libpng-mt "sdl2_image:formats=png,svg:mt=1" icu-mt
43+
44+
export EMSCRIPTEN_SYS_ROOT="$EMSCRIPTEN_UPSTREAM_ROOT/cache/sysroot"
45+
46+
export BUILD_DIR="build-web"
47+
48+
export CC="emcc"
49+
export CXX="em++"
50+
export AR="emar"
51+
export RANLIB="emranlib"
52+
export STRIP="emstrip"
53+
export NM="emnm"
54+
55+
export ARCH="wasm32"
56+
export CPU_ARCH="wasm32"
57+
export ENDIANESS="little"
58+
59+
export ROMFS="platforms/romfs"
60+
61+
export PACKAGE_FLAGS="'--use-port=sdl2', '--use-port=harfbuzz', '--use-port=freetype', '--use-port=zlib', '--use-port=sdl2_ttf', '--use-port=mpg123', '--use-port=sdl2_mixer', '-sSDL2_MIXER_FORMATS=[\"mp3\"]','--use-port=libpng', '--use-port=sdl2_image','-sSDL2_IMAGE_FORMATS=[\"png\",\"svg\"]', '--use-port=icu'"
62+
63+
export COMMON_FLAGS="'-fexceptions', '-pthread', '-sUSE_PTHREADS=1', '-sEXCEPTION_CATCHING_ALLOWED=[..]', $PACKAGE_FLAGS"
64+
65+
# TODO see if ALLOW_MEMORY_GROWTH is needed, but if we load ttf's and music it likely is and we don't have to debug OOm crashes, that aren't handled by some third party library, which is painful
66+
export LINK_FLAGS="$COMMON_FLAGS, '-sEXPORT_ALL=1', '-sUSE_WEBGPU=1', '-sWASM=1', '-sALLOW_MEMORY_GROWTH=1', '-sASSERTIONS=1','-sERROR_ON_UNDEFINED_SYMBOLS=1', '-sFETCH=1', '-sEXIT_RUNTIME=1'"
67+
export COMPILE_FLAGS="$COMMON_FLAGS ,'-DAUDIO_PREFER_MP3'"
68+
69+
export CROSS_FILE="./platforms/crossbuild-web.ini"
70+
71+
cat <<EOF >"$CROSS_FILE"
72+
[host_machine]
73+
system = 'emscripten'
74+
cpu_family = '$ARCH'
75+
cpu = '$CPU_ARCH'
76+
endian = '$ENDIANESS'
77+
78+
[target_machine]
79+
system = 'emscripten'
80+
cpu_family = '$ARCH'
81+
cpu = '$CPU_ARCH'
82+
endian = '$ENDIANESS'
83+
84+
[constants]
85+
emscripten_root = '$(pwd)/emsdk'
86+
87+
[binaries]
88+
c = '$CC'
89+
cpp = '$CXX'
90+
ar = '$AR'
91+
ranlib = '$RANLIB'
92+
strip = '$STRIP'
93+
nm = '$NM'
94+
95+
pkg-config = ['emmake', 'pkg-config']
96+
cmake = ['emmake', 'cmake']
97+
sdl2-config = ['emconfigure', 'sdl2-config']
98+
99+
exe_wrapper = '$EMSDK_NODE'
100+
101+
[built-in options]
102+
c_std = 'c11'
103+
cpp_std = 'c++23'
104+
c_args = [$COMPILE_FLAGS]
105+
cpp_args = [$COMPILE_FLAGS]
106+
c_link_args = [$LINK_FLAGS]
107+
cpp_link_args = [$LINK_FLAGS]
108+
109+
[properties]
110+
needs_exe_wrapper = true
111+
sys_root = '$EMSCRIPTEN_SYS_ROOT'
112+
113+
APP_ROMFS='$ROMFS/assets/'
114+
115+
EOF
116+
117+
## options: "smart, complete_rebuild"
118+
export COMPILE_TYPE="smart"
119+
120+
export BUILDTYPE="debug"
121+
122+
if [ "$#" -eq 0 ]; then
123+
# nothing
124+
echo "Using compile type '$COMPILE_TYPE'"
125+
elif [ "$#" -eq 1 ]; then
126+
COMPILE_TYPE="$1"
127+
elif [ "$#" -eq 2 ]; then
128+
COMPILE_TYPE="$1"
129+
BUILDTYPE="$2"
130+
else
131+
echo "Too many arguments given, expected 1 or 2"
132+
exit 1
133+
fi
134+
135+
if [ "$COMPILE_TYPE" == "smart" ]; then
136+
: # noop
137+
elif [ "$COMPILE_TYPE" == "complete_rebuild" ]; then
138+
: # noop
139+
else
140+
echo "Invalid COMPILE_TYPE, expected: 'smart' or 'complete_rebuild'"
141+
exit 1
142+
fi
143+
144+
if [ ! -d "$ROMFS" ]; then
145+
146+
mkdir -p "$ROMFS"
147+
148+
cp -r assets "$ROMFS/"
149+
150+
fi
151+
152+
if [ "$COMPILE_TYPE" == "complete_rebuild" ] || [ ! -e "$BUILD_DIR" ]; then
153+
154+
meson setup "$BUILD_DIR" \
155+
"--wipe" \
156+
--cross-file "$CROSS_FILE" \
157+
"-Dbuildtype=$BUILDTYPE" \
158+
-Ddefault_library=static \
159+
-Dtests=false
160+
161+
fi
162+
163+
meson compile -C "$BUILD_DIR"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
diff --git a/src/settings.js b/src/settings.js
2+
index 981c44fa..17ca0078 100644
3+
--- a/src/settings.js
4+
+++ b/src/settings.js
5+
@@ -1624,7 +1624,7 @@ var SDL2_IMAGE_FORMATS = [];
6+
7+
// Formats to support in SDL2_mixer. Valid values: ogg, mp3, mod, mid
8+
// [link]
9+
-var SDL2_MIXER_FORMATS = ["ogg"];
10+
+var SDL2_MIXER_FORMATS = [];
11+
12+
// 1 = use sqlite3 from emscripten-ports
13+
// Alternate syntax: --use-port=sqlite3
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
diff --git a/tools/ports/sdl2_image.py b/tools/ports/sdl2_image.py
2+
index c72ef576..0c12feba 100644
3+
--- a/tools/ports/sdl2_image.py
4+
+++ b/tools/ports/sdl2_image.py
5+
@@ -16,15 +16,17 @@ variants = {
6+
}
7+
8+
OPTIONS = {
9+
- 'formats': 'A comma separated list of formats (ex: --use-port=sdl2_image:formats=png,jpg)'
10+
+ 'formats': 'A comma separated list of formats (ex: --use-port=sdl2_image:formats=png,jpg)',
11+
+ 'mt': 'use pthread'
12+
}
13+
14+
SUPPORTED_FORMATS = {'avif', 'bmp', 'gif', 'jpg', 'jxl', 'lbm', 'pcx', 'png',
15+
'pnm', 'qoi', 'svg', 'tga', 'tif', 'webp', 'xcf', 'xpm', 'xv'}
16+
17+
# user options (from --use-port)
18+
-opts: Dict[str, Set] = {
19+
- 'formats': set()
20+
+opts = {
21+
+ 'formats': set(),
22+
+ 'mt': 0
23+
}
24+
25+
26+
@@ -42,7 +44,7 @@ def get_lib_name(settings):
27+
libname = 'libSDL2_image'
28+
if formats != '':
29+
libname += '_' + formats
30+
- return libname + '.a'
31+
+ return libname + ('-mt' if opts['mt'] else '') + '.a'
32+
33+
34+
def get(ports, settings, shared):
35+
@@ -70,6 +72,8 @@ def get(ports, settings, shared):
36+
37+
if 'jpg' in formats:
38+
defs += ['-sUSE_LIBJPEG']
39+
+ if opts['mt']:
40+
+ defs += ['-pthread']
41+
42+
ports.build_port(src_dir, final, 'sdl2_image', flags=defs, srcs=srcs)
43+
44+
@@ -99,7 +103,12 @@ def handle_options(options, error_handler):
45+
error_handler(f'{format} is not a supported format')
46+
else:
47+
opts['formats'].add(format)
48+
-
49+
+
50+
+ mt = options['mt']
51+
+ if mt not in ["1","0"]:
52+
+ error_handler(f'{mt} has to be either 0 or 1')
53+
+ else:
54+
+ opts['mt'] = int(mt)
55+
56+
def show():
57+
return 'sdl2_image (-sUSE_SDL_IMAGE=2 or --use-port=sdl2_image; zlib license)'

0 commit comments

Comments
 (0)