mirror of
https://github.com/citron-neo/emulator.git
synced 2026-07-05 15:21:57 -07:00
build(linux): remove obsolete scripts, fix audio deps, and improve AppImage cleanup
Deleted scripts/CI files: - Remove AppImage-build-debian-inner.sh, ppImage-build-debian.sh, AppImage-build-local.sh: replaced by AppImageBuilder/package-citron-linux.sh - Remove AppImageBuilder/build.sh, AppImageBuilder/build-v2.sh: superseded by package-citron-linux.sh - Remove build-for-mingw.bat, build-for-mingw.sh, fix-pgo-dll.ps1, pgo-build.ps1, pgo-build.sh: obsolete windows/PGO build helpers - Remove .gitlab-ci.yml: entirely commented-out dead config build-citron-linux.sh: - Add ALSA + PulseAudio dev packages as required across all supported package managers (apt, pacman, dnf, yum, zypper, emerge) to encourage Linux audio output to be present in packaged AppImages AppImageBuilder/package-citron-linux.sh: - Expand AppDir post-packaging cleanup: remove additional Qt plugin dirs, stale symlinks, and other bloat before the AppImage is assembled
This commit is contained in:
-435
@@ -1,435 +0,0 @@
|
||||
# GitLab CI config for Citron - DISABLED
|
||||
# This CI configuration has been disabled as GitHub Actions is now being used
|
||||
# To re-enable, uncomment the configuration below
|
||||
|
||||
# stages:
|
||||
# - build
|
||||
# - test
|
||||
# - package
|
||||
|
||||
# variables:
|
||||
# BUILD_TYPE: "Release"
|
||||
# CMAKE_BUILD_PARALLEL_LEVEL: "4"
|
||||
# DOCKER_DRIVER: overlay2
|
||||
# DOCKER_TLS_CERTDIR: ""
|
||||
|
||||
# # Cache configuration for faster builds
|
||||
# cache:
|
||||
# paths:
|
||||
# - build/vcpkg_installed/
|
||||
# - build/_deps/
|
||||
# key: "$CI_COMMIT_REF_SLUG"
|
||||
# policy: pull-push
|
||||
|
||||
|
||||
# # Linux Build (CachyOS optimized)
|
||||
# build-linux:
|
||||
# stage: build
|
||||
# image: cachyos/cachyos:latest
|
||||
# tags:
|
||||
# - citron-build
|
||||
# before_script:
|
||||
# - pacman -Syu --noconfirm
|
||||
# - pacman -S --noconfirm alsa-lib base-devel boost boost-libs catch2 cmake curl ffmpeg fmt fuse2 gamemode gcc gdb git glslang glu libusb libxi libxkbcommon libxkbcommon-x11 libxss libzip lz4 mbedtls2 mesa nasm ninja nlohmann-json openal openssl opus perl pipewire-audio pulseaudio pulseaudio-alsa qt6-base qt6-multimedia qt6-tools qt6-wayland sdl2 sdl2-compat unzip vulkan-headers vulkan-icd-loader vulkan-mesa-layers wget xcb-util-cursor xcb-util-image xcb-util-keysyms xcb-util-renderutil xcb-util-wm xorg-server-xvfb zip zstd zsync
|
||||
# - echo '#!/bin/bash' > /usr/local/bin/shasum
|
||||
# - echo 'if [ "$1" = "-a" ] && [ "$2" = "256" ]; then' >> /usr/local/bin/shasum
|
||||
# - echo ' shift 2' >> /usr/local/bin/shasum
|
||||
# - echo ' sha256sum "$@"' >> /usr/local/bin/shasum
|
||||
# - echo 'else' >> /usr/local/bin/shasum
|
||||
# - echo ' sha256sum "$@"' >> /usr/local/bin/shasum
|
||||
# - echo 'fi' >> /usr/local/bin/shasum
|
||||
# - chmod +x /usr/local/bin/shasum
|
||||
# script: |
|
||||
# # Clean and reset submodules to handle any inconsistencies
|
||||
# git submodule deinit --all --force || true
|
||||
# # Forcefully remove stale lock files that can block submodule updates
|
||||
# find .git/modules -type f -name "*.lock" -delete
|
||||
# git submodule update --init --recursive --force
|
||||
# mkdir -p build && cd build
|
||||
# # Dynamically find the Qt private header path
|
||||
# HEADER_PATH=$(pacman -Ql qt6-base | grep 'qpa/qplatformnativeinterface.h$' | awk '{print $2}')
|
||||
# if [ -z "$HEADER_PATH" ]; then echo "ERROR: Could not find qplatformnativeinterface.h path." >&2; exit 1; fi
|
||||
# QT_PRIVATE_INCLUDE_DIR=$(dirname "$(dirname "$HEADER_PATH")")
|
||||
# echo "Found Qt private include directory: ${QT_PRIVATE_INCLUDE_DIR}"
|
||||
# # Configure and build with the dynamically found path
|
||||
# cmake .. \
|
||||
# -G Ninja \
|
||||
# -DCMAKE_C_COMPILER=gcc \
|
||||
# -DCMAKE_CXX_COMPILER=g++ \
|
||||
# -DCMAKE_BUILD_TYPE=Release \
|
||||
# -DCMAKE_INSTALL_PREFIX=/usr \
|
||||
# -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
# -DUSE_SYSTEM_QT=ON \
|
||||
# -DCMAKE_C_FLAGS="-O3 -ffast-math -funsafe-math-optimizations -fno-math-errno -fno-trapping-math -freciprocal-math -ffp-contract=fast -fassociative-math -fno-rounding-math -fno-signaling-nans -march=x86-64-v2 -mtune=native -fomit-frame-pointer -fstrict-aliasing -frename-registers -fno-plt -funroll-loops -floop-interchange -floop-strip-mine -floop-block -fprefetch-loop-arrays -fpredictive-commoning -ftree-vectorize -fsplit-paths -finline-functions -finline-limit=1000 -finline-functions-called-once -fgcse-sm -fgcse-las -freorder-blocks-and-partition -fipa-pta -fipa-cp-clone -fwhole-program -flto=auto -fuse-linker-plugin -fvisibility=hidden -fdata-sections -ffunction-sections -fno-semantic-interposition -fopenmp -fexceptions -frtti" \
|
||||
# -DCMAKE_CXX_FLAGS="-I${QT_PRIVATE_INCLUDE_DIR} -O3 -ffast-math -funsafe-math-optimizations -fno-math-errno -fno-trapping-math -freciprocal-math -ffp-contract=fast -fassociative-math -fno-rounding-math -fno-signaling-nans -march=x86-64-v2 -mtune=native -fomit-frame-pointer -fstrict-aliasing -frename-registers -fno-plt -funroll-loops -floop-interchange -floop-strip-mine -floop-block -fprefetch-loop-arrays -fpredictive-commoning -ftree-vectorize -fsplit-paths -finline-functions -finline-limit=1000 -finline-functions-called-once -fgcse-sm -fgcse-las -freorder-blocks-and-partition -fipa-pta -fipa-cp-clone -fwhole-program -flto=auto -fuse-linker-plugin -fvisibility=hidden -fdata-sections -ffunction-sections -fno-semantic-interposition -fopenmp -fexceptions -frtti -Wno-error -w" \
|
||||
# -DCMAKE_EXE_LINKER_FLAGS="-Wl,--gc-sections -Wl,-O2 -Wl,--as-needed" \
|
||||
# -DSDL_PIPEWIRE=OFF \
|
||||
# -DCITRON_USE_BUNDLED_VCPKG=OFF \
|
||||
# -DUSE_DISCORD_PRESENCE=OFF \
|
||||
# -DBUNDLE_SPEEX=ON \
|
||||
# -DCITRON_USE_BUNDLED_FFMPEG=OFF \
|
||||
# -DCITRON_USE_QT_MULTIMEDIA=OFF \
|
||||
# -DCITRON_USE_QT_WEB_ENGINE=OFF
|
||||
# ninja
|
||||
# cd ..
|
||||
# echo "Build completed, checking for executables..."
|
||||
# ls -la build/bin/ || echo "No build/bin directory found"
|
||||
# find build/ -name "*.so" -o -name "citron*" | head -20 || echo "No shared libraries or executables found"
|
||||
# echo "Checking library dependencies..."
|
||||
# ldd build/bin/citron || echo "citron binary not found or ldd failed"
|
||||
# chmod +x AppImage-build-local.sh
|
||||
# echo "Attempting AppImage build with FUSE workaround..."
|
||||
# export APPIMAGE_EXTRACT_AND_RUN=1
|
||||
# export ARCH=x86_64
|
||||
# export VERSION=$(git describe --tags --always)
|
||||
# echo "Testing shasum compatibility..."
|
||||
# which shasum || echo "shasum not found in PATH"
|
||||
# echo "Testing shasum -a 256 syntax..."
|
||||
# echo "test" | shasum -a 256 || echo "shasum -a 256 failed"
|
||||
# echo "test" | sha256sum || echo "sha256sum failed"
|
||||
# echo "Running AppImage build..."
|
||||
# ./AppImage-build-local.sh || echo "AppImage build failed, continuing..."
|
||||
# ls -la *.AppImage || echo "No AppImage files found"
|
||||
# echo "AppImage size information:"
|
||||
# du -h *.AppImage || echo "No AppImage to measure"
|
||||
# echo "Total artifact size:"
|
||||
# du -sh citron.AppImage build/bin/citron 2>/dev/null || echo "Cannot measure artifact sizes"
|
||||
# echo "Compressing AppImage for upload..."
|
||||
# gzip -9 -c citron.AppImage > citron.AppImage.gz
|
||||
# ls -la citron.AppImage.gz
|
||||
# du -h citron.AppImage.gz
|
||||
# echo "AppImage compressed with gzip successfully"
|
||||
# tar -czf citron-binary.tar.gz build/bin/
|
||||
# ls -la citron-binary.tar.gz
|
||||
# du -h citron-binary.tar.gz
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - citron.AppImage.gz
|
||||
# - citron-binary.tar.gz
|
||||
# expire_in: 1 week
|
||||
# when: always
|
||||
# only:
|
||||
# - main
|
||||
# - master
|
||||
# - develop
|
||||
# - ci-fixes
|
||||
# - Boss-Build-Flags-For-CI-CMAKE-ON-CachyOS
|
||||
# - merge_requests
|
||||
|
||||
# # Linux Build (CachyOS v3 optimized)
|
||||
# build-linux-v3:
|
||||
# stage: build
|
||||
# image: cachyos/cachyos-v3
|
||||
# tags:
|
||||
# - citron-build
|
||||
# before_script:
|
||||
# - pacman -Syu --noconfirm
|
||||
# - pacman -S --noconfirm alsa-lib base-devel boost boost-libs catch2 cmake curl ffmpeg fmt fuse2 gamemode gcc gdb git glslang glu libusb libxi libxkbcommon libxkbcommon-x11 libxss libzip lz4 mbedtls2 mesa nasm ninja nlohmann-json openal openssl opus perl pipewire-audio pulseaudio pulseaudio-alsa python-pip qt6-base qt6-multimedia qt6-tools qt6-wayland sdl2 sdl2-compat unzip vulkan-headers vulkan-icd-loader vulkan-mesa-layers wget xcb-util-cursor xcb-util-image xcb-util-keysyms xcb-util-renderutil xcb-util-wm xorg-server-xvfb zip zstd zsync
|
||||
# - echo '#!/bin/bash' > /usr/local/bin/shasum
|
||||
# - echo 'if [ "$1" = "-a" ] && [ "$2" = "256" ]; then' >> /usr/local/bin/shasum
|
||||
# - echo ' shift 2' >> /usr/local/bin/shasum
|
||||
# - echo ' sha256sum "$@"' >> /usr/local/bin/shasum
|
||||
# - echo 'else' >> /usr/local/bin/shasum
|
||||
# - echo ' sha256sum "$@"' >> /usr/local/bin/shasum
|
||||
# - echo 'fi' >> /usr/local/bin/shasum
|
||||
# - chmod +x /usr/local/bin/shasum
|
||||
# script: |
|
||||
# git submodule deinit --all --force || true
|
||||
# find .git/modules -type f -name "*.lock" -delete
|
||||
# git submodule update --init --recursive --force
|
||||
# mkdir -p build && cd build
|
||||
# HEADER_PATH=$(pacman -Ql qt6-base | grep 'qpa/qplatformnativeinterface.h$' | awk '{print $2}')
|
||||
# if [ -z "$HEADER_PATH" ]; then echo "ERROR: Could not find qplatformnativeinterface.h path." >&2; exit 1; fi
|
||||
# QT_PRIVATE_INCLUDE_DIR=$(dirname "$(dirname "$HEADER_PATH")")
|
||||
# echo "Found Qt private include directory: ${QT_PRIVATE_INCLUDE_DIR}"
|
||||
# cmake .. \
|
||||
# -G Ninja \
|
||||
# -DCMAKE_C_COMPILER=gcc \
|
||||
# -DCMAKE_CXX_COMPILER=g++ \
|
||||
# -DCMAKE_BUILD_TYPE=Release \
|
||||
# -DCMAKE_INSTALL_PREFIX=/usr \
|
||||
# -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
# -DCMAKE_C_FLAGS="-O3 -ffast-math -funsafe-math-optimizations -fno-math-errno -fno-trapping-math -freciprocal-math -ffp-contract=fast -fassociative-math -fno-rounding-math -fno-signaling-nans -march=x86-64-v3 -mtune=native -fomit-frame-pointer -fstrict-aliasing -frename-registers -fno-plt -funroll-loops -floop-interchange -floop-strip-mine -floop-block -fprefetch-loop-arrays -fpredictive-commoning -ftree-vectorize -fsplit-paths -finline-functions -finline-limit=1000 -finline-functions-called-once -fgcse-sm -fgcse-las -freorder-blocks-and-partition -fipa-pta -fipa-cp-clone -fwhole-program -flto=auto -fuse-linker-plugin -fvisibility=hidden -fdata-sections -ffunction-sections -fno-semantic-interposition -fopenmp -fexceptions -frtti" \
|
||||
# -DCMAKE_CXX_FLAGS="-I${QT_PRIVATE_INCLUDE_DIR} -O3 -ffast-math -funsafe-math-optimizations -fno-math-errno -fno-trapping-math -freciprocal-math -ffp-contract=fast -fassociative-math -fno-rounding-math -fno-signaling-nans -march=x86-64-v3 -mtune=native -fomit-frame-pointer -fstrict-aliasing -frename-registers -fno-plt -funroll-loops -floop-interchange -floop-strip-mine -floop-block -fprefetch-loop-arrays -fpredictive-commoning -ftree-vectorize -fsplit-paths -finline-functions -finline-limit=1000 -finline-functions-called-once -fgcse-sm -fgcse-las -freorder-blocks-and-partition -fipa-pta -fipa-cp-clone -fwhole-program -flto=auto -fuse-linker-plugin -fvisibility=hidden -fdata-sections -ffunction-sections -fno-semantic-interposition -fopenmp -fexceptions -frtti -Wno-error -w" \
|
||||
# -DCMAKE_EXE_LINKER_FLAGS="-Wl,--gc-sections -Wl,-O2 -Wl,--as-needed" \
|
||||
# -DSDL_PIPEWIRE=OFF \
|
||||
# -DCITRON_USE_BUNDLED_VCPKG=OFF \
|
||||
# -DUSE_DISCORD_PRESENCE=OFF \
|
||||
# -DBUNDLE_SPEEX=ON \
|
||||
# -DCITRON_USE_BUNDLED_FFMPEG=OFF \
|
||||
# -DCITRON_USE_QT_MULTIMEDIA=OFF \
|
||||
# -DCITRON_USE_QT_WEB_ENGINE=OFF
|
||||
# ninja
|
||||
# cd ..
|
||||
# echo "Build completed, checking for executables..."
|
||||
# ls -la build/bin/ || echo "No build/bin directory found"
|
||||
# find build/ -name "*.so" -o -name "citron*" | head -20 || echo "No shared libraries or executables found"
|
||||
# echo "Checking library dependencies..."
|
||||
# ldd build/bin/citron || echo "citron binary not found or ldd failed"
|
||||
# chmod +x AppImage-build-local.sh
|
||||
# echo "Attempting AppImage build with FUSE workaround..."
|
||||
# export APPIMAGE_EXTRACT_AND_RUN=1
|
||||
# export ARCH=x86_64
|
||||
# export VERSION=$(git describe --tags --always)
|
||||
# echo "Testing shasum compatibility..."
|
||||
# which shasum || echo "shasum not found in PATH"
|
||||
# echo "Testing shasum -a 256 syntax..."
|
||||
# echo "test" | shasum -a 256 || echo "shasum -a 256 failed"
|
||||
# echo "test" | sha256sum || echo "sha256sum failed"
|
||||
# echo "Running AppImage build..."
|
||||
# ./AppImage-build-local.sh || echo "AppImage build failed, continuing..."
|
||||
# ls -la *.AppImage || echo "No AppImage files found"
|
||||
# echo "AppImage size information:"
|
||||
# du -h *.AppImage || echo "No AppImage to measure"
|
||||
# echo "Total artifact size:"
|
||||
# du -sh citron.AppImage build/bin/citron 2>/dev/null || echo "Cannot measure artifact sizes"
|
||||
# echo "Compressing AppImage for upload..."
|
||||
# gzip -9 -c citron.AppImage > citron.AppImage.gz
|
||||
# ls -la citron.AppImage.gz
|
||||
# du -h citron.AppImage.gz
|
||||
# echo "AppImage compressed with gzip successfully"
|
||||
# tar -czf citron-binary.tar.gz build/bin/
|
||||
# ls -la citron-binary.tar.gz
|
||||
# du -h citron-binary.tar.gz
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - citron.AppImage.gz
|
||||
# - citron-binary.tar.gz
|
||||
# expire_in: 1 week
|
||||
# when: always
|
||||
# only:
|
||||
# - main
|
||||
# - master
|
||||
# - develop
|
||||
# - ci-fixes
|
||||
# - Boss-Build-Flags-For-CI-CMAKE-ON-CachyOS
|
||||
# - merge_requests
|
||||
|
||||
# # Linux Build (Steam Deck optimized - AMD Zen 2)
|
||||
# build-linux-steamdeck:
|
||||
# stage: build
|
||||
# image: cachyos/cachyos:latest
|
||||
# tags:
|
||||
# - citron-build
|
||||
# before_script:
|
||||
# - pacman -Syu --noconfirm
|
||||
# - pacman -S --noconfirm alsa-lib base-devel boost boost-libs catch2 cmake curl ffmpeg fmt fuse2 gamemode gcc gdb git glslang glu libusb libxi libxkbcommon libxkbcommon-x11 libxss libzip lz4 mbedtls2 mesa nasm ninja nlohmann-json openal openssl opus perl pipewire-audio pulseaudio pulseaudio-alsa python-pip qt6-base qt6-multimedia qt6-tools qt6-wayland sdl2 sdl2-compat unzip vulkan-headers vulkan-icd-loader vulkan-mesa-layers wget xcb-util-cursor xcb-util-image xcb-util-keysyms xcb-util-renderutil xcb-util-wm xorg-server-xvfb zip zstd zsync
|
||||
# - echo '#!/bin/bash' > /usr/local/bin/shasum
|
||||
# - echo 'if [ "$1" = "-a" ] && [ "$2" = "256" ]; then' >> /usr/local/bin/shasum
|
||||
# - echo ' shift 2' >> /usr/local/bin/shasum
|
||||
# - echo ' sha256sum "$@"' >> /usr/local/bin/shasum
|
||||
# - echo 'else' >> /usr/local/bin/shasum
|
||||
# - echo ' sha256sum "$@"' >> /usr/local/bin/shasum
|
||||
# - echo 'fi' >> /usr/local/bin/shasum
|
||||
# - chmod +x /usr/local/bin/shasum
|
||||
# script: |
|
||||
# git submodule deinit --all --force || true
|
||||
# find .git/modules -type f -name "*.lock" -delete
|
||||
# git submodule update --init --recursive --force
|
||||
# mkdir -p build && cd build
|
||||
# HEADER_PATH=$(pacman -Ql qt6-base | grep 'qpa/qplatformnativeinterface.h$' | awk '{print $2}')
|
||||
# if [ -z "$HEADER_PATH" ]; then echo "ERROR: Could not find qplatformnativeinterface.h path." >&2; exit 1; fi
|
||||
# QT_PRIVATE_INCLUDE_DIR=$(dirname "$(dirname "$HEADER_PATH")")
|
||||
# echo "Found Qt private include directory: ${QT_PRIVATE_INCLUDE_DIR}"
|
||||
# cmake .. \
|
||||
# -G Ninja \
|
||||
# -DCMAKE_C_COMPILER=gcc \
|
||||
# -DCMAKE_CXX_COMPILER=g++ \
|
||||
# -DCMAKE_BUILD_TYPE=Release \
|
||||
# -DCMAKE_INSTALL_PREFIX=/usr \
|
||||
# -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
# -DCMAKE_C_FLAGS="-O3 -ffast-math -funsafe-math-optimizations -fno-math-errno -fno-trapping-math -freciprocal-math -ffp-contract=fast -fassociative-math -fno-rounding-math -fno-signaling-nans -march=znver2 -mtune=znver2 -fomit-frame-pointer -fstrict-aliasing -frename-registers -fno-plt -funroll-loops -floop-interchange -floop-strip-mine -floop-block -fprefetch-loop-arrays -fpredictive-commoning -ftree-vectorize -fsplit-paths -finline-functions -finline-limit=1000 -finline-functions-called-once -fgcse-sm -fgcse-las -freorder-blocks-and-partition -fipa-pta -fipa-cp-clone -fwhole-program -flto=auto -fuse-linker-plugin -fvisibility=hidden -fdata-sections -ffunction-sections -fno-semantic-interposition -fopenmp -fexceptions -frtti" \
|
||||
# -DCMAKE_CXX_FLAGS="-I${QT_PRIVATE_INCLUDE_DIR} -O3 -ffast-math -funsafe-math-optimizations -fno-math-errno -fno-trapping-math -freciprocal-math -ffp-contract=fast -fassociative-math -fno-rounding-math -fno-signaling-nans -march=znver2 -mtune=znver2 -fomit-frame-pointer -fstrict-aliasing -frename-registers -fno-plt -funroll-loops -floop-interchange -floop-strip-mine -floop-block -fprefetch-loop-arrays -fpredictive-commoning -ftree-vectorize -fsplit-paths -finline-functions -finline-limit=1000 -finline-functions-called-once -fgcse-sm -fgcse-las -freorder-blocks-and-partition -fipa-pta -fipa-cp-clone -fwhole-program -flto=auto -fuse-linker-plugin -fvisibility=hidden -fdata-sections -ffunction-sections -fno-semantic-interposition -fopenmp -fexceptions -frtti -Wno-error -w" \
|
||||
# -DCMAKE_EXE_LINKER_FLAGS="-Wl,--gc-sections -Wl,-O2 -Wl,--as-needed" \
|
||||
# -DSDL_PIPEWIRE=OFF \
|
||||
# -DCITRON_USE_BUNDLED_VCPKG=OFF \
|
||||
# -DUSE_DISCORD_PRESENCE=OFF \
|
||||
# -DBUNDLE_SPEEX=ON \
|
||||
# -DCITRON_USE_BUNDLED_FFMPEG=OFF \
|
||||
# -DCITRON_USE_QT_MULTIMEDIA=OFF \
|
||||
# -DCITRON_USE_QT_WEB_ENGINE=OFF
|
||||
# ninja
|
||||
# cd ..
|
||||
# echo "Build completed, checking for executables..."
|
||||
# ls -la build/bin/ || echo "No build/bin directory found"
|
||||
# find build/ -name "*.so" -o -name "citron*" | head -20 || echo "No shared libraries or executables found"
|
||||
# echo "Checking library dependencies..."
|
||||
# ldd build/bin/citron || echo "citron binary not found or ldd failed"
|
||||
# chmod +x AppImage-build-local.sh
|
||||
# echo "Attempting AppImage build with FUSE workaround..."
|
||||
# export APPIMAGE_EXTRACT_AND_RUN=1
|
||||
# export ARCH=x86_64
|
||||
# export VERSION=$(git describe --tags --always)
|
||||
# echo "Testing shasum compatibility..."
|
||||
# which shasum || echo "shasum not found in PATH"
|
||||
# echo "Testing shasum -a 256 syntax..."
|
||||
# echo "test" | shasum -a 256 || echo "shasum -a 256 failed"
|
||||
# echo "test" | sha256sum || echo "sha256sum failed"
|
||||
# echo "Running AppImage build..."
|
||||
# ./AppImage-build-local.sh || echo "AppImage build failed, continuing..."
|
||||
# ls -la *.AppImage || echo "No AppImage files found"
|
||||
# echo "AppImage size information:"
|
||||
# du -h *.AppImage || echo "No AppImage to measure"
|
||||
# echo "Total artifact size:"
|
||||
# du -sh citron.AppImage build/bin/citron 2>/dev/null || echo "Cannot measure artifact sizes"
|
||||
# echo "Compressing AppImage for upload..."
|
||||
# gzip -9 -c citron.AppImage > citron.AppImage.gz
|
||||
# ls -la citron.AppImage.gz
|
||||
# du -h citron.AppImage.gz
|
||||
# echo "AppImage compressed with gzip successfully"
|
||||
# tar -czf citron-binary.tar.gz build/bin/
|
||||
# ls -la citron-binary.tar.gz
|
||||
# du -h citron-binary.tar.gz
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - citron.AppImage.gz
|
||||
# - citron-binary.tar.gz
|
||||
# expire_in: 1 week
|
||||
# when: always
|
||||
# only:
|
||||
# - main
|
||||
# - master
|
||||
# - develop
|
||||
# - ci-fixes
|
||||
# - Boss-Build-Flags-For-CI-CMAKE-ON-CachyOS
|
||||
# - merge_requests
|
||||
|
||||
# # Android Build (Ubuntu 24.04 optimized)
|
||||
# build-android:
|
||||
# stage: build
|
||||
# image: ubuntu:24.04
|
||||
# tags:
|
||||
# - citron-build
|
||||
# before_script:
|
||||
# - apt-get update -qq
|
||||
# - apt-get install -y -qq openjdk-17-jdk wget unzip curl git cmake build-essential pkg-config zip glslang-tools
|
||||
# - wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
|
||||
# - unzip -q commandlinetools-linux-11076708_latest.zip
|
||||
# - mkdir -p android-sdk/cmdline-tools
|
||||
# - mv cmdline-tools android-sdk/cmdline-tools/latest
|
||||
# - export ANDROID_SDK_ROOT=$PWD/android-sdk
|
||||
# - export PATH=$PATH:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin
|
||||
# - printf "y\ny\ny\ny\ny\ny\ny\n" | sdkmanager --licenses || true
|
||||
# - sdkmanager "platform-tools" "platforms;android-34" "build-tools;34.0.0"
|
||||
# - wget -q https://dl.google.com/android/repository/android-ndk-r26b-linux.zip
|
||||
# - unzip -q android-ndk-r26b-linux.zip
|
||||
# - export ANDROID_NDK_HOME=$PWD/android-ndk-r26b
|
||||
# script:
|
||||
# - git submodule deinit --all --force || true
|
||||
# - git submodule update --init --recursive --force
|
||||
# - cmake -B build-android -S . -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-30 -DENABLE_QT=OFF -DENABLE_SDL2=OFF -DENABLE_WEB_SERVICE=OFF -DCITRON_USE_BUNDLED_VCPKG=ON -DCITRON_USE_BUNDLED_FFMPEG=ON -DANDROID_ARM_NEON=ON -DCITRON_ENABLE_LTO=ON
|
||||
# - cmake --build build-android --config $BUILD_TYPE --parallel $CMAKE_BUILD_PARALLEL_LEVEL
|
||||
# - cd src/android
|
||||
# - ./gradlew assembleMainlineRelease
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - src/android/app/build/outputs/apk/mainline/release/*.apk
|
||||
# expire_in: 1 week
|
||||
# only:
|
||||
# - main
|
||||
# - master
|
||||
# - develop
|
||||
# - ci-fixes
|
||||
# - merge_requests
|
||||
# allow_failure: true
|
||||
|
||||
# # Unit Tests
|
||||
# test-unit:
|
||||
# stage: test
|
||||
# image: ubuntu:24.04
|
||||
# tags:
|
||||
# - citron-build
|
||||
# before_script:
|
||||
# # Set the environment to be non-interactive
|
||||
# - export DEBIAN_FRONTEND=noninteractive
|
||||
#
|
||||
# # Update package lists and install tool for managing repositories
|
||||
# - apt-get update -qq
|
||||
# - apt-get install -y -qq software-properties-common
|
||||
#
|
||||
# # Reliably add the 'universe' and 'multiverse' repositories
|
||||
# - add-apt-repository universe
|
||||
# - add-apt-repository multiverse
|
||||
#
|
||||
# # Update the package lists again to include the new repositories
|
||||
# - apt-get update -qq
|
||||
#
|
||||
# # Install all required system packages for the build
|
||||
# - apt-get install -y -qq
|
||||
# build-essential
|
||||
# cmake
|
||||
# ninja-build
|
||||
# git
|
||||
# pkg-config
|
||||
# catch2
|
||||
# libasound2-dev
|
||||
# libpulse-dev
|
||||
# libboost-all-dev
|
||||
# libavcodec-dev
|
||||
# libavfilter-dev
|
||||
# libavformat-dev
|
||||
# libavutil-dev
|
||||
# libswscale-dev
|
||||
# llvm-17-dev
|
||||
# gamemode-dev
|
||||
# libenet-dev
|
||||
# libfmt-dev
|
||||
# liblz4-dev
|
||||
# libopus-dev
|
||||
# libssl-dev
|
||||
# libusb-1.0-0-dev
|
||||
# libvulkan-dev
|
||||
# nlohmann-json3-dev
|
||||
# zlib1g-dev
|
||||
# libzstd-dev
|
||||
# libopenal-dev
|
||||
# libedit-dev
|
||||
# libcurl4-openssl-dev
|
||||
# libstb-dev
|
||||
# libcubeb-dev
|
||||
# libspeexdsp-dev
|
||||
# libva-dev
|
||||
# glslang-tools
|
||||
# libx11-dev
|
||||
#
|
||||
|
||||
# script:
|
||||
# - git submodule deinit --all --force || true
|
||||
# - git submodule update --init --recursive --force
|
||||
# - cmake -B build-test -S . -DCMAKE_BUILD_TYPE=Debug -DCITRON_TESTS=ON -DENABLE_QT=OFF -DENABLE_SDL2=OFF -DENABLE_WEB_SERVICE=OFF
|
||||
# - cmake --build build-test --config Debug --parallel $CMAKE_BUILD_PARALLEL_LEVEL
|
||||
# - cd build-test
|
||||
# - ctest --output-on-failure
|
||||
# artifacts:
|
||||
# reports:
|
||||
# junit: build-test/Testing/**/*.xml
|
||||
# expire_in: 1 week
|
||||
# only:
|
||||
# - main
|
||||
# - master
|
||||
# - develop
|
||||
# - ci-fixes
|
||||
# - merge_requests
|
||||
|
||||
# # Package Release
|
||||
# package-release:
|
||||
# stage: package
|
||||
# image: ubuntu:24.04
|
||||
# tags:
|
||||
# - citron-build
|
||||
# dependencies:
|
||||
# - build-linux
|
||||
# script:
|
||||
# - mkdir -p release
|
||||
# - echo "Creating release package..."
|
||||
# - tar -czf citron-release-$(date +%Y%m%d).tar.gz release/ || true
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - citron-release-*.tar.gz
|
||||
# expire_in: 1 month
|
||||
# only:
|
||||
# - main
|
||||
# - master
|
||||
# - develop
|
||||
# - ci-fixes
|
||||
# - tags
|
||||
@@ -1,83 +0,0 @@
|
||||
#! /bin/bash
|
||||
set -e
|
||||
|
||||
# Make sure script is called from inside our container
|
||||
test -e /tmp/torzu-src-ro || (echo "Script MUST NOT be called directly!" ; exit 1)
|
||||
|
||||
# Set up environment
|
||||
export LANG=C.UTF-8
|
||||
export LC_ALL=C.UTF-8
|
||||
unset LC_ADDRESS LC_NAME LC_MONETARY LC_PAPER LC_TELEPHONE LC_MEASUREMENT LC_TIME
|
||||
|
||||
# Raise max open files count
|
||||
ulimit -n 50000
|
||||
|
||||
# Install dependencies
|
||||
apt -y install cmake ninja-build build-essential autoconf pkg-config locales wget git file mold libtool lsb-release wget software-properties-common gnupg \
|
||||
qtbase5-dev qtmultimedia5-dev qtbase5-private-dev glslang-tools libssl-dev libavcodec-dev libavfilter-dev libavutil-dev libswscale-dev libpulse-dev libasound2-dev
|
||||
if [ ! "$BUILD_USE_CPM" = 1 ]; then
|
||||
apt -y install libfmt-dev libenet-dev liblz4-dev nlohmann-json3-dev zlib1g-dev libopus-dev libsimpleini-dev libstb-dev libzstd-dev libusb-1.0-0-dev libcubeb-dev libcpp-jwt-dev libvulkan-dev gamemode-dev libasound2-dev libglu1-mesa-dev libxext-dev mesa-common-dev libva-dev
|
||||
|
||||
if [ ! -f /usr/local/lib/cmake/Boost-1.88.0/BoostConfigVersion.cmake ]; then
|
||||
# Install Boost
|
||||
wget https://archives.boost.io/release/1.88.0/source/boost_1_88_0.tar.bz2
|
||||
echo "Extracting Boost sources..."
|
||||
tar xf boost_1_88_0.tar.bz2
|
||||
cd boost_1_88_0
|
||||
./bootstrap.sh
|
||||
./b2 install --with-{headers,context,system,fiber,atomic,filesystem} link=static
|
||||
cd ..
|
||||
rm -rf boost_1_88_0 boost_1_88_0.tar.bz2
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install Clang
|
||||
if ([ "$BUILD_USE_CLANG" = 1 ] && ! clang-19 --version); then
|
||||
cd /tmp
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
./llvm.sh 19
|
||||
rm llvm.sh
|
||||
fi
|
||||
|
||||
# Mount Torzu sources with temporary overlay
|
||||
cd /tmp
|
||||
mkdir torzu-src-upper torzu-src-work torzu-src
|
||||
mount -t overlay overlay -olowerdir=torzu-src-ro,upperdir=torzu-src-upper,workdir=torzu-src-work torzu-src
|
||||
|
||||
# Get extra configuration/compilation options
|
||||
EXTRA_COMPILE_FLAGS=""
|
||||
EXTRA_CMAKE_FLAGS=""
|
||||
if [ "$BUILD_USE_CLANG" = 1 ]; then
|
||||
EXTRA_CMAKE_FLAGS="-DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19"
|
||||
FATLTO_FLAG="-flto=full"
|
||||
else
|
||||
FATLTO_FLAG="-flto"
|
||||
fi
|
||||
if [ "$BUILD_USE_THIN_LTO" = 1 ]; then
|
||||
EXTRA_COMPILE_FLAGS="-flto=thin"
|
||||
fi
|
||||
if [ "$BUILD_USE_FAT_LTO" = 1 ]; then
|
||||
EXTRA_COMPILE_FLAGS="$FATLTO_FLAG"
|
||||
fi
|
||||
if [ "$BUILD_USE_CPM" = 1 ]; then
|
||||
EXTRA_CMAKE_FLAGS="$EXTRA_CMAKE_FLAGS -DYUZU_USE_CPM=ON"
|
||||
fi
|
||||
|
||||
# Build Torzu
|
||||
cd /tmp
|
||||
mkdir torzu-build
|
||||
cd torzu-build
|
||||
cmake /tmp/torzu-src -GNinja -DCMAKE_BUILD_TYPE=Release -DYUZU_TESTS=OFF -DENABLE_QT_TRANSLATION=OFF -DSPIRV_WERROR=OFF -DCMAKE_FIND_LIBRARY_SUFFIXES=".a;.so" -DSPIRV-Headers_SOURCE_DIR=/tmp/torzu-src/externals/SPIRV-Headers -DCMAKE_{C,CXX}_FLAGS="$EXTRA_COMPILE_FLAGS -fdata-sections -ffunction-sections" -DCMAKE_{EXE,SHARED}_LINKER_FLAGS="-Wl,--gc-sections" $EXTRA_CMAKE_FLAGS
|
||||
ninja || (
|
||||
echo "Compilation has failed. Dropping you into a shell so you can inspect the situation. Run 'ninja' to retry and exit shell once compilation has finished successfully."
|
||||
echo "Note that any changes made here will not be reflected to the host environment, but changes made from the host environment will be reflected here."
|
||||
bash
|
||||
)
|
||||
|
||||
# Generate AppImage
|
||||
cp -rv /tmp/torzu-src/AppImageBuilder /tmp/AppImageBuilder
|
||||
cd /tmp/AppImageBuilder
|
||||
./build.sh /tmp/torzu-build /tmp/torzu.AppImage || echo "This error is known. Using workaround..."
|
||||
cp /lib/$(uname -m)-linux-gnu/libICE.so.6 build/
|
||||
mv build /tmp/hosttmp/torzu-debian-appimage-rootfs
|
||||
@@ -1,73 +0,0 @@
|
||||
#! /bin/bash
|
||||
set -e
|
||||
|
||||
# Parse options
|
||||
for i in "$@"
|
||||
do
|
||||
case $i in
|
||||
-l|--clang)
|
||||
export BUILD_USE_CLANG=1
|
||||
echo "-> Using Clang for compilation."
|
||||
;;
|
||||
-o|--thin-lto)
|
||||
export BUILD_USE_THIN_LTO=1
|
||||
echo "-> Thin link time optimization enabled."
|
||||
;;
|
||||
-O|--fat-lto)
|
||||
export BUILD_USE_FAT_LTO=1
|
||||
echo "-> Fat link time optimization enabled."
|
||||
;;
|
||||
-p|--use-cpm)
|
||||
export BUILD_USE_CPM=1
|
||||
echo "-> Using CPM to download most dependencies."
|
||||
;;
|
||||
-k|--keep-rootfs)
|
||||
BUILD_KEEP_ROOTFS=1
|
||||
echo "-> Not deleting rootfs after successful build."
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [--clang/-l] [--thin-lto/-o] [--fat-lto/-O] [--use-cpm/-p] [--keep-rootfs/-k]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Make sure options are valid
|
||||
if [ "$BUILD_USE_THIN_LTO" = 1 ] && [ "$BUILD_USE_CLANG" != 1 ]; then
|
||||
echo "Thin LTO can't be used without Clang!"
|
||||
exit 2
|
||||
fi
|
||||
if [ "$BUILD_USE_THIN_LTO" = 1 ] && [ "$BUILD_USE_FAT_LTO" = 1 ]; then
|
||||
echo "Only either thin or fat LTO can be used!"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Get citron source dir
|
||||
citron_SOURCE_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
|
||||
echo "-> Source dir is $citron_SOURCE_DIR"
|
||||
rm -rf "$citron_SOURCE_DIR/AppImageBuilder/build"
|
||||
|
||||
# Generate debian rootfs
|
||||
cd /tmp
|
||||
echo "Cleaning up before build..."
|
||||
rm -rf citron-debian-appimage-rootfs
|
||||
[ -d rootfs-citron-appimage-build ] ||
|
||||
debootstrap stable rootfs-citron-appimage-build http://deb.debian.org/debian/
|
||||
bwrap --bind rootfs-citron-appimage-build / \
|
||||
--unshare-pid \
|
||||
--dev-bind /dev /dev --proc /proc --tmpfs /tmp --ro-bind /sys /sys --dev-bind /run /run \
|
||||
--tmpfs /var/tmp \
|
||||
--chmod 1777 /tmp \
|
||||
--ro-bind /etc/resolv.conf /etc/resolv.conf \
|
||||
--ro-bind "$citron_SOURCE_DIR" /tmp/citron-src-ro \
|
||||
--chdir / \
|
||||
--tmpfs /home \
|
||||
--setenv HOME /home \
|
||||
--bind /tmp /tmp/hosttmp \
|
||||
/tmp/citron-src-ro/AppImage-build-debian-inner.sh
|
||||
appimagetool citron-debian-appimage-rootfs citron.AppImage
|
||||
echo "AppImage generated at /tmp/citron.AppImage! Cleaning up..."
|
||||
rm -rf citron-debian-appimage-rootfs
|
||||
if [ ! "$BUILD_KEEP_ROOTFS" = 1 ]; then
|
||||
rm -rf rootfs-citron-appimage-build
|
||||
fi
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
FILE=build/bin/citron
|
||||
if test -f "$FILE"; then
|
||||
# remove any previously made AppImage in the base citron git folder
|
||||
rm ./citron.AppImage
|
||||
|
||||
# enter AppImage utility folder
|
||||
cd AppImageBuilder
|
||||
|
||||
# run the build script to create the AppImage
|
||||
# (usage) ./build.sh [source citron build folder] [destination .AppImage file]
|
||||
./build.sh ../build ./citron.AppImage
|
||||
|
||||
FILE=./citron.AppImage
|
||||
if test -f "$FILE"; then
|
||||
# move the AppImage to the main citron folder
|
||||
mv citron.AppImage ..
|
||||
# return to main citron folder
|
||||
cd ..
|
||||
# show contents of current folder
|
||||
echo
|
||||
ls
|
||||
# show AppImages specifically
|
||||
echo
|
||||
ls *.AppImage
|
||||
echo
|
||||
echo "'citron.AppImage' is now located in the current folder."
|
||||
echo
|
||||
else
|
||||
cd ..
|
||||
echo "AppImage was not built."
|
||||
fi
|
||||
else
|
||||
echo
|
||||
echo "$FILE does not exist."
|
||||
echo
|
||||
echo "No citron executable found in the /citron/build/bin folder!"
|
||||
echo
|
||||
echo "You must first build a native linux version of citron before running this script!"
|
||||
echo
|
||||
fi
|
||||
@@ -1,104 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Get script directory
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
BUILD_DIR_RAW="${1:-$SCRIPT_DIR/../build/generate}"
|
||||
BUILD_DIR="$(readlink -f "${BUILD_DIR_RAW}")"
|
||||
|
||||
# Save environment overrides
|
||||
ENV_QT_PATH="${CITRON_QT_PATH:-}"
|
||||
ENV_ICU_PATH="${CITRON_ICU_PATH:-}"
|
||||
ENV_XCB_PATH="${CITRON_XCB_PATH:-}"
|
||||
ENV_BINARY_DIR="${CITRON_BINARY_DIR:-}"
|
||||
|
||||
if [ ! -f "$BUILD_DIR/AppImageBuilder/config.sh" ]; then
|
||||
echo "Error: config.sh not found in $BUILD_DIR/AppImageBuilder/"
|
||||
echo "Please run CMake first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$BUILD_DIR/AppImageBuilder/config.sh"
|
||||
|
||||
# Allow environment variables to override config.sh
|
||||
export CITRON_QT_PATH="${ENV_QT_PATH:-$CITRON_QT_PATH}"
|
||||
export CITRON_ICU_PATH="${ENV_ICU_PATH:-$CITRON_ICU_PATH}"
|
||||
export CITRON_XCB_PATH="${ENV_XCB_PATH:-$CITRON_XCB_PATH}"
|
||||
export CITRON_BINARY_DIR="${ENV_BINARY_DIR:-$CITRON_BINARY_DIR}"
|
||||
|
||||
# Tools setup
|
||||
TOOLS_DIR="$BUILD_DIR/AppImageBuilder/tools"
|
||||
mkdir -p "$TOOLS_DIR"
|
||||
LINUXDEPLOY="$TOOLS_DIR/linuxdeploy-x86_64.AppImage"
|
||||
LINUXDEPLOY_QT="$TOOLS_DIR/linuxdeploy-plugin-qt-x86_64.AppImage"
|
||||
|
||||
download_tool() {
|
||||
local url=$1
|
||||
local file=$2
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "Downloading $file..."
|
||||
wget -q --show-progress "$url" -O "$file"
|
||||
chmod +x "$file"
|
||||
fi
|
||||
}
|
||||
|
||||
download_tool "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" "$LINUXDEPLOY"
|
||||
download_tool "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage" "$LINUXDEPLOY_QT"
|
||||
|
||||
# AppDir setup
|
||||
APPDIR="$BUILD_DIR/AppImageBuilder/AppDir"
|
||||
rm -rf "$APPDIR"
|
||||
mkdir -p "$APPDIR"
|
||||
|
||||
# Build the AppImage
|
||||
# We need to tell linuxdeploy where our custom libraries are
|
||||
export LD_LIBRARY_PATH="$CITRON_ICU_PATH:$CITRON_XCB_PATH/lib:$LD_LIBRARY_PATH"
|
||||
export EXTRA_QT_PLUGINS="wayland" # Add any extra plugins needed
|
||||
export NO_STRIP=1 # Avoid strip failures on modern binaries (SHT_RELR)
|
||||
|
||||
# Run linuxdeploy
|
||||
# --plugin qt handles Qt dependencies
|
||||
export QMAKE="$CITRON_QT_PATH/bin/qmake"
|
||||
export QT_ROOT="$CITRON_QT_PATH"
|
||||
export LD_LIBRARY_PATH="$CITRON_QT_PATH/lib:$CITRON_ICU_PATH:$CITRON_XCB_PATH/lib:${LD_LIBRARY_PATH:-}"
|
||||
|
||||
pushd "$BUILD_DIR" > /dev/null
|
||||
# Run linuxdeploy to populate AppDir
|
||||
"$LINUXDEPLOY" --appdir "$APPDIR" \
|
||||
--executable "$CITRON_BINARY_DIR/citron" \
|
||||
--desktop-file "$SCRIPT_DIR/assets/citron.desktop" \
|
||||
--icon-file "$SCRIPT_DIR/assets/citron.svg" \
|
||||
--library "$CITRON_ICU_PATH/libicuuc.so.73" \
|
||||
--library "$CITRON_ICU_PATH/libicui18n.so.73" \
|
||||
--library "$CITRON_ICU_PATH/libicudata.so.73" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb.so.1" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-cursor.so.0" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-xkb.so.1" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-render.so.0" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-render-util.so.0" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-shape.so.0" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-shm.so.0" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-sync.so.1" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-xfixes.so.0" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-randr.so.0" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-image.so.0" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-keysyms.so.1" \
|
||||
--library "$CITRON_XCB_PATH/lib/libxcb-icccm.so.4" \
|
||||
--library "$CITRON_XCB_PATH/lib/libXau.so.6" \
|
||||
--library "$CITRON_XCB_PATH/lib/libXdmcp.so.6" \
|
||||
--plugin qt
|
||||
|
||||
# Inject the wrapper script to support portable mode (user folder) and PGO profiles
|
||||
# We rename the real binary to citron.bin and put the script as 'citron'
|
||||
if [ -f "$APPDIR/usr/bin/citron" ]; then
|
||||
mv "$APPDIR/usr/bin/citron" "$APPDIR/usr/bin/citron.bin"
|
||||
cp "$SCRIPT_DIR/assets/citron.sh" "$APPDIR/usr/bin/citron"
|
||||
chmod +x "$APPDIR/usr/bin/citron"
|
||||
fi
|
||||
|
||||
# Build the final AppImage
|
||||
"$LINUXDEPLOY" --appdir "$APPDIR" --output appimage
|
||||
|
||||
popd > /dev/null
|
||||
|
||||
echo "AppImage build complete in $BUILD_DIR"
|
||||
@@ -1,170 +0,0 @@
|
||||
#! /bin/bash
|
||||
set -e
|
||||
|
||||
# Check arguments
|
||||
if [[ $# != 2 ]]; then
|
||||
>&2 echo "Bad usage!"
|
||||
echo "Usage: $0 <build dir> <output file>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get paths
|
||||
ARCH="$(uname -m)"
|
||||
SYSTEM_LIBS="/usr/lib"
|
||||
SYSTEM_LIBS64="/usr/lib64"
|
||||
citron_BIN="${1}/bin"
|
||||
citron_BIN_GUI="${citron_BIN}/citron"
|
||||
|
||||
# Make sure executable exists
|
||||
if [[ $(file -b --mime-type "$citron_BIN_GUI") != application/x-pie-executable ]]; then
|
||||
>&2 echo "Invalid citron executable!"
|
||||
fi
|
||||
|
||||
# Clean up build dir
|
||||
rm -rf build
|
||||
mkdir build
|
||||
|
||||
# NOTE: some of these aren't used now, but can be reordered in priority when citron is converted to QT6
|
||||
# QT5 - /usr/lib/${ARCH}-linux-gnu/qt5 (debian), /usr/lib64/qt5 (fedora), /usr/lib/qt (steam deck)
|
||||
# QT5 - /usr/lib/${ARCH}-linux-gnu/qt6 (debian), /usr/lib64/qt6 (fedora), /usr/lib/qt6 (steam deck)
|
||||
QTFOUND="true"
|
||||
QTDIR="$SYSTEM_LIBS"/${ARCH}-linux-gnu/qt5/plugins
|
||||
if [ ! -d "$QTDIR" ]; then
|
||||
# default qt5 folder not found, check for 64-bit qt5 folder
|
||||
QTDIR="$SYSTEM_LIBS64"/qt5/plugins
|
||||
if [ ! -d "$QTDIR" ]; then
|
||||
# 64-bit qt5 folder not found, check for Steam Deck qt (qt5) folder
|
||||
QTDIR="$SYSTEM_LIBS"/qt/plugins
|
||||
if [ ! -d "$QTDIR" ]; then
|
||||
# Steam Deck qt (qt5) folder not found, check for regular qt6 folder
|
||||
QTDIR="$SYSTEM_LIBS"/${ARCH}-linux-gnu/qt6/plugins
|
||||
if [ ! -d "$QTDIR" ]; then
|
||||
# regular qt6 folder not found, check for 64-bit qt6 folder
|
||||
QTDIR="$SYSTEM_LIBS64"/qt6/plugins
|
||||
if [ ! -d "$QTDIR" ]; then
|
||||
# 64-bit qt6 folder not found, check for Steam Deck qt6 folder
|
||||
QTDIR="$SYSTEM_LIBS"/qt6/plugins
|
||||
if [ ! -d "$QTDIR" ]; then
|
||||
QTFOUND="false"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ $QTFOUND == "true" ]; then
|
||||
echo "QT plugins from $QTDIR will be used."
|
||||
|
||||
# Copy system dependencies used to build and required by the citron binary
|
||||
# includes:
|
||||
# - '/lib64/ld-linux-x86-64.so.2' or `/lib/ld-linux-aarch64.so.1` file per architecture
|
||||
# - required files from `/usr/lib/x86_64-linux-gnu` or `/usr/lib/aarch64-linux-gnu`
|
||||
# - different for SteamDeck, but still does it automatically
|
||||
function copy_libs {
|
||||
for lib in $(ldd "$1"); do
|
||||
(cp -vn "$lib" ./build/ 2> /dev/null) || true
|
||||
done
|
||||
}
|
||||
echo "Copying main dependencies..."
|
||||
copy_libs "$citron_BIN_GUI"
|
||||
|
||||
# Copy QT dependency folders, path determined above
|
||||
echo "Copying Qt dependencies..."
|
||||
mkdir ./build/qt5
|
||||
cp -rv "$QTDIR"/{imageformats,platforms,platformthemes,xcbglintegrations} ./build/qt5/
|
||||
|
||||
# Discover indirect dependencies (mostly from runtime-loaded Qt plugins)
|
||||
echo "Copying extra dependencies..."
|
||||
while true; do
|
||||
LIBS="$(find ./build -name \*.so\*)"
|
||||
LIB_COUNT=$(echo "$LIBS" | wc -l)
|
||||
echo "$LIB_COUNT dependency libraries discovered so far..."
|
||||
if [ $LIB_COUNT == "$PREV_LIB_COUNT" ]; then
|
||||
break
|
||||
fi
|
||||
PREV_LIB_COUNT=$LIB_COUNT
|
||||
|
||||
for plib in $LIBS; do
|
||||
if [ -f "$plib" ]; then
|
||||
copy_libs "$plib"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Copy executable
|
||||
cp -v "$citron_BIN_GUI" ./build/
|
||||
|
||||
# Copy assets for the appropriate arch
|
||||
cp -v ./assets_"${ARCH}"/* ./build/
|
||||
# Copy common assets
|
||||
cp -v ./assets/* ./build/
|
||||
|
||||
# Strip all libraries and executables
|
||||
for file in $(find ./build -type f); do
|
||||
(strip -v "$file" 2> /dev/null) || true
|
||||
done
|
||||
|
||||
PASSED_CHECKSUM="false"
|
||||
FILE=appimagetool.AppImage
|
||||
# total number of times to try downloading if a checksum doesn't match
|
||||
DL_TRIES=3
|
||||
while [ $PASSED_CHECKSUM == "false" ] && [ "$DL_TRIES" -gt 0 ]; do
|
||||
case $ARCH in
|
||||
x86_64)
|
||||
# Static copy from the 'ext-linux-bin' repo.
|
||||
# Checksum will need to be changed when/if this file in the repo is updated.
|
||||
if ! test -f "$FILE"; then
|
||||
echo "Downloading appimagetool for architecture '$ARCH'"
|
||||
wget -O appimagetool.AppImage https://github.com/litucks/ext-linux-bin/raw/refs/heads/main/appimage/appimagetool-x86_64.AppImage
|
||||
fi
|
||||
if [ $(shasum -a 256 appimagetool.AppImage | cut -d' ' -f1) = "110751478abece165a18460acbd7fd1398701f74a9405ad8ac053427d937bd5d" ] ; then
|
||||
PASSED_CHECKSUM="true"
|
||||
fi
|
||||
# DISABLED TO USE THE ABOVE
|
||||
# The current continuous release channel option, until a static copy is put in 'ext-linux-bin'.
|
||||
# The checksum will pass until the continuous release is updated, then a new one needs to be
|
||||
# generated to update this script.
|
||||
#if ! test -f "$FILE"; then
|
||||
# echo "Downloading appimagetool for architecture '$ARCH'"
|
||||
# wget -O appimagetool.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
#fi
|
||||
#if [ $(shasum -a 256 appimagetool.AppImage | cut -d' ' -f1) = "46fdd785094c7f6e545b61afcfb0f3d98d8eab243f644b4b17698c01d06083d1" ] ; then
|
||||
# PASSED_CHECKSUM="true"
|
||||
#fi
|
||||
;;
|
||||
aarch64)
|
||||
# Currently set to the continuous release channel until a static copy is put in 'ext-linux-bin'.
|
||||
# The checksum will pass until the continuous release is updated, then a new one needs to be
|
||||
# generated to update this script.
|
||||
if ! test -f "$FILE"; then
|
||||
echo "Downloading appimagetool for architecture '$ARCH'"
|
||||
wget -O appimagetool.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-aarch64.AppImage
|
||||
fi
|
||||
if [ $(shasum -a 256 appimagetool.AppImage | cut -d' ' -f1) = "04f45ea45b5aa07bb2b071aed9dbf7a5185d3953b11b47358c1311f11ea94a96" ] ; then
|
||||
PASSED_CHECKSUM="true"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
PASSED_CHECKSUM="invalid_arch"
|
||||
;;
|
||||
esac
|
||||
# delete the appimagetool downloaded if the checksum doesn't match.
|
||||
if [ ! $PASSED_CHECKSUM == "true" ]; then
|
||||
rm -f appimagetool.AppImage
|
||||
fi
|
||||
((DL_TRIES-=1))
|
||||
done
|
||||
if [ $PASSED_CHECKSUM == "true" ]; then
|
||||
echo "Checksum passed. Proceeding to build image."
|
||||
# Build AppImage
|
||||
chmod a+x appimagetool.AppImage
|
||||
./appimagetool.AppImage ./build "$2"
|
||||
elif [ $PASSED_CHECKSUM == "invalid_arch" ]; then
|
||||
echo "No download found for architecture '$ARCH'. Building halted."
|
||||
else
|
||||
echo "Checksum for appimagetool does not match. Building halted."
|
||||
echo "If the file to be downloaded has been changed, a new checksum will need to be generated for this script."
|
||||
fi
|
||||
else
|
||||
echo "QT not found, aborting AppImage build."
|
||||
fi
|
||||
@@ -373,7 +373,10 @@ mv -v ./*.AppImage.* "${OUTPATH}/" 2>/dev/null || true
|
||||
# squashed into the AppImage above (every DEPLOY_*/STRACE_MODE suppression and
|
||||
# the post-dep-scan find/-delete block above already ran before
|
||||
# --make-appimage), so this is a complete, AppRun-runnable, install-free
|
||||
# alternative to the AppImage.
|
||||
# alternative to the AppImage — not a partial copy. (AppDir/usr/ is not used
|
||||
# by this layout — translations land under AppDir/lib/qt6/, see comment above —
|
||||
# so packing only "usr", as the pre-quick-sharun pipeline did, would produce a
|
||||
# near-empty archive here.)
|
||||
#
|
||||
# AppDir is then removed. It has no further purpose once packed, and leaving
|
||||
# it sitting in OUTPATH means anything that uploads/copies OUTPATH wholesale
|
||||
@@ -384,4 +387,19 @@ if [ -d ./AppDir ]; then
|
||||
rm -rf ./AppDir
|
||||
fi
|
||||
|
||||
# Clean up build-tool byproducts that land in this same directory (OUTPATH),
|
||||
# not just AppDir. build-citron-linux.sh sets OUTPATH to the same working
|
||||
# directory this script cd's into and downloads tooling into, so anything
|
||||
# these tools write to cwd ends up sitting next to the final artifacts unless
|
||||
# removed explicitly:
|
||||
#
|
||||
# quick-sharun — the tool itself, copied to ./quick-sharun near the top of
|
||||
# this script (see the vendoring comment above). It has no
|
||||
# purpose after packaging finishes.
|
||||
# appinfo — a debug/metadata text file written to cwd by the
|
||||
# underlying appimagetool binary during --make-appimage.
|
||||
# Not generated by quick-sharun.sh itself, not meant for
|
||||
# redistribution — internal build debug output only.
|
||||
rm -f ./quick-sharun ./appinfo
|
||||
|
||||
echo "Artifacts in: ${OUTPATH}"
|
||||
|
||||
Regular → Executable
+45
@@ -447,6 +447,31 @@ _setup_apt() {
|
||||
sudo apt-get install -y libvdpau-dev \
|
||||
|| warn "libvdpau-dev unavailable — FFmpeg will build with --disable-vdpau"
|
||||
|
||||
# ── Linux audio output (ALSA + PulseAudio) — REQUIRED, not optional ─────
|
||||
# SDL2's CheckALSA()/CheckPulseAudio() configure-time checks look for
|
||||
# alsa/asoundlib.h and pulse/pulseaudio.h. If either header is missing,
|
||||
# SDL2 silently disables that backend (SDL_ALSA / SDL_PULSEAUDIO → OFF)
|
||||
# rather than hard-failing the build — the same "quiet fallback" pattern
|
||||
# as the VAAPI/VDPAU checks above, except here the fallback is SDL2's
|
||||
# SDL_DUMMYAUDIO/SDL_DISKAUDIO drivers, neither of which produces any
|
||||
# actual sound. A machine missing both dev packages therefore still
|
||||
# builds and packages successfully, but ships an AppImage with no
|
||||
# functioning Linux audio output at all — a failure mode with no build
|
||||
# warning to catch it, which is why this group is REQUIRED (unlike the
|
||||
# --ignore-missing X11/XCB extras below).
|
||||
#
|
||||
# This also solves packaging determinism: package-citron-linux.sh finds
|
||||
# libasound.so.2 and libpulse.so.0 to bundle into the AppImage via
|
||||
# `ldconfig -p` against whatever happens to be installed on the machine
|
||||
# running the packaging step (see comments there). Installing the -dev
|
||||
# packages here pulls in their runtime libs (libasound2, libpulse0) as
|
||||
# apt dependencies, so that probe now succeeds identically on every
|
||||
# machine that runs this script — CI included — instead of depending on
|
||||
# whether that machine happens to already have a desktop audio stack.
|
||||
info "Installing ALSA + PulseAudio dev packages (required for audio output)..."
|
||||
sudo apt-get install -y libasound2-dev libpulse-dev \
|
||||
|| error "ALSA/PulseAudio dev packages failed to install — Linux builds would have no audio output"
|
||||
|
||||
# ── X11 / XCB optional extras (SDL2 Xi/XSS/XCB, Qt XCB platform plugin) ─
|
||||
# These extend the X11 install above with input, screensaver, and XCB
|
||||
# extension headers. All are optional — their cmake checks produce soft
|
||||
@@ -496,6 +521,10 @@ _setup_pacman() {
|
||||
# Optional: bundled into the AppImage by package-citron-linux.sh if present.
|
||||
sudo pacman -S --needed --noconfirm gamemode 2>/dev/null || true
|
||||
|
||||
# ── Linux audio output (ALSA + PulseAudio) —
|
||||
sudo pacman -S --needed --noconfirm alsa-lib libpulse \
|
||||
|| error "ALSA/PulseAudio packages failed to install — Linux builds would have no audio output"
|
||||
|
||||
# Arch ships unversioned tools — symlink to versioned names
|
||||
for tool in clang clang++ lld llvm-profdata llvm-bolt merge-fdata; do
|
||||
local versioned="/usr/local/bin/${tool}-${CLANG_VERSION}"
|
||||
@@ -538,6 +567,10 @@ _setup_dnf() {
|
||||
|
||||
# Optional: bundled into the AppImage by package-citron-linux.sh if present.
|
||||
sudo dnf install -y gamemode 2>/dev/null || true
|
||||
|
||||
# ── Linux audio output (ALSA + PulseAudio) —
|
||||
sudo dnf install -y alsa-lib-devel pulseaudio-libs-devel \
|
||||
|| error "ALSA/PulseAudio dev packages failed to install — Linux builds would have no audio output"
|
||||
}
|
||||
|
||||
_setup_yum() {
|
||||
@@ -556,6 +589,10 @@ _setup_yum() {
|
||||
# Optional: bundled into the AppImage by package-citron-linux.sh if present.
|
||||
# May require EPEL or an RPM Fusion-style repo on RHEL-based distros.
|
||||
sudo yum install -y gamemode 2>/dev/null || true
|
||||
|
||||
# ── Linux audio output (ALSA + PulseAudio) —
|
||||
sudo yum install -y alsa-lib-devel pulseaudio-libs-devel \
|
||||
|| error "ALSA/PulseAudio dev packages failed to install — Linux builds would have no audio output"
|
||||
}
|
||||
|
||||
_setup_zypper() {
|
||||
@@ -578,6 +615,10 @@ _setup_zypper() {
|
||||
|
||||
# Optional: bundled into the AppImage by package-citron-linux.sh if present.
|
||||
sudo zypper install -y --no-recommends gamemode 2>/dev/null || true
|
||||
|
||||
# ── Linux audio output (ALSA + PulseAudio) —
|
||||
sudo zypper install -y --no-recommends alsa-devel libpulse-devel \
|
||||
|| error "ALSA/PulseAudio dev packages failed to install — Linux builds would have no audio output"
|
||||
}
|
||||
|
||||
_setup_emerge() {
|
||||
@@ -594,6 +635,10 @@ _setup_emerge() {
|
||||
|
||||
# Optional: bundled into the AppImage by package-citron-linux.sh if present.
|
||||
sudo emerge --ask=n games-util/gamemode 2>/dev/null || true
|
||||
|
||||
# ── Linux audio output (ALSA + PulseAudio) —
|
||||
sudo emerge --ask=n media-libs/alsa-lib media-libs/libpulse \
|
||||
|| error "ALSA/PulseAudio packages failed to install — Linux builds would have no audio output"
|
||||
}
|
||||
|
||||
_install_llvm_clang() {
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
@echo off
|
||||
REM SPDX-FileCopyrightText: 2026 citron Emulator Project
|
||||
REM SPDX-License-Identifier: GPL-3.0-or-later
|
||||
REM
|
||||
REM One-click MinGW build launcher for Citron Neo.
|
||||
REM Finds your MSYS2 installation and runs build-for-mingw.sh in UCRT64 mode.
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM ---------- locate MSYS2 ----------
|
||||
set "MSYS2_PATH="
|
||||
|
||||
REM Check common install locations
|
||||
for %%P in (
|
||||
"C:\msys64"
|
||||
"C:\msys2"
|
||||
"%USERPROFILE%\msys64"
|
||||
"%USERPROFILE%\msys2"
|
||||
"D:\msys64"
|
||||
"D:\msys2"
|
||||
) do (
|
||||
if exist "%%~P\usr\bin\bash.exe" (
|
||||
set "MSYS2_PATH=%%~P"
|
||||
goto :found_msys2
|
||||
)
|
||||
)
|
||||
|
||||
REM Try the PATH
|
||||
where bash.exe >nul 2>&1
|
||||
if %ERRORLEVEL% equ 0 (
|
||||
for /f "delims=" %%I in ('where bash.exe') do (
|
||||
set "BASH_LOC=%%~dpI"
|
||||
if exist "!BASH_LOC!..\..\..\usr\bin\bash.exe" (
|
||||
for %%J in ("!BASH_LOC!..\..\..") do set "MSYS2_PATH=%%~fJ"
|
||||
goto :found_msys2
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
echo.
|
||||
echo ERROR: Could not find an MSYS2 installation.
|
||||
echo.
|
||||
echo Please install MSYS2 from https://www.msys2.org/ and try again,
|
||||
echo or set MSYS2_PATH before running this script:
|
||||
echo.
|
||||
echo set MSYS2_PATH=C:\msys64
|
||||
echo build-for-mingw.bat
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
:found_msys2
|
||||
echo Found MSYS2 at: %MSYS2_PATH%
|
||||
|
||||
REM ---------- resolve script path ----------
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
REM Remove trailing backslash
|
||||
if "%SCRIPT_DIR:~-1%"=="\" set "SCRIPT_DIR=%SCRIPT_DIR:~0,-1%"
|
||||
|
||||
REM Convert Windows path to MSYS2 path (C:\foo\bar -> /c/foo/bar)
|
||||
set "MSYS_SOURCE=%SCRIPT_DIR:\=/%"
|
||||
set "MSYS_SOURCE=/%MSYS_SOURCE:~0,1%%MSYS_SOURCE:~2%"
|
||||
REM Lowercase the drive letter
|
||||
for %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
|
||||
set "MSYS_SOURCE=!MSYS_SOURCE:/%%a/=/%%a/!"
|
||||
)
|
||||
|
||||
REM ---------- run the build ----------
|
||||
echo.
|
||||
echo Launching MSYS2 UCRT64 build ...
|
||||
echo.
|
||||
|
||||
"%MSYS2_PATH%\usr\bin\env.exe" MSYSTEM=UCRT64 ^
|
||||
"%MSYS2_PATH%\usr\bin\bash.exe" -lc ^
|
||||
"cd '%MSYS_SOURCE%' && bash build-for-mingw.sh %*"
|
||||
|
||||
if %ERRORLEVEL% neq 0 (
|
||||
echo.
|
||||
echo Build failed with error code %ERRORLEVEL%.
|
||||
pause
|
||||
exit /b %ERRORLEVEL%
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Build succeeded! Executables are in build-mingw\bin\
|
||||
pause
|
||||
@@ -1,101 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-FileCopyrightText: 2026 citron Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Automated MinGW (MSYS2 UCRT64) build script for Citron Neo.
|
||||
# Run from the MSYS2 UCRT64 shell, or use build-for-mingw.bat to launch it.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ---------- configuration ----------
|
||||
BUILD_DIR="${1:-build-mingw}"
|
||||
BUILD_TYPE="${2:-Release}"
|
||||
JOBS="${3:-$(nproc)}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SOURCE_DIR="$SCRIPT_DIR"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
|
||||
ok() { echo -e "${GREEN}[ OK ]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
fail() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; }
|
||||
|
||||
# ---------- environment check ----------
|
||||
if [[ -z "${MSYSTEM:-}" ]]; then
|
||||
fail "Not running inside an MSYS2 shell. Use the UCRT64 terminal or build-for-mingw.bat."
|
||||
fi
|
||||
if [[ "$MSYSTEM" != "UCRT64" ]]; then
|
||||
warn "MSYSTEM is '$MSYSTEM', expected 'UCRT64'. Builds may use the wrong toolchain."
|
||||
fi
|
||||
|
||||
command -v pacman >/dev/null 2>&1 || fail "pacman not found — is this really MSYS2?"
|
||||
|
||||
# ---------- dependency installation ----------
|
||||
info "Installing / updating build tools and dependencies via pacman …"
|
||||
|
||||
PACKAGES=(
|
||||
# build tools
|
||||
mingw-w64-ucrt-x86_64-cmake
|
||||
mingw-w64-ucrt-x86_64-ninja
|
||||
mingw-w64-ucrt-x86_64-toolchain
|
||||
|
||||
# required libraries
|
||||
mingw-w64-ucrt-x86_64-boost
|
||||
mingw-w64-ucrt-x86_64-fmt
|
||||
mingw-w64-ucrt-x86_64-nlohmann-json
|
||||
mingw-w64-ucrt-x86_64-opus
|
||||
mingw-w64-ucrt-x86_64-SDL2
|
||||
mingw-w64-ucrt-x86_64-qt6-base
|
||||
mingw-w64-ucrt-x86_64-qt6-multimedia
|
||||
mingw-w64-ucrt-x86_64-qt6-svg
|
||||
mingw-w64-ucrt-x86_64-qt6-tools
|
||||
mingw-w64-ucrt-x86_64-ffmpeg
|
||||
mingw-w64-ucrt-x86_64-openal
|
||||
mingw-w64-ucrt-x86_64-vulkan-headers
|
||||
mingw-w64-ucrt-x86_64-vulkan-utility-libraries
|
||||
mingw-w64-ucrt-x86_64-vulkan-memory-allocator
|
||||
mingw-w64-ucrt-x86_64-libusb
|
||||
mingw-w64-ucrt-x86_64-enet
|
||||
mingw-w64-ucrt-x86_64-stb
|
||||
)
|
||||
|
||||
pacman -S --needed --noconfirm "${PACKAGES[@]}" || fail "pacman install failed"
|
||||
ok "All dependencies installed."
|
||||
|
||||
# ---------- configure ----------
|
||||
info "Configuring CMake (${BUILD_TYPE}) in ${BUILD_DIR} …"
|
||||
mkdir -p "${SOURCE_DIR}/${BUILD_DIR}"
|
||||
cd "${SOURCE_DIR}/${BUILD_DIR}"
|
||||
|
||||
cmake "$SOURCE_DIR" -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DCITRON_USE_BUNDLED_VCPKG=OFF \
|
||||
-DCITRON_USE_BUNDLED_SDL2=OFF \
|
||||
-DCITRON_USE_BUNDLED_QT=OFF \
|
||||
-DCITRON_USE_BUNDLED_FFMPEG=OFF \
|
||||
-DCITRON_USE_EXTERNAL_VULKAN_HEADERS=OFF \
|
||||
-DCITRON_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES=OFF \
|
||||
-DENABLE_QT_TRANSLATION=OFF \
|
||||
-DUSE_DISCORD_PRESENCE=OFF \
|
||||
-DCITRON_TESTS=OFF \
|
||||
-DENABLE_WEB_SERVICE=OFF \
|
||||
-DCITRON_USE_FASTER_LD=OFF \
|
||||
|| fail "CMake configuration failed"
|
||||
|
||||
ok "CMake configuration succeeded."
|
||||
|
||||
# ---------- build ----------
|
||||
info "Building with ${JOBS} parallel jobs …"
|
||||
ninja -j"$JOBS" || fail "Build failed"
|
||||
|
||||
ok "Build complete!"
|
||||
echo ""
|
||||
info "Executables are in: ${SOURCE_DIR}/${BUILD_DIR}/bin/"
|
||||
ls -lh "${SOURCE_DIR}/${BUILD_DIR}/bin/"*.exe 2>/dev/null || true
|
||||
echo ""
|
||||
ok "Done. You can run citron from: ${BUILD_DIR}/bin/citron.exe"
|
||||
-174
@@ -1,174 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# Fix PGO DLL Script for Citron (Windows)
|
||||
# This script helps locate and copy the required pgort140.dll for MSVC PGO builds
|
||||
|
||||
param(
|
||||
[Parameter()]
|
||||
[string]$OutputDir = "build\bin\Release",
|
||||
|
||||
[Parameter()]
|
||||
[switch]$Help
|
||||
)
|
||||
|
||||
function Show-Usage {
|
||||
Write-Host @"
|
||||
Usage: .\fix-pgo-dll.ps1 [OPTIONS]
|
||||
|
||||
This script helps fix the "pgort140.DLL was not found" error by locating
|
||||
and copying the required PGO runtime DLL to your build output directory.
|
||||
|
||||
Options:
|
||||
-OutputDir PATH Target directory to copy DLL (default: build\bin\Release)
|
||||
-Help Show this help message
|
||||
|
||||
Example:
|
||||
.\fix-pgo-dll.ps1
|
||||
.\fix-pgo-dll.ps1 -OutputDir "C:\MyBuild\bin"
|
||||
"@
|
||||
}
|
||||
|
||||
function Write-Header {
|
||||
param([string]$Message)
|
||||
Write-Host "`n=================================================================" -ForegroundColor Cyan
|
||||
Write-Host $Message -ForegroundColor Cyan
|
||||
Write-Host "=================================================================`n" -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function Write-Info {
|
||||
param([string]$Message)
|
||||
Write-Host "[INFO] $Message" -ForegroundColor Green
|
||||
}
|
||||
|
||||
function Write-Warning {
|
||||
param([string]$Message)
|
||||
Write-Host "[WARNING] $Message" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
function Write-Error-Custom {
|
||||
param([string]$Message)
|
||||
Write-Host "[ERROR] $Message" -ForegroundColor Red
|
||||
}
|
||||
|
||||
if ($Help) {
|
||||
Show-Usage
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Header "PGO DLL Fixer for Citron"
|
||||
|
||||
# Find Visual Studio installation
|
||||
$VSInstallPath = $null
|
||||
$VSWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
|
||||
if (Test-Path $VSWhere) {
|
||||
Write-Info "Searching for Visual Studio installations..."
|
||||
$VSInstallPath = & $VSWhere -latest -property installationPath
|
||||
if ($VSInstallPath) {
|
||||
Write-Info "Found Visual Studio at: $VSInstallPath"
|
||||
}
|
||||
} else {
|
||||
Write-Warning "vswhere.exe not found. Trying common installation paths..."
|
||||
}
|
||||
|
||||
# Common Visual Studio installation paths
|
||||
$CommonPaths = @(
|
||||
"${env:ProgramFiles}\Microsoft Visual Studio\2022\Community",
|
||||
"${env:ProgramFiles}\Microsoft Visual Studio\2022\Professional",
|
||||
"${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise",
|
||||
"${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community",
|
||||
"${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Professional",
|
||||
"${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Enterprise"
|
||||
)
|
||||
|
||||
if (-not $VSInstallPath) {
|
||||
foreach ($path in $CommonPaths) {
|
||||
if (Test-Path $path) {
|
||||
$VSInstallPath = $path
|
||||
Write-Info "Found Visual Studio at: $VSInstallPath"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $VSInstallPath) {
|
||||
Write-Error-Custom "Visual Studio installation not found!"
|
||||
Write-Host "Please ensure Visual Studio 2019 or 2022 is installed with C++ support."
|
||||
Write-Host "You can download it from: https://visualstudio.microsoft.com/downloads/"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Search for pgort140.dll
|
||||
Write-Info "Searching for pgort140.dll..."
|
||||
|
||||
$DllPaths = @(
|
||||
"$VSInstallPath\VC\Redist\MSVC\*\x64\Microsoft.VC*.CRT\pgort140.dll",
|
||||
"$VSInstallPath\VC\Redist\MSVC\*\x86\Microsoft.VC*.CRT\pgort140.dll",
|
||||
"$VSInstallPath\VC\Tools\MSVC\*\bin\Hostx64\x64\pgort140.dll",
|
||||
"$VSInstallPath\VC\Tools\MSVC\*\bin\Hostx64\x86\pgort140.dll",
|
||||
"$VSInstallPath\VC\Tools\MSVC\*\bin\Hostx86\x64\pgort140.dll",
|
||||
"$VSInstallPath\VC\Tools\MSVC\*\bin\Hostx86\x86\pgort140.dll"
|
||||
)
|
||||
|
||||
$FoundDll = $null
|
||||
foreach ($pattern in $DllPaths) {
|
||||
$matches = Get-ChildItem -Path $pattern -ErrorAction SilentlyContinue
|
||||
if ($matches) {
|
||||
$FoundDll = $matches[0].FullName
|
||||
Write-Info "Found pgort140.dll at: $FoundDll"
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $FoundDll) {
|
||||
Write-Error-Custom "pgort140.dll not found in Visual Studio installation!"
|
||||
Write-Host "This usually means:"
|
||||
Write-Host "1. Visual Studio was installed without PGO support"
|
||||
Write-Host "2. You need to install the 'MSVC v143 - VS 2022 C++ x64/x86 build tools' component"
|
||||
Write-Host "3. Try repairing your Visual Studio installation"
|
||||
Write-Host ""
|
||||
Write-Host "To fix this:"
|
||||
Write-Host "1. Open Visual Studio Installer"
|
||||
Write-Host "2. Click 'Modify' on your Visual Studio installation"
|
||||
Write-Host "3. Go to 'Individual components' tab"
|
||||
Write-Host "4. Search for 'PGO' and ensure it's checked"
|
||||
Write-Host "5. Click 'Modify' to install the component"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Create output directory if it doesn't exist
|
||||
if (-not (Test-Path $OutputDir)) {
|
||||
Write-Info "Creating output directory: $OutputDir"
|
||||
New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null
|
||||
}
|
||||
|
||||
# Copy the DLL
|
||||
try {
|
||||
Write-Info "Copying pgort140.dll to: $OutputDir"
|
||||
Copy-Item -Path $FoundDll -Destination $OutputDir -Force
|
||||
Write-Info "Successfully copied pgort140.dll!"
|
||||
|
||||
# Verify the copy
|
||||
$CopiedDll = Join-Path $OutputDir "pgort140.dll"
|
||||
if (Test-Path $CopiedDll) {
|
||||
Write-Info "Verification: pgort140.dll is now available in $OutputDir"
|
||||
Write-Host ""
|
||||
Write-Host "You can now run your PGO instrumented Citron build!"
|
||||
} else {
|
||||
Write-Error-Custom "Failed to copy pgort140.dll"
|
||||
exit 1
|
||||
}
|
||||
} catch {
|
||||
Write-Error-Custom "Error copying pgort140.dll: $($_.Exception.Message)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Header "PGO DLL Fix Complete!"
|
||||
Write-Info "The pgort140.dll has been copied to your build output directory."
|
||||
Write-Info "Your PGO instrumented Citron build should now run without the DLL error."
|
||||
Write-Host ""
|
||||
Write-Info "Next steps:"
|
||||
Write-Host "1. Run your PGO instrumented build"
|
||||
Write-Host "2. Play games to collect profile data"
|
||||
Write-Host "3. Rebuild with PGO USE stage for optimization"
|
||||
-344
@@ -1,344 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# PGO Build Script for Citron (Windows/PowerShell)
|
||||
# This script automates the Profile-Guided Optimization build process
|
||||
|
||||
param(
|
||||
[Parameter(Position=0, Mandatory=$true)]
|
||||
[ValidateSet('generate', 'use', 'clean', 'merge', 'summary')]
|
||||
[string]$Stage,
|
||||
|
||||
[Parameter()]
|
||||
[int]$Jobs = 0,
|
||||
|
||||
[Parameter()]
|
||||
[switch]$EnableLTO,
|
||||
|
||||
[Parameter()]
|
||||
[switch]$Help
|
||||
)
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$BuildDir = Join-Path $ScriptDir "build"
|
||||
$PgoProfilesDir = Join-Path $BuildDir "pgo-profiles"
|
||||
$BackupProfilesDir = Join-Path $ScriptDir "pgo-profiles-backup"
|
||||
|
||||
function Show-Usage {
|
||||
Write-Host @"
|
||||
Usage: .\pgo-build.ps1 [STAGE] [OPTIONS]
|
||||
|
||||
STAGE can be:
|
||||
generate - Build with PGO instrumentation (Stage 1)
|
||||
use - Build using PGO profile data (Stage 2)
|
||||
clean - Clean build directory but preserve profiles
|
||||
merge - Merge PGC files into PGD without rebuilding
|
||||
summary - Show profile coverage statistics
|
||||
|
||||
Example workflow:
|
||||
.\pgo-build.ps1 generate # Build instrumented version
|
||||
# Run citron.exe, play 2-3 games for 5-10 min each, exit cleanly
|
||||
.\pgo-build.ps1 merge # Merge collected profiles
|
||||
.\pgo-build.ps1 summary # Check coverage
|
||||
.\pgo-build.ps1 use # Build optimized version
|
||||
|
||||
Options:
|
||||
-Jobs N Number of parallel jobs (default: auto-detect)
|
||||
-EnableLTO Enable Link-Time Optimization
|
||||
-Help Show this help message
|
||||
"@
|
||||
}
|
||||
|
||||
function Write-Header {
|
||||
param([string]$Message)
|
||||
Write-Host "`n=================================================================" -ForegroundColor Cyan
|
||||
Write-Host $Message -ForegroundColor Cyan
|
||||
Write-Host "=================================================================`n" -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function Write-Info {
|
||||
param([string]$Message)
|
||||
Write-Host "[INFO] $Message" -ForegroundColor Green
|
||||
}
|
||||
|
||||
function Write-Warning {
|
||||
param([string]$Message)
|
||||
Write-Host "[WARNING] $Message" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
function Write-Error-Custom {
|
||||
param([string]$Message)
|
||||
Write-Host "[ERROR] $Message" -ForegroundColor Red
|
||||
}
|
||||
|
||||
function Find-Pgomgr {
|
||||
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
if (Test-Path $vswhere) {
|
||||
$vsPath = & $vswhere -latest -property installationPath
|
||||
$pgomgr = Get-ChildItem -Path "$vsPath\VC\Tools\MSVC" -Recurse -Filter "pgomgr.exe" -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.FullName -match "Hostx64\\x64" } |
|
||||
Select-Object -First 1
|
||||
if ($pgomgr) { return $pgomgr.FullName }
|
||||
}
|
||||
$found = Get-Command pgomgr.exe -ErrorAction SilentlyContinue
|
||||
if ($found) { return $found.Source }
|
||||
return $null
|
||||
}
|
||||
|
||||
function Clean-StaleProfiles {
|
||||
if (-not (Test-Path $PgoProfilesDir)) { return }
|
||||
|
||||
$pgcFiles = Get-ChildItem -Path $PgoProfilesDir -Filter "*.pgc" -ErrorAction SilentlyContinue
|
||||
if ($pgcFiles -and $pgcFiles.Count -gt 0) {
|
||||
Write-Info "Removing $($pgcFiles.Count) stale PGC file(s)..."
|
||||
$pgcFiles | Remove-Item -Force
|
||||
}
|
||||
}
|
||||
|
||||
function Merge-Profiles {
|
||||
$pgomgr = Find-Pgomgr
|
||||
if (-not $pgomgr) {
|
||||
Write-Warning "pgomgr.exe not found. Cannot merge profiles."
|
||||
Write-Info "Ensure Visual Studio Build Tools are installed and on PATH."
|
||||
return $false
|
||||
}
|
||||
|
||||
$pgdFiles = Get-ChildItem -Path $PgoProfilesDir -Filter "*.pgd" -ErrorAction SilentlyContinue
|
||||
if (-not $pgdFiles -or $pgdFiles.Count -eq 0) {
|
||||
Write-Warning "No PGD files found in $PgoProfilesDir"
|
||||
return $false
|
||||
}
|
||||
|
||||
$pgcFiles = Get-ChildItem -Path $PgoProfilesDir -Filter "*.pgc" -ErrorAction SilentlyContinue
|
||||
if (-not $pgcFiles -or $pgcFiles.Count -eq 0) {
|
||||
Write-Info "No PGC files to merge."
|
||||
return $true
|
||||
}
|
||||
|
||||
foreach ($pgd in $pgdFiles) {
|
||||
Write-Info "Merging PGC files into $($pgd.Name)..."
|
||||
& $pgomgr /merge $pgd.FullName
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Warning "pgomgr /merge returned exit code $LASTEXITCODE for $($pgd.Name)"
|
||||
}
|
||||
}
|
||||
|
||||
# Clean PGC files after successful merge
|
||||
Write-Info "Cleaning merged PGC files..."
|
||||
Get-ChildItem -Path $PgoProfilesDir -Filter "*.pgc" -ErrorAction SilentlyContinue | Remove-Item -Force
|
||||
|
||||
return $true
|
||||
}
|
||||
|
||||
function Show-ProfileSummary {
|
||||
$pgomgr = Find-Pgomgr
|
||||
if (-not $pgomgr) {
|
||||
Write-Warning "pgomgr.exe not found. Cannot show summary."
|
||||
return
|
||||
}
|
||||
|
||||
$pgdFiles = Get-ChildItem -Path $PgoProfilesDir -Filter "*.pgd" -ErrorAction SilentlyContinue
|
||||
if (-not $pgdFiles -or $pgdFiles.Count -eq 0) {
|
||||
Write-Warning "No PGD files found in $PgoProfilesDir"
|
||||
return
|
||||
}
|
||||
|
||||
foreach ($pgd in $pgdFiles) {
|
||||
Write-Header "Profile Summary: $($pgd.Name)"
|
||||
& $pgomgr /summary $pgd.FullName
|
||||
Write-Host ""
|
||||
}
|
||||
}
|
||||
|
||||
if ($Help) {
|
||||
Show-Usage
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Auto-detect number of processors
|
||||
if ($Jobs -eq 0) {
|
||||
$Jobs = $env:NUMBER_OF_PROCESSORS
|
||||
if (-not $Jobs) { $Jobs = 4 }
|
||||
}
|
||||
|
||||
$LtoFlag = if ($EnableLTO) { "ON" } else { "OFF" }
|
||||
|
||||
# --- Clean stage ---
|
||||
if ($Stage -eq "clean") {
|
||||
Write-Header "Cleaning Build Directory"
|
||||
|
||||
if (Test-Path $PgoProfilesDir) {
|
||||
Write-Info "Backing up PGO profiles..."
|
||||
New-Item -ItemType Directory -Force -Path $BackupProfilesDir | Out-Null
|
||||
Copy-Item -Path "$PgoProfilesDir\*" -Destination $BackupProfilesDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
if (Test-Path $BuildDir) {
|
||||
Write-Info "Removing build directory..."
|
||||
Remove-Item -Path $BuildDir -Recurse -Force
|
||||
}
|
||||
|
||||
if (Test-Path $BackupProfilesDir) {
|
||||
Write-Info "Restoring PGO profiles..."
|
||||
New-Item -ItemType Directory -Force -Path $PgoProfilesDir | Out-Null
|
||||
Move-Item -Path "$BackupProfilesDir\*" -Destination $PgoProfilesDir -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path $BackupProfilesDir -Recurse -Force
|
||||
}
|
||||
|
||||
Write-Info "Clean complete!"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# --- Merge stage ---
|
||||
if ($Stage -eq "merge") {
|
||||
Write-Header "Merging PGO Profiles"
|
||||
|
||||
if (-not (Test-Path $PgoProfilesDir)) {
|
||||
Write-Error-Custom "Profile directory not found: $PgoProfilesDir"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$result = Merge-Profiles
|
||||
if ($result) {
|
||||
Write-Info "Merge complete! Run '.\pgo-build.ps1 summary' to check coverage."
|
||||
} else {
|
||||
Write-Error-Custom "Merge failed."
|
||||
exit 1
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
|
||||
# --- Summary stage ---
|
||||
if ($Stage -eq "summary") {
|
||||
Write-Header "PGO Profile Summary"
|
||||
|
||||
if (-not (Test-Path $PgoProfilesDir)) {
|
||||
Write-Error-Custom "Profile directory not found: $PgoProfilesDir"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Show-ProfileSummary
|
||||
exit 0
|
||||
}
|
||||
|
||||
# --- Generate stage ---
|
||||
if ($Stage -eq "generate") {
|
||||
Write-Header "PGO Stage 1: Generate Profile Data"
|
||||
|
||||
# Clean stale PGC files from any previous run
|
||||
if (Test-Path $PgoProfilesDir) {
|
||||
Clean-StaleProfiles
|
||||
}
|
||||
|
||||
# Create build directory
|
||||
New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null
|
||||
Set-Location $BuildDir
|
||||
|
||||
# Configure
|
||||
Write-Info "Configuring CMake..."
|
||||
cmake .. `
|
||||
-DCITRON_ENABLE_PGO_GENERATE=ON `
|
||||
-DCITRON_ENABLE_LTO=$LtoFlag `
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error-Custom "CMake configuration failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Build
|
||||
Write-Info "Building instrumented Citron (this may take a while)..."
|
||||
cmake --build . --config Release -j $Jobs
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error-Custom "Build failed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Header "Build Complete!"
|
||||
Write-Host ""
|
||||
Write-Host " Training guide for best PGO results:" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host " 1. Run: .\bin\Release\citron.exe"
|
||||
Write-Host " 2. Launch a game and play PAST initial loading"
|
||||
Write-Host " (first-time shader compilation is a critical hot path)"
|
||||
Write-Host " 3. Play for at least 5-10 minutes per game"
|
||||
Write-Host " 4. Test 2-3 different games for broader code coverage"
|
||||
Write-Host " 5. Navigate menus, settings, and game list to profile the UI"
|
||||
Write-Host " 6. Exit citron cleanly (File -> Exit or Ctrl+Q)"
|
||||
Write-Host ""
|
||||
Write-Host " After each session, you can run:" -ForegroundColor Yellow
|
||||
Write-Host " .\pgo-build.ps1 merge # Consolidate collected profiles"
|
||||
Write-Host " .\pgo-build.ps1 summary # Check profile coverage"
|
||||
Write-Host ""
|
||||
Write-Host " When satisfied with coverage, build the optimized binary:" -ForegroundColor Yellow
|
||||
Write-Host " .\pgo-build.ps1 use"
|
||||
Write-Host ""
|
||||
|
||||
Set-Location $ScriptDir
|
||||
}
|
||||
|
||||
# --- Use stage ---
|
||||
if ($Stage -eq "use") {
|
||||
Write-Header "PGO Stage 2: Build Optimized Binary"
|
||||
|
||||
# Check if profile data exists
|
||||
if (-not (Test-Path $PgoProfilesDir) -or -not (Get-ChildItem $PgoProfilesDir -ErrorAction SilentlyContinue)) {
|
||||
Write-Error-Custom "No profile data found in $PgoProfilesDir"
|
||||
Write-Info "Please run the generate stage first and collect profile data"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Merge any outstanding PGC files before building
|
||||
Write-Info "Merging any outstanding PGC files..."
|
||||
Merge-Profiles | Out-Null
|
||||
|
||||
# Backup profiles if build directory exists
|
||||
if (Test-Path $BuildDir) {
|
||||
Write-Info "Backing up PGO profiles..."
|
||||
New-Item -ItemType Directory -Force -Path $BackupProfilesDir | Out-Null
|
||||
Copy-Item -Path "$PgoProfilesDir\*" -Destination $BackupProfilesDir -Recurse -Force
|
||||
Remove-Item -Path $BuildDir -Recurse -Force
|
||||
}
|
||||
|
||||
# Create build directory and restore profiles
|
||||
New-Item -ItemType Directory -Force -Path $BuildDir | Out-Null
|
||||
if (Test-Path $BackupProfilesDir) {
|
||||
New-Item -ItemType Directory -Force -Path $PgoProfilesDir | Out-Null
|
||||
Move-Item -Path "$BackupProfilesDir\*" -Destination $PgoProfilesDir -Force
|
||||
Remove-Item -Path $BackupProfilesDir -Recurse -Force
|
||||
}
|
||||
|
||||
Set-Location $BuildDir
|
||||
|
||||
# Configure
|
||||
Write-Info "Configuring CMake..."
|
||||
cmake .. `
|
||||
-DCITRON_ENABLE_PGO_USE=ON `
|
||||
-DCITRON_ENABLE_LTO=$LtoFlag `
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error-Custom "CMake configuration failed"
|
||||
Set-Location $ScriptDir
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Build
|
||||
Write-Info "Building optimized Citron (this may take a while)..."
|
||||
cmake --build . --config Release -j $Jobs
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error-Custom "Build failed"
|
||||
Set-Location $ScriptDir
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Header "Build Complete!"
|
||||
Write-Info "Your optimized Citron binary is ready!"
|
||||
Write-Info "Location: $BuildDir\bin\Release\citron.exe"
|
||||
Write-Host ""
|
||||
Write-Info "This build is optimized for your specific usage patterns."
|
||||
|
||||
Set-Location $ScriptDir
|
||||
}
|
||||
-328
@@ -1,328 +0,0 @@
|
||||
#!/bin/bash
|
||||
# SPDX-FileCopyrightText: 2025 citron Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# PGO Build Script for Citron (Linux/macOS)
|
||||
# This script automates the Profile-Guided Optimization build process
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BUILD_DIR="${SCRIPT_DIR}/build"
|
||||
PGO_PROFILES_DIR="${BUILD_DIR}/pgo-profiles"
|
||||
BACKUP_PROFILES_DIR="${SCRIPT_DIR}/pgo-profiles-backup"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
print_header() {
|
||||
echo -e "${BLUE}=================================================================${NC}"
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
echo -e "${BLUE}=================================================================${NC}"
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
echo "Usage: $0 [STAGE] [OPTIONS]"
|
||||
echo ""
|
||||
echo "STAGE can be:"
|
||||
echo " generate - Build with PGO instrumentation (Stage 1)"
|
||||
echo " use - Build using PGO profile data (Stage 2)"
|
||||
echo " clean - Clean build directory but preserve profiles"
|
||||
echo " merge - Merge profile data (Clang: .profraw -> .profdata)"
|
||||
echo " summary - Show profile file statistics"
|
||||
echo ""
|
||||
echo "Example workflow:"
|
||||
echo " $0 generate # Build instrumented version"
|
||||
echo " # Run citron, play 2-3 games for 5-10 min each, exit cleanly"
|
||||
echo " $0 merge # Merge collected profiles"
|
||||
echo " $0 summary # Check coverage"
|
||||
echo " $0 use # Build optimized version"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -j N Number of parallel jobs (default: auto-detect)"
|
||||
echo " -lto Enable Link-Time Optimization"
|
||||
echo " -h Show this help message"
|
||||
}
|
||||
|
||||
clean_stale_profiles() {
|
||||
if [ ! -d "$PGO_PROFILES_DIR" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
local gcda_count
|
||||
gcda_count=$(find "$PGO_PROFILES_DIR" -name "*.gcda" 2>/dev/null | wc -l)
|
||||
if [ "$gcda_count" -gt 0 ]; then
|
||||
print_info "Removing $gcda_count stale .gcda file(s)..."
|
||||
find "$PGO_PROFILES_DIR" -name "*.gcda" -delete
|
||||
fi
|
||||
|
||||
local profraw_count
|
||||
profraw_count=$(find "$PGO_PROFILES_DIR" -name "*.profraw" 2>/dev/null | wc -l)
|
||||
if [ "$profraw_count" -gt 0 ]; then
|
||||
print_info "Removing $profraw_count stale .profraw file(s)..."
|
||||
find "$PGO_PROFILES_DIR" -name "*.profraw" -delete
|
||||
fi
|
||||
}
|
||||
|
||||
merge_clang_profiles() {
|
||||
if ! command -v llvm-profdata &>/dev/null; then
|
||||
print_warning "llvm-profdata not found. Cannot merge Clang profiles."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local profraw_files
|
||||
profraw_files=$(find "$PGO_PROFILES_DIR" -name "*.profraw" 2>/dev/null)
|
||||
if [ -z "$profraw_files" ]; then
|
||||
print_info "No .profraw files to merge."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local count
|
||||
count=$(echo "$profraw_files" | wc -l)
|
||||
print_info "Merging $count .profraw file(s)..."
|
||||
|
||||
llvm-profdata merge \
|
||||
-output="${PGO_PROFILES_DIR}/default.profdata" \
|
||||
${profraw_files}
|
||||
|
||||
print_info "Merged into ${PGO_PROFILES_DIR}/default.profdata"
|
||||
|
||||
# Clean raw files after merge
|
||||
print_info "Cleaning merged .profraw files..."
|
||||
find "$PGO_PROFILES_DIR" -name "*.profraw" -delete
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
show_profile_summary() {
|
||||
if [ ! -d "$PGO_PROFILES_DIR" ]; then
|
||||
print_warning "Profile directory not found: $PGO_PROFILES_DIR"
|
||||
return
|
||||
fi
|
||||
|
||||
print_header "Profile Summary"
|
||||
|
||||
local profdata="${PGO_PROFILES_DIR}/default.profdata"
|
||||
if [ -f "$profdata" ]; then
|
||||
local size
|
||||
size=$(du -h "$profdata" | cut -f1)
|
||||
print_info "Clang profile: $profdata ($size)"
|
||||
if command -v llvm-profdata &>/dev/null; then
|
||||
llvm-profdata show --counts --all-functions "$profdata" 2>/dev/null | tail -5
|
||||
fi
|
||||
fi
|
||||
|
||||
local gcda_count
|
||||
gcda_count=$(find "$PGO_PROFILES_DIR" -name "*.gcda" 2>/dev/null | wc -l)
|
||||
if [ "$gcda_count" -gt 0 ]; then
|
||||
print_info "GCC profile files: $gcda_count .gcda files"
|
||||
local total_size
|
||||
total_size=$(find "$PGO_PROFILES_DIR" -name "*.gcda" -exec du -ch {} + 2>/dev/null | tail -1 | cut -f1)
|
||||
print_info "Total .gcda size: $total_size"
|
||||
fi
|
||||
|
||||
local profraw_count
|
||||
profraw_count=$(find "$PGO_PROFILES_DIR" -name "*.profraw" 2>/dev/null | wc -l)
|
||||
if [ "$profraw_count" -gt 0 ]; then
|
||||
print_warning "$profraw_count unmerged .profraw file(s) found. Run '$0 merge' first."
|
||||
fi
|
||||
|
||||
if [ "$gcda_count" -eq 0 ] && [ ! -f "$profdata" ] && [ "$profraw_count" -eq 0 ]; then
|
||||
print_warning "No profile data found in $PGO_PROFILES_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
STAGE=""
|
||||
JOBS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo "4")
|
||||
ENABLE_LTO="OFF"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
generate|use|clean|merge|summary)
|
||||
STAGE="$1"
|
||||
shift
|
||||
;;
|
||||
-j)
|
||||
JOBS="$2"
|
||||
shift 2
|
||||
;;
|
||||
-lto)
|
||||
ENABLE_LTO="ON"
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown option: $1"
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$STAGE" ]; then
|
||||
print_error "No stage specified"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Clean stage ---
|
||||
if [ "$STAGE" == "clean" ]; then
|
||||
print_header "Cleaning Build Directory"
|
||||
|
||||
if [ -d "$PGO_PROFILES_DIR" ]; then
|
||||
print_info "Backing up PGO profiles..."
|
||||
mkdir -p "$BACKUP_PROFILES_DIR"
|
||||
cp -r "$PGO_PROFILES_DIR"/* "$BACKUP_PROFILES_DIR/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [ -d "$BUILD_DIR" ]; then
|
||||
print_info "Removing build directory..."
|
||||
rm -rf "$BUILD_DIR"
|
||||
fi
|
||||
|
||||
if [ -d "$BACKUP_PROFILES_DIR" ]; then
|
||||
print_info "Restoring PGO profiles..."
|
||||
mkdir -p "$PGO_PROFILES_DIR"
|
||||
mv "$BACKUP_PROFILES_DIR"/* "$PGO_PROFILES_DIR/" 2>/dev/null || true
|
||||
rm -rf "$BACKUP_PROFILES_DIR"
|
||||
fi
|
||||
|
||||
print_info "Clean complete!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Merge stage ---
|
||||
if [ "$STAGE" == "merge" ]; then
|
||||
print_header "Merging PGO Profiles"
|
||||
|
||||
if [ ! -d "$PGO_PROFILES_DIR" ]; then
|
||||
print_error "Profile directory not found: $PGO_PROFILES_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
merge_clang_profiles
|
||||
print_info "Done! Run '$0 summary' to check coverage."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Summary stage ---
|
||||
if [ "$STAGE" == "summary" ]; then
|
||||
show_profile_summary
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Generate stage ---
|
||||
if [ "$STAGE" == "generate" ]; then
|
||||
print_header "PGO Stage 1: Generate Profile Data"
|
||||
|
||||
# Clean stale profile data from any previous run
|
||||
if [ -d "$PGO_PROFILES_DIR" ]; then
|
||||
clean_stale_profiles
|
||||
fi
|
||||
|
||||
# Create build directory
|
||||
mkdir -p "$BUILD_DIR"
|
||||
cd "$BUILD_DIR"
|
||||
|
||||
# Configure
|
||||
print_info "Configuring CMake..."
|
||||
cmake .. \
|
||||
-DCITRON_ENABLE_PGO_GENERATE=ON \
|
||||
-DCITRON_ENABLE_LTO=$ENABLE_LTO \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
# Build
|
||||
print_info "Building instrumented Citron (this may take a while)..."
|
||||
cmake --build . -j"$JOBS"
|
||||
|
||||
print_header "Build Complete!"
|
||||
echo ""
|
||||
echo -e "${YELLOW} Training guide for best PGO results:${NC}"
|
||||
echo ""
|
||||
echo " 1. Run: ./bin/citron"
|
||||
echo " 2. Launch a game and play PAST initial loading"
|
||||
echo " (first-time shader compilation is a critical hot path)"
|
||||
echo " 3. Play for at least 5-10 minutes per game"
|
||||
echo " 4. Test 2-3 different games for broader code coverage"
|
||||
echo " 5. Navigate menus, settings, and game list to profile the UI"
|
||||
echo " 6. Exit citron cleanly (File -> Exit or Ctrl+Q)"
|
||||
echo ""
|
||||
echo -e "${YELLOW} After each session, you can run:${NC}"
|
||||
echo " $0 merge # Consolidate collected profiles"
|
||||
echo " $0 summary # Check profile coverage"
|
||||
echo ""
|
||||
echo -e "${YELLOW} When satisfied with coverage, build the optimized binary:${NC}"
|
||||
echo " $0 use"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# --- Use stage ---
|
||||
if [ "$STAGE" == "use" ]; then
|
||||
print_header "PGO Stage 2: Build Optimized Binary"
|
||||
|
||||
# Check if profile data exists
|
||||
if [ ! -d "$PGO_PROFILES_DIR" ] || [ -z "$(ls -A $PGO_PROFILES_DIR 2>/dev/null)" ]; then
|
||||
print_error "No profile data found in $PGO_PROFILES_DIR"
|
||||
print_info "Please run the generate stage first and collect profile data"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Merge any outstanding raw profiles before building
|
||||
print_info "Merging any outstanding profile data..."
|
||||
merge_clang_profiles || true
|
||||
|
||||
# Backup profiles if build directory exists
|
||||
if [ -d "$BUILD_DIR" ]; then
|
||||
print_info "Backing up PGO profiles..."
|
||||
mkdir -p "$BACKUP_PROFILES_DIR"
|
||||
cp -r "$PGO_PROFILES_DIR"/* "$BACKUP_PROFILES_DIR/"
|
||||
rm -rf "$BUILD_DIR"
|
||||
fi
|
||||
|
||||
# Create build directory and restore profiles
|
||||
mkdir -p "$BUILD_DIR"
|
||||
if [ -d "$BACKUP_PROFILES_DIR" ]; then
|
||||
mkdir -p "$PGO_PROFILES_DIR"
|
||||
mv "$BACKUP_PROFILES_DIR"/* "$PGO_PROFILES_DIR/"
|
||||
rm -rf "$BACKUP_PROFILES_DIR"
|
||||
fi
|
||||
|
||||
cd "$BUILD_DIR"
|
||||
|
||||
# Configure
|
||||
print_info "Configuring CMake..."
|
||||
cmake .. \
|
||||
-DCITRON_ENABLE_PGO_USE=ON \
|
||||
-DCITRON_ENABLE_LTO=$ENABLE_LTO \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
# Build
|
||||
print_info "Building optimized Citron (this may take a while)..."
|
||||
cmake --build . -j"$JOBS"
|
||||
|
||||
print_header "Build Complete!"
|
||||
print_info "Your optimized Citron binary is ready!"
|
||||
print_info "Location: $BUILD_DIR/bin/citron"
|
||||
echo ""
|
||||
print_info "This build is optimized for your specific usage patterns."
|
||||
fi
|
||||
Reference in New Issue
Block a user