Fix linking issues #28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Emscripten Build | |
| on: | |
| push: | |
| pull_request: | |
| workflow_dispatch: | |
| jobs: | |
| build-emscripten: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 # increase as needed (default is 360 minutes max) | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v3 | |
| with: | |
| submodules: recursive | |
| - name: Setup Emscripten | |
| uses: mymindstorm/setup-emsdk@v14 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| cmake \ | |
| ninja-build \ | |
| python3 \ | |
| python3-pip \ | |
| wget \ | |
| git | |
| - name: Cache build files | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| build-emscripten/ | |
| emscripten-deps/ | |
| key: ${{ runner.os }}-emscripten-build-${{ github.sha }} | |
| restore-keys: | | |
| ${{ runner.os }}-emscripten-build- | |
| - name: Build Emscripten dependencies | |
| run: | | |
| mkdir -p emscripten-deps | |
| cd emscripten-deps | |
| # Create a simple wrapper that provides zlib and libpng from Emscripten ports | |
| # This allows CMake's find_package to work with Emscripten's built-in libraries | |
| # Create pkg-config files for Emscripten's built-in zlib | |
| mkdir -p install/lib/pkgconfig | |
| cat > install/lib/pkgconfig/zlib.pc << 'EOF' | |
| prefix=/emsdk/upstream/emscripten/cache/sysroot | |
| exec_prefix=${prefix} | |
| libdir=${exec_prefix}/lib | |
| includedir=${prefix}/include | |
| Name: zlib | |
| Description: zlib compression library (Emscripten port) | |
| Version: 1.2.11 | |
| Libs: -lz | |
| Cflags: -I${includedir} | |
| EOF | |
| # Create CMake config for zlib | |
| mkdir -p install/lib/cmake/ZLIB | |
| cat > install/lib/cmake/ZLIB/ZLIBConfig.cmake << 'EOF' | |
| set(ZLIB_FOUND TRUE) | |
| set(ZLIB_INCLUDE_DIRS "/include") | |
| set(ZLIB_LIBRARIES "z") | |
| set(ZLIB_LIBRARY "z") | |
| set(ZLIB_INCLUDE_DIR "/include") | |
| if(NOT TARGET ZLIB::ZLIB) | |
| add_library(ZLIB::ZLIB INTERFACE IMPORTED) | |
| set_target_properties(ZLIB::ZLIB PROPERTIES | |
| INTERFACE_COMPILE_OPTIONS "-s;USE_ZLIB=1" | |
| INTERFACE_LINK_OPTIONS "-s;USE_ZLIB=1" | |
| INTERFACE_LINK_LIBRARIES "z" | |
| ) | |
| endif() | |
| EOF | |
| # Create CMake config for SDL2 (Emscripten port) | |
| mkdir -p install/lib/cmake/SDL2 | |
| cat > install/lib/cmake/SDL2/SDL2Config.cmake << 'EOF' | |
| set(SDL2_FOUND TRUE) | |
| set(SDL2_INCLUDE_DIRS "/include/SDL2") | |
| set(SDL2_LIBRARIES "SDL2") | |
| if(NOT TARGET SDL2::SDL2) | |
| add_library(SDL2::SDL2 INTERFACE IMPORTED) | |
| set_target_properties(SDL2::SDL2 PROPERTIES | |
| INTERFACE_COMPILE_OPTIONS "-s;USE_SDL=2" | |
| INTERFACE_LINK_OPTIONS "-s;USE_SDL=2" | |
| INTERFACE_LINK_LIBRARIES "SDL2" | |
| ) | |
| endif() | |
| # Also create SDL2-static for compatibility | |
| if(NOT TARGET SDL2::SDL2-static) | |
| add_library(SDL2::SDL2-static INTERFACE IMPORTED) | |
| set_target_properties(SDL2::SDL2-static PROPERTIES | |
| INTERFACE_COMPILE_OPTIONS "-s;USE_SDL=2" | |
| INTERFACE_LINK_OPTIONS "-s;USE_SDL=2" | |
| INTERFACE_LINK_LIBRARIES "SDL2" | |
| ) | |
| endif() | |
| # Also create SDL2main for compatibility | |
| if(NOT TARGET SDL2::SDL2main) | |
| add_library(SDL2::SDL2main INTERFACE IMPORTED) | |
| endif() | |
| EOF | |
| # Build a minimal libzip without zlib dependency checks | |
| if [ ! -d "libzip-1.10.1" ]; then | |
| wget https://github.com/nih-at/libzip/releases/download/v1.10.1/libzip-1.10.1.tar.gz | |
| tar -xzf libzip-1.10.1.tar.gz | |
| cd libzip-1.10.1 | |
| # Patch CMakeLists.txt to skip zlib version check | |
| sed -i 's/find_package(ZLIB 1.1.2 REQUIRED)/find_package(ZLIB REQUIRED)/' CMakeLists.txt | |
| mkdir -p build && cd build | |
| # Configure with Emscripten's zlib | |
| # First ensure ZLIB can be found | |
| export ZLIB_ROOT=$PWD/../../../emscripten-deps/install | |
| export PKG_CONFIG_PATH=$PWD/../../../emscripten-deps/install/lib/pkgconfig:$PKG_CONFIG_PATH | |
| CFLAGS="-s USE_ZLIB=1" LDFLAGS="-s USE_ZLIB=1" emcmake cmake .. \ | |
| -DENABLE_COMMONCRYPTO=OFF \ | |
| -DENABLE_GNUTLS=OFF \ | |
| -DENABLE_MBEDTLS=OFF \ | |
| -DENABLE_OPENSSL=OFF \ | |
| -DENABLE_WINDOWS_CRYPTO=OFF \ | |
| -DENABLE_BZIP2=OFF \ | |
| -DENABLE_LZMA=OFF \ | |
| -DENABLE_ZSTD=OFF \ | |
| -DBUILD_TOOLS=OFF \ | |
| -DBUILD_REGRESS=OFF \ | |
| -DBUILD_EXAMPLES=OFF \ | |
| -DBUILD_DOC=OFF \ | |
| -DBUILD_SHARED_LIBS=OFF \ | |
| -DCMAKE_PREFIX_PATH=$PWD/../../../emscripten-deps/install \ | |
| -DZLIB_DIR=$PWD/../../../emscripten-deps/install/lib/cmake/ZLIB \ | |
| -DCMAKE_INSTALL_PREFIX=$PWD/../../../emscripten-deps/install | |
| emmake make -j4 | |
| emmake make install | |
| # Patch the installed libzip config to not require ZLIB::ZLIB | |
| echo "Patching libzip config to work with Emscripten..." | |
| sed -i 's/ZLIB::ZLIB/z/g' $PWD/../../../emscripten-deps/install/lib/cmake/libzip/libzip-targets.cmake || true | |
| sed -i 's/INTERFACE_LINK_LIBRARIES "ZLIB::ZLIB"/INTERFACE_LINK_LIBRARIES "z"/g' $PWD/../../../emscripten-deps/install/lib/cmake/libzip/libzip-targets.cmake || true | |
| # Debug: Check what was actually installed | |
| echo "Checking installed files for libzip:" | |
| ls -la $PWD/../../../emscripten-deps/install/lib/cmake/ || true | |
| ls -la $PWD/../../../emscripten-deps/install/lib/ || true | |
| cd ../.. | |
| fi | |
| # Install nlohmann_json (use single header version for simplicity) | |
| echo "Installing nlohmann_json..." | |
| mkdir -p install/include/nlohmann | |
| wget https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp \ | |
| -O install/include/nlohmann/json.hpp | |
| # Create a minimal CMake config for nlohmann_json | |
| mkdir -p install/lib/cmake/nlohmann_json | |
| cat > install/lib/cmake/nlohmann_json/nlohmann_jsonConfig.cmake << 'EOF' | |
| # Config file for nlohmann_json | |
| set(nlohmann_json_FOUND TRUE) | |
| set(nlohmann_json_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/../../../include") | |
| if(NOT TARGET nlohmann_json::nlohmann_json) | |
| add_library(nlohmann_json::nlohmann_json INTERFACE IMPORTED) | |
| set_target_properties(nlohmann_json::nlohmann_json PROPERTIES | |
| INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/../../../include" | |
| ) | |
| endif() | |
| EOF | |
| echo "nlohmann_json installed as single header" | |
| # Verify nlohmann_json installation | |
| echo "Verifying nlohmann_json installation:" | |
| ls -la install/include/nlohmann/ || echo "Include directory not found" | |
| ls -la install/lib/cmake/nlohmann_json/ || echo "CMake config directory not found" | |
| cat install/lib/cmake/nlohmann_json/nlohmann_jsonConfig.cmake || echo "Config file not found" | |
| # Build tinyxml2 | |
| if [ ! -d "tinyxml2-10.0.0" ]; then | |
| wget https://github.com/leethomason/tinyxml2/archive/refs/tags/10.0.0.tar.gz | |
| tar -xzf 10.0.0.tar.gz | |
| cd tinyxml2-10.0.0 | |
| mkdir -p build && cd build | |
| emcmake cmake .. \ | |
| -Dtinyxml2_BUILD_TESTING=OFF \ | |
| -DCMAKE_INSTALL_PREFIX=$PWD/../../../emscripten-deps/install | |
| emmake make -j4 | |
| emmake make install | |
| cd ../.. | |
| fi | |
| # Build spdlog (use older version that works better with Emscripten) | |
| echo "Building spdlog..." | |
| if [ ! -d "spdlog-1.12.0" ]; then | |
| echo "Building spdlog 1.12.0 (better Emscripten compatibility)..." | |
| wget https://github.com/gabime/spdlog/archive/refs/tags/v1.12.0.tar.gz -O spdlog-1.12.0.tar.gz | |
| tar -xzf spdlog-1.12.0.tar.gz | |
| cd spdlog-1.12.0 | |
| mkdir -p build && cd build | |
| # Configure as header-only to avoid compilation issues | |
| emcmake cmake .. \ | |
| -DSPDLOG_BUILD_EXAMPLE=OFF \ | |
| -DSPDLOG_BUILD_TESTS=OFF \ | |
| -DSPDLOG_BUILD_BENCH=OFF \ | |
| -DSPDLOG_INSTALL=ON \ | |
| -DSPDLOG_HEADER_ONLY=ON \ | |
| -DSPDLOG_FMT_EXTERNAL=OFF \ | |
| -DCMAKE_CXX_STANDARD=17 \ | |
| -DCMAKE_INSTALL_PREFIX=$PWD/../../../emscripten-deps/install | |
| emmake make -j4 | |
| emmake make install | |
| cd ../.. | |
| fi | |
| # Comprehensive dependency verification | |
| echo "=== Verifying all installed dependencies ===" | |
| echo "Current directory: $PWD" | |
| echo "" | |
| echo "1. Checking zlib (Emscripten port):" | |
| ls -la install/lib/cmake/ZLIB/ || echo "ZLIB cmake config not found" | |
| echo "" | |
| echo "2. Checking SDL2 (Emscripten port):" | |
| ls -la install/lib/cmake/SDL2/ || echo "SDL2 cmake config not found" | |
| echo "" | |
| echo "3. Checking libzip:" | |
| ls -la install/lib/cmake/libzip/ || echo "libzip cmake config not found" | |
| ls -la install/lib/*libzip* || echo "libzip library not found" | |
| echo "" | |
| echo "4. Checking nlohmann_json:" | |
| ls -la install/include/nlohmann/json.hpp || echo "json.hpp not found" | |
| ls -la install/lib/cmake/nlohmann_json/nlohmann_jsonConfig.cmake || echo "nlohmann_json cmake config not found" | |
| echo "" | |
| echo "5. Checking tinyxml2:" | |
| ls -la install/lib/cmake/tinyxml2/ || echo "tinyxml2 cmake config not found" | |
| ls -la install/lib/*tinyxml2* || echo "tinyxml2 library not found" | |
| echo "" | |
| echo "6. Checking spdlog:" | |
| ls -la install/lib/cmake/spdlog/ || echo "spdlog cmake config not found" | |
| ls -la install/lib/*spdlog* || echo "spdlog library not found" | |
| echo "" | |
| echo "All CMake configs in install/lib/cmake:" | |
| find install/lib/cmake -name "*Config.cmake" -o -name "*config.cmake" 2>/dev/null || echo "No cmake configs found" | |
| echo "" | |
| echo "Complete install directory structure:" | |
| find install -type d | head -30 | |
| - name: Configure CMake for Emscripten | |
| run: | | |
| export EMSCRIPTEN=1 | |
| export CMAKE_PREFIX_PATH=$PWD/emscripten-deps/install | |
| # Ensure Emscripten's zlib is available | |
| export CFLAGS="-s USE_ZLIB=1 -s USE_LIBPNG=1" | |
| export LDFLAGS="-s USE_ZLIB=1 -s USE_LIBPNG=1" | |
| # Help CMake find all libraries specifically | |
| export ZLIB_DIR=$PWD/emscripten-deps/install/lib/cmake/ZLIB | |
| export SDL2_DIR=$PWD/emscripten-deps/install/lib/cmake/SDL2 | |
| export libzip_DIR=$PWD/emscripten-deps/install/lib/cmake/libzip | |
| export nlohmann_json_DIR=$PWD/emscripten-deps/install/lib/cmake/nlohmann_json | |
| export tinyxml2_DIR=$PWD/emscripten-deps/install/lib/cmake/tinyxml2 | |
| export spdlog_DIR=$PWD/emscripten-deps/install/lib/cmake/spdlog | |
| # Debug: verify paths exist before configuring | |
| echo "Verifying CMake config paths before configuration:" | |
| echo "ZLIB_DIR: $ZLIB_DIR" | |
| ls -la $ZLIB_DIR/*.cmake 2>/dev/null || echo "ZLIB config not found" | |
| echo "libzip_DIR: $libzip_DIR" | |
| ls -la $libzip_DIR/*.cmake 2>/dev/null || echo "libzip config not found" | |
| echo "nlohmann_json_DIR: $nlohmann_json_DIR" | |
| ls -la $nlohmann_json_DIR/*.cmake 2>/dev/null || echo "nlohmann_json config not found" | |
| echo "tinyxml2_DIR: $tinyxml2_DIR" | |
| ls -la $tinyxml2_DIR/*.cmake 2>/dev/null || echo "tinyxml2 config not found" | |
| echo "spdlog_DIR: $spdlog_DIR" | |
| ls -la $spdlog_DIR/*.cmake 2>/dev/null || echo "spdlog config not found" | |
| emcmake cmake -S . -B build-emscripten \ | |
| -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_CXX_STANDARD=17 \ | |
| -DCMAKE_PREFIX_PATH=$PWD/emscripten-deps/install \ | |
| -DZLIB_DIR=$PWD/emscripten-deps/install/lib/cmake/ZLIB \ | |
| -DSDL2_DIR=$PWD/emscripten-deps/install/lib/cmake/SDL2 \ | |
| -Dlibzip_DIR=$PWD/emscripten-deps/install/lib/cmake/libzip \ | |
| -Dnlohmann_json_DIR=$PWD/emscripten-deps/install/lib/cmake/nlohmann_json \ | |
| -Dtinyxml2_DIR=$PWD/emscripten-deps/install/lib/cmake/tinyxml2 \ | |
| -Dspdlog_DIR=$PWD/emscripten-deps/install/lib/cmake/spdlog \ | |
| -DCMAKE_C_FLAGS="-s USE_ZLIB=1 -s USE_LIBPNG=1 -s USE_SDL=2 -s USE_WEBGL2=1 -s FULL_ES3=1" \ | |
| -DCMAKE_CXX_FLAGS="-s USE_ZLIB=1 -s USE_LIBPNG=1 -s USE_SDL=2 -s USE_WEBGL2=1 -s FULL_ES3=1 -DSPDLOG_HEADER_ONLY" \ | |
| -DCMAKE_EXE_LINKER_FLAGS="-s USE_ZLIB=1 -s USE_LIBPNG=1 -s USE_SDL=2 -s USE_WEBGL2=1 -s FULL_ES3=1 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2" \ | |
| -DBUILD_CROWD_CONTROL=OFF \ | |
| -DBUILD_REMOTE_CONTROL=OFF \ | |
| -DSUPPRESS_WARNINGS=ON \ | |
| -DUSE_OPENGLES=ON | |
| - name: Build soh.o2r | |
| run: | | |
| cmake --build build-emscripten --target GenerateSohOtr || true | |
| # Copy any existing OTR files if the build step fails | |
| if [ -f "soh/soh.o2r" ]; then | |
| cp soh/soh.o2r build-emscripten/soh/ | |
| fi | |
| - name: Build Ship of Harkinian for Web | |
| run: | | |
| cmake --build build-emscripten --config Release | |
| - name: Prepare Web Distribution | |
| run: | | |
| mkdir -p web-dist | |
| cp build-emscripten/soh/soh.html web-dist/index.html || true | |
| cp build-emscripten/soh/soh.js web-dist/ || true | |
| cp build-emscripten/soh/soh.wasm web-dist/ || true | |
| cp build-emscripten/soh/soh.data web-dist/ || true | |
| cp web/index.html web-dist/index.html || true | |
| # Copy OTR files if available | |
| if [ -f "build-emscripten/soh/soh.o2r" ]; then | |
| cp build-emscripten/soh/soh.o2r web-dist/ | |
| fi | |
| - name: Upload Web Build Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: soh-web-build | |
| path: web-dist/ | |
| retention-days: 7 | |
| - name: Deploy to GitHub Pages (optional) | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| uses: peaceiris/actions-gh-pages@v3 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./web-dist | |
| destination_dir: web | |
| keep_files: true | |
| test-web-build: | |
| needs: build-emscripten | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download Web Build | |
| uses: actions/download-artifact@v3 | |
| with: | |
| name: soh-web-build | |
| path: web-dist/ | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v3 | |
| with: | |
| node-version: '18' | |
| - name: Install HTTP Server | |
| run: npm install -g http-server | |
| - name: Test Web Server | |
| run: | | |
| # Start HTTP server in background | |
| http-server web-dist -p 8080 & | |
| SERVER_PID=$! | |
| # Wait for server to start | |
| sleep 5 | |
| # Check if files are accessible | |
| curl -f http://localhost:8080/index.html || exit 1 | |
| curl -f http://localhost:8080/soh.js || exit 1 | |
| curl -f http://localhost:8080/soh.wasm || exit 1 | |
| # Kill the server | |
| kill $SERVER_PID | |
| - name: Validate Build Files | |
| run: | | |
| # Check file sizes | |
| echo "Build file sizes:" | |
| ls -lh web-dist/ | |
| # Verify WASM file | |
| file web-dist/soh.wasm | grep WebAssembly || exit 1 | |
| # Check JavaScript file | |
| if [ ! -s web-dist/soh.js ]; then | |
| echo "Error: soh.js is empty" | |
| exit 1 | |
| fi |