Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,10 @@ include(RttrTestingCfg)
set(rttrContribBoostDir ${CMAKE_CURRENT_SOURCE_DIR}/contrib/boost)
if(EXISTS ${rttrContribBoostDir} AND IS_DIRECTORY ${rttrContribBoostDir})
set(BOOST_ROOT ${rttrContribBoostDir} CACHE PATH "Path to find boost at")
if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
set(Boost_INCLUDE_DIR "${rttrContribBoostDir}/include" CACHE PATH "Path to find boost at")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not required: BOOST_ROOT is enough. Possibly should be replaced by Boost_ROOT though.

set(Boost_LIBRARY_DIR "${rttrContribBoostDir}/lib" CACHE PATH "Path to find boost at")
endif ()
endif()

set(BoostPackages filesystem iostreams locale program_options)
Expand All @@ -306,7 +310,7 @@ if(BUILD_TESTING)
list(APPEND BoostPackages unit_test_framework)
endif()

find_package(Boost 1.71 COMPONENTS ${BoostPackages})
find_package(Boost 1.86 COMPONENTS ${BoostPackages})
if(NOT Boost_FOUND)
message(FATAL_ERROR "You have to install boost (>=1.71) into contrib/boost or set (as CMake or environment variable) "
"BOOST_ROOT (currently: '${BOOST_ROOT}', Environment: '$ENV{BOOST_ROOT}'), "
Expand All @@ -315,7 +319,9 @@ if(NOT Boost_FOUND)
endif()

option(RTTR_USE_SYSTEM_BOOST_NOWIDE "Use system installed Boost.Nowide. Fails if not found!" "${RTTR_USE_SYSTEM_LIBS}")

if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
set(RTTR_USE_SYSTEM_BOOST_NOWIDE ON)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify indents

Suggested change
set(RTTR_USE_SYSTEM_BOOST_NOWIDE ON)
set(RTTR_USE_SYSTEM_BOOST_NOWIDE ON)

endif ()
if(Boost_VERSION_MINOR GREATER_EQUAL "74" OR RTTR_USE_SYSTEM_BOOST_NOWIDE)
# Boost 1.73 contains Boost.Nowide, 1.74 a required fix
find_package(Boost COMPONENTS nowide)
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ Copyright (C) 2005 - 2025 Settlers Freaks <sf-team at siedler25.org>

SPDX-License-Identifier: GPL-2.0-or-later
-->
# emscripten build (wasm)

1. checkout and build `boost-1.86.0` with following command
```bash
docker run --rm -v $(pwd):/src emscripten-image sh -c './b2 install toolset=emscripten link=static runtime-link=static variant=release -j 1 --prefix=/src/contrib/boost --with-program_options --with-nowide --with-filesystem --with-iostreams --with-locale --with-thread --with-system --with-regex'
```
2. download lua `lua-5.4.7` update config its Makefile add both C and LD flags `-fwasm-exceptions -sSUPPORT_LONGJMP=wasm` and then build
3. run standard build

# Return To The Roots

Expand Down
2 changes: 2 additions & 0 deletions external/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ add_subdirectory(liblobby)
add_subdirectory(libsiedler2)
add_subdirectory(libutil)
add_subdirectory(mygettext)
if (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
add_subdirectory(s25edit)
endif ()
if(RTTR_BUILD_UPDATER)
add_subdirectory(s25update)
endif()
Expand Down
2 changes: 2 additions & 0 deletions extras/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)

add_subdirectory(audioDrivers)
add_subdirectory(videoDrivers)
if (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
add_subdirectory(ai-battle)
endif ()
if(RTTR_BUNDLE AND APPLE)
add_subdirectory(macosLauncher)
endif()
Expand Down
4 changes: 2 additions & 2 deletions extras/audioDrivers/SDL/AudioSDL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void FreeAudioInstance(driver::IAudioDriver* driver)
delete driver;
}

const char* GetDriverName()
const char* GetAudioDriverName()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks the interface, see

auto GetDriverName = dll.get<GetDriverName_t>("GetDriverName");

{
return "(SDL2) Audio via SDL2_mixer-Library";
}
Expand Down Expand Up @@ -62,7 +62,7 @@ AudioSDL::~AudioSDL()
*/
const char* AudioSDL::GetName() const
{
return GetDriverName();
return GetAudioDriverName();
}

static AudioSDL* currentInstance = nullptr;
Expand Down
19 changes: 16 additions & 3 deletions extras/audioDrivers/SDL/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
# SPDX-License-Identifier: GPL-2.0-or-later

set(SDL_BUILDING_LIBRARY ON)
if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
set(SDL_MIXER_FOUND TRUE)
else ()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
else ()
else()

Same for endif()

and indent the find_package

find_package(SDL_mixer 2.0.1)

endif ()
if(NOT SDL_MIXER_FOUND)
message(WARNING "SDL_mixer library not found: Not building SDL audiodriver")
else()
Expand All @@ -16,8 +19,18 @@ else()
gather_dll_by_name(OGG libogg-0.dll)
endif()

add_library(audioSDL SHARED ${RTTR_DRIVER_INTERFACE} AudioSDL.cpp AudioSDL.h)
target_link_libraries(audioSDL PRIVATE audiodrv SDL_mixer::SDL_mixer)
if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
add_library(audioSDL STATIC ${RTTR_DRIVER_INTERFACE} AudioSDL.cpp AudioSDL.h)
set(USE_FLAGS "--use-port=sdl2_mixer -sSDL2_MIXER_FORMATS=ogg")
set_target_properties(audioSDL PROPERTIES
COMPILE_FLAGS "${USE_FLAGS}"
LINK_FLAGS "${USE_FLAGS}"
)
target_link_libraries(audioSDL PRIVATE audiodrv)
else ()
add_library(audioSDL SHARED ${RTTR_DRIVER_INTERFACE} AudioSDL.cpp AudioSDL.h)
target_link_libraries(audioSDL PRIVATE audiodrv SDL_mixer::SDL_mixer)
endif ()
enable_warnings(audioSDL)

install(TARGETS audioSDL
Expand Down
19 changes: 16 additions & 3 deletions extras/videoDrivers/SDL2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@
# SPDX-License-Identifier: GPL-2.0-or-later

set(SDL2_BUILDING_LIBRARY ON)
if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
set(SDL2_FOUND TRUE)
else ()
find_package(SDL2 2.0.5)

endif ()
if(SDL2_FOUND)
add_library(videoSDL2 SHARED ${RTTR_DRIVER_INTERFACE} VideoSDL2.cpp VideoSDL2.h icon.h icon.cpp)
target_link_libraries(videoSDL2 PRIVATE videodrv s25util::common glad Boost::nowide SDL2::SDL2)
if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
add_library(videoSDL2 STATIC ${RTTR_DRIVER_INTERFACE} VideoSDL2.cpp VideoSDL2.h icon.h icon.cpp)
set(USE_FLAGS "--use-port=sdl2 --use-port=sdl2_image")
set_target_properties(videoSDL2 PROPERTIES
COMPILE_FLAGS "${USE_FLAGS}"
LINK_FLAGS "${USE_FLAGS}"
)
target_link_libraries(videoSDL2 PRIVATE videodrv s25util::common Boost::nowide)
else ()
add_library(videoSDL2 SHARED ${RTTR_DRIVER_INTERFACE} VideoSDL2.cpp VideoSDL2.h icon.h icon.cpp)
target_link_libraries(videoSDL2 PRIVATE videodrv s25util::common glad Boost::nowide SDL2::SDL2)
endif ()
enable_warnings(videoSDL2)

if(WIN32)
Expand Down
13 changes: 11 additions & 2 deletions extras/videoDrivers/SDL2/VideoSDL2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
#include "helpers/LSANUtils.h"
#include "helpers/containerUtils.h"
#include "icon.h"
#if !__EMSCRIPTEN__
#include "openglCfg.hpp"
#endif
#include <s25util/utf8.h>
#include <boost/nowide/iostream.hpp>
#include <SDL.h>
Expand Down Expand Up @@ -54,7 +56,7 @@ void FreeVideoInstance(IVideoDriver* driver)
delete driver;
}

const char* GetDriverName()
const char* GetVideoDriverName()
{
return "(SDL2) OpenGL via SDL2-Library";
}
Expand All @@ -68,7 +70,7 @@ VideoSDL2::~VideoSDL2()

const char* VideoSDL2::GetName() const
{
return GetDriverName();
return GetVideoDriverName();
}

bool VideoSDL2::Initialize()
Expand Down Expand Up @@ -112,6 +114,7 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo
if(!initialized)
return false;

#if !__EMSCRIPTEN__
// GL-Attributes
CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RTTR_OGL_MAJOR));
CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RTTR_OGL_MINOR));
Expand All @@ -128,6 +131,7 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo
CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8));
CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8));
CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1));
#endif

int wndPos = SDL_WINDOWPOS_CENTERED;

Expand Down Expand Up @@ -170,6 +174,11 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo

context = SDL_GL_CreateContext(window);

if(!context)
{
PrintError(SDL_GetError());
return false;
}
#ifdef _WIN32
SetWindowTextW(GetConsoleWindow(), boost::nowide::widen(title).c_str());
#endif
Expand Down
8 changes: 6 additions & 2 deletions libs/libGamedata/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ AddDirectory(lua)
file(GLOB SOURCES_OTHER *.cpp *.h)
source_group(other FILES ${SOURCES_OTHER})

find_package(Lua 5.1 REQUIRED)

if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
set(LUA_LIBRARIES /src/contrib/lua-5.4.7/build/lib/liblua.a)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded paths are a no-no. Can't the readme just state something like -DLua_ROOT=/src/contrib/lua-5.4.7/build?

set(LUA_INCLUDE_DIR /src/contrib/lua-5.4.7/build/include)
else ()
find_package(Lua 5.1 REQUIRED)
endif ()
include(GatherDll)
gather_dll(Lua)

Expand Down
3 changes: 2 additions & 1 deletion libs/rttrConfig/src/RttrConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ bfs::path RttrConfig::GetPrefixPath()
// Get path to current executable (at least for checks)
bfs::path fullExeFilepath = System::getExecutablePath();
// This should always work unless we have some missing implementation or a bad error
#if !__EMSCRIPTEN__
if(fullExeFilepath.empty())
{
LOG.write("Could not get path to current executable\n", LogTarget::Stderr);
Expand All @@ -47,7 +48,7 @@ bfs::path RttrConfig::GetPrefixPath()
LOG.write("Executable not at '%1%'\n", LogTarget::Stderr) % fullExeFilepath;
return "";
}

#endif
bfs::path rttrBinDir(RTTR_BINDIR);

// Allow overwrite with RTTR_PREFIX_DIR
Expand Down
22 changes: 21 additions & 1 deletion libs/s25client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,27 @@ else()
endif()

add_executable(s25client s25client.cpp commands.cpp ${s25client_RC})
target_link_libraries(s25client PRIVATE s25Main Boost::program_options Boost::nowide rttr::vld)
if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
set(USE_FLAGS "-fwasm-exceptions \
--use-port=sdl2 --use-port=sdl2_image --use-port=sdl2_mixer -sSDL2_MIXER_FORMATS=ogg")

set_target_properties(s25client PROPERTIES
COMPILE_FLAGS "${USE_FLAGS}"
LINK_FLAGS "${USE_FLAGS} \
-sALLOW_MEMORY_GROWTH -sINITIAL_MEMORY=256mb -sMEMORY_GROWTH_LINEAR_STEP=128mb \
-sSTACK_SIZE=1024kb \
-sENVIRONMENT=web \
-sMODULARIZE \
-sEXPORT_ALL -sEXPORTED_RUNTIME_METHODS=callMain,addRunDependency,removeRunDependency \
-sEXIT_RUNTIME \
-sFULL_ES2 -L/src/contrib/gl4es/lib/ -lgl4es \
-lwebsocket.js -lidbfs.js -sCASE_INSENSITIVE_FS --profiling-funcs"
SUFFIX ".js"
)
target_link_libraries(s25client PRIVATE s25Main Boost::program_options rttr::vld)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is nowide removed?

else ()
target_link_libraries(s25client PRIVATE s25Main Boost::program_options Boost::nowide rttr::vld)
endif ()
add_dependencies(s25client drivers)

if(WIN32)
Expand Down
33 changes: 26 additions & 7 deletions libs/s25client/s25client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
# include <csignal>
#endif

#ifdef __EMSCRIPTEN__
# include <emscripten.h>
#endif

namespace bfs = boost::filesystem;
namespace bnw = boost::nowide;
namespace po = boost::program_options;
Expand Down Expand Up @@ -435,6 +439,17 @@ bool InitGame(GameManager& gameManager)
return true;
}

#ifdef __EMSCRIPTEN__
static void mainLoop()
{
killme = false;
if (!GAMEMANAGER.Run())
{
emscripten_cancel_main_loop();
}
}
#endif

int RunProgram(po::variables_map& options)
{
LOG.write("%1%\n\n", LogTarget::Stdout) % GetProgramDescription();
Expand Down Expand Up @@ -466,11 +481,10 @@ int RunProgram(po::variables_map& options)
}
}

SetGlobalInstanceWrapper<GameManager> gameManager(setGlobalGameManager, LOG, SETTINGS, VIDEODRIVER, AUDIODRIVER,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need that for the regular game. Why the change?

WINDOWMANAGER);
setGlobalGameManager(new GameManager(LOG, SETTINGS, VIDEODRIVER, AUDIODRIVER, WINDOWMANAGER));
try
{
if(!InitGame(gameManager))
if(!InitGame(GAMEMANAGER))
return 2;

if(options.count("map"))
Expand All @@ -484,16 +498,21 @@ int RunProgram(po::variables_map& options)
}

// Hauptschleife

while(gameManager.Run())
#ifdef __EMSCRIPTEN__
EM_ASM({
Module?.gameReady?.();
});
emscripten_set_main_loop(&mainLoop, 0, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is blocking, isn't it? So using GAMEMANAGER inside is fine even without the above change. But better would be to pass gameManager to it as we were trying to reduce use of globals

#else
while(GAMEMANAGER.Run())
{
#ifndef _WIN32
killme = false;
#endif // !_WIN32
}

#endif
// Spiel beenden
gameManager.Stop();
GAMEMANAGER.Stop();
libsiedler2::setAllocator(nullptr);
} catch(const RTTR_AssertError& error)
{
Expand Down
13 changes: 12 additions & 1 deletion libs/s25main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,22 @@ target_link_libraries(s25Main PUBLIC
s25Common
rttrConfig
gamedata
glad
driver
Boost::filesystem Boost::disable_autolinking
PRIVATE BZip2::BZip2 Boost::iostreams Boost::locale Boost::nowide samplerate_cpp
)
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
target_link_libraries(s25Main PUBLIC videoSDL2 audioSDL)
set(USE_FLAGS "--use-port=sdl2 --use-port=sdl2_image \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the repetition I'm wondering if this can/should be passed to cmake rather than every variable. Especially with the hard-coded path

--use-port=sdl2_mixer -sSDL2_MIXER_FORMATS=ogg")
set_target_properties(s25Main PROPERTIES
COMPILE_FLAGS "${USE_FLAGS} -I/src/contrib/gl4es/include"
LINK_FLAGS "${USE_FLAGS}"
)
add_definitions(-DRTTR_OGL_ES=0)
else ()
target_link_libraries(s25Main PUBLIC glad)
endif ()

if(WIN32 OR CYGWIN)
include(CheckIncludeFiles)
Expand Down
10 changes: 9 additions & 1 deletion libs/s25main/GameManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ bool GameManager::Start()
settings_.Load();

/// Videotreiber laden
#ifdef __EMSCRIPTEN__
if(!videoDriver_.LoadDriver())
#else
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the change suggested to this function this change could be removed (it ignores the settings then)

if(!videoDriver_.LoadDriver(settings_.driver.video))
#endif
{
s25util::error(_("Video driver couldn't be loaded!"));
return false;
Expand All @@ -57,7 +61,11 @@ bool GameManager::Start()
videoDriver_.setGuiScalePercent(settings_.video.guiScale);

/// Audiodriver laden
#ifdef __EMSCRIPTEN__
if(!audioDriver_.LoadDriver())
#else
if(!audioDriver_.LoadDriver(settings_.driver.audio))
#endif
{
s25util::warning(_("Audio driver couldn't be loaded!"));
// return false;
Expand Down Expand Up @@ -195,7 +203,7 @@ void GameManager::ResetAverageGFPS()
gfCounter_ = FrameCounter(FrameCounter::clock::duration::max()); // Never update
}

static GameManager* globalGameManager = nullptr;
GameManager* globalGameManager;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change? This breaks encapsulation as the below function should be used


GameManager& getGlobalGameManager()
{
Expand Down
2 changes: 2 additions & 0 deletions libs/s25main/GameManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class GameManager
boost::optional<SkipReport> lastSkipReport;
};

extern GameManager *globalGameManager;

GameManager& getGlobalGameManager();
void setGlobalGameManager(GameManager* gameManager);

Expand Down
Loading