From 5b3b6df5444431254709ccf25d7f2beeafcc8132 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 18 Feb 2026 18:18:30 -0800 Subject: [PATCH] Add native installer packaging to CI for all platforms Linux: DEB with /opt/wowee prefix and /usr/local/bin/wowee wrapper script Windows x86-64: NSIS installer with DLL bundling and Start Menu shortcut Windows ARM64: ZIP archive with bundled DLLs macOS ARM64: .app bundle via dylibbundler + DMG via hdiutil Assets are bundled into all packages (Original Music excluded). StormLib is installed where available so asset_extract is included in packages. --- .github/workflows/build.yml | 107 +++++++++++++++++++++++++++++++----- CMakeLists.txt | 86 +++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6ec053ab..5bc4cc1a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,8 +16,10 @@ jobs: include: - arch: x86-64 runner: ubuntu-24.04 + deb_arch: amd64 - arch: arm64 runner: ubuntu-24.04-arm + deb_arch: arm64 steps: - name: Checkout @@ -50,7 +52,8 @@ jobs: libswscale-dev \ libavutil-dev \ libunicorn-dev \ - libx11-dev + libx11-dev \ + libstormlib-dev || true - name: Configure run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release @@ -58,11 +61,14 @@ jobs: - name: Build run: cmake --build build --parallel $(nproc) - - name: Upload artifacts + - name: Package (DEB) + run: cd build && cpack -G DEB + + - name: Upload DEB uses: actions/upload-artifact@v4 with: - name: wowee-${{ matrix.arch }} - path: build/bin/ + name: wowee-linux-${{ matrix.arch }}-deb + path: build/wowee-*.deb if-no-files-found: error build-macos: @@ -84,7 +90,10 @@ jobs: - name: Install dependencies run: | - brew install cmake pkg-config sdl2 glew glm openssl@3 zlib ffmpeg unicorn + brew install cmake pkg-config sdl2 glew glm openssl@3 zlib ffmpeg unicorn \ + stormlib dylibbundler || true + # dylibbundler may not be in all brew mirrors; install separately to not block others + brew install dylibbundler 2>/dev/null || true - name: Configure run: | @@ -98,11 +107,56 @@ jobs: - name: Build run: cmake --build build --parallel $(sysctl -n hw.logicalcpu) - - name: Upload artifacts + - name: Create .app bundle + run: | + mkdir -p Wowee.app/Contents/{MacOS,Frameworks,Resources} + + # Wrapper launch script — cd to MacOS/ so ./assets/ resolves correctly + printf '#!/bin/bash\ncd "$(dirname "$0")"\nexec ./wowee_bin "$@"\n' \ + > Wowee.app/Contents/MacOS/wowee + chmod +x Wowee.app/Contents/MacOS/wowee + + # Actual binary + cp build/bin/wowee Wowee.app/Contents/MacOS/wowee_bin + + # Assets (exclude proprietary music) + rsync -a --exclude='Original Music' build/bin/assets/ \ + Wowee.app/Contents/MacOS/assets/ + + # Bundle dylibs (if dylibbundler available) + if command -v dylibbundler &>/dev/null; then + dylibbundler -od -b \ + -x Wowee.app/Contents/MacOS/wowee_bin \ + -d Wowee.app/Contents/Frameworks/ \ + -p @executable_path/../Frameworks/ + fi + + # Info.plist + cat > Wowee.app/Contents/Info.plist << 'EOF' + + + + CFBundleExecutablewowee + CFBundleIdentifiercom.wowee.app + CFBundleNameWowee + CFBundleVersion1.0.0 + CFBundleShortVersionString1.0.0 + CFBundlePackageTypeAPPL + + EOF + + # Ad-hoc codesign (allows running on the local machine) + codesign --force --deep --sign - Wowee.app + + - name: Create DMG + run: hdiutil create -volname Wowee -srcfolder Wowee.app -ov -format UDZO Wowee.dmg + + - name: Upload DMG uses: actions/upload-artifact@v4 with: - name: wowee-macos-${{ matrix.arch }} - path: build/bin/ + name: wowee-macos-${{ matrix.arch }}-dmg + path: Wowee.dmg if-no-files-found: error build-windows-arm: @@ -142,11 +196,23 @@ jobs: shell: msys2 {0} run: cmake --build build --parallel $(nproc) - - name: Upload artifacts + - name: Bundle DLLs + shell: msys2 {0} + run: | + ldd build/bin/wowee.exe \ + | awk '/=> \// { print $3 }' \ + | grep -iv '^/c/Windows' \ + | xargs -I{} sh -c 'cp -n "{}" build/bin/ 2>/dev/null || true' + + - name: Package (ZIP) + shell: msys2 {0} + run: cd build && cpack -G ZIP + + - name: Upload ZIP uses: actions/upload-artifact@v4 with: - name: wowee-windows-arm64 - path: build/bin/ + name: wowee-windows-arm64-zip + path: build/wowee-*.zip if-no-files-found: error build-windows: @@ -173,6 +239,7 @@ jobs: mingw-w64-x86_64-zlib mingw-w64-x86_64-ffmpeg mingw-w64-x86_64-unicorn + mingw-w64-x86_64-nsis git - name: Clone ImGui @@ -187,9 +254,21 @@ jobs: shell: msys2 {0} run: cmake --build build --parallel $(nproc) - - name: Upload artifacts + - name: Bundle DLLs + shell: msys2 {0} + run: | + ldd build/bin/wowee.exe \ + | awk '/=> \// { print $3 }' \ + | grep -iv '^/c/Windows' \ + | xargs -I{} sh -c 'cp -n "{}" build/bin/ 2>/dev/null || true' + + - name: Package (NSIS) + shell: msys2 {0} + run: cd build && cpack -G NSIS + + - name: Upload installer uses: actions/upload-artifact@v4 with: - name: wowee-windows-x86-64 - path: build/bin/ + name: wowee-windows-x86-64-installer + path: build/wowee-*.exe if-no-files-found: error diff --git a/CMakeLists.txt b/CMakeLists.txt index aead6806..b990b3b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -389,6 +389,29 @@ install(TARGETS wowee ARCHIVE DESTINATION lib ) +# Install tools alongside main binary +foreach(_tool dbc_to_csv blp_convert auth_probe auth_login_probe) + if(TARGET ${_tool}) + install(TARGETS ${_tool} RUNTIME DESTINATION bin) + endif() +endforeach() +if(STORMLIB_LIBRARY AND STORMLIB_INCLUDE_DIR) + install(TARGETS asset_extract RUNTIME DESTINATION bin) +endif() + +# Install built-in assets (exclude proprietary music) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/assets + DESTINATION bin + PATTERN "Original Music" EXCLUDE) + +# On Windows, install any DLLs that were bundled into the build output dir +# (populated by the CI workflow's DLL-bundling step before cpack runs) +if(WIN32) + install(DIRECTORY "${CMAKE_BINARY_DIR}/bin/" + DESTINATION bin + FILES_MATCHING PATTERN "*.dll") +endif() + # Linux desktop integration (launcher + icon) if(UNIX AND NOT APPLE) set(WOWEE_LINUX_ICON_PATH "${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/hicolor/256x256/apps/wowee.png") @@ -512,3 +535,66 @@ message(STATUS " SDL2: ${SDL2_VERSION}") message(STATUS " OpenSSL: ${OPENSSL_VERSION}") message(STATUS " ImGui: ${IMGUI_DIR}") message(STATUS "") + +# ---- CPack packaging ---- +set(CPACK_PACKAGE_NAME "wowee") +set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "World of Warcraft client emulator") +set(CPACK_PACKAGE_VENDOR "Wowee") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "Wowee") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") + +if(WIN32) + set(CPACK_GENERATOR "NSIS") + set(CPACK_NSIS_DISPLAY_NAME "Wowee") + set(CPACK_NSIS_PACKAGE_NAME "Wowee") + set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") + set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) + # Run wowee from bin/ so that ./assets/ resolves correctly. + # SetOutPath sets the shortcut's working directory in NSIS. + set(CPACK_NSIS_CREATE_ICONS_EXTRA + "SetOutPath '$INSTDIR\\bin'\nCreateShortCut '$SMPROGRAMS\\$STARTMENU_FOLDER\\Wowee.lnk' '$INSTDIR\\bin\\wowee.exe'") + set(CPACK_NSIS_DELETE_ICONS_EXTRA + "Delete '$SMPROGRAMS\\$STARTMENU_FOLDER\\Wowee.lnk'") +elseif(APPLE) + set(CPACK_GENERATOR "DragNDrop") +else() + # Linux — generate postinst/prerm wrapper scripts + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/packaging) + # postinst: write a wrapper script at /usr/local/bin/wowee that cd's to + # the install dir so ./assets/ resolves correctly. + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst +[[#!/bin/sh +cat > /usr/local/bin/wowee << 'WOWEE_WRAPPER' +#!/bin/sh +cd /opt/wowee/bin +exec ./wowee "$@" +WOWEE_WRAPPER +chmod +x /usr/local/bin/wowee +]]) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm +"#!/bin/sh\nrm -f /usr/local/bin/wowee\n") + file(CHMOD + ${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst + ${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm + PERMISSIONS + OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ) + + set(CPACK_GENERATOR "DEB") + set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/wowee") + set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Wowee") + set(CPACK_DEBIAN_PACKAGE_SECTION "games") + set(CPACK_DEBIAN_PACKAGE_DEPENDS + "libsdl2-2.0-0, libglew2.2 | libglew2.1, libssl3, zlib1g") + set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA + "${CMAKE_CURRENT_BINARY_DIR}/packaging/postinst;${CMAKE_CURRENT_BINARY_DIR}/packaging/prerm") + if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|ARM64") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64") + endif() +endif() + +include(CPack)