feat(ci): add release workflow + update readme
This commit is contained in:
parent
00261033fa
commit
1071c9e09c
|
|
@ -0,0 +1,111 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ['v*']
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
CONFIGURE: >-
|
||||
-G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON
|
||||
-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
WINLIBS_RELEASE: 15.2.0posix-14.0.0-ucrt-r7
|
||||
WINLIBS_ZIP: winlibs-x86_64-posix-seh-gcc-15.2.0-mingw-w64ucrt-14.0.0-r7.zip
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and test (${{ matrix.platform }})
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux
|
||||
runner: ubuntu-latest
|
||||
timeout: 30
|
||||
- platform: windows
|
||||
runner: windows-latest
|
||||
timeout: 45
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: ${{ matrix.timeout }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: true
|
||||
- id: toolchain
|
||||
if: matrix.platform == 'windows'
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: C:\winlibs
|
||||
key: ${{ env.WINLIBS_ZIP }}
|
||||
- if: matrix.platform == 'windows' && steps.toolchain.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
curl -sSfL -o "$RUNNER_TEMP/winlibs.zip" "https://github.com/brechtsanders/winlibs_mingw/releases/download/$WINLIBS_RELEASE/$WINLIBS_ZIP"
|
||||
7z x "$RUNNER_TEMP/winlibs.zip" -oC:/winlibs
|
||||
- if: matrix.platform == 'windows'
|
||||
run: echo 'C:\winlibs\mingw64\bin' >> "$GITHUB_PATH"
|
||||
- uses: hendrikmuhs/ccache-action@v1.2.24
|
||||
with:
|
||||
key: ${{ matrix.platform }}
|
||||
save: false
|
||||
- name: Configure Linux
|
||||
if: matrix.platform == 'linux'
|
||||
run: cmake -S . -B build $CONFIGURE
|
||||
- name: Configure Windows
|
||||
if: matrix.platform == 'windows'
|
||||
shell: cmd
|
||||
run: cmake -S . -B build %CONFIGURE%
|
||||
- name: Build project and tests
|
||||
run: cmake --build build
|
||||
- name: Run tests
|
||||
run: ctest --test-dir build --output-on-failure --timeout 120 --stop-on-failure --no-tests=error
|
||||
- name: Build patched libraries
|
||||
run: cmake --build build --target libs
|
||||
- name: Package release files
|
||||
run: python tools/package_release.py --platform "${{ matrix.platform }}" --build build --output dist
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: release-${{ matrix.platform }}
|
||||
path: dist/*
|
||||
if-no-files-found: error
|
||||
compression-level: 0
|
||||
|
||||
publish:
|
||||
name: Publish release
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: release-*
|
||||
merge-multiple: true
|
||||
path: dist
|
||||
- name: Check release files and collect documentation
|
||||
shell: bash
|
||||
run: |
|
||||
for file in prx-windows.zip prx-windows.tar.gz prx-linux.zip prx-linux.tar.gz relinker.exe relinker; do
|
||||
test -s "dist/$file"
|
||||
done
|
||||
python tools/package_release.py --docs docs/user --output dist
|
||||
chmod +x dist/relinker
|
||||
- name: Create draft and upload files
|
||||
run: gh release create "$RELEASE_TAG" dist/* --verify-tag --draft --title "$RELEASE_TAG" --generate-notes
|
||||
- name: Publish complete release
|
||||
run: gh release edit "$RELEASE_TAG" --draft=false
|
||||
16
README.md
16
README.md
|
|
@ -4,21 +4,21 @@ Tool for automatic executables porting to Linux and Windows.
|
|||
|
||||
Includes a [relinker](core/relinker) that converts executable to the target system's native format and implementations of [system prx libraries](core/libs/prx) suitable for dynamic linking. No emulation or separate runtime process.
|
||||
|
||||
|
||||
|
||||
## Status
|
||||
|
||||
[](https://boykopovar.github.io/AnyPS5/) [](https://boykopovar.github.io/AnyPS5/)
|
||||
|
||||
[](https://boykopovar.github.io/AnyPS5/)
|
||||
|
||||
<sub>* System libraries: percentage of the functions known to the project so far (declared in [core/libs/prx](core/libs/prx)), not of every PS5 system function. The total grows as more functions are declared.</sub>
|
||||
[List of verified games](docs/user/COMPATIBILITY.md)
|
||||
|
||||
Releases will be published after the first full successful launch of at least one game.
|
||||
Dreaming Sarah (2D platformer) runs at a stable 60 fps on a GTX 1050 Ti / i5-7500 3.4GHz.
|
||||
|
||||
## Status
|
||||
Unsupported or unexpected states strictly throw `std::runtime_error`. `what()` is printed to stderr and the process terminates.
|
||||
|
||||
Execution reaches `_start`, [stack unwinding](core/libs/prx/libc/src/exception/Unwind.cpp) and exception handling tables are built, reaches main. Unsupported or unexpected states strictly throw `std::runtime_error`. `what()` is printed to stderr and the process terminates.
|
||||
|
||||
The [shader recompiler](core/shader/recompiler/Recompiler.cpp) successfully produces SPIR-V, validated via [Spirv-Tools](3rdparty/SPIRV-Tools) when built with `ANYPS5_ENABLE_SPIRV_TOOLS`.
|
||||
|
||||
The real game reaches the logo, main menu, and [gameplay](https://gist.github.com/user-attachments/assets/81d28e9b-c237-4545-b2ca-720071129816) with audio.
|
||||
The [shader recompiler](core/shader/recompiler/Recompiler.cpp) successfully produces SPIR-V (validated via [Spirv-Tools](3rdparty/SPIRV-Tools) when built with `ANYPS5_ENABLE_SPIRV_TOOLS`).
|
||||
|
||||
[Technical debt of the project](docs/dev/TechnicalDebt.md), [code style conventions](docs/dev/CONVENTIONS.md)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Compatibility
|
||||
# Tested compatibility
|
||||
|
||||
| Game | ID | Windows | Linux | GTX 1050 Ti / i5-7500 |
|
||||
|----------------|-----------|-------------------|-------|-----------------------|
|
||||
| Dreaming Sarah | PPSA02929 | In game, playable | ? | 60 FPS |
|
||||
| Game | ID | Windows | Linux | GTX 1050 Ti / i5-7500 3.4GHz | Intel(R) HD Graphic 620 / i5-7200 2.5GHz |
|
||||
|----------------|-----------|-------------------|-------|------------------------------|------------------------------------------|
|
||||
| Dreaming Sarah | PPSA02929 | In game, playable | ? | 60 FPS | 36 FPS |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
import argparse
|
||||
import shutil
|
||||
import tarfile
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def package(platform, build, output):
|
||||
libraries = sorted((build / "core/libs/libs").glob("*.prx"))
|
||||
expected = {f"{directory.name}.prx" for directory in Path("core/libs/prx").iterdir() if directory.is_dir()}
|
||||
expected.add("libcohtml.Prospero.prx")
|
||||
missing = expected - {library.name for library in libraries}
|
||||
if missing:
|
||||
raise RuntimeError(f"Missing patched libraries: {', '.join(sorted(missing))}")
|
||||
executable = "relinker.exe" if platform == "windows" else "relinker"
|
||||
files = list(libraries)
|
||||
if platform == "windows":
|
||||
runtime = Path("C:/winlibs/mingw64/bin")
|
||||
files.extend(runtime / name for name in ("libgcc_s_seh-1.dll", "libstdc++-6.dll", "libwinpthread-1.dll"))
|
||||
binary = build / "core/relinker" / executable
|
||||
for file in [*files, binary]:
|
||||
if not file.is_file() or file.stat().st_size == 0:
|
||||
raise RuntimeError(f"Missing or empty release file: {file}")
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
with zipfile.ZipFile(output / f"prx-{platform}.zip", "w", compression=zipfile.ZIP_DEFLATED) as archive:
|
||||
for file in files:
|
||||
archive.write(file, arcname=file.name)
|
||||
with tarfile.open(output / f"prx-{platform}.tar.gz", "w:gz") as archive:
|
||||
for file in files:
|
||||
archive.add(file, arcname=file.name)
|
||||
shutil.copy2(binary, output / executable)
|
||||
|
||||
|
||||
def collect_docs(source, output):
|
||||
documents = sorted(source.rglob("*.md"))
|
||||
if not documents:
|
||||
raise RuntimeError(f"No Markdown documents found in {source}")
|
||||
names = set()
|
||||
for document in documents:
|
||||
if document.name in names or (output / document.name).exists():
|
||||
raise RuntimeError(f"Duplicate release asset name: {document.name}")
|
||||
names.add(document.name)
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
for document in documents:
|
||||
shutil.copy2(document, output / document.name)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--platform", choices=("linux", "windows"))
|
||||
parser.add_argument("--build", type=Path)
|
||||
parser.add_argument("--docs", type=Path)
|
||||
parser.add_argument("--output", required=True, type=Path)
|
||||
args = parser.parse_args()
|
||||
if args.docs is not None:
|
||||
if args.platform is not None or args.build is not None:
|
||||
parser.error("--docs cannot be combined with --platform or --build")
|
||||
collect_docs(args.docs, args.output)
|
||||
else:
|
||||
if args.platform is None or args.build is None:
|
||||
parser.error("--platform and --build are required when --docs is not specified")
|
||||
package(args.platform, args.build, args.output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -26,7 +26,7 @@ OPCODE_ALIASES = {
|
|||
}
|
||||
REPORT_ROWS = 100
|
||||
PANEL_WIDTH, GAP, MAP_HEIGHT, HEADER = 495, 10, 280, 30
|
||||
DONE_COLOR, TODO_COLOR, BORDER, TEXT = "#2ea043", "#1f6feb", "#0d1117", "#ffffff"
|
||||
DONE_COLOR, TODO_COLOR, BORDER, TEXT = "#2ea043", "#6e7681", "#0d1117", "#ffffff"
|
||||
|
||||
|
||||
def body_end(text, start):
|
||||
|
|
|
|||
Loading…
Reference in New Issue