mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-19 18:36:53 +02:00
4e8e335b7b
* macOS: auto-discover bundled MoltenVK on startup
On macOS the Vulkan loader comes from MoltenVK. SDL's default
probe only searches system paths, so a bundled libMoltenVK.dylib
next to the executable is invisible under the hardened runtime.
Probe it explicitly via SDL_GetBasePath() before falling back to
SDL's default search. Respect SDL_VULKAN_LIBRARY overrides and
log which loader is used. Update README to reflect that no
environment variable is required for bundled builds.
Co-Authored-By: internal-model
* window: fix Vulkan portability enumeration on macOS
MoltenVK requires VK_KHR_portability_enumeration and
VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR to surface
portability devices via enumeratePhysicalDevices. Without the flag
the adapter is hidden on some driver versions, causing
"Could not find suitable device" failures.
Add the instance extension and flag when available, and add
diagnostic logs for all MoltenVK fallbacks (depthClipEnable,
colorWriteEnable, depthBounds, fragmentShaderBarycentric)
so black-screen diagnostics are actionable.
* macOS: add KytyPS5.app bundle packaging
Add a proper macOS application bundle when the launcher is built.
launcher becomes KytyPS5.app (CFBundleIdentifier org.kytyps5.kytyps5)
with KytyPS5 as the executable, and kyty_emulator is installed as a
helper inside Contents/MacOS so QCoreApplication::applicationDirPath()
finds it. MoltenVK is auto-discovered via SDL_GetBasePath() in that
directory, so no SDL_VULKAN_LIBRARY is required.
- src/launcher/Info.plist.in: minimal bundle plist (version from
PROJECT_VERSION, LSMinimumSystemVersion 13.0).
- src/launcher/CMakeLists.txt: set MACOSX_BUNDLE, BUNDLE DESTINATION,
install helper, re-sign helper with JIT entitlements, and invoke
macdeployqt when available. Keep flat kyty_emulator for CLI.
- .github/workflows/build.yml: bundle MoltenVK into
KytyPS5.app/Contents/MacOS when present, verify bundle artifacts
(file/lipo/codesign), and handle bundle paths in the release zip.
- README.md: document bundle double-click and MoltenVK locations.
* launcher: fix bundle rpath for Qt frameworks
The bundle executable had @rpath references to Qt frameworks but no
LC_RPATH, causing dyld to abort at launch:
Library not loaded: @rpath/QtConcurrent.framework
Reason: no LC_RPATH's found
Set INSTALL_RPATH to @executable_path/../Frameworks and
BUILD_WITH_INSTALL_RPATH so the built and installed bundles
resolve Qt from Contents/Frameworks. Verified via otool -l
(LC_RPATH now present) and macdeployqt now succeeds without
"Cannot resolve rpath" errors.
* launcher: add Import game button
Add a prominent Import button to ConfigurationListWidget that lets
users select a game folder (containing eboot.bin) or a folder
containing multiple games via QFileDialog. Handles:
- Single game folder selected: adds its parent to game_dirs (Scan
searches subdirectories, so parent is needed)
- Folder with multiple games: adds the selected folder
- Deduplication via PathKey/NormalizeGameDirectories, writes
settings, rescans, and selects the imported game if found
- Shows info/warning dialogs when no games are found
UI: QToolButton with SP_DirOpenIcon and text Import beside the
existing toolbar, styled with a blue background for visibility.
Logic in ConfigurationListWidget::import_game().
* macOS: fix bundled loader and artifact packaging
* Revert "launcher: add Import game button"
This reverts commit 2f670ef95c.
---------
Co-authored-by: nmzik <Nmzik@mail.ru>
501 lines
16 KiB
YAML
501 lines
16 KiB
YAML
name: Build and Release KytyPS5
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
push:
|
|
branches: [ main, master ]
|
|
pull_request:
|
|
|
|
env:
|
|
KYTY_BUILD_ORIGIN: ${{ github.repository != 'KytyPS5/KytyPS5' && 'Fork' || github.event_name == 'push' && 'Official' || 'Source' }}
|
|
KYTY_BUILD_REPOSITORY: ${{ github.repository }}
|
|
|
|
jobs:
|
|
metadata:
|
|
name: Prepare build metadata
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
release_tag: ${{ steps.release_tag.outputs.value }}
|
|
|
|
steps:
|
|
- name: Generate release tag
|
|
id: release_tag
|
|
shell: bash
|
|
run: |
|
|
echo "value=KytyPS5-$(date -u +'%Y-%m-%d')-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
|
|
|
|
windows:
|
|
name: Build KytyPS5 (Windows)
|
|
needs: metadata
|
|
runs-on: windows-2022
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
|
|
- name: Setup Visual Studio environment
|
|
uses: ilammy/msvc-dev-cmd@v1
|
|
|
|
- name: Setup Ninja
|
|
uses: seanmiddleditch/gha-setup-ninja@v5
|
|
|
|
- name: Locate vcpkg
|
|
id: vcpkg
|
|
shell: pwsh
|
|
run: |
|
|
$vcpkgRoot = Split-Path (Get-Command vcpkg).Source
|
|
$portHash = (Get-FileHash "$vcpkgRoot\ports\glslang\vcpkg.json" -Algorithm SHA256).Hash
|
|
"root=$vcpkgRoot" |
|
|
Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
|
"port_hash=$($portHash.ToLowerInvariant())" |
|
|
Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
|
|
|
|
- name: Cache glslang
|
|
id: glslang_cache
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ${{ steps.vcpkg.outputs.root }}\installed\x64-windows
|
|
key: glslang-${{ runner.os }}-${{ runner.arch }}-${{ steps.vcpkg.outputs.port_hash }}-tools-opt
|
|
|
|
- name: Install glslang
|
|
shell: pwsh
|
|
run: |
|
|
$vcpkgRoot = "${{ steps.vcpkg.outputs.root }}"
|
|
if ("${{ steps.glslang_cache.outputs.cache-hit }}" -ne "true") {
|
|
vcpkg install glslang[tools,opt]:x64-windows
|
|
}
|
|
"$vcpkgRoot\installed\x64-windows\tools\glslang" |
|
|
Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
|
|
|
- name: Install Qt 6.10.3
|
|
uses: jurplel/install-qt-action@v4
|
|
with:
|
|
version: "6.10.3"
|
|
host: windows
|
|
target: desktop
|
|
arch: win64_msvc2022_64
|
|
cache: true
|
|
|
|
- name: Verify toolchain
|
|
shell: cmd
|
|
run: |
|
|
git --version
|
|
cmake --version
|
|
ninja --version
|
|
clang-cl --version
|
|
glslangValidator --version
|
|
echo Qt6_DIR=%Qt6_DIR%
|
|
|
|
- name: Configure
|
|
shell: cmd
|
|
run: |
|
|
cmake -S . -B _Build/windows ^
|
|
-G Ninja ^
|
|
-DCMAKE_BUILD_TYPE=Release ^
|
|
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON ^
|
|
-DKYTY_BUILD_ORIGIN=%KYTY_BUILD_ORIGIN% ^
|
|
-DKYTY_BUILD_REPOSITORY=%KYTY_BUILD_REPOSITORY% ^
|
|
-DKYTY_RELEASE_TAG=${{ needs.metadata.outputs.release_tag }} ^
|
|
-DCMAKE_C_COMPILER=clang-cl ^
|
|
-DCMAKE_CXX_COMPILER=clang-cl ^
|
|
-DCMAKE_PREFIX_PATH="%Qt6_DIR%"
|
|
|
|
- name: Build
|
|
shell: cmd
|
|
run: |
|
|
cmake --build _Build/windows --target launcher audio_out2_port_tests ime_dialog_tests virtual_memory_allocation_tests --parallel
|
|
|
|
- name: Test
|
|
shell: cmd
|
|
run: |
|
|
ctest --test-dir _Build/windows --output-on-failure -R "^(audio_out2_port|ime_dialog|virtual_memory_allocation)$"
|
|
|
|
- name: Install
|
|
shell: cmd
|
|
run: |
|
|
cmake --install _Build/windows --prefix _Build/windows/install
|
|
|
|
- name: Upload Windows artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: KytyPS5-Windows-x64
|
|
path: _Build/windows/install/**
|
|
if-no-files-found: error
|
|
|
|
macos:
|
|
name: Build KytyPS5 (macOS)
|
|
needs: metadata
|
|
runs-on: macos-15
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
|
|
- name: Select Xcode 26
|
|
shell: bash
|
|
run: |
|
|
xcode_path="$(ls -d /Applications/Xcode_26*.app | tail -n 1)"
|
|
test -n "$xcode_path"
|
|
sudo xcode-select --switch "$xcode_path/Contents/Developer"
|
|
xcodebuild -version
|
|
|
|
- name: Install build dependencies
|
|
shell: bash
|
|
run: brew install glslang ninja
|
|
|
|
- name: Install Qt 6.10.3
|
|
uses: jurplel/install-qt-action@v4
|
|
with:
|
|
version: "6.10.3"
|
|
host: mac
|
|
target: desktop
|
|
arch: clang_64
|
|
cache: true
|
|
|
|
- name: Verify toolchain
|
|
shell: bash
|
|
run: |
|
|
git --version
|
|
cmake --version
|
|
ninja --version
|
|
clang++ --version
|
|
glslangValidator --version
|
|
echo "Host architecture: $(uname -m)"
|
|
echo "QT_ROOT_DIR=$QT_ROOT_DIR"
|
|
|
|
- name: Configure
|
|
shell: bash
|
|
run: |
|
|
cmake -S . -B _Build/macos \
|
|
-G Ninja \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
|
-DKYTY_BUILD_ORIGIN="$KYTY_BUILD_ORIGIN" \
|
|
-DKYTY_BUILD_REPOSITORY="$KYTY_BUILD_REPOSITORY" \
|
|
-DKYTY_RELEASE_TAG="${{ needs.metadata.outputs.release_tag }}" \
|
|
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
|
|
-DCMAKE_C_COMPILER=clang \
|
|
-DCMAKE_CXX_COMPILER=clang++ \
|
|
-DCMAKE_PREFIX_PATH="$QT_ROOT_DIR"
|
|
|
|
- name: Build
|
|
shell: bash
|
|
run: |
|
|
cmake --build _Build/macos \
|
|
--target launcher audio_out2_port_tests ime_dialog_tests virtual_memory_allocation_tests \
|
|
--parallel
|
|
|
|
- name: Test
|
|
shell: bash
|
|
run: |
|
|
ctest --test-dir _Build/macos --output-on-failure \
|
|
-R '^(audio_out2_port|ime_dialog|virtual_memory_allocation)$'
|
|
|
|
- name: Install
|
|
shell: bash
|
|
run: |
|
|
cmake --install _Build/macos --prefix _Build/macos/install
|
|
|
|
- name: Bundle MoltenVK
|
|
shell: bash
|
|
env:
|
|
MOLTENVK_VERSION: v1.4.2
|
|
MOLTENVK_SHA256: f95765a6229cb7b915990a2890ce12ebe36a730b021545d3d52ae69ce4c4024e
|
|
run: |
|
|
archive="$RUNNER_TEMP/MoltenVK-macos.tar"
|
|
package="$RUNNER_TEMP/MoltenVK"
|
|
install_dir="_Build/macos/install"
|
|
app_dir="$install_dir/KytyPS5.app"
|
|
moltenvk="$install_dir/libMoltenVK.dylib"
|
|
curl --fail --location --retry 3 \
|
|
--output "$archive" \
|
|
"https://github.com/KhronosGroup/MoltenVK/releases/download/$MOLTENVK_VERSION/MoltenVK-macos.tar"
|
|
echo "$MOLTENVK_SHA256 $archive" | shasum -a 256 --check
|
|
tar -xf "$archive" -C "$RUNNER_TEMP"
|
|
test -d "$app_dir"
|
|
install -m 755 \
|
|
"$package/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib" \
|
|
"$moltenvk"
|
|
install -m 644 "$package/LICENSE" "$install_dir/LICENSE.MoltenVK"
|
|
codesign --force --sign - --timestamp=none "$moltenvk"
|
|
install -d -m 755 "$app_dir/Contents/Frameworks" "$app_dir/Contents/Resources"
|
|
install -m 755 "$moltenvk" "$app_dir/Contents/Frameworks/libMoltenVK.dylib"
|
|
install -m 644 "$package/LICENSE" "$app_dir/Contents/Resources/LICENSE.MoltenVK"
|
|
codesign --force --sign - --timestamp=none "$app_dir"
|
|
|
|
- name: Verify artifacts
|
|
shell: bash
|
|
run: |
|
|
install_dir="_Build/macos/install"
|
|
app_dir="$install_dir/KytyPS5.app"
|
|
test -d "$app_dir"
|
|
for binary in \
|
|
"$install_dir/kyty_emulator" \
|
|
"$install_dir/libMoltenVK.dylib" \
|
|
"$app_dir/Contents/MacOS/KytyPS5" \
|
|
"$app_dir/Contents/MacOS/kyty_emulator" \
|
|
"$app_dir/Contents/Frameworks/libMoltenVK.dylib"; do
|
|
file "$binary"
|
|
lipo "$binary" -verify_arch x86_64
|
|
done
|
|
for binary in \
|
|
"$install_dir/kyty_emulator" \
|
|
"$install_dir/libMoltenVK.dylib" \
|
|
"$app_dir/Contents/MacOS/KytyPS5" \
|
|
"$app_dir/Contents/MacOS/kyty_emulator" \
|
|
"$app_dir/Contents/Frameworks/libMoltenVK.dylib"; do
|
|
codesign --verify --strict "$binary"
|
|
done
|
|
codesign --verify --deep --strict --verbose=2 "$app_dir"
|
|
|
|
- name: Package macOS artifacts
|
|
shell: bash
|
|
run: |
|
|
install_dir="_Build/macos/install"
|
|
archive="$RUNNER_TEMP/KytyPS5-macOS-x86_64.zip"
|
|
(
|
|
cd "$install_dir"
|
|
zip -qry "$archive" .
|
|
)
|
|
unzip -t "$archive"
|
|
|
|
- name: Upload macOS artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: KytyPS5-macOS-x86_64
|
|
path: ${{ runner.temp }}/KytyPS5-macOS-x86_64.zip
|
|
if-no-files-found: error
|
|
|
|
linux:
|
|
name: Build KytyPS5 (Linux)
|
|
needs: metadata
|
|
runs-on: ubuntu-24.04
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
|
|
- name: Install build dependencies
|
|
shell: bash
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install --no-install-recommends --yes \
|
|
clang \
|
|
glslang-tools \
|
|
libasound2-dev \
|
|
libdbus-1-dev \
|
|
libgl1-mesa-dev \
|
|
libpulse-dev \
|
|
libudev-dev \
|
|
libwayland-dev \
|
|
libx11-dev \
|
|
libxcursor-dev \
|
|
libxext-dev \
|
|
libxfixes-dev \
|
|
libxi-dev \
|
|
libxkbcommon-dev \
|
|
libxrandr-dev \
|
|
libxss-dev \
|
|
lld \
|
|
ninja-build \
|
|
wayland-protocols
|
|
|
|
- name: Install Qt 6.10.3
|
|
uses: jurplel/install-qt-action@v4
|
|
with:
|
|
version: "6.10.3"
|
|
host: linux
|
|
target: desktop
|
|
arch: linux_gcc_64
|
|
cache: true
|
|
|
|
- name: Verify toolchain
|
|
shell: bash
|
|
run: |
|
|
git --version
|
|
cmake --version
|
|
ninja --version
|
|
clang++ --version
|
|
ld.lld --version
|
|
glslangValidator --version
|
|
echo "Qt6_DIR=$Qt6_DIR"
|
|
|
|
- name: Configure
|
|
shell: bash
|
|
run: |
|
|
mkdir -p _Build
|
|
cmake -S . -B _Build/linux \
|
|
-G Ninja \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
|
-DKYTY_BUILD_ORIGIN="$KYTY_BUILD_ORIGIN" \
|
|
-DKYTY_BUILD_REPOSITORY="$KYTY_BUILD_REPOSITORY" \
|
|
-DKYTY_RELEASE_TAG="${{ needs.metadata.outputs.release_tag }}" \
|
|
-DCMAKE_C_COMPILER=clang \
|
|
-DCMAKE_CXX_COMPILER=clang++ \
|
|
-DCMAKE_PREFIX_PATH="$Qt6_DIR" 2>&1 | tee _Build/configure.log
|
|
exit "${PIPESTATUS[0]}"
|
|
|
|
- name: Verify SDL2 backends
|
|
shell: bash
|
|
run: |
|
|
status=0
|
|
for feature in SDL_ALSA SDL_PULSEAUDIO SDL_WAYLAND SDL_X11 SDL_LIBUDEV SDL_DBUS; do
|
|
if grep -qE "^-- ${feature} +\\(Wanted: ON\\): ON" _Build/configure.log; then
|
|
echo "ok ${feature}"
|
|
else
|
|
echo "FAIL ${feature} is not enabled"
|
|
status=1
|
|
fi
|
|
done
|
|
exit "$status"
|
|
|
|
- name: Build
|
|
shell: bash
|
|
run: |
|
|
cmake --build _Build/linux \
|
|
--target launcher page_manager_tests memory_tracker_tests \
|
|
audio_out2_port_tests ime_dialog_tests virtual_memory_allocation_tests \
|
|
--parallel
|
|
|
|
- name: Test
|
|
shell: bash
|
|
run: |
|
|
ctest --test-dir _Build/linux --output-on-failure \
|
|
-R '^(audio_out2_port|ime_dialog|page_manager|memory_tracker|virtual_memory_allocation)$'
|
|
|
|
- name: Install
|
|
shell: bash
|
|
run: |
|
|
cmake --install _Build/linux --prefix _Build/linux/install
|
|
|
|
- name: Verify artifacts
|
|
shell: bash
|
|
run: |
|
|
file _Build/linux/install/launcher
|
|
file _Build/linux/install/kyty_emulator
|
|
file _Build/linux/install/kyty_emulator | grep -q "ELF 64-bit LSB .*x86-64"
|
|
ldd _Build/linux/install/kyty_emulator > /dev/null
|
|
readelf -d _Build/linux/install/launcher | grep -q 'RPATH.*\$ORIGIN/lib'
|
|
while IFS= read -r -d '' binary; do
|
|
while read -r dependency; do
|
|
test -e "_Build/linux/install/lib/$dependency"
|
|
done < <(
|
|
readelf -d "$binary" |
|
|
sed -n 's/.*Shared library: \[\(libQt6[^]]*\|libicu[^]]*\)\].*/\1/p'
|
|
)
|
|
done < <(
|
|
find _Build/linux/install/launcher _Build/linux/install/plugins \
|
|
-type f \( -name launcher -o -name '*.so' \) -print0
|
|
)
|
|
_Build/linux/install/kyty_emulator --help > /dev/null
|
|
|
|
- name: Upload Linux artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: KytyPS5-Linux-x86_64
|
|
path: _Build/linux/install/**
|
|
if-no-files-found: error
|
|
|
|
release:
|
|
name: Release KytyPS5
|
|
if: >-
|
|
always() &&
|
|
github.event_name == 'push' &&
|
|
github.repository == 'KytyPS5/KytyPS5' &&
|
|
(needs.windows.result == 'success' ||
|
|
needs.macos.result == 'success' ||
|
|
needs.linux.result == 'success')
|
|
needs: [metadata, windows, macos, linux]
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
env:
|
|
RELEASE_NAME: ${{ needs.metadata.outputs.release_tag }}
|
|
|
|
steps:
|
|
- name: Download Windows build
|
|
if: needs.windows.result == 'success'
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: KytyPS5-Windows-x64
|
|
path: artifacts/KytyPS5-Windows-x64
|
|
|
|
- name: Download macOS build
|
|
if: needs.macos.result == 'success'
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: KytyPS5-macOS-x86_64
|
|
path: artifacts/KytyPS5-macOS-x86_64
|
|
|
|
- name: Download Linux build
|
|
if: needs.linux.result == 'success'
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: KytyPS5-Linux-x86_64
|
|
path: artifacts/KytyPS5-Linux-x86_64
|
|
|
|
- name: Package Windows build
|
|
if: needs.windows.result == 'success'
|
|
shell: bash
|
|
run: |
|
|
windows_dir="artifacts/KytyPS5-Windows-x64"
|
|
test -d "$windows_dir"
|
|
(
|
|
cd "$windows_dir"
|
|
zip -r "$GITHUB_WORKSPACE/$RELEASE_NAME-Windows-x64.zip" .
|
|
)
|
|
|
|
- name: Package macOS build
|
|
if: needs.macos.result == 'success'
|
|
shell: bash
|
|
run: |
|
|
macos_archive="artifacts/KytyPS5-macOS-x86_64/KytyPS5-macOS-x86_64.zip"
|
|
test -f "$macos_archive"
|
|
cp "$macos_archive" "$RELEASE_NAME-macOS-x86_64.zip"
|
|
|
|
- name: Package Linux build
|
|
if: needs.linux.result == 'success'
|
|
shell: bash
|
|
run: |
|
|
linux_dir="artifacts/KytyPS5-Linux-x86_64"
|
|
test -d "$linux_dir"
|
|
chmod a+x \
|
|
"$linux_dir/launcher" \
|
|
"$linux_dir/kyty_emulator"
|
|
tar -C "$linux_dir" -czf \
|
|
"$GITHUB_WORKSPACE/$RELEASE_NAME-Linux-x86_64.tar.gz" .
|
|
|
|
- name: Create release
|
|
shell: bash
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
assets=()
|
|
for artifact in \
|
|
"$RELEASE_NAME-Windows-x64.zip" \
|
|
"$RELEASE_NAME-macOS-x86_64.zip" \
|
|
"$RELEASE_NAME-Linux-x86_64.tar.gz"; do
|
|
if [[ -f "$artifact" ]]; then
|
|
assets+=("$artifact")
|
|
fi
|
|
done
|
|
test "${#assets[@]}" -gt 0
|
|
if gh release view "$RELEASE_NAME" --repo "$GITHUB_REPOSITORY" > /dev/null 2>&1; then
|
|
gh release upload "$RELEASE_NAME" "${assets[@]}" \
|
|
--clobber \
|
|
--repo "$GITHUB_REPOSITORY"
|
|
else
|
|
gh release create "$RELEASE_NAME" "${assets[@]}" \
|
|
--generate-notes \
|
|
--repo "$GITHUB_REPOSITORY" \
|
|
--target "$GITHUB_SHA" \
|
|
--title "$RELEASE_NAME"
|
|
fi
|