Skip to content

Commit

Permalink
Add build target "web"
Browse files Browse the repository at this point in the history
  • Loading branch information
ololoken committed Jan 1, 2025
1 parent 2c69952 commit 9ae4bb0
Show file tree
Hide file tree
Showing 13 changed files with 372 additions and 4 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,10 @@ android/app/src/main/assets/files/

# Mac magic folders
.DS_Store

#web build artifacts
*.wasm
*.wasm.map
fheroes2.js
fheroes2.data
src/dist/web/dist/*
37 changes: 37 additions & 0 deletions Makefile.web
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
###########################################################################
# fheroes2: https://github.com/ihhub/fheroes2 #
# Copyright (C) 2021 - 2024 #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the #
# Free Software Foundation, Inc., #
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
###########################################################################

# Options:
#
# FHEROES2_STRICT_COMPILATION: build in strict compilation mode (turns warnings into errors)
# FHEROES2_WITH_DEBUG: build in debug mode
# FHEROES2_DATA: set the built-in path to the fheroes2 data directory (e.g. /usr/share/fheroes2)

PROJECT_NAME := fheroes2
PROJECT_VERSION := $(file < version.txt)

.PHONY: all clean

all:
$(MAKE) -C src/dist PLATFORM=web

clean:
$(MAKE) -C src/dist PLATFORM=web clean
$(MAKE) -C files/lang clean
60 changes: 60 additions & 0 deletions files/web/dist/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<html lang="en">
<head>
<title>fheroes2</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/progress.js/0.1.0/progress.min.js" integrity="sha512-CklrzCqwODBOEJHJq73SZrgWC7xcxssgg5M1xokosfDDz2/nLTCuMDyc51gbJtb8DriV4EYjJSlklPH5Ejn9XA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/progress.js/0.1.0/progressjs.min.css" integrity="sha512-ovRFHsWpnYUBNZd/8CmbaWAKBDO8xb0l5Y8PdIae1O5RXO2QyU3CZGNzuYuE0CQHKazIzWMQpnTn26WpPjexfw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
body { margin: 0; height: 0; }
canvas {
height: 100vh;
width: 100vw;
display: block;
margin: 0 auto;
}
</style>
</head>
<body>
<canvas id="canvas" width="640" height="400"></canvas>
<script>
const progressBar = progressJs("#canvas").setOptions({
theme: 'blueOverlayRadiusWithPercentBar',
overlayMode: true,
considerTransition: true
});
const canvas = document.querySelector('canvas');
canvas.oncontextmenu = event => event.preventDefault();
Object.assign(window, { Module: {
preRun: [
() => Object.assign(window.ENV, {
FHEROES2_DATA: `data`,
HOME: '/fheroes2'
}),
() => {
addRunDependency('syncfs');
FS.mkdir('/fheroes2');
FS.mount(IDBFS, { root: '/' }, '/fheroes2');
FS.syncfs(true, (err) => {
if (err) throw err;
console.log('IDBFS Synced')
removeRunDependency('syncfs')
});
}
],
setStatus: status => {
const dlProgressRE = /(?<progress>\d+)\/(?<total>\d+)/ig;
if (!status || !dlProgressRE.test(status)) {
if ((status??'').startsWith('Downloading data')) progressBar.start();
return;
}
dlProgressRE.lastIndex = 0;
const { groups: { progress, total } } = [...status.matchAll(dlProgressRE)][0];
const done = Math.round(progress/total*100);
progressBar.set(done);
if (100 === done) progressBar.end();
},
canvas
} } );

document.head.append(Object.assign(document.createElement('script'), { src: './fheroes2.js' }));
</script>
</body>
14 changes: 14 additions & 0 deletions files/web/readme
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
building with pthread:
1. modify src/dist/Makefile.web to enable pthread support
2. modify src/engine/thread.cpp to allow spawn threads
3. use patch sdl2_mixer.py; PR and issue description https://github.com/emscripten-core/emscripten/pull/23094
4. check how to enable SharedArrayBuffer, options: serve with custom headers, use service worker to intercept request, use custom browser flags

docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 \
sh -c \
'cp -f files/web/sdl2_mixer.py /emsdk/upstream/emscripten/tools/ports/sdl2_mixer.py && apt update && apt install -y gettext && emmake make -f Makefile.web'

building without pthread:
docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 \
sh -c \
'apt update && apt install -y gettext && emmake make -f Makefile.web'
126 changes: 126 additions & 0 deletions files/web/sdl2_mixer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Copyright 2016 The Emscripten Authors. All rights reserved.
# Emscripten is available under two separate licenses, the MIT license and the
# University of Illinois/NCSA Open Source License. Both these licenses can be
# found in the LICENSE file.

import os

TAG = 'release-2.8.0'
HASH = '494ccd74540f74e717f7e4f1dc7f96398c0f4b1883ab00c4a76b0c7239bd2c185cb4358a35ef47819c49e7c14dac7c37b98a29c7b5237478121571f5e7ac4dfc'

deps = ['sdl2']
variants = {
'sdl2_mixer-mp3': {'SDL2_MIXER_FORMATS': ["mp3"]},
'sdl2_mixer-none': {'SDL2_MIXER_FORMATS': []},
'sdl2_mixer-mp3-mt': {'SDL2_MIXER_FORMATS': ["mp3"], 'PTHREADS': 1},
'sdl2_mixer-none-mt': {'SDL2_MIXER_FORMATS': [], 'PTHREADS': 1},
}


def needed(settings):
return settings.USE_SDL_MIXER == 2


def get_lib_name(settings):
settings.SDL2_MIXER_FORMATS.sort()
formats = '-'.join(settings.SDL2_MIXER_FORMATS)

libname = 'libSDL2_mixer'
if formats != '':
libname += '-' + formats
if settings.PTHREADS:
libname += '-mt'
libname += '.a'

return libname


def get(ports, settings, shared):
sdl_build = os.path.join(ports.get_build_dir(), 'sdl2')
assert os.path.exists(sdl_build), 'You must use SDL2 to use SDL2_mixer'
ports.fetch_project('sdl2_mixer', f'https://github.com/libsdl-org/SDL_mixer/archive/{TAG}.zip', sha512hash=HASH)
libname = get_lib_name(settings)

def create(final):
source_path = ports.get_dir('sdl2_mixer', 'SDL_mixer-' + TAG)
flags = [
'-sUSE_SDL=2',
'-O2',
'-DMUSIC_WAV',
]

if "ogg" in settings.SDL2_MIXER_FORMATS:
flags += [
'-sUSE_VORBIS',
'-DMUSIC_OGG',
]

if "mp3" in settings.SDL2_MIXER_FORMATS:
flags += [
'-sUSE_MPG123',
'-DMUSIC_MP3_MPG123',
]

if "mod" in settings.SDL2_MIXER_FORMATS:
flags += [
'-sUSE_MODPLUG',
'-DMUSIC_MOD_MODPLUG',
]

if "mid" in settings.SDL2_MIXER_FORMATS:
flags += [
'-DMUSIC_MID_TIMIDITY',
]

if settings.PTHREADS:
flags.append('-pthread')

build_dir = ports.clear_project_build('sdl2_mixer')
include_path = os.path.join(source_path, 'include')
includes = [
include_path,
os.path.join(source_path, 'src'),
os.path.join(source_path, 'src', 'codecs')
]
ports.build_port(
source_path,
final,
build_dir,
flags=flags,
exclude_files=[
'playmus.c',
'playwave.c',
'main.c',
],
exclude_dirs=[
'native_midi',
'external',
'Xcode',
],
includes=includes,
)

ports.install_headers(include_path, target='SDL2')

return [shared.cache.get_lib(libname, create, what='port')]


def clear(ports, settings, shared):
shared.cache.erase_lib(get_lib_name(settings))


def process_dependencies(settings):
settings.USE_SDL = 2
if "ogg" in settings.SDL2_MIXER_FORMATS:
deps.append('vorbis')
settings.USE_VORBIS = 1
if "mp3" in settings.SDL2_MIXER_FORMATS:
deps.append('mpg123')
settings.USE_MPG123 = 1
if "mod" in settings.SDL2_MIXER_FORMATS:
deps.append('libmodplug')
settings.USE_MODPLUG = 1


def show():
return 'sdl2_mixer (-sUSE_SDL_MIXER=2 or --use-port=sdl2_mixer; zlib license)'
8 changes: 8 additions & 0 deletions src/dist/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,11 @@ ifndef FHEROES2_WITH_SYSTEM_SMACKER
$(MAKE) -C thirdparty/libsmacker CCFLAGS="$(CCFLAGS_TP)" CFLAGS="$(CFLAGS_TP)" CXXFLAGS="$(CXXFLAGS_TP)" CPPFLAGS="$(CPPFLAGS_TP)"
endif
$(MAKE) -C engine
ifeq ($(PLATFORM),web)
$(MAKE) -C web
else
$(MAKE) -C fheroes2
endif
ifdef FHEROES2_WITH_TOOLS
$(MAKE) -C tools
endif
Expand All @@ -169,5 +173,9 @@ ifndef FHEROES2_WITH_SYSTEM_SMACKER
$(MAKE) -C thirdparty/libsmacker clean
endif
$(MAKE) -C engine clean
ifeq ($(PLATFORM),web)
$(MAKE) -C web clean
else
$(MAKE) -C fheroes2 clean
endif
$(MAKE) -C tools clean
40 changes: 40 additions & 0 deletions src/dist/Makefile.web
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
###########################################################################
# fheroes2: https://github.com/ihhub/fheroes2 #
# Copyright (C) 2021 - 2024 #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the #
# Free Software Foundation, Inc., #
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
###########################################################################

CCFLAGS := $(filter-out -pthread,$(CCFLAGS)) --use-port=sdl2_mixer \
--use-port=sdl2 \
--use-port=zlib

LDFLAGS := $(filter-out -pthread,$(LDFLAGS)) -sENVIRONMENT=web \
--preload-file ../../../files/data/resurrection.h2d@/files/data/resurrection.h2d \
--preload-file ../../../files/lang/@/files/lang/ \
--preload-file ../../../files/soundfonts/fheroes2.sf3@/files/soundfonts/fheroes2.sf3 \
--preload-file ../../../data/@/data/ \
-sSTACK_SIZE=262144 \
-sINITIAL_MEMORY=64mb \
-sENVIRONMENT=web \
-sASYNCIFY \
-sASYNCIFY_STACK_SIZE=20480 \
-lidbfs.js

ifdef FHEROES2_WITH_DEBUG
LDFLAGS := $(LDFLAGS) -gsource-map
CCFLAGS := $(CCFLAGS) -gsource-map
endif
55 changes: 55 additions & 0 deletions src/dist/web/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
###########################################################################
# fheroes2: https://github.com/ihhub/fheroes2 #
# Copyright (C) 2021 - 2024 #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the #
# Free Software Foundation, Inc., #
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
###########################################################################

DEPLIBS := ../engine/libengine.a
CCFLAGS := $(CCFLAGS) -I../../engine

ifndef FHEROES2_WITH_SYSTEM_SMACKER
DEPLIBS := $(DEPLIBS) ../thirdparty/libsmacker/libsmacker.a
CCFLAGS := $(CCFLAGS) -I../../thirdparty/libsmacker
endif

SOURCEROOT := ../../fheroes2
SOURCEDIRS := $(filter %/,$(wildcard $(SOURCEROOT)/*/))
SOURCES := $(wildcard $(SOURCEROOT)/*/*.cpp)

VPATH := $(SOURCEDIRS)

.PHONY: all clean

all: fheroes2.js

fheroes2.js: $(notdir $(patsubst %.cpp, %.o, $(SOURCES))) $(DEPLIBS)
xgettext -d fheroes2.js --language=JavaScript -F -k_ -k_n:1,2 -o fheroes2.pot $(sort $(SOURCES))
$(MAKE) -C ../../../files/lang
$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)
rm -f *.d *.o *.tmp *.pot~ *.pot
mkdir -p dist
mv -f fheroes2.* dist
cp ../../../files/web/dist/* dist

%.o: %.cpp
$(CXX) -c -MD $< $(addprefix -I, $(SOURCEDIRS)) $(CCFLAGS) $(CXXFLAGS) $(CPPFLAGS)

include $(wildcard *.d)

clean:
rm -f *.d *.o fheroes2.js fheroes2.wasm fheroes2.wasm.* fheroes2.data fheroes2.pot fheroes2.pot~
rm -rf dist
3 changes: 2 additions & 1 deletion src/engine/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ namespace MultiThreading
{
if ( !_worker ) {
_runFlag = true;
#if !defined( __EMSCRIPTEN__ ) // disable pthread for web target
_worker = std::make_unique<std::thread>( AsyncManager::_workerThread, this );

{
std::unique_lock<std::mutex> lock( _mutex );

_masterNotification.wait( lock, [this] { return !_runFlag; } );
}
#endif
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/fheroes2/game/fheroes2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,10 +337,11 @@ int main( int argc, char ** argv )

if ( conf.isShowIntro() ) {
fheroes2::showTeamInfo();

#if !defined( __EMSCRIPTEN__ )
Video::ShowVideo( "NWCLOGO.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END );
Video::ShowVideo( "CYLOGO.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END );
Video::ShowVideo( "H2XINTRO.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END );
#endif
}

try {
Expand Down
Loading

0 comments on commit 9ae4bb0

Please sign in to comment.