mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd2e73d664 |
No files matched your search
@@ -1,16 +0,0 @@
|
||||
;;; Directory Local Variables
|
||||
;;; See Info node `(emacs) Directory Variables' for more information.
|
||||
|
||||
(
|
||||
(c-mode . ((standard-indent . 3)
|
||||
(c-basic-offset . 3)
|
||||
(c-file-offsets . ((arglist-intro . ++)
|
||||
(arglist-cont-nonempty . ++)
|
||||
(block-close . 0)
|
||||
(block-open . 0)))
|
||||
(eval . (setq-local c-cleanup-list
|
||||
(cl-set-difference c-cleanup-list
|
||||
'(brace-else-brace
|
||||
brace-elseif-brace))))))
|
||||
(objc-mode . ((c-basic-offset . 3)))
|
||||
)
|
||||
+1
-6
@@ -1,4 +1,4 @@
|
||||
# EditorConfig: https://EditorConfig.org
|
||||
# EditorConfig: http://EditorConfig.org
|
||||
|
||||
# Top-most EditorConfig file
|
||||
root = true
|
||||
@@ -15,11 +15,6 @@ charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 3
|
||||
|
||||
# 2 space indentation
|
||||
[*.{json,xml,yaml,yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# Tab indentation
|
||||
[Makefile*]
|
||||
indent_style = tab
|
||||
@@ -1,12 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [libretro]
|
||||
patreon: libretro
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with a single custom sponsorship URL
|
||||
@@ -0,0 +1,35 @@
|
||||
# First and foremost consider this:
|
||||
- Only RetroArch bugs should be filed here. Not core bugs or game bugs
|
||||
- This is not a forum or a help section, this is strictly developer oriented
|
||||
|
||||
## Description
|
||||
|
||||
[Description of the bug]
|
||||
|
||||
### Expected behavior
|
||||
|
||||
[What you expected to happen]
|
||||
|
||||
### Actual behavior
|
||||
|
||||
[What is actually happening]
|
||||
|
||||
### Steps to reproduce the bug
|
||||
|
||||
1. [First step]
|
||||
2. [Second step]
|
||||
3. [and so on...]
|
||||
|
||||
### Bisect Results
|
||||
|
||||
[Try to bisect and tell us when this started happening]
|
||||
|
||||
### Version/Commit
|
||||
You can find this information under Information/System Information
|
||||
|
||||
- RetroArch: [version/commit]
|
||||
|
||||
### Environment information
|
||||
|
||||
- OS: [The operating system you're running]
|
||||
- Compiler: [In case you are running local builds]
|
||||
@@ -1,100 +0,0 @@
|
||||
name: Bug report
|
||||
description: This is not a forum or a help section, this is strictly developer oriented.
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Only RetroArch bugs should be filed here. Not core bugs or game bugs
|
||||
options:
|
||||
- label: This is a bug in RetroArch frontend
|
||||
required: true
|
||||
- label: I have searched the existing issues
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Description of the actual behavior of the bug
|
||||
placeholder: What is actually happening
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: What you expected to happen
|
||||
|
||||
- type: textarea
|
||||
id: reproduce_steps
|
||||
attributes:
|
||||
label: Steps to reproduce the bug
|
||||
description: List all steps to reproduce the problem
|
||||
placeholder: |
|
||||
1. [First step]
|
||||
2. [Second step]
|
||||
3. [and so on...]
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version/Commit
|
||||
description: You can find this information under Information/System Information
|
||||
placeholder: 1.20.0 (Git ab3b175)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: bisecting
|
||||
attributes:
|
||||
label: Bisect Results
|
||||
description: Did this work with any older RetroArch version? Can you point to a version (or even commit) where it broke?
|
||||
placeholder: 43105ab
|
||||
|
||||
- type: dropdown
|
||||
id: nigthly
|
||||
attributes:
|
||||
label: Present in the nightly version
|
||||
description: Is the issue reproducible with current [nightly builds](https://buildbot.libretro.com/nightly/)?
|
||||
options:
|
||||
- I don't know
|
||||
- Yes, this is reproduced in the nightly build
|
||||
- No, looks like this is already resolved
|
||||
default: 0
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform & operating system
|
||||
description: The system you're running RetroArch on
|
||||
placeholder: Linux aarch64, Windows 11 23H2, Android 14, PS Vita
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: cores
|
||||
attributes:
|
||||
label: Affected Cores
|
||||
description: List the affected cores and their versions here, if applicable. If the issue **only occurs with a single core** then the bug may not be with RetroArch; in that case, you should report it in that core's repository instead of here.
|
||||
placeholder: bsnes (115), FCEUmm ((SVN) aebea87), Snes9x (1.63.229933ea)
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment information
|
||||
description: Additional information about hardware and software
|
||||
placeholder: |
|
||||
* Window Manager: dwm/X11
|
||||
* Affected video drivers: sdl2, glcore
|
||||
* Installed through Flatpak
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Paste [RetroArch log](https://docs.libretro.com/guides/generating-retroarch-logs/) and/or [GDB backtrace](https://docs.libretro.com/development/retroarch/debugging/). This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
title: "[Feature Request] <FEATURE NAME>"
|
||||
about: Is there something you'd like to see in RetroArch?
|
||||
labels: feature request
|
||||
---
|
||||
@@ -1,14 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Libretro Forums
|
||||
url: https://forums.libretro.com
|
||||
about: A place to discuss all things libretro
|
||||
- name: Discord
|
||||
url: https://ra-link.web.app/discord
|
||||
about: Join our Discord server for help
|
||||
- name: RetroArch/libretro subreddit
|
||||
url: https://www.reddit.com/r/RetroArch
|
||||
about: Subreddit dedicated to RetroArch and the libretro API framework
|
||||
- name: Documentation
|
||||
url: https://docs.libretro.com
|
||||
about: Official RetroArch documentation for users and developers
|
||||
@@ -3,7 +3,7 @@
|
||||
1. Rebase before opening a pull request
|
||||
2. If you are sending several unrelated fixes or features, use a branch and a separate pull request for each
|
||||
3. If possible try squashing everything in a single commit. This is particularly beneficial in the case of feature merges since it allows easy bisecting when a problem arises
|
||||
4. RetroArch codebase follows C89 coding rules for portability across many old platforms check using `C89_BUILD=1`
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
name: CI 3DS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-devkitpro:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@v1
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
make -f Makefile.ctr.salamander -j$(getconf _NPROCESSORS_ONLN) USE_CTRULIB_2=1 clean
|
||||
make -f Makefile.ctr.salamander -j$(getconf _NPROCESSORS_ONLN) USE_CTRULIB_2=1
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.ctr -j$(getconf _NPROCESSORS_ONLN) USE_CTRULIB_2=1 clean
|
||||
make -f Makefile.ctr -j$(getconf _NPROCESSORS_ONLN) USE_CTRULIB_2=1 HAVE_STATIC_DUMMY=1 info all
|
||||
@@ -1,440 +0,0 @@
|
||||
name: CI Android
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Set up JDK 25
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: 'temurin'
|
||||
cache: 'gradle'
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
cd pkg/android/phoenix
|
||||
# A repository that answers with a server error is retried with
|
||||
# a backoff (2 s doubling, six tries) before Gradle gives up on
|
||||
# it for the rest of the build. A build that still fails to fetch
|
||||
# a dependency is run again, keeping what it already fetched and
|
||||
# built; any other failure fails the step at once.
|
||||
set -o pipefail
|
||||
for i in 1 2 3; do
|
||||
./gradlew assembleDebug \
|
||||
-Dorg.gradle.internal.repository.max.tentatives=6 \
|
||||
-Dorg.gradle.internal.repository.initial.backoff=2000 \
|
||||
2>&1 | tee gradle.log && break
|
||||
grep -qE 'Could not (resolve|GET|HEAD|download)' gradle.log \
|
||||
&& [ $i != 3 ] || exit 1
|
||||
echo "dependency fetch failed (attempt $i); retrying in 30s"
|
||||
sleep 30
|
||||
done
|
||||
find . -iname "*.apk" -exec ls -l "{}" \;
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: retroarch-android-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
pkg/android/phoenix/build/outputs/apk/normal/debug/phoenix-normal-debug.apk
|
||||
pkg/android/phoenix/build/outputs/apk/aarch64/debug/phoenix-aarch64-debug.apk
|
||||
pkg/android/phoenix/build/outputs/apk/quest/debug/phoenix-quest-debug.apk
|
||||
|
||||
vp9-stack-abi:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Use the Android project NDK version
|
||||
run: |
|
||||
set -eu
|
||||
version=$(sed -n 's/.*ndkVersion "\([^"]*\)".*/\1/p' pkg/android/phoenix/build.gradle)
|
||||
test -n "$version"
|
||||
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" "ndk;$version"
|
||||
echo "MEDIA_NDK=$ANDROID_HOME/ndk/$version" >> "$GITHUB_ENV"
|
||||
- name: VP9 C89 stack ceiling on both Android ABIs and file-offset modes
|
||||
run: |
|
||||
set -eu
|
||||
bin="$MEDIA_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin"
|
||||
unity="$RUNNER_TEMP/android-record-unity.c"
|
||||
: > "$unity"
|
||||
for source in record/record_audio_tap.c record/drivers/record_mediacodec.c gfx/common/mediacodec_inventory.c record/record_mediacodec_encoder.c \
|
||||
record/record_mux_mediacodec.c record/record_mediacodec_worker.c \
|
||||
record/record_mediacodec_surface.c record/record_android_capture_images.c \
|
||||
record/record_android_capture_submit.c record/record_android_capture_pipe.c \
|
||||
record/record_android_capture_pool.c record/record_android_capture_device.c record/record_android_capture_request.c record/record_android_capture_config.c record/record_android_capture_ops.c \
|
||||
record/record_android_capture_egl.c \
|
||||
record/record_android_capture_gl.c \
|
||||
record/record_android_capture_draw.c record/record_mediacodec_gpu_worker.c \
|
||||
record/record_mediacodec_file.c record/record_session_mediacodec.c \
|
||||
record/record_dispatch_mediacodec.c record/record_gpu_dispatch_mediacodec.c \
|
||||
record/record_gpu_queue.c \
|
||||
record/record_audio_queue.c libretro-common/queues/retro_spsc.c; do
|
||||
printf '#include "%s/%s"\n' "$PWD" "$source" >> "$unity"
|
||||
done
|
||||
for target in armv7a-linux-androideabi aarch64-linux-android; do
|
||||
for api in 21 29; do
|
||||
for offset in default 64; do
|
||||
extra=""
|
||||
if [ "$offset" = 64 ]; then extra="-D_FILE_OFFSET_BITS=64"; fi
|
||||
CC="$bin/$target$api-clang $extra" python3 libretro-common/samples/formats/vp9/check_stack.py
|
||||
"$bin/$target$api-clang" $extra -O1 -std=c89 -pedantic -Wall -Wextra -Werror \
|
||||
-Wno-long-long -Wno-c99-extensions -Wframe-larger-than=2048 \
|
||||
-DANDROID -DHAVE_VULKAN -DHAVE_RECORD_MEDIACODEC -DHAVE_CONFIGFILE \
|
||||
-DHAVE_THREADS -DHAVE_DYLIB -Ilibretro-common/include -Igfx/include \
|
||||
-c "$unity" -o "$RUNNER_TEMP/record-$target-$api-$offset.o"
|
||||
if "$bin/llvm-nm" -u "$RUNNER_TEMP/record-$target-$api-$offset.o" | \
|
||||
grep -Eq ' U (AMedia|ANativeWindow|AHardwareBuffer|egl|gl[A-Z]|record_android_capture_|record_mediacodec_|record_session_mediacodec_|record_dispatch_mediacodec_|record_gpu_dispatch_mediacodec_|record_mux_mediacodec_|record_audio_tap_|record_audio_queue_|record_gpu_queue_|retro_spsc_|mediacodec_inventory_)'; then
|
||||
echo "Unresolved Android recording dependency"
|
||||
exit 1
|
||||
fi
|
||||
for source in android_image_queue android_image_ndk mediacodec_session android_frame \
|
||||
mediacodec_color mediacodec_frame_export vulkan_android_device \
|
||||
vulkan_android_image vulkan_android_pipeline vulkan_android_sync \
|
||||
vulkan_android_submit vulkan_android_cache_entry vulkan_android_cache vulkan_android_queue; do
|
||||
"$bin/$target$api-clang" $extra -O1 -std=c89 -pedantic -Wall -Wextra -Werror \
|
||||
-Wno-long-long -Wno-c99-extensions -Wframe-larger-than=2048 \
|
||||
-DHAVE_THREADS -DHAVE_DYLIB -Ilibretro-common/include -Igfx/include \
|
||||
-c "gfx/common/$source.c" -o "$RUNNER_TEMP/$source-$target-$api-$offset.o"
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
codec-inventory:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
cc: [gcc, clang]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
- name: Real JNI codec admission and exception contracts
|
||||
run: make -C samples/gfx/mediacodec_inventory clean all check CC=${{ matrix.cc }} SANITIZER=undefined
|
||||
|
||||
image-ownership:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
cc: [gcc, clang]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Image ownership and runtime reader fault contracts
|
||||
run: make -C samples/gfx/android_image_queue clean all check CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
|
||||
codec-session:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
cc: [gcc, clang]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
- name: Android encoder, AAC, mux and worker contracts
|
||||
run: make -C samples/record/mediacodec_encode check CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
- name: Cold session, Surface timestamps and terminal output contracts
|
||||
run: make -C samples/gfx/mediacodec_session session-check CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
- name: Opaque frame leases, HDR refinement and concurrent handoffs
|
||||
run: make -C samples/gfx/mediacodec_session frame-check CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
- name: HEVC VP9 AV1 color intersection and renderer export contracts
|
||||
run: make -C samples/gfx/mediacodec_session export-check CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
|
||||
vulkan-import-resources:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
cc: [gcc, clang]
|
||||
env:
|
||||
APT_PKGS: libvulkan-dev mesa-vulkan-drivers glslc spirv-tools libegl1 libgles2 libgl1-mesa-dri
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
- name: FD ownership, warm submission and cache retirement contracts
|
||||
run: make -C samples/gfx/mediacodec_session warm-check CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
- name: Modeled image resources, device admission and pipeline contracts
|
||||
run: make -C samples/gfx/mediacodec_session vulkan-check CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
- name: Install pixel oracle and shader validation dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
- name: Execute embedded and freshly compiled SDR PQ HLG cropped pixels
|
||||
run: make -C samples/gfx/mediacodec_session vulkan-gpu-check CC=${{ matrix.cc }} SANITIZER=
|
||||
- name: GLES recording SDR PQ and scRGB pixel oracle
|
||||
run: EGL_PLATFORM=surfaceless LIBGL_ALWAYS_SOFTWARE=1 CC=${{ matrix.cc }} python3 samples/record/mediacodec_encode/draw_pixels.py
|
||||
|
||||
jni-contract:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
cc: [gcc, clang]
|
||||
env:
|
||||
APT_PKGS: libvulkan-dev mesa-vulkan-drivers ffmpeg
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
- name: Install test dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
- name: Native decoder session failure and Surface timestamp contracts
|
||||
run: make -C samples/gfx/mediacodec_session clean all check CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
- name: Hardware startup, first-frame refusal and software playback recovery
|
||||
run: |
|
||||
for threads in 0 1; do
|
||||
make -C libretro-common/samples/formats/video_player clean all CC=${{ matrix.cc }} THREADS="$threads" SANITIZER=address,undefined
|
||||
libretro-common/samples/formats/video_player/video_player_test
|
||||
done
|
||||
- name: HEVC drain and software output after hardware admission refusal
|
||||
run: |
|
||||
make -C samples/gfx/d3d11_video_decode rh265_hw_stream_test hevc_color_stream_test CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
(cd samples/gfx/d3d11_video_decode && ./rh265_hw_stream_test && ./hevc_color_stream_test)
|
||||
- name: Execute RGB shader crop and SDR PQ HLG pixel oracle on Vulkan software device
|
||||
run: make -C samples/gfx/mediacodec_session gpu-check CC=${{ matrix.cc }} SANITIZER=
|
||||
- name: HEVC Annex-B configuration and packet preservation
|
||||
run: make -C samples/gfx/mediacodec_hevc_packet clean all check parser-check CC=${{ matrix.cc }} SANITIZER=address,undefined
|
||||
ndk-compile:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Use the Android project NDK version
|
||||
run: |
|
||||
set -eu
|
||||
version=$(sed -n 's/.*ndkVersion "\([^"]*\)".*/\1/p' pkg/android/phoenix/build.gradle)
|
||||
test -n "$version"
|
||||
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" "ndk;$version"
|
||||
echo "MEDIA_NDK=$ANDROID_HOME/ndk/$version" >> "$GITHUB_ENV"
|
||||
- name: Strict C89, SDK function signatures and Android file-offset ABIs
|
||||
run: |
|
||||
set -euo pipefail
|
||||
bin="$MEDIA_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin"
|
||||
sources=(mediacodec_inventory android_image_queue android_image_ndk android_frame mediacodec_session mediacodec_color mediacodec_frame_export mediacodec_hevc_packet mediacodec_hevc_decoder mediacodec_hevc_backend mediacodec_vp9_decoder mediacodec_vp9_backend mediacodec_av1_decoder mediacodec_av1_backend vulkan_android_image vulkan_android_sync vulkan_android_pipeline vulkan_android_submit vulkan_android_queue vulkan_android_cache_entry vulkan_android_cache vulkan_android_device)
|
||||
unity="$RUNNER_TEMP/android-media-unity.c"
|
||||
printf '#include "%s/gfx/common/mediacodec_hevc_registry.h"\n' "$PWD" > "$unity"
|
||||
printf '#include "%s/gfx/common/mediacodec_vp9_registry.h"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/gfx/common/mediacodec_av1_registry.h"\n' "$PWD" >> "$unity"
|
||||
printf '#ifndef MEDIACODEC_HEVC_REGISTRY\n#error registry atomics unavailable\n#endif\n' >> "$unity"
|
||||
for source in "${sources[@]}"; do
|
||||
printf '#include "%s/gfx/common/%s.c"\n' "$PWD" "$source" >> "$unity"
|
||||
done
|
||||
printf '#include "%s/record/record_mediacodec_encoder.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_mux_mediacodec.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_mediacodec_worker.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_mediacodec_surface.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_audio_tap.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/drivers/record_mediacodec.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_images.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_submit.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_pipe.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_config.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_request.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_device.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_pool.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_ops.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_egl.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_gl.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_android_capture_draw.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_mediacodec_gpu_worker.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_mediacodec_file.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_session_mediacodec.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_dispatch_mediacodec.c"\n' "$PWD" >> "$unity"
|
||||
printf '#include "%s/record/record_gpu_dispatch_mediacodec.c"\n' "$PWD" >> "$unity"
|
||||
for target in aarch64-linux-android armv7a-linux-androideabi; do
|
||||
for api in 21 29; do
|
||||
for offset in default 64; do
|
||||
extra=()
|
||||
if [ "$offset" = 64 ]; then extra=(-D_FILE_OFFSET_BITS=64); fi
|
||||
for source in "${sources[@]}"; do
|
||||
object="$RUNNER_TEMP/$source-$target-$api-$offset.o"
|
||||
"$bin/$target$api-clang" \
|
||||
-std=c89 -pedantic -Wall -Wextra -Werror -Wno-long-long -Wno-c99-extensions \
|
||||
-DHAVE_THREADS -DHAVE_DYLIB -Wframe-larger-than=2048 -Ilibretro-common/include -Igfx/include \
|
||||
"${extra[@]}" -c "gfx/common/$source.c" -o "$object"
|
||||
if "$bin/llvm-nm" -u "$object" | grep -Eq ' U (AMedia|AImage|AHardwareBuffer|ANativeWindow_setFrameRateWithChangeStrategy)'; then
|
||||
echo "Unexpected direct media API dependency: $object"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
for record_source in record_audio_tap record_mediacodec_encoder record_mux_mediacodec record_mediacodec_worker record_mediacodec_surface record_android_capture_images record_android_capture_submit record_android_capture_pipe record_android_capture_pool record_android_capture_device record_android_capture_request record_android_capture_config record_android_capture_gl record_android_capture_draw record_mediacodec_gpu_worker record_mediacodec_file record_session_mediacodec record_dispatch_mediacodec record_gpu_dispatch_mediacodec record_gpu_queue record_audio_queue; do
|
||||
"$bin/$target$api-clang" \
|
||||
-std=c89 -pedantic -Wall -Wextra -Werror -Wno-long-long -Wno-c99-extensions \
|
||||
-DHAVE_THREADS -DHAVE_DYLIB -Wframe-larger-than=2048 -Ilibretro-common/include -Igfx/include \
|
||||
"${extra[@]}" -c "record/$record_source.c" \
|
||||
-o "$RUNNER_TEMP/$record_source-$target-$api-$offset.o"
|
||||
done
|
||||
"$bin/$target$api-clang" \
|
||||
-std=c89 -pedantic -Wall -Wextra -Werror -Wno-long-long -Wno-c99-extensions \
|
||||
-DANDROID -DHAVE_VULKAN -DHAVE_RECORD_MEDIACODEC -DHAVE_CONFIGFILE \
|
||||
-DHAVE_THREADS -DHAVE_DYLIB -Wframe-larger-than=2048 -Ilibretro-common/include -Igfx/include \
|
||||
"${extra[@]}" -c "$unity" -o "$RUNNER_TEMP/unity-$target-$api-$offset.o"
|
||||
"$bin/$target$api-clang" \
|
||||
-std=c89 -pedantic -Wall -Wextra -Werror -Wno-long-long -Wno-c99-extensions \
|
||||
-DANDROID -DHAVE_VULKAN -DHAVE_RECORD_MEDIACODEC -DHAVE_CONFIGFILE \
|
||||
-DHAVE_WEBMPLAYER -DHAVE_THREADS -DHAVE_DYLIB -Wframe-larger-than=2048 \
|
||||
-Ilibretro-common/include -Igfx/include "${extra[@]}" \
|
||||
-c record/drivers/record_mediacodec.c \
|
||||
-o "$RUNNER_TEMP/record-history-$target-$api-$offset.o"
|
||||
for root_source in gfx/common/vulkan_common.c gfx/drivers/vulkan.c gfx/gfx_surface_player.c libretro-common/jni/rjni.c; do
|
||||
"$bin/$target$api-clang" \
|
||||
-DANDROID -DHAVE_MENU -DHAVE_GFX_WIDGETS \
|
||||
-DHAVE_VULKAN -DHAVE_RMP4 -DHAVE_RVP9 -DHAVE_RAV1 -DHAVE_DYLIB -DHAVE_THREADS \
|
||||
-Dinline=__inline__ -O1 -std=c89 \
|
||||
-Werror=declaration-after-statement -Werror=frame-larger-than -Wframe-larger-than=4096 \
|
||||
-I. -Ilibretro-common/include -Igfx/include "${extra[@]}" \
|
||||
-c "$root_source" -o "$RUNNER_TEMP/$(basename "$root_source")-$target-$api-$offset.o"
|
||||
done
|
||||
for variant in vp9-only av1-only no-codecs recording-only; do
|
||||
codec_flags=()
|
||||
case "$variant" in
|
||||
vp9-only) codec_flags=(-DHAVE_RVP9 -DHAVE_THREADS) ;;
|
||||
av1-only) codec_flags=(-DHAVE_RAV1 -DHAVE_THREADS) ;;
|
||||
no-codecs) codec_flags=(-DHAVE_THREADS) ;;
|
||||
recording-only) codec_flags=(-DHAVE_THREADS -DHAVE_CONFIGFILE -DHAVE_RECORD_MEDIACODEC) ;;
|
||||
esac
|
||||
for root_source in gfx/common/vulkan_common.c gfx/drivers/vulkan.c; do
|
||||
"$bin/$target$api-clang" \
|
||||
-DANDROID -DHAVE_MENU -DHAVE_GFX_WIDGETS \
|
||||
-DHAVE_VULKAN -DHAVE_DYLIB "${codec_flags[@]}" \
|
||||
-Dinline=__inline__ -O1 -std=c89 \
|
||||
-Werror=declaration-after-statement -Werror=frame-larger-than -Wframe-larger-than=4096 \
|
||||
-I. -Ilibretro-common/include -Igfx/include "${extra[@]}" \
|
||||
-c "$root_source" -o "$RUNNER_TEMP/$variant-$(basename "$root_source")-$target-$api-$offset.o"
|
||||
done
|
||||
done
|
||||
for player_source in libretro-common/formats/video_player.c libretro-common/formats/image_transfer.c libretro-common/formats/webm/rwebm_video.c libretro-common/formats/mp4/rmp4_video.c; do
|
||||
"$bin/$target$api-clang" \
|
||||
-DHAVE_RMP4 -DHAVE_RWEBM -DHAVE_RVP9 -DHAVE_RAV1 -DHAVE_THREADS \
|
||||
-Dinline=__inline__ -O1 -std=c89 -Wno-long-long -Wno-c99-extensions \
|
||||
-Werror=declaration-after-statement -Werror=frame-larger-than -Wframe-larger-than=2048 \
|
||||
-I. -Ilibretro-common/include "${extra[@]}" \
|
||||
-c "$player_source" -o "$RUNNER_TEMP/$(basename "$player_source")-$target-$api-$offset.o"
|
||||
done
|
||||
for parser_source in libretro-common/formats/h265/rh265.c libretro-common/formats/vp9/rvp9.c libretro-common/formats/av1/rav1_hw.c libretro-common/queues/retro_spsc.c; do
|
||||
"$bin/$target$api-clang" \
|
||||
-DHAVE_THREADS -O2 -std=c89 -pedantic -Wall -Wextra -Werror \
|
||||
-Wno-unused-parameter -Wno-long-long -Wno-c99-extensions -Wframe-larger-than=2048 -fstack-usage \
|
||||
-Ilibretro-common/include "${extra[@]}" -c "$parser_source" \
|
||||
-o "$RUNNER_TEMP/$(basename "$parser_source")-$target-$api-$offset.o"
|
||||
done
|
||||
"$bin/$target$api-clang" \
|
||||
-O2 -std=c89 -pedantic -Wall -Wextra -Werror \
|
||||
-Wno-unused-parameter -Wno-long-long -Wno-c99-extensions -Wframe-larger-than=2048 -fstack-usage \
|
||||
-Ilibretro-common/include "${extra[@]}" -c libretro-common/formats/vp9/rvp9.c \
|
||||
-o "$RUNNER_TEMP/threadless-rvp9.c-$target-$api-$offset.o"
|
||||
# Link AV1-only roots with exactly their selected native sources.
|
||||
av1_objects=()
|
||||
for source in mediacodec_inventory android_image_queue android_image_ndk android_frame mediacodec_session mediacodec_color mediacodec_frame_export mediacodec_av1_decoder mediacodec_av1_backend vulkan_android_image vulkan_android_sync vulkan_android_pipeline vulkan_android_submit vulkan_android_queue vulkan_android_cache_entry vulkan_android_cache vulkan_android_device; do
|
||||
av1_objects+=("$RUNNER_TEMP/$source-$target-$api-$offset.o")
|
||||
done
|
||||
"$bin/ld.lld" -r "${av1_objects[@]}" \
|
||||
"$RUNNER_TEMP/av1-only-vulkan_common.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/av1-only-vulkan.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/rjni.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/rav1_hw.c-$target-$api-$offset.o" \
|
||||
-o "$RUNNER_TEMP/av1-only-root-$target-$api-$offset.o"
|
||||
if "$bin/llvm-nm" -u "$RUNNER_TEMP/av1-only-root-$target-$api-$offset.o" | \
|
||||
grep -Eq ' U (rav1_|rvp9_|rh265_|rjni_env$|mediacodec_|android_frame_|android_image_|vulkan_android_)'; then
|
||||
echo "Unresolved private helper in AV1-only Android root"
|
||||
exit 1
|
||||
fi
|
||||
for variant in no-codecs; do
|
||||
if "$bin/llvm-nm" -u "$RUNNER_TEMP/$variant-vulkan.c-$target-$api-$offset.o" | \
|
||||
grep -Eq ' U (mediacodec_|rav1_(set|unset)_hw_backend)'; then
|
||||
echo "Unexpected native decoder dependency: $variant"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
"$bin/ld.lld" -r \
|
||||
"$RUNNER_TEMP/unity-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/vulkan_common.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/vulkan.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/gfx_surface_player.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/rjni.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/video_player.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/image_transfer.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/rwebm_video.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/rmp4_video.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/rh265.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/rvp9.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/rav1_hw.c-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/record_audio_queue-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/record_gpu_queue-$target-$api-$offset.o" \
|
||||
"$RUNNER_TEMP/retro_spsc.c-$target-$api-$offset.o" \
|
||||
-o "$RUNNER_TEMP/media-root-$target-$api-$offset.o"
|
||||
if "$bin/llvm-nm" -u "$RUNNER_TEMP/media-root-$target-$api-$offset.o" | \
|
||||
grep -Eq ' U (record_android_capture_|record_mediacodec_|record_session_mediacodec_|record_dispatch_mediacodec_|record_gpu_dispatch_mediacodec_|record_mux_mediacodec_|record_audio_tap_|record_audio_queue_|record_gpu_queue_|retro_spsc_|rav1_|rvp9_|rjni_env$|mediacodec_|android_frame_|android_image_|vulkan_android_|video_player_(request_software|set_hw_fallback)|image_transfer_anim_stream_stop_hw|rwebm_video_stream_stop_hw)'; then
|
||||
echo "Unresolved private Android media helper in root link"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -1,152 +0,0 @@
|
||||
name: CI Apple
|
||||
|
||||
# Umbrella workflow for Apple-specific checks that are not a plain
|
||||
# "does it build" - the full builds live in MacOS.yml and iOS.yml.
|
||||
#
|
||||
# Add new jobs here rather than as new top-level workflows: things like
|
||||
# build-graph integrity checks, xcconfig assertions, extra Apple
|
||||
# targets, and anything else that is Apple-shaped but does not warrant
|
||||
# its own entry in the Actions sidebar. Each job carries its own
|
||||
# rationale in a comment above it.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
# ------------------------------------------------------------------
|
||||
# Build-graph guard: the Bonjour/mDNS netplay discovery path.
|
||||
#
|
||||
# network/netplay/netplay_nsnetservice.m is a member of no target.
|
||||
# It reaches the compiler only through griffin/griffin_objc.m, behind
|
||||
#
|
||||
# #if defined(HAVE_NETWORKING) && defined(HAVE_NETPLAYDISCOVERY) \
|
||||
# && defined(HAVE_NETPLAYDISCOVERY_NSNET)
|
||||
#
|
||||
# and those macros arrive from pkg/apple/BaseConfig.xcconfig by way
|
||||
# of an $(inherited) chain: the CI builds pass
|
||||
# -xcconfig GitHubCI.xcconfig on the command line, which includes
|
||||
# Metal.xcconfig, whose OTHER_CFLAGS[sdk=macosx*] assignment relies
|
||||
# on $(inherited) to pull the project-level BaseConfig settings back
|
||||
# in. Metal.xcconfig defines none of the three macros itself.
|
||||
#
|
||||
# Every link in that chain can be broken without breaking the build.
|
||||
# Drop the file from griffin's include list, drop griffin_objc.m from
|
||||
# a Sources phase, drop $(inherited) from Metal.xcconfig, or move the
|
||||
# -D out of BaseConfig, and the file simply stops being compiled - CI
|
||||
# stays green while an entire Apple-only source file goes unbuilt.
|
||||
# That is not hypothetical: the file parses a remote peer's mDNS TXT
|
||||
# records into fixed-size buffers, so it is exactly the sort of thing
|
||||
# that should not be able to rot unnoticed.
|
||||
#
|
||||
# This asserts the preconditions rather than duplicating the build.
|
||||
# The existing "CI macOS" and "CI iOS (13)" jobs already compile the
|
||||
# file; what they cannot tell you is whether they still are.
|
||||
# ------------------------------------------------------------------
|
||||
netplay-discovery-guard:
|
||||
name: Build graph - netplay mDNS discovery
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
# Source-level checks. These need no toolchain and give a precise
|
||||
# message when the wiring, rather than the code, is what broke.
|
||||
- name: griffin still imports the file
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if ! grep -q 'netplay_nsnetservice\.m' griffin/griffin_objc.m; then
|
||||
echo "::error file=griffin/griffin_objc.m::netplay_nsnetservice.m is no longer imported; it is a member of no target, so nothing else compiles it"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: griffin_objc.m is still in both Sources build phases
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rc=0
|
||||
for proj in RetroArch_Metal RetroArch_iOS13; do
|
||||
pbx="pkg/apple/$proj.xcodeproj/project.pbxproj"
|
||||
n=$(awk '/Begin PBXSourcesBuildPhase/,/End PBXSourcesBuildPhase/' "$pbx" \
|
||||
| grep -c 'griffin_objc\.m in Sources' || true)
|
||||
echo "$proj: griffin_objc.m appears in Sources x$n"
|
||||
if [ "$n" -eq 0 ]; then
|
||||
echo "::error file=$pbx::griffin_objc.m is not in any Sources build phase"
|
||||
rc=1
|
||||
fi
|
||||
done
|
||||
exit $rc
|
||||
|
||||
- name: The three guard macros survive the xcconfig chain
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rc=0
|
||||
|
||||
check() {
|
||||
# $1 = human label, remaining args = xcodebuild selector
|
||||
label="$1"; shift
|
||||
echo "--- $label ---"
|
||||
settings=$(xcodebuild -showBuildSettings "$@" \
|
||||
-xcconfig pkg/apple/GitHubCI.xcconfig 2>/dev/null \
|
||||
| grep -E '^\s*OTHER_CFLAGS =' || true)
|
||||
if [ -z "$settings" ]; then
|
||||
echo "::error::could not resolve OTHER_CFLAGS for $label"
|
||||
rc=1
|
||||
return
|
||||
fi
|
||||
echo "$settings" | tr ' ' '\n' | grep -E '^-DHAVE_NETPLAY|^-DHAVE_NETWORKING' || true
|
||||
for macro in HAVE_NETWORKING HAVE_NETPLAYDISCOVERY HAVE_NETPLAYDISCOVERY_NSNET; do
|
||||
if ! echo "$settings" | grep -qE -- "-D$macro([[:space:]]|=|$)"; then
|
||||
echo "::error::$label does not define $macro - netplay_nsnetservice.m is NOT being compiled"
|
||||
rc=1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check "macOS (scheme RetroArch)" \
|
||||
-workspace pkg/apple/RetroArch.xcworkspace \
|
||||
-scheme RetroArch -config Release
|
||||
|
||||
check "iOS (scheme RetroArch iOS Release)" \
|
||||
-workspace pkg/apple/RetroArch.xcworkspace \
|
||||
-destination generic/platform=iOS \
|
||||
-scheme "RetroArch iOS Release" -config Release
|
||||
|
||||
exit $rc
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# tvOS. The one Apple target with no build job of its own, so a break
|
||||
# in code it shares with iOS - netplay_nsnetservice.m included - ships
|
||||
# unnoticed there. Not gating: unrelated problems in the tvOS scheme
|
||||
# should not hold up the tree.
|
||||
# ------------------------------------------------------------------
|
||||
tvos:
|
||||
name: tvOS build (non-gating)
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Compile RA (tvOS)
|
||||
run: |
|
||||
set -o pipefail
|
||||
xcodebuild -workspace pkg/apple/RetroArch.xcworkspace \
|
||||
-destination generic/platform=tvOS -config Release \
|
||||
-scheme "RetroArch tvOS Release" \
|
||||
-xcconfig pkg/apple/GitHubCI.xcconfig \
|
||||
CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO \
|
||||
CODE_SIGN_IDENTITY="" PROVISIONING_PROFILE_SPECIFIER="" \
|
||||
-derivedDataPath build
|
||||
@@ -1,61 +0,0 @@
|
||||
name: Deferred auto-state regression
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'runloop.c'
|
||||
- 'runloop.h'
|
||||
- 'runahead.c'
|
||||
- 'command.c'
|
||||
- 'samples/runloop/auto_state_load/**'
|
||||
- '.github/workflows/Auto-state-load.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'runloop.c'
|
||||
- 'runloop.h'
|
||||
- 'runahead.c'
|
||||
- 'command.c'
|
||||
- 'samples/runloop/auto_state_load/**'
|
||||
- '.github/workflows/Auto-state-load.yml'
|
||||
jobs:
|
||||
regression:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: gcc-mingw-w64-x86-64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
- name: Linux and sanitizer tests
|
||||
working-directory: samples/runloop/auto_state_load
|
||||
run: |
|
||||
make check
|
||||
make clean
|
||||
make check EXTRA_CFLAGS='-DHAVE_NETWORKING -DHAVE_CHEEVOS' SANITIZER=address,undefined
|
||||
- name: Windows cross-build
|
||||
working-directory: samples/runloop/auto_state_load
|
||||
run: |
|
||||
make clean
|
||||
make CC=x86_64-w64-mingw32-gcc TARGET=auto_state_load_test.exe EXTRA_CFLAGS='-DHAVE_NETWORKING -DHAVE_CHEEVOS'
|
||||
@@ -1,84 +0,0 @@
|
||||
name: CI local workflow runner
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
ci-local-selftest:
|
||||
name: tools/ci_local.py reads and runs every workflow
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: python3-yaml
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Every workflow parses exactly as PyYAML reads it, every job and
|
||||
# matrix combination resolves in a dry run, and a fixture job runs
|
||||
# with GitHub's step semantics.
|
||||
python3 tools/ci_local.py selftest
|
||||
|
||||
- name: Every runner job installs through apt-install.sh
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# A bare apt-get waits on a stalled mirror until the job is
|
||||
# cancelled, and fetches every package again each run.
|
||||
python3 tools/ci_apt_check.py --selftest
|
||||
python3 tools/ci_apt_check.py
|
||||
|
||||
- name: compile_commands.py self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
python3 tools/compile_commands.py --selftest
|
||||
|
||||
- name: A checker workflow, run through the runner
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
python3 tools/ci_local.py run Extern-C-Prototype-Check
|
||||
@@ -1,53 +0,0 @@
|
||||
name: CI Compile Matrix [Codec Combinations]
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
compile-matrix: # every codec combination real builds select, not just this one
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential libgl-dev libegl-dev libgles-dev libsdl1.2-dev gcc-mingw-w64-x86-64 clang gcc-aarch64-linux-gnu gcc-mipsel-linux-gnu libdrm-dev
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
- name: Compile matrix
|
||||
run: ./.github/workflows/scripts/compile-matrix.sh
|
||||
@@ -1,209 +0,0 @@
|
||||
name: CI cross-libc libretro-common/vfs samples
|
||||
|
||||
# libretro-common/samples runs on ubuntu-latest only, which means
|
||||
# every VFS test in the tree is validated against exactly one C
|
||||
# library. That is the wrong number for this code: file_stream.c and
|
||||
# vfs_implementation.c sit directly on top of stdio and the file
|
||||
# descriptor API, and the libraries disagree about both.
|
||||
#
|
||||
# glibc fread() reads straight into the caller's buffer once
|
||||
# the request reaches the block size, whoever owns the
|
||||
# buffer (libio/fileops.c, _IO_file_xsgetn).
|
||||
# Apple libc the same bypass exists but is skipped when setvbuf()
|
||||
# supplied the buffer - '__SMBF' is then clear - which is
|
||||
# exactly what retro_vfs_file_open_impl() does
|
||||
# (Libc/stdio/FreeBSD/fread.c, radar 5980080 / 6180417).
|
||||
# UCRT not open source; behaviour is inferred and therefore
|
||||
# worth measuring rather than assuming.
|
||||
# msvcrt the older runtime MINGW64 links against, again
|
||||
# different code from UCRT.
|
||||
#
|
||||
# The tests here assert behaviour, not performance, so a difference in
|
||||
# any of the above shows up as a failure rather than a slowdown. The
|
||||
# Windows entries matter most for the descriptor path, which opens
|
||||
# with open()/_wopen() instead of fopen(mode "rb") and so depends on
|
||||
# O_BINARY being in the flags; vfs_bulk_read_test's binary
|
||||
# transparency case is the one that catches its absence.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'libretro-common/streams/file_stream.c'
|
||||
- 'libretro-common/vfs/**'
|
||||
- 'libretro-common/include/vfs/**'
|
||||
- 'libretro-common/include/streams/file_stream.h'
|
||||
- 'libretro-common/samples/file/vfs/**'
|
||||
- 'libretro-common/fastjmp/**'
|
||||
- 'libretro-common/include/fastjmp.h'
|
||||
- 'libretro-common/samples/fastjmp/**'
|
||||
- '.github/workflows/Cross-libc-vfs-samples.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'libretro-common/streams/file_stream.c'
|
||||
- 'libretro-common/vfs/**'
|
||||
- 'libretro-common/include/vfs/**'
|
||||
- 'libretro-common/include/streams/file_stream.h'
|
||||
- 'libretro-common/samples/file/vfs/**'
|
||||
- 'libretro-common/fastjmp/**'
|
||||
- 'libretro-common/include/fastjmp.h'
|
||||
- 'libretro-common/samples/fastjmp/**'
|
||||
- '.github/workflows/Cross-libc-vfs-samples.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
# glibc and Apple libc. Both take the descriptor path, since
|
||||
# VFS_HAVE_FILE_MAPPING covers anything with mmap.
|
||||
unix:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 15
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: glibc (ubuntu-latest)
|
||||
runner: ubuntu-latest
|
||||
# LeakSanitizer exists here, so run it at full strictness.
|
||||
asan_opts: detect_leaks=1
|
||||
- name: Apple libc (macos-latest)
|
||||
runner: macos-latest
|
||||
# LeakSanitizer is not implemented on Darwin, and asking
|
||||
# for it is fatal rather than ignored: the runtime prints
|
||||
# "detect_leaks is not supported on this platform" and
|
||||
# aborts. Leak coverage for these sources comes from the
|
||||
# Linux leg above; this one is here for Apple's libc
|
||||
# behaviour, which is what differs.
|
||||
asan_opts: detect_leaks=0
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Build and run
|
||||
shell: bash
|
||||
working-directory: libretro-common/samples/file/vfs
|
||||
run: |
|
||||
set -euo pipefail
|
||||
run_cfg() {
|
||||
echo "==> $*"
|
||||
make clean >/dev/null
|
||||
make "$@" SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=${{ matrix.asan_opts }} ./vfs_bulk_read_test
|
||||
./vfs_seek_contract_test
|
||||
./vfs_mapped_ptr_test
|
||||
./vfs_v5_metadata_test
|
||||
}
|
||||
# Mapping on (what the platform actually ships), mapping off
|
||||
# with the descriptor path forced (what the consoles have),
|
||||
# and neither (a target on no list, which must keep its
|
||||
# buffered behaviour).
|
||||
run_cfg MMAP=1
|
||||
run_cfg MMAP=0 DESCRIPTOR_IO=1
|
||||
run_cfg MMAP=0
|
||||
|
||||
- name: Thread sanitizer
|
||||
# Not on macOS: TSan there reports on system libraries the
|
||||
# runner image ships, which is noise this job cannot fix.
|
||||
if: matrix.runner == 'ubuntu-latest'
|
||||
shell: bash
|
||||
working-directory: libretro-common/samples/file/vfs
|
||||
run: |
|
||||
set -euo pipefail
|
||||
make clean >/dev/null
|
||||
make SANITIZER=thread
|
||||
./vfs_bulk_read_test
|
||||
|
||||
# UCRT and msvcrt, through MSYS2. Same C runtimes an MSVC-built
|
||||
# RetroArch links against, so the runtime behaviour these tests
|
||||
# check is the behaviour that ships; the MSVC job covers the
|
||||
# compiler.
|
||||
windows:
|
||||
name: ${{ matrix.sys }} (windows-latest)
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
sys: [UCRT64, MINGW64]
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
# The system upgrade runs in the action: an msys2-runtime update
|
||||
# kills every MSYS2 process, which a run step's own shell would
|
||||
# not survive.
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.sys }}
|
||||
update: true
|
||||
|
||||
- name: Install packages
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
# A mirror that stalls or rate-limits (HTTP 429) fails pacman's
|
||||
# whole transaction; what it fetched stays in the cache, so a
|
||||
# retry fetches only the rest, one file at a time after a
|
||||
# growing wait so a shared runner's rate limit can clear.
|
||||
# pacman waits out a slow mirror instead of aborting;
|
||||
# timeout-minutes bounds a hang.
|
||||
p=$MINGW_PACKAGE_PREFIX
|
||||
pkgs="base-devel $p-toolchain"
|
||||
for i in 1 2 3 4 5; do
|
||||
pacman -S --noconfirm --needed --disable-download-timeout $pkgs &&
|
||||
exit 0
|
||||
[ $i = 5 ] && break
|
||||
echo "package install failed (attempt $i); retrying in $((30 * i))s, serial downloads"
|
||||
sed -i -e '/^#*ParallelDownloads/d' -e '/^\[options\]/a ParallelDownloads = 1' /etc/pacman.conf
|
||||
sleep $((30 * i))
|
||||
done
|
||||
exit 1
|
||||
|
||||
- name: Build and run
|
||||
working-directory: libretro-common/samples/file/vfs
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# No sanitizers here: the MSYS2 toolchains do not ship a
|
||||
# usable ASan runtime for this target, and the point of this
|
||||
# job is which C runtime the calls land on, not memory
|
||||
# safety - the Linux job covers that with the same sources.
|
||||
#
|
||||
# MMAP=0 is required, not cosmetic: -DHAVE_MMAP pulls in
|
||||
# <sys/mman.h>, which does not exist here. The Win32
|
||||
# file-mapping backend is selected by _WIN32 inside vfs.h
|
||||
# rather than by that flag, so VFS_HAVE_FILE_MAPPING - and
|
||||
# with it descriptor I/O and the mapped-pointer path - is on
|
||||
# regardless.
|
||||
make clean MMAP=0
|
||||
make MMAP=0
|
||||
./vfs_bulk_read_test.exe
|
||||
./vfs_seek_contract_test.exe
|
||||
# Win32 branches of the v5 metadata ops: attributes,
|
||||
# SetFileTime, CopyFileW, find-data dirent_stat.
|
||||
./vfs_v5_metadata_test.exe
|
||||
# Exercises the Win32 CreateFileMapping/MapViewOfFile
|
||||
# backend, which no other job in the tree reaches.
|
||||
./vfs_mapped_ptr_test.exe
|
||||
|
||||
# The Win64 fastjmp_set stores xmm6-xmm15 with movaps and faults
|
||||
# on a misaligned buffer. Linux has no such stores, so the Linux
|
||||
# samples job cannot see a fastjmp_buf that lost its alignment;
|
||||
# this is the only lane that can. Under a second to build and run.
|
||||
- name: fastjmp on Win64
|
||||
working-directory: libretro-common/samples/fastjmp/fastjmp_test
|
||||
run: |
|
||||
set -euo pipefail
|
||||
make clean
|
||||
make
|
||||
./fastjmp_test.exe
|
||||
@@ -1,49 +0,0 @@
|
||||
name: CI Context presentable() contract
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
ctx-presentable-check:
|
||||
name: gfx_ctx_driver_t presentable() consistency
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Checker self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Fixture pass: a correct driver is clean, a presentable()
|
||||
# casting another driver's context type is flagged, and one
|
||||
# that is defined but never wired into the vtable is flagged.
|
||||
tools/check.sh tools/ctx_presentable_check.c --selftest
|
||||
|
||||
- name: Tree check
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Each context driver is compiled by one platform's CI, so a
|
||||
# presentable() that casts the wrong driver's type, or that is
|
||||
# never wired in, is invisible to every other job. This is the
|
||||
# check that sees all of them at once.
|
||||
tools/check.sh tools/ctx_presentable_check.c
|
||||
@@ -1,86 +0,0 @@
|
||||
name: CI DOS/DJGPP
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-djgpp-build-container:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Set up ccache
|
||||
run: |
|
||||
# Best effort: without ccache, ccache-make.sh runs plain make.
|
||||
command -v ccache > /dev/null || {
|
||||
s=$(command -v sudo || true)
|
||||
for i in 1 2 3; do
|
||||
$s timeout 90 apt-get -yq update \
|
||||
-o Acquire::Retries=3 -o Acquire::http::Timeout=30 &&
|
||||
$s timeout 120 apt-get -yq install --no-install-recommends \
|
||||
ccache > /dev/null && break
|
||||
echo "installing ccache failed (attempt $i); retrying in 10s"
|
||||
sleep 10
|
||||
done
|
||||
}
|
||||
echo "CCACHE_DIR=$GITHUB_WORKSPACE/.ccache" >> "$GITHUB_ENV"
|
||||
echo "CCACHE_MAXSIZE=250M" >> "$GITHUB_ENV"
|
||||
if command -v ccache > /dev/null; then
|
||||
CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" ccache -z
|
||||
fi
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.dos -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
bash .github/workflows/scripts/ccache-make.sh -f Makefile.dos -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 info all
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv || ccache -s
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: RA-DOS-dummy-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
retrodos.exe
|
||||
@@ -1,34 +0,0 @@
|
||||
name: CI Emscripten
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-emscripten:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@v1
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
emmake make -f Makefile.emscripten -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
emmake make -f Makefile.emscripten -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1
|
||||
@@ -1,51 +0,0 @@
|
||||
name: CI extern "C" prototype parity
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
extern-c-prototype-check:
|
||||
name: extern "C" definitions match their C prototypes
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Checker self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Fixture pass: a matching definition is clean, a definition
|
||||
# with a parameter more than its prototype (the shape of the
|
||||
# 0b2613d Xbox boot crash) is flagged, and a parameter of
|
||||
# another type is flagged.
|
||||
tools/check.sh tools/extern_c_prototype_check.c --selftest
|
||||
|
||||
- name: Tree check
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# A .cpp file that defines a win32_common.h function under
|
||||
# extern "C" without including the header (uwp_main.cpp) is
|
||||
# never checked against the prototype by any compiler: the
|
||||
# linker matches on the name alone. This is the check that
|
||||
# compares the two, for every such definition in the tree.
|
||||
tools/check.sh tools/extern_c_prototype_check.c
|
||||
@@ -1,94 +0,0 @@
|
||||
name: CI FreeBSD
|
||||
|
||||
# Builds RetroArch inside a FreeBSD VM (GitHub has no FreeBSD runners)
|
||||
# with the same feature set the games/retroarch port enables by default,
|
||||
# minus Qt (very slow to install). This is what kept the port carrying
|
||||
# patches on top of each release: libudev is FreeBSD's libudev-devd, the
|
||||
# input headers come from dev/evdev/, and there is no linux_common.o to
|
||||
# link against.
|
||||
#
|
||||
# Deliberately NOT installed: evdev-proto and v4l_compat (the Linux
|
||||
# compatibility headers). A stock FreeBSD box must build udev + Wayland
|
||||
# from the dev/evdev/ headers in base, and configure must turn V4L2 off
|
||||
# on its own when libv4l is present but linux/videodev2.h is not.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 90
|
||||
|
||||
steps:
|
||||
- name: Check Out Repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Build in FreeBSD
|
||||
uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
release: "14.3"
|
||||
usesh: true
|
||||
copyback: false
|
||||
prepare: |
|
||||
pkg install -y \
|
||||
gmake pkgconf \
|
||||
ffmpeg freetype2 openal-soft mesa-libs \
|
||||
libudev-devd libxkbcommon wayland wayland-protocols \
|
||||
libX11 libXext libXxf86vm libXinerama libXrandr libXv \
|
||||
sdl2 pipewire alsa-lib pulseaudio libdrm libv4l
|
||||
run: |
|
||||
set -e
|
||||
freebsd-version
|
||||
NCPU=$(sysctl -n hw.ncpu)
|
||||
|
||||
# --disable-pipewire must not leave HAVE_PIPEWIRE_STABLE
|
||||
# behind just because libpipewire is installed.
|
||||
./configure --disable-qt --disable-discord --disable-pipewire
|
||||
grep -q '^HAVE_PIPEWIRE_STABLE = 0' config.mk
|
||||
# libv4l2.pc is installed but linux/videodev2.h is not
|
||||
# (v4l_compat): V4L2 must be auto-disabled, not left on to
|
||||
# fail at compile time.
|
||||
grep -q '^HAVE_V4L2 = 0' config.mk
|
||||
|
||||
# Real build: force the FreeBSD-specific paths on so a missing
|
||||
# dependency fails configure instead of silently skipping them.
|
||||
./configure --disable-qt --disable-discord \
|
||||
--enable-udev --enable-x11 --enable-wayland --enable-sdl2 \
|
||||
--enable-ffmpeg --enable-pipewire --enable-alsa \
|
||||
--enable-pulse --enable-oss
|
||||
gmake -j$NCPU clean
|
||||
gmake -j$NCPU info all
|
||||
./retroarch --version
|
||||
# udev input must multiplex with kqueue here, so the binary
|
||||
# must not need libepoll-shim's epoll_* at all.
|
||||
if nm -u retroarch | grep -q 'epoll_'; then
|
||||
echo "retroarch still references epoll (libepoll-shim)"; exit 1
|
||||
fi
|
||||
|
||||
# A fresh RetroArch must pick up data sets the ports install
|
||||
# under /usr/local/share/libretro (assets, info, shaders,
|
||||
# autoconfig) without any retroarch.cfg edits.
|
||||
sh samples/frontend/packaged_dirs/run.sh
|
||||
|
||||
# With v4l_compat the V4L2 camera and video processor core
|
||||
# must still compile; only those two objects are rebuilt.
|
||||
pkg install -y v4l_compat
|
||||
./configure --disable-qt --disable-discord --enable-v4l2
|
||||
grep -q '^HAVE_V4L2 = 1' config.mk
|
||||
gmake -j$NCPU camera/drivers/video4linux2.o \
|
||||
cores/libretro-video-processor/video_processor_v4l2.o
|
||||
@@ -1,77 +0,0 @@
|
||||
name: CI GameCube
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: devkitpro/devkitppc:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@v1
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Set up ccache
|
||||
run: |
|
||||
# Best effort: without ccache, ccache-make.sh runs plain make.
|
||||
command -v ccache > /dev/null || {
|
||||
s=$(command -v sudo || true)
|
||||
for i in 1 2 3; do
|
||||
$s timeout 90 apt-get -yq update \
|
||||
-o Acquire::Retries=3 -o Acquire::http::Timeout=30 &&
|
||||
$s timeout 120 apt-get -yq install --no-install-recommends \
|
||||
ccache > /dev/null && break
|
||||
echo "installing ccache failed (attempt $i); retrying in 10s"
|
||||
sleep 10
|
||||
done
|
||||
}
|
||||
echo "CCACHE_DIR=$GITHUB_WORKSPACE/.ccache" >> "$GITHUB_ENV"
|
||||
echo "CCACHE_MAXSIZE=250M" >> "$GITHUB_ENV"
|
||||
if command -v ccache > /dev/null; then
|
||||
CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" ccache -z
|
||||
fi
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.ngc -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
bash .github/workflows/scripts/ccache-make.sh -f Makefile.ngc -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 info all
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv || ccache -s
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
name: CI Linux Headless [No Menu] (i686)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
linux-nomenu: # Smoketest build with no menu support compiled in
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential libxkbcommon-dev libx11-xcb-dev zlib1g-dev libfreetype6-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev nvidia-cg-toolkit nvidia-cg-dev libavcodec-dev libsdl2-dev libsdl-image1.2-dev libxml2-dev yasm ccache
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Configure
|
||||
run: ./configure --disable-menu
|
||||
- name: Build
|
||||
run: make
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,477 +0,0 @@
|
||||
name: CI Linux ASan + UBSan [No Menu]
|
||||
|
||||
# Builds full RetroArch with -fsanitize=address,undefined and runs
|
||||
# headless smoke invocations. Three coverage tiers, in increasing
|
||||
# order of how much of the binary they actually instrument:
|
||||
#
|
||||
# 1. --help and --features. Exit(0) directly after printing.
|
||||
# Coverage scope: libc init, main(), frontend driver bootstrap,
|
||||
# argv duplication, the getopt walk, and the print functions.
|
||||
# Strict ASan + UBSan -- baseline confirmed clean (run #1).
|
||||
#
|
||||
# 2. Headless imageviewer core under Xvfb + sdl2 video driver +
|
||||
# null audio driver, --max-frames=300 for a clean shutdown
|
||||
# through the normal runloop teardown. Exercises core loading
|
||||
# via dlopen, the imageviewer's stb_image-driven loader, the
|
||||
# SDL2 + X11 + MIT-SHM rendering pipeline, the runloop, and
|
||||
# cleanup-on-shutdown. Soft-fail (continue-on-error) on this
|
||||
# first iteration: lots can go wrong (libGL leaks, driver
|
||||
# init noise) that aren't RetroArch bugs but would fail the
|
||||
# run if treated strictly. Sanitizer findings are still
|
||||
# surfaced in step output for triage.
|
||||
#
|
||||
# The per-sample tests under .github/workflows/Linux-samples-gfx.yml,
|
||||
# Linux-samples-tasks.yml, Linux-samples-audio.yml,
|
||||
# Linux-samples-network.yml, Linux-samples-settings.yml, and
|
||||
# Linux-libretro-{db,common}-samples.yml regression-test specific
|
||||
# predicates that previously had bugs. This
|
||||
# job is complementary -- it covers everything those harnesses can't
|
||||
# reach because the code only runs from main(), and catches future
|
||||
# heap-corruption / UB regressions across the whole code base for
|
||||
# free as a side effect of any change that can be exercised by a
|
||||
# headless run.
|
||||
#
|
||||
# Build configuration matches Linux-Headless.yml (--disable-menu) with
|
||||
# additional --disable-discord --disable-cheevos --disable-networking
|
||||
# to shrink the third-party surface on this first iteration. Each can
|
||||
# be re-enabled once the baseline is green.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
asan-ubsan:
|
||||
name: Build with ASan+UBSan and run headless smoke
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential libxkbcommon-dev libx11-xcb-dev xvfb x11-utils zlib1g-dev libfreetype6-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev nvidia-cg-toolkit nvidia-cg-dev libavcodec-dev libsdl2-dev libsdl-image1.2-dev libxml2-dev yasm ccache
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Configure (no menu, no discord/cheevos/networking, sdl2 on)
|
||||
# Trim the build surface for the first iteration so any
|
||||
# sanitizer hit is a RetroArch-internal bug rather than noise
|
||||
# from a vendored third-party subsystem. The disabled
|
||||
# subsystems will be re-enabled in follow-up patches as the
|
||||
# baseline stays green. --enable-sdl2 is explicit because
|
||||
# the imageviewer smoke step below selects sdl2 as the video
|
||||
# driver; if its build deps were ever missing, a silent fall-
|
||||
# back to a different driver would skew the smoke's coverage
|
||||
# without warning.
|
||||
run: |
|
||||
./configure \
|
||||
--disable-menu \
|
||||
--disable-discord \
|
||||
--disable-cheevos \
|
||||
--disable-networking \
|
||||
--enable-sdl2
|
||||
|
||||
- name: Build with -fsanitize=address,undefined
|
||||
# The top-level Makefile (line 153) propagates SANITIZER into
|
||||
# CFLAGS / CXXFLAGS / LDFLAGS for every translation unit and
|
||||
# the final link. ASan defaults to abort-on-heap-corruption;
|
||||
# UBSan recovery is controlled at runtime via UBSAN_OPTIONS
|
||||
# (see the smoke-run steps below).
|
||||
run: |
|
||||
make -j$(getconf _NPROCESSORS_ONLN) \
|
||||
SANITIZER=address,undefined
|
||||
test -x retroarch
|
||||
file retroarch
|
||||
|
||||
- name: Smoke run --help (ASan + UBSan strict)
|
||||
# `--help` exits cleanly via exit(0) after printing the usage
|
||||
# banner. Coverage scope: libc init, main(), frontend
|
||||
# driver bootstrap, argv duplication, the getopt walk over
|
||||
# the full option table, and retroarch_print_help() itself.
|
||||
# Doesn't reach into core loading / video init / cleanup-on-
|
||||
# shutdown; the imageviewer smoke step below covers those.
|
||||
# ASan and UBSan both run in halt-on-error mode: the first
|
||||
# run of this workflow (Apr 28 2026, run #1) reported zero
|
||||
# distinct UBSan diagnostics across both --help and
|
||||
# --features, so the baseline for these two surfaces is
|
||||
# clean and we enforce it. If a future change introduces
|
||||
# signed-overflow / alignment / shift-too-large UB along
|
||||
# the option-parsing or print paths, this step will fail
|
||||
# and the diagnostic line will be in the captured stderr.
|
||||
env:
|
||||
ASAN_OPTIONS: abort_on_error=1:detect_leaks=0:print_stacktrace=1:strict_string_checks=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
# Avoid noise from libGL / Mesa / Wayland symbol-resolution
|
||||
# leaks at process shutdown; those are not RetroArch bugs.
|
||||
LSAN_OPTIONS: exitcode=0
|
||||
run: |
|
||||
set -eu
|
||||
timeout 30 ./retroarch --help > /tmp/help.out 2> /tmp/help.err || rc=$?
|
||||
echo "exit=${rc:-0}"
|
||||
echo "=== stdout (head) ==="
|
||||
head -40 /tmp/help.out
|
||||
echo "=== stderr ==="
|
||||
cat /tmp/help.err
|
||||
# ASan abort_on_error sends the process to exit code 1 + a
|
||||
# SUMMARY: line on stderr. Treat any "AddressSanitizer:"
|
||||
# or UBSan "runtime error:" marker as fatal regardless of
|
||||
# exit code -- belt-and-suspenders to the runtime options
|
||||
# in case a future sanitizer release changes its default
|
||||
# exit semantics.
|
||||
if grep -q "AddressSanitizer:" /tmp/help.err; then
|
||||
echo "[FAIL] AddressSanitizer reported a finding"
|
||||
exit 1
|
||||
fi
|
||||
if grep -q "runtime error:" /tmp/help.err; then
|
||||
echo "[FAIL] UBSan reported a finding"
|
||||
exit 1
|
||||
fi
|
||||
echo "[pass] retroarch --help under ASan+UBSan"
|
||||
|
||||
- name: Smoke run --features (ASan + UBSan strict)
|
||||
# `--features` exits cleanly via exit(0) after printing the
|
||||
# compile-time feature list. Coverage scope is the same as
|
||||
# --help (libc init / main / frontend bootstrap / arg parse)
|
||||
# plus retroarch_print_features(), which walks the static
|
||||
# video / audio / input / camera / location / record / cheats
|
||||
# / network / database / overlay / hid feature tables. Each
|
||||
# such walk reads pointers into a static-string table -- low
|
||||
# corruption surface but a useful sanity check that the link-
|
||||
# time feature flags resolve consistently. Doesn't reach
|
||||
# core loading or cleanup-on-shutdown. Like the --help step
|
||||
# this enforces UBSan strict because the baseline is clean.
|
||||
env:
|
||||
ASAN_OPTIONS: abort_on_error=1:detect_leaks=0:print_stacktrace=1:strict_string_checks=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
LSAN_OPTIONS: exitcode=0
|
||||
run: |
|
||||
set -eu
|
||||
timeout 30 ./retroarch --features > /tmp/features.out 2> /tmp/features.err || rc=$?
|
||||
echo "exit=${rc:-0}"
|
||||
echo "=== stdout (head) ==="
|
||||
head -40 /tmp/features.out
|
||||
echo "=== stderr ==="
|
||||
cat /tmp/features.err
|
||||
if grep -q "AddressSanitizer:" /tmp/features.err; then
|
||||
echo "[FAIL] AddressSanitizer reported a finding"
|
||||
exit 1
|
||||
fi
|
||||
if grep -q "runtime error:" /tmp/features.err; then
|
||||
echo "[FAIL] UBSan reported a finding"
|
||||
exit 1
|
||||
fi
|
||||
echo "[pass] retroarch --features under ASan+UBSan"
|
||||
|
||||
- name: Build imageviewer core under ASan + UBSan
|
||||
# The standalone Makefile under cores/libretro-imageviewer/
|
||||
# honours the same SANITIZER= knob as the top-level Makefile
|
||||
# (added in the v9 Makefile cleanup, efae310). Building the
|
||||
# core with sanitizers enabled means the stb_image-driven
|
||||
# decode path is fully instrumented when RetroArch dlopens
|
||||
# it -- ASan would otherwise only catch heap corruption via
|
||||
# the global allocator interceptor and would miss stack-
|
||||
# buffer-overflow / use-after-return inside stb_image
|
||||
# itself. Same SANITIZER= value as the main build.
|
||||
run: |
|
||||
set -eu
|
||||
cd cores/libretro-imageviewer
|
||||
make clean
|
||||
make SANITIZER=address,undefined
|
||||
test -x image_core.so
|
||||
file image_core.so
|
||||
|
||||
- name: Generate test PNG for imageviewer
|
||||
# Tiny 8x8 solid-red PNG, 75 bytes. Hand-rolled via Python
|
||||
# struct + zlib to avoid an apt dependency on imagemagick or
|
||||
# similar. Python ships on every ubuntu-latest by default.
|
||||
# Saved under /tmp because the workspace lives on a path
|
||||
# GitHub Actions cleans up post-run anyway.
|
||||
run: |
|
||||
set -eu
|
||||
python3 - <<'PY'
|
||||
import struct, zlib
|
||||
def chunk(name, data):
|
||||
crc = zlib.crc32(name + data)
|
||||
return struct.pack('>I', len(data)) + name + data + \
|
||||
struct.pack('>I', crc)
|
||||
sig = b'\x89PNG\r\n\x1a\n'
|
||||
ihdr = chunk(b'IHDR',
|
||||
struct.pack('>IIBBBBB', 8, 8, 8, 2, 0, 0, 0))
|
||||
raw = b''
|
||||
for _ in range(8):
|
||||
raw += b'\x00' + b'\xff\x00\x00' * 8
|
||||
idat = chunk(b'IDAT', zlib.compress(raw))
|
||||
iend = chunk(b'IEND', b'')
|
||||
with open('/tmp/test.png', 'wb') as f:
|
||||
f.write(sig + ihdr + idat + iend)
|
||||
PY
|
||||
file /tmp/test.png
|
||||
|
||||
- name: Smoke run imageviewer headless under Xvfb (soft-fail)
|
||||
# Loads cores/libretro-imageviewer/image_core.so against a
|
||||
# tiny PNG, runs --max-frames=300 (~5s nominal at 60fps,
|
||||
# ~15-25s under sanitizer overhead), then exits via the
|
||||
# normal runloop teardown path. Covers what the --help and
|
||||
# --features smokes can't: dlopen of a libretro core,
|
||||
# retro_load_game, the stb_image decode path, the SDL2 +
|
||||
# X11 + MIT-SHM rendering pipeline, the runloop, and full
|
||||
# cleanup-on-shutdown.
|
||||
#
|
||||
# Why sdl2 specifically: the v10 first attempt selected
|
||||
# xvideo (smaller, more self-contained, real YUV color
|
||||
# tables). Run #1 of that workflow tripped on Xvfb
|
||||
# exposing the XVideo extension but providing zero
|
||||
# adaptors:
|
||||
#
|
||||
# [XVideo] XvQueryAdaptors() found 0 adaptors.
|
||||
# [Video] Cannot open video driver. Exiting...
|
||||
#
|
||||
# That's correct defensive code in the xvideo driver, not
|
||||
# a bug -- but it means xvideo can't be exercised on Xvfb
|
||||
# without real video hardware, which the runner doesn't
|
||||
# have. SDL2 over X11 / MIT-SHM works on Xvfb out of the
|
||||
# box (verified via a standalone SDL_CreateRenderer probe
|
||||
# before this patch landed). Coverage tradeoff: we lose
|
||||
# xvideo's YUV color-conversion path but keep all the
|
||||
# high-leverage surface (dlopen, core lifecycle, stb_image,
|
||||
# runloop, video driver init, full cleanup).
|
||||
#
|
||||
# Soft-fail (continue-on-error: true) on this iteration.
|
||||
# Reasoning: lots can go wrong here that aren't RetroArch
|
||||
# bugs -- libGL / Mesa software-rasterizer leaks at
|
||||
# shutdown, X11 driver init noise -- and forcing strict
|
||||
# cleanliness before measuring the baseline would block
|
||||
# merges on noise. Sanitizer findings ARE still surfaced
|
||||
# in the step output for triage; they just don't fail
|
||||
# the job. Once the baseline is characterised, this step
|
||||
# can be flipped to strict the same way the --help step
|
||||
# was in v8.
|
||||
#
|
||||
# Audio driver is "null" (no PulseAudio / ALSA dependency
|
||||
# on the runner). Verbose output is on so the run captures
|
||||
# the full log for triage.
|
||||
continue-on-error: true
|
||||
env:
|
||||
# detect_leaks=0 because libGL / Mesa symbol-resolution
|
||||
# plus X11 connection caches produce non-trivial leaks at
|
||||
# process shutdown that aren't RetroArch bugs. Can be
|
||||
# flipped on later with a suppression file. Heap
|
||||
# corruption / UAF / double-free still abort under
|
||||
# abort_on_error=1.
|
||||
ASAN_OPTIONS: abort_on_error=1:detect_leaks=0:print_stacktrace=1:strict_string_checks=1
|
||||
# halt_on_error=0 so a single signed-overflow somewhere
|
||||
# in the runloop doesn't truncate the stderr log before
|
||||
# we see the full picture. The grep below still
|
||||
# surfaces every "runtime error:" line for triage.
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=0
|
||||
LSAN_OPTIONS: exitcode=0
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
# Start Xvfb on display :99. -screen geometry is small
|
||||
# because the imageviewer doesn't care about resolution
|
||||
# and we're trying to minimise X server memory. SDL2's
|
||||
# X11 backend uses MIT-SHM (which Xvfb provides by
|
||||
# default) for image transfer.
|
||||
Xvfb :99 -screen 0 320x240x24 -nolisten tcp &
|
||||
XVFB_PID=$!
|
||||
# Ensure cleanup on any exit (including soft-fail ones).
|
||||
trap "kill $XVFB_PID 2>/dev/null || true" EXIT
|
||||
# Give Xvfb time to come up; xdpyinfo confirms MIT-SHM is
|
||||
# available before we waste cycles trying to use it.
|
||||
# Extension names in xdpyinfo output are indented with
|
||||
# leading whitespace, hence ^[[:space:]]+.
|
||||
for i in 1 2 3 4 5; do
|
||||
if DISPLAY=:99 xdpyinfo -queryExtensions 2>/dev/null \
|
||||
| grep -qE "^[[:space:]]+MIT-SHM\b"; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
DISPLAY=:99 xdpyinfo -queryExtensions \
|
||||
| grep -E "^[[:space:]]+MIT-SHM\b" || true
|
||||
|
||||
# Minimal config: sdl2 video, null audio. Everything
|
||||
# else takes built-in defaults.
|
||||
mkdir -p /tmp/asan-cfg
|
||||
cat > /tmp/asan-cfg/retroarch.cfg <<EOF
|
||||
video_driver = "sdl2"
|
||||
audio_driver = "null"
|
||||
video_threaded = "false"
|
||||
video_fullscreen = "false"
|
||||
video_windowed_fullscreen = "false"
|
||||
EOF
|
||||
|
||||
# Run. --max-frames triggers a clean shutdown via the
|
||||
# normal runloop teardown after N frames, which is what
|
||||
# we want for cleanup-path coverage. Wall-clock timeout
|
||||
# is a safety net at 60s; --max-frames at 300 should
|
||||
# finish in well under that even with sanitizer overhead.
|
||||
set +e
|
||||
DISPLAY=:99 timeout 60 ./retroarch \
|
||||
-c /tmp/asan-cfg/retroarch.cfg \
|
||||
-L cores/libretro-imageviewer/image_core.so \
|
||||
/tmp/test.png \
|
||||
--max-frames=300 \
|
||||
--verbose \
|
||||
> /tmp/imageviewer.out 2> /tmp/imageviewer.err
|
||||
rc=$?
|
||||
set -e
|
||||
|
||||
echo "exit=${rc}"
|
||||
echo "=== stdout (last 80) ==="
|
||||
tail -80 /tmp/imageviewer.out || true
|
||||
echo "=== stderr (last 200) ==="
|
||||
tail -200 /tmp/imageviewer.err || true
|
||||
|
||||
# Surface sanitizer findings explicitly (informational --
|
||||
# we do NOT exit 1 because this step is soft-fail). Once
|
||||
# the baseline is characterised, this section will gate
|
||||
# on findings the same way the --help / --features steps
|
||||
# do.
|
||||
if grep -q "AddressSanitizer:" /tmp/imageviewer.err; then
|
||||
echo ""
|
||||
echo "[INFO] AddressSanitizer reported finding(s):"
|
||||
grep -A 2 "AddressSanitizer:" /tmp/imageviewer.err \
|
||||
| head -40
|
||||
fi
|
||||
ub_count=$(grep -c "runtime error:" /tmp/imageviewer.err \
|
||||
2>/dev/null || true)
|
||||
if [ "${ub_count:-0}" != "0" ]; then
|
||||
echo ""
|
||||
echo "[INFO] UBSan reported ${ub_count} runtime error(s):"
|
||||
grep -h "runtime error:" /tmp/imageviewer.err \
|
||||
| sort -u | head -20
|
||||
fi
|
||||
echo "[done] imageviewer headless smoke (soft-fail)"
|
||||
|
||||
- name: Screenshot on exit under LeakSanitizer (strict)
|
||||
# The smoke above runs with detect_leaks=0, which is how a
|
||||
# synchronous screenshot leaking its task state and the whole
|
||||
# captured frame on every call went unnoticed: --max-frames-ss
|
||||
# and save-state thumbnails both take that path. This run
|
||||
# takes one and checks for leaks with only the system libraries
|
||||
# suppressed - Mesa, X11, SDL, D-Bus and friends keep caches
|
||||
# alive to exit that are not RetroArch's - so anything left is
|
||||
# ours and fails the job.
|
||||
env:
|
||||
ASAN_OPTIONS: abort_on_error=1:detect_leaks=1:print_stacktrace=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
LSAN_OPTIONS: suppressions=/tmp/lsan-system.supp:print_suppressions=0
|
||||
run: |
|
||||
set -eu
|
||||
cat > /tmp/lsan-system.supp <<EOF
|
||||
leak:libGL
|
||||
leak:libGLX
|
||||
leak:libGLdispatch
|
||||
leak:libgallium
|
||||
leak:libLLVM
|
||||
leak:_dri.so
|
||||
leak:libEGL
|
||||
leak:libgbm
|
||||
leak:libX11
|
||||
leak:libxcb
|
||||
leak:libSDL2
|
||||
leak:libdbus-1
|
||||
leak:libfontconfig
|
||||
leak:libfreetype
|
||||
leak:libasound
|
||||
leak:libpulse
|
||||
EOF
|
||||
mkdir -p /tmp/lsan-cfg /tmp/lsan-shots
|
||||
cat > /tmp/lsan-cfg/retroarch.cfg <<EOF
|
||||
video_driver = "sdl2"
|
||||
audio_driver = "null"
|
||||
video_threaded = "false"
|
||||
video_fullscreen = "false"
|
||||
video_windowed_fullscreen = "false"
|
||||
screenshot_directory = "/tmp/lsan-shots"
|
||||
EOF
|
||||
set +e
|
||||
timeout 120 xvfb-run -a -s "-screen 0 320x240x24" ./retroarch \
|
||||
-c /tmp/lsan-cfg/retroarch.cfg \
|
||||
-L cores/libretro-imageviewer/image_core.so \
|
||||
/tmp/test.png \
|
||||
--max-frames=60 \
|
||||
--max-frames-ss \
|
||||
--max-frames-ss-path=/tmp/lsan-shots/exit.png \
|
||||
> /tmp/lsan.log 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
if [ "$rc" != 0 ] || grep -qE "leak of|AddressSanitizer:|runtime error:" /tmp/lsan.log; then
|
||||
echo "exit=${rc}"
|
||||
grep -E -A 12 "leak of|AddressSanitizer:|runtime error:" /tmp/lsan.log | head -120
|
||||
exit 1
|
||||
fi
|
||||
test -s /tmp/lsan-shots/exit.png
|
||||
echo "[pass] screenshot on exit, no leaks outside the system libraries"
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,103 +0,0 @@
|
||||
name: CI Linux native audio transport
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
native-transport:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
sanitizer: ['', 'address,undefined']
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
- name: Build the shipping frontend and real audio wrapper fixture
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
run: make clean all SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Stereo tempo extremes and live controls
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-tempo check-live SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Native and mixed formats through 5.1 and 7.1
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-wide SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Live source layouts on a fixed device
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-layout SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Speed-linked low-pass control requests
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-speed-lpf SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Runloop speed-state requests
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-runloop SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Automatic producer controls and fallback
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-auto SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: A device's lend reached through the real wrapper
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-lend SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Pause boundary on the real wrapper
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-pause SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Consumer leaving under a parked producer
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-consumer-exit SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Device kept stopped across a rebuild
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1:detect_stack_use_after_return=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
run: make check-kept-device SANITIZER='${{ matrix.sanitizer }}'
|
||||
- name: Consumer leaving and a kept device (ThreadSanitizer)
|
||||
if: matrix.sanitizer == ''
|
||||
working-directory: samples/audio/pipeline_wakeups
|
||||
env:
|
||||
TSAN_OPTIONS: halt_on_error=1 second_deadlock_stack=1
|
||||
run: |
|
||||
# Last: it rebuilds the fixture instrumented. The lanes are the
|
||||
# pipe_consumer_gone handshake and a stopped wrapper beside the
|
||||
# state rebuilt under it, which only the race detector can judge.
|
||||
make clean
|
||||
make check-consumer-exit check-kept-device SANITIZER=thread
|
||||
@@ -1,133 +0,0 @@
|
||||
name: CI Linux autoconfig regression
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
autoconf-tests:
|
||||
name: Build and run the autoconfig regression suite (${{ matrix.lane }})
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential zlib1g-dev libfreetype6-dev ccache
|
||||
timeout-minutes: ${{ matrix.sanitizer == '' && 15 || 40 }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# The suite fails on any sanitizer report in any run, so the
|
||||
# sanitized lanes hold the whole frontend it drives - runloop,
|
||||
# task queue, autodetect - to the same bar as the assertions.
|
||||
include:
|
||||
- lane: plain
|
||||
sanitizer: ''
|
||||
- lane: ASan + UBSan
|
||||
sanitizer: address,undefined
|
||||
- lane: TSan
|
||||
sanitizer: thread
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ strategy.job-index }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-${{ strategy.job-index }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Configure (headless, test drivers)
|
||||
run: |
|
||||
set -eu
|
||||
# The suite drives the test input/joypad drivers with the
|
||||
# null video/audio/menu drivers - no X11/Vulkan/menu needed.
|
||||
# HAVE_TEST_DRIVERS is on by default; assert it survived
|
||||
# configure so a silent drop turns into a clear failure
|
||||
# rather than a skipped test.
|
||||
./configure --disable-menu --disable-ffmpeg --disable-x11 --disable-wayland
|
||||
grep -q '^HAVE_TEST_DRIVERS = 1' config.mk
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
if [ -n "${{ matrix.sanitizer }}" ]; then
|
||||
CFLAGS="-O0 -g1" CXXFLAGS="-O0 -g1" make -j"$(nproc)" SANITIZER=${{ matrix.sanitizer }} DEBUG=1
|
||||
else
|
||||
make -j"$(nproc)"
|
||||
fi
|
||||
|
||||
- name: Run autoconfig regression suite
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
test -x ./retroarch
|
||||
if [ "${{ matrix.sanitizer }}" = thread ]; then
|
||||
# TSan cannot map its shadow under the runner's ASLR
|
||||
# entropy; setarch -R carries to every child the suite runs.
|
||||
setarch "$(uname -m)" -R ./tests-other/test_autoconf.sh ./retroarch
|
||||
else
|
||||
./tests-other/test_autoconf.sh ./retroarch
|
||||
fi
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ strategy.job-index }}-${{ github.sha }}
|
||||
@@ -1,73 +0,0 @@
|
||||
name: CI CDFS sector I/O
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'libretro-common/formats/cdfs/**'
|
||||
- 'libretro-common/include/formats/cdfs.h'
|
||||
- 'libretro-common/samples/formats/cdfs/**'
|
||||
- 'cheevos/cheevos.c'
|
||||
- '.github/workflows/Linux-cdfs-io.yml'
|
||||
pull_request:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'libretro-common/formats/cdfs/**'
|
||||
- 'libretro-common/include/formats/cdfs.h'
|
||||
- 'libretro-common/samples/formats/cdfs/**'
|
||||
- 'cheevos/cheevos.c'
|
||||
- '.github/workflows/Linux-cdfs-io.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
cdfs:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential gcc-mingw-w64-x86-64 wine64
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 15
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Linux sectors and faults
|
||||
working-directory: libretro-common/samples/formats/cdfs
|
||||
run: |
|
||||
set -eu
|
||||
make -j2 SANITIZER=address,undefined SAMPLE_OBJDIR=obj-ci-asan
|
||||
./cdfs_dir_record_test
|
||||
./cdfs_pure_api_test
|
||||
./cdfs_io_error_test
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
- name: Windows sectors and faults
|
||||
working-directory: libretro-common/samples/formats/cdfs
|
||||
run: |
|
||||
set -eu
|
||||
make -j2 CC=x86_64-w64-mingw32-gcc OS=Windows_NT EXE=.exe SAMPLE_OBJDIR=obj-ci-win
|
||||
WINEDEBUG=-all wine ./cdfs_dir_record_test.exe
|
||||
WINEDEBUG=-all wine ./cdfs_pure_api_test.exe
|
||||
WINEDEBUG=-all wine ./cdfs_io_error_test.exe
|
||||
@@ -1,150 +0,0 @@
|
||||
name: CI driver vtables
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
driver-vtables:
|
||||
name: Every driver against its interface
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: --no-install-recommends build-essential libasound2-dev libpulse-dev libjack-jackd2-dev libopenal-dev libpipewire-0.3-dev libsdl2-dev
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Check no input driver's table outgrows the structure
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The step below compiles the drivers Linux can. The UWP,
|
||||
# Cocoa and console input drivers are not among them, and a
|
||||
# table with one entry more than struct input_driver has
|
||||
# members is only a warning to gcc anyway - and C2078, a
|
||||
# failed build, to MSVC. That reached master for the UWP
|
||||
# driver. This counts the entries of every input driver's
|
||||
# table in the source, whatever SDK the driver needs.
|
||||
tools/check.sh tools/input_driver_table_check.c --selftest
|
||||
tools/check.sh tools/input_driver_table_check.c
|
||||
|
||||
- name: Compile each driver against its interface
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# A driver fills in a vtable of function pointers, and almost
|
||||
# every one of them does it positionally and names nothing.
|
||||
# So an entry added to the middle of one of those structures
|
||||
# silently moves every entry after it in every driver that
|
||||
# did not name its fields, and what the compiler then says is
|
||||
# that a layout function is being installed as an underrun
|
||||
# counter - which is an error only if you ask for it to be.
|
||||
#
|
||||
# That happened: frames_consumed_fallback went in between
|
||||
# frames_consumed and underruns, three Windows drivers took
|
||||
# the shift, and the break reached master because the check
|
||||
# run before the commit was one file rather than all of them.
|
||||
#
|
||||
# This is that check. It compiles every driver it can on
|
||||
# Linux - the rest need SDKs that are not here - and treats a
|
||||
# mismatched function pointer as the error it is.
|
||||
#
|
||||
# The names are matched with digits in them as well: a driver
|
||||
# called sdl3 or v4l2 or ps2 is exactly as positional as one
|
||||
# that spells itself in letters, and six of them were being
|
||||
# walked past. The display drivers fill in a vtable of the
|
||||
# same shape, so they are here too.
|
||||
#
|
||||
# A static function nobody calls is in the same family and is
|
||||
# caught here too: it is what a call site that was meant to
|
||||
# be there and is not looks like from the compiler's side.
|
||||
# That happened as well - the pump's scheduler class was
|
||||
# taken but never given back, and the only sign was the
|
||||
# helper that returns it going unused.
|
||||
fail=0
|
||||
defs="-DRARCH_INTERNAL -DHAVE_THREADS -DHAVE_MENU -DHAVE_CONFIGFILE"
|
||||
defs="$defs -DHAVE_AUDIOMIXER -DHAVE_REWIND -DHAVE_RWAV"
|
||||
have="-DHAVE_ALSA -DHAVE_PULSE -DHAVE_JACK -DHAVE_OSS -DHAVE_OPENAL"
|
||||
have="$have -DHAVE_PIPEWIRE -DHAVE_TINYALSA -DHAVE_SDL2"
|
||||
inc="-I. -Ilibretro-common/include -Ideps -Ideps/rcheevos/include"
|
||||
inc="$inc $(pkg-config --cflags libpipewire-0.3 2>/dev/null || true)"
|
||||
# Every file that fills one of these structures in, found by
|
||||
# looking rather than by listing a directory: the Android
|
||||
# build broke on audio/audio_thread_wrapper.c, which fills in
|
||||
# an audio_driver_t and does not live under audio/drivers,
|
||||
# and so was not in the list this job first carried.
|
||||
files=$(grep -rl -E \
|
||||
'audio_driver_t [a-z_0-9]+ *=|camera_driver_t [a-z_0-9]+ *=|record_driver_t [a-z_0-9]+ *=|microphone_driver_t [a-z_0-9]+ *=|gfx_display_ctx_driver_t [a-z_0-9]+ *=' \
|
||||
--include='*.c' . | grep -v '^\./samples/' | sort)
|
||||
echo "$files" | sed 's/^/ /'
|
||||
echo
|
||||
for f in $files; do
|
||||
[ -f "$f" ] || continue
|
||||
out=$(gcc -fsyntax-only -std=gnu99 -Wall \
|
||||
-Werror=incompatible-pointer-types \
|
||||
-Werror=unused-function \
|
||||
$defs $have $inc "$f" 2>&1 || true)
|
||||
# A driver whose platform SDK is not here does not compile
|
||||
# at all, and that is not what this job is about: it is
|
||||
# skipped, and only a pointer mismatch fails.
|
||||
if printf '%s' "$out" | grep -qE "incompatible pointer type|defined but not used"; then
|
||||
echo "=== $f"
|
||||
printf '%s\n' "$out" | grep -E -A2 "incompatible pointer type|defined but not used"
|
||||
fail=1
|
||||
elif printf '%s' "$out" | grep -q ": error:"; then
|
||||
echo "[skip] $f (needs an SDK that is not here)"
|
||||
else
|
||||
echo "[ok] $f"
|
||||
fi
|
||||
done
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
echo
|
||||
echo "A driver does not match the interface it fills in, or has a"
|
||||
echo "static function nothing calls. An optional vtable entry belongs"
|
||||
echo "at the end of the structure, where it cannot move the entries a"
|
||||
echo "positional initialiser relies on; an uncalled helper usually"
|
||||
echo "means the call site that was meant to use it is missing."
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,87 +0,0 @@
|
||||
name: CI optical DVD blocks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'tasks/task_content_disc.c'
|
||||
- 'libretro-common/cdrom/**'
|
||||
- 'libretro-common/vfs/**'
|
||||
- 'libretro-common/include/cdrom/**'
|
||||
- 'libretro-common/include/vfs/**'
|
||||
- 'libretro-common/samples/file/vfs_cdrom/**'
|
||||
- '.github/workflows/Linux-dvd-blocks.yml'
|
||||
pull_request:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'tasks/task_content_disc.c'
|
||||
- 'libretro-common/cdrom/**'
|
||||
- 'libretro-common/vfs/**'
|
||||
- 'libretro-common/include/cdrom/**'
|
||||
- 'libretro-common/include/vfs/**'
|
||||
- 'libretro-common/samples/file/vfs_cdrom/**'
|
||||
- '.github/workflows/Linux-dvd-blocks.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
blocks:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential gcc-mingw-w64-x86-64 wine64
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 15
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Linux commands and VFS
|
||||
working-directory: libretro-common/samples/file/vfs_cdrom
|
||||
run: |
|
||||
set -eu
|
||||
make -j2 dvd_blocks_test SANITIZER=address,undefined SAMPLE_OBJDIR=obj-dvd-asan
|
||||
./dvd_blocks_test
|
||||
make -j2 disc_dump_test SANITIZER=address,undefined SAMPLE_OBJDIR=obj-dvd-asan
|
||||
./disc_dump_test
|
||||
make -j2 vfs_close_test SANITIZER=address,undefined SAMPLE_OBJDIR=obj-dvd-asan
|
||||
./vfs_close_test
|
||||
make -j2 macos_command_test SANITIZER=address,undefined SAMPLE_OBJDIR=obj-dvd-asan
|
||||
./macos_command_test
|
||||
make -j2 SANITIZER=address,undefined SAMPLE_OBJDIR=obj-dvd-asan
|
||||
./cdrom_cuesheet_overflow_test
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
- name: Windows commands and VFS
|
||||
working-directory: libretro-common/samples/file/vfs_cdrom
|
||||
run: |
|
||||
set -eu
|
||||
make -j2 dvd_blocks_test.exe CC=x86_64-w64-mingw32-gcc OS=Windows_NT EXE=.exe SAMPLE_OBJDIR=obj-dvd-win
|
||||
WINEDEBUG=-all wine ./dvd_blocks_test.exe
|
||||
make -j2 disc_dump_test.exe CC=x86_64-w64-mingw32-gcc OS=Windows_NT EXE=.exe SAMPLE_OBJDIR=obj-dvd-win
|
||||
WINEDEBUG=-all wine ./disc_dump_test.exe
|
||||
make -j2 vfs_close_test.exe CC=x86_64-w64-mingw32-gcc OS=Windows_NT EXE=.exe SAMPLE_OBJDIR=obj-dvd-win
|
||||
WINEDEBUG=-all wine ./vfs_close_test.exe
|
||||
make -j2 macos_command_test.exe CC=x86_64-w64-mingw32-gcc OS=Windows_NT EXE=.exe SAMPLE_OBJDIR=obj-dvd-win
|
||||
WINEDEBUG=-all wine ./macos_command_test.exe
|
||||
@@ -1,135 +0,0 @@
|
||||
name: CI Linux EGL hardware core
|
||||
|
||||
# Runs the gl video driver on the X11 EGL context under Xvfb with an
|
||||
# OpenGL hardware core, and checks that the core was given a context
|
||||
# and that its frame is what reaches the screen - with threaded video
|
||||
# on, where the core's context lives on the main thread and cannot be
|
||||
# bound to the window surface the video thread holds, and with it off.
|
||||
# Mesa takes the surfaceless path by itself; a preloaded shim hides
|
||||
# parts of its EGL so the pbuffer paths run too.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'gfx/common/egl_common.c'
|
||||
- 'gfx/common/egl_common.h'
|
||||
- 'gfx/drivers_context/xegl_ctx.c'
|
||||
- 'gfx/drivers/gl2.c'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_hw.c'
|
||||
- 'gfx/video_thread_wrapper.c'
|
||||
- 'samples/gfx/egl_hw_core/**'
|
||||
- '.github/workflows/Linux-egl-hw-core.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'gfx/common/egl_common.c'
|
||||
- 'gfx/common/egl_common.h'
|
||||
- 'gfx/drivers_context/xegl_ctx.c'
|
||||
- 'gfx/drivers/gl2.c'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_hw.c'
|
||||
- 'gfx/video_thread_wrapper.c'
|
||||
- 'samples/gfx/egl_hw_core/**'
|
||||
- '.github/workflows/Linux-egl-hw-core.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
egl-hw-core:
|
||||
name: Run a GL hardware core on the EGL context under Xvfb
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential zlib1g-dev ccache python3 xvfb libgl1-mesa-dri libx11-dev libx11-xcb-dev libxcb1-dev libxext-dev libxxf86vm-dev libxrandr-dev libxinerama-dev libgl-dev libegl-dev
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build RetroArch (X11 + OpenGL + EGL, the rest off)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
./configure --disable-qt --disable-wayland --disable-sdl \
|
||||
--disable-sdl2 --disable-ffmpeg --disable-vulkan \
|
||||
--disable-pulse --disable-discord \
|
||||
--disable-networking --disable-cheevos \
|
||||
--disable-glslang --disable-slang \
|
||||
--disable-spirv_cross --disable-xmb \
|
||||
--disable-materialui --disable-ozone \
|
||||
--disable-7zip --disable-flac \
|
||||
--disable-audiomixer --disable-translate \
|
||||
--disable-accessibility --disable-crtswitchres \
|
||||
--disable-langextra --disable-libretrodb \
|
||||
--disable-video_filter --disable-dsp_filter
|
||||
grep -q '^HAVE_OPENGL = 1' config.mk
|
||||
grep -q '^HAVE_EGL = 1' config.mk
|
||||
grep -q '^HAVE_X11 = 1' config.mk
|
||||
make -j$(nproc)
|
||||
ccache -s
|
||||
|
||||
- name: Run egl_hw_core_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
make -C samples/gfx/egl_hw_core
|
||||
timeout 600 python3 samples/gfx/egl_hw_core/egl_hw_core_test.py ./retroarch
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,82 +0,0 @@
|
||||
name: CI Linux filter plugins
|
||||
|
||||
# Builds every video filter (gfx/video_filters) and audio DSP filter
|
||||
# (libretro-common/audio/dsp_filters) plugin with its own Makefile and
|
||||
# runs samples/gfx/filter_plugins over all of them: each plugin is
|
||||
# loaded with RTLD_NOW into a host that does not link libm, so a
|
||||
# symbol it cannot resolve fails the load, then fed a frame or a run
|
||||
# of audio blocks at its default settings. Every video filter that
|
||||
# takes more than one worker must give the single-worker output byte for
|
||||
# byte with 2, 3 and 4 workers running at once. The same run is repeated
|
||||
# with the plugins and the harness built under ASan, UBSan and
|
||||
# LeakSanitizer, and under ThreadSanitizer.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'gfx/video_filters/**'
|
||||
- 'libretro-common/audio/dsp_filters/**'
|
||||
- 'libretro-common/include/libretro_dspfilter.h'
|
||||
- 'samples/gfx/filter_plugins/**'
|
||||
- '.github/workflows/Linux-filter-plugins.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'gfx/video_filters/**'
|
||||
- 'libretro-common/audio/dsp_filters/**'
|
||||
- 'libretro-common/include/libretro_dspfilter.h'
|
||||
- 'samples/gfx/filter_plugins/**'
|
||||
- '.github/workflows/Linux-filter-plugins.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
filter-plugins:
|
||||
name: Load and run every filter plugin
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Build the plugins and the harness
|
||||
run: |
|
||||
set -eu
|
||||
make -C samples/gfx/filter_plugins
|
||||
# The harness must not bring libm in on the plugins' behalf.
|
||||
if readelf -d samples/gfx/filter_plugins/filter_plugins_test \
|
||||
| grep -q 'libm\.so'; then
|
||||
echo "filter_plugins_test links libm; it would hide a plugin that does not"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Load and run every plugin
|
||||
run: make -C samples/gfx/filter_plugins check
|
||||
|
||||
- name: Load and run every plugin under ASan, UBSan and LeakSanitizer
|
||||
env:
|
||||
ASAN_OPTIONS: abort_on_error=1:detect_leaks=1:print_stacktrace=1
|
||||
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
|
||||
run: |
|
||||
set -eu
|
||||
make -C samples/gfx/filter_plugins clean
|
||||
make -C samples/gfx/filter_plugins check SANITIZER=address,undefined
|
||||
|
||||
- name: Load and run every plugin under ThreadSanitizer
|
||||
env:
|
||||
TSAN_OPTIONS: halt_on_error=1
|
||||
run: |
|
||||
set -eu
|
||||
make -C samples/gfx/filter_plugins clean
|
||||
make -C samples/gfx/filter_plugins check SANITIZER=thread
|
||||
@@ -1,84 +0,0 @@
|
||||
name: CI Linux frontend overhead [frame-path harness]
|
||||
|
||||
# What one runloop_iterate() costs when the core costs nothing, and
|
||||
# whether anything on the frame path allocates. The harness links the
|
||||
# shipping release objects with main() replaced, boots on the null
|
||||
# drivers, runs a core that pushes one frame, one audio batch and one
|
||||
# input read per retro_run, and counts heap calls over the frame path
|
||||
# by glibc interposition - which is why this is a release build with
|
||||
# no allocator sanitizer in the way. It also prints microseconds per
|
||||
# frame under fast-forward and trips on a loose bound, so a blocking
|
||||
# call or a sleep that lands on the frame path fails here rather than
|
||||
# in a bug report about stutter.
|
||||
#
|
||||
# Everything a default desktop build compiles in is compiled in, so a
|
||||
# product that starts costing the frame while idle is measured, not
|
||||
# excluded.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
linux-frontend-overhead:
|
||||
name: Release build, frame-path heap and cost
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential libxkbcommon-dev libx11-xcb-dev zlib1g-dev libfreetype6-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev libavcodec-dev libsdl2-dev libxml2-dev yasm
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Configure
|
||||
# Non-Qt, as the harness requires (with Qt, main() lives in
|
||||
# ui_qt.o). Everything else at its default.
|
||||
run: ./configure --disable-qt
|
||||
|
||||
- name: Build (release)
|
||||
run: make -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: Run the frontend-overhead harness
|
||||
shell: bash
|
||||
run: |
|
||||
set -o pipefail
|
||||
SAN=none make -C samples/runloop/frontend_overhead check
|
||||
make -C samples/runloop/frontend_overhead clean
|
||||
@@ -1,123 +0,0 @@
|
||||
name: CI Linux gl1 upload
|
||||
|
||||
# Runs the gl1 video driver under Xvfb with a test core and checks the
|
||||
# screen against the frame the core drew, pixel for pixel, down each of
|
||||
# the driver's upload paths: frames taken straight from the core's
|
||||
# buffer, the no-GL_EXT_bgra swizzle, native RGB565, the GL 1.1 CPU
|
||||
# expansion, and texture storage respecified across frame size changes.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'gfx/drivers/gl1.c'
|
||||
- 'libretro-common/gfx/scaler/pixconv.c'
|
||||
- 'libretro-common/include/gfx/scaler/pixconv.h'
|
||||
- 'samples/gfx/gl1_upload/**'
|
||||
- '.github/workflows/Linux-gl1-upload.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'gfx/drivers/gl1.c'
|
||||
- 'libretro-common/gfx/scaler/pixconv.c'
|
||||
- 'libretro-common/include/gfx/scaler/pixconv.h'
|
||||
- 'samples/gfx/gl1_upload/**'
|
||||
- '.github/workflows/Linux-gl1-upload.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
gl1-upload:
|
||||
name: Run retroarch on gl1 under Xvfb and check the frame
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential zlib1g-dev ccache python3 xvfb libgl1-mesa-dri libx11-dev libx11-xcb-dev libxcb1-dev libxext-dev libxxf86vm-dev libxrandr-dev libxinerama-dev libgl-dev libegl-dev
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build RetroArch (X11 + OpenGL, the rest off)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
./configure --disable-qt --disable-wayland --disable-sdl \
|
||||
--disable-sdl2 --disable-ffmpeg --disable-vulkan \
|
||||
--disable-pulse --disable-discord \
|
||||
--disable-networking --disable-cheevos \
|
||||
--disable-glslang --disable-slang \
|
||||
--disable-spirv_cross --disable-xmb \
|
||||
--disable-materialui --disable-ozone \
|
||||
--disable-7zip --disable-flac \
|
||||
--disable-audiomixer --disable-translate \
|
||||
--disable-accessibility --disable-crtswitchres \
|
||||
--disable-langextra --disable-libretrodb \
|
||||
--disable-video_filter --disable-dsp_filter
|
||||
grep -q '^HAVE_OPENGL1 = 1' config.mk
|
||||
make -j$(nproc)
|
||||
ccache -s
|
||||
|
||||
- name: Run gl1_upload_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
make -C samples/gfx/gl1_upload
|
||||
timeout 600 python3 samples/gfx/gl1_upload/gl1_upload_test.py ./retroarch
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,196 +0,0 @@
|
||||
name: CI Linux library network backends
|
||||
|
||||
# The built-in TLS, SMB and NFS clients are the defaults and nothing is
|
||||
# bundled. A system mbedTLS or BearSSL can stand in for the TLS client
|
||||
# (--enable-mbedtls, --enable-bearssl) and a system libsmb2 for the SMB
|
||||
# client (--enable-libsmb). Each lane configures with its option, builds
|
||||
# RetroArch to the link, checks the binary carries that library's
|
||||
# backend and not the built-in client, and then operates the backend:
|
||||
# the TLS lanes run the cheevos login transport against a local HTTPS
|
||||
# server, the libsmb2 lane runs the SMB VFS tests against a local smbd.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
library-backends:
|
||||
name: ${{ matrix.lane }}
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential pkg-config cmake libgl1-mesa-dev libx11-dev libxext-dev libasound2-dev libsdl2-dev zlib1g-dev libfreetype6-dev python3 openssl libmbedtls-dev libbearssl-dev samba ccache
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- lane: mbedtls
|
||||
configure: --enable-mbedtls
|
||||
present: mbedtls_ssl_handshake
|
||||
absent: ' T ssl_socket_retro_was_resumed'
|
||||
- lane: bearssl
|
||||
configure: --enable-bearssl
|
||||
present: br_ssl_client_init_full
|
||||
absent: ' T ssl_socket_retro_was_resumed'
|
||||
- lane: libsmb2
|
||||
configure: --enable-libsmb
|
||||
present: ' U smb2_connect_share'
|
||||
absent: ' T rsmb_connect'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ strategy.job-index }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-${{ strategy.job-index }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: libsmb2 from upstream (no Ubuntu package)
|
||||
if: matrix.lane == 'libsmb2'
|
||||
run: |
|
||||
set -eu
|
||||
git clone -q --depth 1 https://github.com/sahlberg/libsmb2.git "$RUNNER_TEMP/libsmb2"
|
||||
cmake -S "$RUNNER_TEMP/libsmb2" -B "$RUNNER_TEMP/libsmb2/build" \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_SHARED_LIBS=ON >/dev/null
|
||||
make -C "$RUNNER_TEMP/libsmb2/build" -j"$(nproc)" >/dev/null
|
||||
sudo make -C "$RUNNER_TEMP/libsmb2/build" install >/dev/null
|
||||
sudo ldconfig
|
||||
echo "PKG_CONFIG_PATH=/usr/local/lib/pkgconfig" >> "$GITHUB_ENV"
|
||||
pkg-config --modversion libsmb2 || PKG_CONFIG_PATH=/usr/local/lib/pkgconfig pkg-config --modversion libsmb2
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
set -eu
|
||||
./configure ${{ matrix.configure }} --disable-qt --disable-wayland --disable-ffmpeg
|
||||
grep -E '^HAVE_(RETROSSL|MBEDTLS|BEARSSL|RETROSMB|SMBCLIENT|SSL) ' config.mk
|
||||
case "${{ matrix.lane }}" in
|
||||
mbedtls) grep -q '^HAVE_MBEDTLS = 1' config.mk; grep -q '^HAVE_RETROSSL = 0' config.mk ;;
|
||||
bearssl) grep -q '^HAVE_BEARSSL = 1' config.mk; grep -q '^HAVE_RETROSSL = 0' config.mk ;;
|
||||
libsmb2) grep -q '^HAVE_SMBCLIENT = 1' config.mk; grep -q '^HAVE_RETROSMB = 0' config.mk ;;
|
||||
esac
|
||||
|
||||
- name: Build
|
||||
run: make -j"$(nproc)"
|
||||
|
||||
- name: Check which backend linked
|
||||
run: |
|
||||
set -eu
|
||||
nm retroarch | grep -q -- '${{ matrix.present }}'
|
||||
if nm retroarch | grep -q -- '${{ matrix.absent }}'; then
|
||||
echo "the built-in client is still linked in the ${{ matrix.lane }} build"; exit 1
|
||||
fi
|
||||
echo "[pass] ${{ matrix.lane }} backend linked, built-in client absent"
|
||||
|
||||
- name: Operate the TLS backend (cheevos login transport, ASan + UBSan)
|
||||
if: matrix.lane != 'libsmb2'
|
||||
working-directory: samples/network/cheevos_login
|
||||
run: |
|
||||
set -eu
|
||||
case "${{ matrix.lane }}" in mbedtls) be=mbed ;; bearssl) be=bear ;; esac
|
||||
make clean SSL_BACKEND=$be SANITIZER=address,undefined && make -j$(nproc) all SSL_BACKEND=$be SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 timeout 120 \
|
||||
make check SSL_BACKEND=$be
|
||||
echo "[pass] ${{ matrix.lane }}: cheevos login transport over a local HTTPS server"
|
||||
# A server that goes silent mid-handshake: the read bound ends it.
|
||||
make -C ../tls_retro clean SSL_BACKEND=$be && make -C ../tls_retro -j$(nproc) tls_stall SSL_BACKEND=$be
|
||||
../tls_retro/tls_stall
|
||||
# A refused certificate reaches the verify hook.
|
||||
make -C ../tls_retro clean
|
||||
SSL_BACKEND=$be ../tls_retro/verify_hook_test.sh
|
||||
make -C ../tls_retro clean
|
||||
|
||||
- name: Operate the libsmb2 backend (SMB VFS against a local smbd)
|
||||
if: matrix.lane == 'libsmb2'
|
||||
run: |
|
||||
set -eu
|
||||
sudo -E env PATH="$PATH" PKG_CONFIG_PATH="$PKG_CONFIG_PATH" WITH_LIBSMB2=1 \
|
||||
samples/network/smb_retro/local_samba_test.sh
|
||||
sudo make -C samples/network/smb_retro clean
|
||||
|
||||
# libsmb2 keeps process-wide state (its list of live contexts) with
|
||||
# no lock of its own; the VFS backend must serialise it. A race
|
||||
# there needs two cores to show up by timing, so the same tests run
|
||||
# again under TSan against a TSan-built libsmb2, which reports it on
|
||||
# any runner, every time.
|
||||
- name: Operate the libsmb2 backend under TSan (instrumented libsmb2)
|
||||
if: matrix.lane == 'libsmb2'
|
||||
run: |
|
||||
set -eu
|
||||
cmake -S "$RUNNER_TEMP/libsmb2" -B "$RUNNER_TEMP/libsmb2/build-tsan" \
|
||||
-DCMAKE_INSTALL_PREFIX=/opt/libsmb2-tsan -DBUILD_SHARED_LIBS=ON \
|
||||
-DCMAKE_C_FLAGS="-O1 -g1 -fsanitize=thread" \
|
||||
-DCMAKE_SHARED_LINKER_FLAGS="-fsanitize=thread" >/dev/null
|
||||
make -C "$RUNNER_TEMP/libsmb2/build-tsan" -j"$(nproc)" >/dev/null
|
||||
sudo make -C "$RUNNER_TEMP/libsmb2/build-tsan" install >/dev/null
|
||||
sudo -E env PATH="$PATH" \
|
||||
PKG_CONFIG_PATH=/opt/libsmb2-tsan/lib/pkgconfig \
|
||||
LD_LIBRARY_PATH=/opt/libsmb2-tsan/lib \
|
||||
TSAN_OPTIONS="halt_on_error=1 exitcode=66" \
|
||||
CFLAGS="-O1 -g1 -fsanitize=thread" LDLIBS="-fsanitize=thread" \
|
||||
WITH_LIBSMB2=1 samples/network/smb_retro/local_samba_test.sh
|
||||
sudo make -C samples/network/smb_retro clean
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ strategy.job-index }}-${{ github.sha }}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,441 +0,0 @@
|
||||
name: CI Linux libretro-common tests
|
||||
|
||||
# libretro-common/Makefile.test builds and runs the libcheck unit
|
||||
# suites under -fsanitize=address -fsanitize=undefined. Nothing ran
|
||||
# it, which is how three of its suites came to reference sources that
|
||||
# had moved and one referenced a library it never linked: a suite that
|
||||
# cannot be built reads exactly like a suite that passes.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
libretro-common-tests:
|
||||
name: Build and run libretro-common/Makefile.test
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential check pkg-config zlib1g-dev lcov gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 wine wine64 ffmpeg gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf gcc-mipsel-linux-gnu qemu-user ccache
|
||||
# The suites and the stack check have grown with the tree; the
|
||||
# companion harnesses are a job of their own, run beside this one.
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build and run the unit test suites
|
||||
shell: bash
|
||||
working-directory: libretro-common
|
||||
env:
|
||||
# Keep wine quiet and out of $HOME; the first invocation
|
||||
# creates the prefix.
|
||||
WINEDEBUG: "-all"
|
||||
WINEPREFIX: "/tmp/wineprefix"
|
||||
run: |
|
||||
set -eu
|
||||
# The recipe builds each suite, runs it, and collects
|
||||
# coverage, in order -- coverage files collide otherwise.
|
||||
# Any suite failing to build, or any check failing, or any
|
||||
# sanitizer report, fails the job.
|
||||
# 'unit-tests' by name: the default goal of Makefile.test is
|
||||
# win32-configs, so a bare make here builds the Windows A/W
|
||||
# matrix and none of the suites this step exists to run. The
|
||||
# 'all' target adds the concurrency and I/O samples, whose
|
||||
# runtime depends on how many processors the runner has.
|
||||
make -f Makefile.test unit-tests \
|
||||
LIBCHECK_CFLAGS="$(pkg-config --cflags check)" \
|
||||
CFLAGS="$(pkg-config --cflags check)"
|
||||
echo "[pass] libretro-common unit test suites"
|
||||
# The ARMv8 AES + PMULL path executes only on ARM; this
|
||||
# runs the crypto suite under qemu-aarch64 in both the
|
||||
# dispatched and the baseline-crypto shape.
|
||||
make -f Makefile.test crypto-aarch64-check
|
||||
make -f Makefile.test crypto-arm-check
|
||||
make -f Makefile.test crypto-mips-check
|
||||
# every lazily set up table or CPU check, first used by
|
||||
# eight threads at once under TSan
|
||||
make -f Makefile.test crypto-tsan-check
|
||||
# the Windows wait tiers - eventcount and condition variable,
|
||||
# high resolution timer and kernel timeout - as Windows
|
||||
# binaries under wine
|
||||
make -f Makefile.test win32-waits-check
|
||||
|
||||
- name: Check VFS backend symbol parity
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# vfs_implementation_uwp.cpp replaces vfs_implementation.c on
|
||||
# UWP rather than extending it, so a function added to the C
|
||||
# backend and called from the shared file_stream.c compiles
|
||||
# everywhere and fails to link on UWP alone - at the end of a
|
||||
# long MSVC build, on a runner most contributors do not have.
|
||||
# That is how retro_vfs_file_get_mapped_ptr_impl reached the
|
||||
# branch broken. This is the same check at source level, for
|
||||
# free, on Linux.
|
||||
tools/check.sh tools/vfs_backend_parity.c
|
||||
|
||||
- name: Check every command describes itself
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# HELP prints command.h's tables, and interfaces that hand the
|
||||
# commands to a client are generated from them: a command
|
||||
# added without a description reaches all of those blank.
|
||||
tools/check.sh tools/command_table_check.c
|
||||
|
||||
- name: Check video and input code stay out of each other's state
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# The frontend starts the input driver; a video driver says
|
||||
# only what kind of window it put up. What is still to be
|
||||
# moved is listed in the check, file by file, and the lists
|
||||
# only shrink: a video file that starts naming an input
|
||||
# driver, or either side taking the other's state, fails.
|
||||
tools/check.sh tools/input_video_separation_check.c --selftest
|
||||
tools/check.sh tools/input_video_separation_check.c
|
||||
|
||||
- name: Check input drivers ask by name and do not take the frontend's state
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# A driver that needs something from the settings, the run
|
||||
# loop, the menu or the input frontend asks for it by name;
|
||||
# it does not take the whole state and pick a field out.
|
||||
# What is still to be converted is listed in the check, file
|
||||
# by file with a count, and the counts only go down.
|
||||
tools/check.sh tools/input_state_grab_check.c --selftest
|
||||
tools/check.sh tools/input_state_grab_check.c
|
||||
|
||||
- name: Check the GL drivers take the hardware ring's fence ahead of the swap
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# Taken after the swap, the fence completes only when a driver
|
||||
# that queues swaps releases it, and a hardware rendered core
|
||||
# fast-forwards at the display's rate.
|
||||
tools/check.sh tools/gl_ring_fence_check.c --selftest
|
||||
tools/check.sh tools/gl_ring_fence_check.c
|
||||
|
||||
- name: Check the GL drivers set their vsync report with the swap interval
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# Set apart, the threaded presenter counts a vsync wait as
|
||||
# drawing time, or subtracts one that was not made.
|
||||
tools/check.sh tools/gl_present_vsynced_check.c --selftest
|
||||
tools/check.sh tools/gl_present_vsynced_check.c
|
||||
|
||||
- name: Check a setting's label exists wherever its translations name it
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# The translation files name a label for every string they
|
||||
# have, in every build. intl/json2h.py copies a row's feature
|
||||
# guard into them, unless the guard line mentions a
|
||||
# SETTINGS_DEF pass: that line it drops. A line that mentions
|
||||
# a pass and still depends on a feature leaves the
|
||||
# translations naming a label the build does not have, and
|
||||
# nothing fails until the first translation arrives from
|
||||
# Crowdin - then every build without the feature does.
|
||||
tools/check.sh tools/settings_def_guard_check.c --selftest
|
||||
tools/check.sh tools/settings_def_guard_check.c
|
||||
|
||||
- name: Check no video driver deletes overlay textures it was lent
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# load_textures lends a driver the overlay pack's handles for
|
||||
# one page; they are on the pack's other pages too and are
|
||||
# the pack's to delete. gl2 marked them as borrowed and then
|
||||
# deleted them anyway at the next page, so rotating an
|
||||
# Android device blacked the overlay out until the core was
|
||||
# restarted. No runner can run a GL driver, so this is the
|
||||
# check at source level: every driver with load_textures
|
||||
# sets, tests and clears its borrowed marker.
|
||||
tools/check.sh tools/overlay_texture_ownership.c
|
||||
|
||||
- name: Check overlay setters refuse an image the driver does not hold
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# set_alpha, vertex_geom and tex_geom are called whenever the
|
||||
# layout, opacity or page changes, not only after a load()
|
||||
# that worked: with no page the driver's arrays are NULL, and
|
||||
# after a smaller page or a failed load the index is off the
|
||||
# end. 7661ab06e7 bounded the GL geometry setters and missed
|
||||
# set_alpha; D3D, Vulkan and Metal had no check at all. No
|
||||
# runner can run these drivers, so this is the check at
|
||||
# source level for the ones that have been audited.
|
||||
tools/check.sh tools/overlay_setter_bounds.c
|
||||
|
||||
- name: WDM-KS ABI against the system ks.h
|
||||
shell: bash
|
||||
working-directory: samples/audio/wdmks_abi
|
||||
run: |
|
||||
set -eu
|
||||
# audio/common/wdmks_ks.h declares the kernel-streaming
|
||||
# interface the WDM-KS driver uses, because ks.h and
|
||||
# ksmedia.h ship with the driver kit rather than the
|
||||
# Platform SDK and not every toolchain here has them.
|
||||
#
|
||||
# That is only safe while what is declared matches what the
|
||||
# system declares. A wrong layout does not fail to build and
|
||||
# does not misbehave visibly: it hands the kernel a structure
|
||||
# whose fields are in the wrong places. So this compiles ours
|
||||
# beside the real headers and asserts every size, every field
|
||||
# offset, every constant and the IOCTL code, on both word
|
||||
# sizes, and in C89 as well as gnu99.
|
||||
#
|
||||
# It has already earned it. KSDATAFORMAT is a union with a
|
||||
# LONGLONG that aligns it to eight; declared as the plain
|
||||
# struct it resembles, KSDATARANGE_AUDIO came out 84 bytes
|
||||
# against 88 and every field past the first would have been
|
||||
# read four bytes off.
|
||||
make check
|
||||
echo "[pass] wdmks_abi"
|
||||
|
||||
- name: Check stack frame budget
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# PSP and GX threads get 8 KiB of stack (STACKSIZE in
|
||||
# rthreads/psp_pthread.h and rthreads/gx_pthread.h). Nothing
|
||||
# warns when a local buffer outgrows that: it builds
|
||||
# everywhere and overflows only on a target most contributors
|
||||
# cannot build. config_file_write() carried a 16 KiB stdio
|
||||
# buffer as a local - twice that stack - on a path reached
|
||||
# from a task handler, and nothing noticed.
|
||||
python3 tools/stack_budget.py
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
|
||||
companion-tests:
|
||||
name: Companion regression tests
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential pkg-config zlib1g-dev ffmpeg ccache gcc-mingw-w64-i686 gcc-mingw-w64-x86-64 gobjc gnustep-devel gnustep-back-common xvfb wine
|
||||
# beside the suites, not after them: together they took twice as
|
||||
# long as either
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Check companion backend feature parity
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# The Qt, Win32 and Cocoa desktop companions share one C core
|
||||
# but each has its own presentation; a backend can quietly omit
|
||||
# a feature (no file browser, no scan, no core picker) and still
|
||||
# build and run, the gap only showing when a user switches
|
||||
# drivers. Source-level check, for free, on Linux.
|
||||
tools/check.sh tools/companion_parity.c
|
||||
|
||||
- name: Companion thumbnail engine regression test (plain, TSan, ASan)
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# The shared thumbnail engine every desktop companion draws
|
||||
# through: real decoder, decode threads, cache, priority,
|
||||
# cancel, shutdown, and one hover on a video (the still and
|
||||
# the animation share one session). Under both sanitizers,
|
||||
# since it is the one piece of threaded code in the
|
||||
# companions.
|
||||
tools/companion_thumbs_test.sh
|
||||
tools/companion_thumbs_test.sh tsan
|
||||
tools/companion_thumbs_test.sh asan
|
||||
|
||||
- name: Companion core regression test (plain, ASan)
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# The toolkit-free model every desktop companion drives:
|
||||
# playlist listing and All Playlists, the thumbnail path rule,
|
||||
# the file browser, the run / needs-core paths, launch
|
||||
# options - against real .lpl fixtures, with RetroArch's
|
||||
# state replaced by stubs.
|
||||
tools/companion_core_test.sh
|
||||
tools/companion_core_test.sh asan
|
||||
tools/companion_core_test.sh tsan
|
||||
|
||||
- name: C89 / Win32 syntax gate on the companion sources
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# MSVC 2005 builds these as C89 through griffin. The gate's
|
||||
# second pass needs a 32-bit mingw for the Windows-only unit
|
||||
# (the host gcc has no <windows.h>, which used to make the
|
||||
# pass skip it silently - that is how mixed declarations
|
||||
# reached master).
|
||||
tools/mingw_syntax_check.sh ui/drivers/ui_win32_companion.c \
|
||||
ui/companion/companion_core.c ui/companion/companion_thumbs.c \
|
||||
ui/companion/companion_dock.c \
|
||||
gfx/gfx_anim_preview.c
|
||||
|
||||
- name: Cocoa companion regression harness (GNUstep AppKit, headless)
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# The real ui/drivers/ui_cocoa_companion.m, compiled and linked
|
||||
# against GNUstep's Foundation + AppKit with the real companion
|
||||
# core and the core test's fixtures, driven under Xvfb the way a
|
||||
# user drives it (view popup, File Browser tab, close) and
|
||||
# checked on the AppKit objects themselves.
|
||||
tools/companion_cocoa_test.sh
|
||||
# ASan too: the grid's prefetch reaching past the thumbnail
|
||||
# marks only shows under a checking allocator (it crashed the
|
||||
# app on macOS, where Apple's is one).
|
||||
tools/companion_cocoa_test.sh asan
|
||||
|
||||
- name: Win32 companion regression harness (mingw + Wine, headless)
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# The real ui/drivers/ui_win32_companion.c, built with mingw and
|
||||
# linked with the real companion core and the core test's
|
||||
# fixtures, run under Wine on Xvfb and driven with the messages
|
||||
# the widgets send; checked on the real controls.
|
||||
tools/companion_win32_test.sh
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,217 +0,0 @@
|
||||
name: CI Linux libretro-db samples
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
samples:
|
||||
name: Build and run libretro-db/samples
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential zlib1g-dev ccache
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build and run samples
|
||||
shell: bash
|
||||
working-directory: libretro-db/samples
|
||||
env:
|
||||
# Build samples under AddressSanitizer + UndefinedBehaviorSanitizer.
|
||||
# Both libretro-db sample tests support this via the SANITIZER=
|
||||
# convention also used in samples/tasks/http/Makefile. ASan
|
||||
# catches any reintroduced leak (intfstream_t in libretrodb_open
|
||||
# / cursor_close, etc.) and any out-of-bounds memory access, so
|
||||
# this is the regression-protective build for these tests.
|
||||
MAKE_ARGS: "SANITIZER=address,undefined"
|
||||
run: |
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
# Samples whose binary, when invoked with no arguments, runs a
|
||||
# self-contained test and exits 0 on success / non-zero on
|
||||
# failure. These are built AND executed.
|
||||
declare -a RUN_TARGETS=(
|
||||
rmsgpack_overflow_test
|
||||
libretrodb_leak_test
|
||||
)
|
||||
|
||||
# Per-binary run command (overrides ./<binary> if present).
|
||||
declare -A RUN_ENV=()
|
||||
|
||||
# Samples that are build-only.
|
||||
declare -a BUILD_ONLY_DIRS=(
|
||||
)
|
||||
|
||||
# Samples that are currently broken at build time on a stock
|
||||
# Ubuntu host and are therefore neither built nor run.
|
||||
declare -a SKIP_DIRS=(
|
||||
)
|
||||
|
||||
is_in() {
|
||||
local needle=$1; shift
|
||||
local h
|
||||
for h in "$@"; do [[ "$h" == "$needle" ]] && return 0; done
|
||||
return 1
|
||||
}
|
||||
|
||||
fails=0
|
||||
builds=0
|
||||
runs=0
|
||||
|
||||
# Collect all Makefile directories (one or two levels deep).
|
||||
mapfile -t MKDIRS < <(find . -name Makefile -printf '%h\n' | sort)
|
||||
|
||||
printf '\n==> %d sample directories found\n' "${#MKDIRS[@]}"
|
||||
for d in "${MKDIRS[@]}"; do printf ' %s\n' "${d#./}"; done
|
||||
printf '\n'
|
||||
|
||||
for d in "${MKDIRS[@]}"; do
|
||||
rel=${d#./}
|
||||
printf '========================================\n'
|
||||
printf '[%s] %s\n' "$(is_in "$rel" "${SKIP_DIRS[@]}" && echo skip || echo build)" "$rel"
|
||||
printf '========================================\n'
|
||||
|
||||
if is_in "$rel" "${SKIP_DIRS[@]}"; then
|
||||
printf '[skip] %s is on the skip list\n\n' "$rel"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Build
|
||||
if ! ( cd "$d" && make clean all $MAKE_ARGS ); then
|
||||
printf '\n::error title=Build failed::%s failed to build\n' "$rel"
|
||||
fails=$((fails+1))
|
||||
continue
|
||||
fi
|
||||
builds=$((builds+1))
|
||||
|
||||
# Skip run for build-only dirs
|
||||
if is_in "$rel" "${BUILD_ONLY_DIRS[@]}"; then
|
||||
printf '[skip-run] %s (build-only list)\n\n' "$rel"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Extract targets from Makefile. Handles:
|
||||
# TARGET := foo
|
||||
# TARGETS = a b c
|
||||
# TARGET_TEST := foo_test
|
||||
# TARGET_TEST2 := foo_test2
|
||||
mapfile -t targets < <(
|
||||
grep -hE '^(TARGET|TARGETS|TARGET_TEST[0-9]*)[[:space:]]*[:?]?=' "$d/Makefile" \
|
||||
| sed -E 's/^[^=]*=[[:space:]]*//' \
|
||||
| tr -s ' \t' '\n' \
|
||||
| grep -v '^$' \
|
||||
| sort -u
|
||||
)
|
||||
|
||||
for t in "${targets[@]}"; do
|
||||
if ! is_in "$t" "${RUN_TARGETS[@]}"; then
|
||||
printf '[skip-run] %s/%s (not in run allowlist)\n' "$rel" "$t"
|
||||
continue
|
||||
fi
|
||||
|
||||
bin="$d/$t"
|
||||
if [[ ! -x "$bin" ]]; then
|
||||
printf '::error title=Missing binary::%s was in the run allowlist but %s does not exist after build\n' "$t" "$bin"
|
||||
fails=$((fails+1))
|
||||
continue
|
||||
fi
|
||||
|
||||
extra_env=${RUN_ENV[$t]:-}
|
||||
|
||||
printf '\n[run] %s\n' "$bin"
|
||||
if ( cd "$d" && env $extra_env timeout 60 "./$t" ); then
|
||||
printf '[pass] %s\n\n' "$t"
|
||||
runs=$((runs+1))
|
||||
else
|
||||
rc=$?
|
||||
printf '\n::error title=Test failed::%s exited with status %d\n' "$t" "$rc"
|
||||
fails=$((fails+1))
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
printf '========================================\n'
|
||||
printf 'Summary\n'
|
||||
printf '========================================\n'
|
||||
printf ' Built: %d\n' "$builds"
|
||||
printf ' Ran: %d\n' "$runs"
|
||||
printf ' Failed: %d\n' "$fails"
|
||||
|
||||
if [[ $fails -gt 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,72 +0,0 @@
|
||||
name: CI Linux MCP over stdio
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
mcp-stdio:
|
||||
name: retroarch --mcp-stdio driving a core
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential pkg-config zlib1g-dev libfreetype6-dev python3 ccache
|
||||
timeout-minutes: 40
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Build RetroArch and the views test core
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
./configure --disable-qt --disable-ffmpeg --disable-vulkan \
|
||||
--disable-wayland --disable-x11 --disable-opengl
|
||||
grep -q '^HAVE_MCP = 1' config.mk
|
||||
make -j"$(nproc)" CC="ccache gcc" CXX="ccache g++"
|
||||
make -C samples/cores/video_views
|
||||
|
||||
- name: MCP over stdin and stdout, end to end
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# null drivers: no display on the runner
|
||||
timeout 300 python3 samples/network/mcp_server/stdio_e2e.py \
|
||||
./retroarch samples/cores/video_views/video_views_libretro.so
|
||||
@@ -1,475 +0,0 @@
|
||||
name: CI Linux menu harness
|
||||
|
||||
# The menu playlist navigation harness links the SHIPPING RetroArch
|
||||
# objects with only main() replaced, so unlike every other sample it
|
||||
# needs a full build of the program before it can be built at all.
|
||||
#
|
||||
# That is why it lives in its own workflow rather than in
|
||||
# Linux-samples-tasks: a full build does not fit inside that job's
|
||||
# ten-minute budget, and putting it there cancelled the whole job -
|
||||
# every other sample with it - rather than just failing its own step.
|
||||
# Here it can take the time it needs without being able to take
|
||||
# anything else down with it.
|
||||
#
|
||||
# It also needs a NON-Qt build: with Qt enabled main() lives in
|
||||
# ui_qt.o and drags the entire Qt UI in with it.
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'menu/**'
|
||||
- 'playlist.c'
|
||||
- 'playlist.h'
|
||||
- 'tasks/task_content*'
|
||||
- 'samples/menu/playlist_nav/**'
|
||||
- 'samples/network/command_frames/**'
|
||||
- 'samples/menu/nav_repeat_stall/**'
|
||||
- 'samples/menu/mouse_click/**'
|
||||
- 'samples/menu/menu_icon_ownership/**'
|
||||
- 'samples/menu/ozone_sublabel_scroll/**'
|
||||
- 'gfx/gfx_display.c'
|
||||
- 'runloop.c'
|
||||
- 'samples/menu/network_settings/**'
|
||||
- 'intl/msg_hash_lbl.h'
|
||||
- 'msg_hash_lbl_str.h'
|
||||
- 'samples/menu/resolution_reset/**'
|
||||
- 'samples/menu/setting_command/**'
|
||||
- 'samples/menu/core_info_page/**'
|
||||
- 'samples/menu/load_content_filter/**'
|
||||
- 'samples/settings/packed_rows/**'
|
||||
- 'setting_list.h'
|
||||
- 'gfx/video_defines.h'
|
||||
- '.github/workflows/Linux-menu-harness.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'menu/**'
|
||||
- 'playlist.c'
|
||||
- 'playlist.h'
|
||||
- 'tasks/task_content*'
|
||||
- 'samples/menu/playlist_nav/**'
|
||||
- 'samples/network/command_frames/**'
|
||||
- 'samples/menu/nav_repeat_stall/**'
|
||||
- 'samples/menu/mouse_click/**'
|
||||
- 'samples/menu/menu_icon_ownership/**'
|
||||
- 'samples/menu/ozone_sublabel_scroll/**'
|
||||
- 'gfx/gfx_display.c'
|
||||
- 'runloop.c'
|
||||
- 'samples/menu/network_settings/**'
|
||||
- 'intl/msg_hash_lbl.h'
|
||||
- 'msg_hash_lbl_str.h'
|
||||
- 'samples/menu/resolution_reset/**'
|
||||
- 'samples/menu/setting_command/**'
|
||||
- 'samples/menu/core_info_page/**'
|
||||
- 'samples/menu/load_content_filter/**'
|
||||
- 'samples/settings/packed_rows/**'
|
||||
- 'setting_list.h'
|
||||
- 'gfx/video_defines.h'
|
||||
- '.github/workflows/Linux-menu-harness.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
menu-harness:
|
||||
name: Build and run the menu navigation harness
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential zlib1g-dev ccache
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build RetroArch headless
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The harness drives the menu with the null drivers, so
|
||||
# everything that draws or talks to the network is dead
|
||||
# weight here - and building it is the entire cost of this
|
||||
# workflow. Disabling it takes the build from roughly ten
|
||||
# minutes to about three, and avoids depending on graphics
|
||||
# packages the runner may or may not carry: configure found
|
||||
# X11 and xcb but not libX11-xcb, and the link failed on
|
||||
# -lX11-xcb.
|
||||
#
|
||||
# Qt in particular has to go: with it enabled main() lives
|
||||
# in ui_qt.o, and the harness replaces main().
|
||||
# Networking stays on: the network settings harness below
|
||||
# needs the SMB and NFS client screens compiled in.
|
||||
./configure --disable-qt --disable-x11 \
|
||||
--disable-opengl --disable-opengl_core \
|
||||
--disable-opengl1 --disable-vulkan \
|
||||
--disable-cheevos \
|
||||
--disable-ffmpeg
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build and run content_closing_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The guard that keeps the frame loop out of a core being
|
||||
# torn down (core_run() refusing retro_run() while
|
||||
# content_closing is set) cannot fire in shipped code yet:
|
||||
# closing is still synchronous, so no frame runs during it.
|
||||
# It goes live in the change that first lets frames run
|
||||
# during a close, and if it is wrong the symptom is a call
|
||||
# into an unloaded dylib - so it is driven here directly,
|
||||
# against the real core_run() in a real frontend, rather
|
||||
# than going live untested.
|
||||
#
|
||||
# Shares the non-Qt build made above; adds about a second.
|
||||
samples/runloop/content_closing/build.sh
|
||||
./samples/runloop/content_closing/content_closing_test
|
||||
make -C samples/runloop/content_closing clean
|
||||
|
||||
- name: Build and run cloudsync_unload_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Closing content with Cloud Sync in automatic mode asks for
|
||||
# a sync; it has to start once the content's save RAM is on
|
||||
# disk and no core owns the file, which a close from the
|
||||
# menu reaches a frame or more later. The real retroarch.c,
|
||||
# a core with save RAM, and task_push_cloud_sync wrapped at
|
||||
# link time to record what the save file held when the sync
|
||||
# was asked for. No server is contacted.
|
||||
#
|
||||
# Shares the non-Qt build made above.
|
||||
samples/runloop/cloudsync_unload/build.sh
|
||||
./samples/runloop/cloudsync_unload/cloudsync_unload_test
|
||||
make -C samples/runloop/cloudsync_unload clean
|
||||
|
||||
- name: Build and run menu_playlist_nav_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Four field reports came out of the seam between the
|
||||
# playlist reader and the menu - a stale playlist's entries
|
||||
# under a new heading, then a blank list the back button
|
||||
# could not leave, then a list that filled only after the
|
||||
# user pressed something, then #19427's placeholder flashing
|
||||
# on every completed read - and no oracle that stopped at
|
||||
# the reader could see any of them.
|
||||
#
|
||||
# The harness installs a VFS through the seam the frontend
|
||||
# uses for SAF, returning short reads WITH a per-read delay.
|
||||
# Short reads alone reproduce SAF's syscall count but not
|
||||
# its latency, and on local storage the whole playlist still
|
||||
# fits inside one budget slice - which is exactly why none
|
||||
# of the three reports reproduced on a desktop.
|
||||
samples/menu/playlist_nav/build.sh
|
||||
./samples/menu/playlist_nav/menu_playlist_nav_test
|
||||
make -C samples/menu/playlist_nav clean
|
||||
|
||||
- name: Build and run menu_nav_repeat_stall_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# One press on a menu entry whose frame stalls - Ozone and
|
||||
# XMB build a large playlist synchronously when the selection
|
||||
# lands on it - has to move the selection once. The menu acts
|
||||
# on input one poll old, so the hold time has to be measured
|
||||
# between polls or the stall fires an auto-repeat. Drives the
|
||||
# real runloop with a scripted input driver; also checks that
|
||||
# a hold across the stall still repeats and that a steady hold
|
||||
# waits out the initial scroll delay. Shares the non-Qt build
|
||||
# made above.
|
||||
samples/menu/nav_repeat_stall/build.sh
|
||||
./samples/menu/nav_repeat_stall/menu_nav_repeat_stall_test
|
||||
make -C samples/menu/nav_repeat_stall clean
|
||||
|
||||
- name: Build and run menu_icon_ownership_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Every texture handle the menu drivers hold, accounted for
|
||||
# against a counting null driver: a handle unloaded twice or
|
||||
# still live at deinit fails the lane. Ozone's sidebar wrote
|
||||
# the shared cursor texture into a playlist node whose own
|
||||
# icon had not landed, and the context destroy then freed the
|
||||
# cursor twice - a heap-corruption crash at startup under
|
||||
# threaded video. MaterialUI's playlist icon array could be
|
||||
# rebuilt under a decode still in flight. The contentless
|
||||
# cores list's icons, fallback and per core, go at deinit.
|
||||
# Shares the non-Qt build made above; one binary, one run per
|
||||
# lane.
|
||||
samples/menu/menu_icon_ownership/build.sh
|
||||
./samples/menu/menu_icon_ownership/menu_icon_ownership_test ozone
|
||||
./samples/menu/menu_icon_ownership/menu_icon_ownership_test xmb
|
||||
./samples/menu/menu_icon_ownership/menu_icon_ownership_test materialui
|
||||
./samples/menu/menu_icon_ownership/menu_icon_ownership_test contentless
|
||||
make -C samples/menu/menu_icon_ownership clean
|
||||
|
||||
- name: Build and run ozone_sublabel_scroll_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Ozone with sublabels on the selected entry only: a selection
|
||||
# change asking for no animation moves the list at once, an
|
||||
# animated one tweens and fades the cursor once, the list
|
||||
# behind the sidebar follows a new selection, and a selection
|
||||
# past the end is not taken for a new one on every compute.
|
||||
# Shares the non-Qt build made above.
|
||||
samples/menu/ozone_sublabel_scroll/build.sh
|
||||
./samples/menu/ozone_sublabel_scroll/ozone_sublabel_scroll_test
|
||||
make -C samples/menu/ozone_sublabel_scroll clean
|
||||
|
||||
- name: Build and run menu_mouse_click_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# A left click in the menu has to select the entry under the
|
||||
# pointer. The pen support gave every pointer that is not a
|
||||
# touchscreen no gesture on release, and a mouse's left click
|
||||
# reaches the menu drivers as a tap gesture, so the click was
|
||||
# thrown away in every menu driver while movement, the wheel
|
||||
# and the right button kept working. Drives the real runloop
|
||||
# with a scripted mouse: points at Settings by asking the menu
|
||||
# which entry is under the pointer, opens it with a left
|
||||
# click, scrolls its list with the wheel, goes back with a
|
||||
# right click, and checks a long press is not a click. Shares
|
||||
# the non-Qt build made above.
|
||||
samples/menu/mouse_click/build.sh
|
||||
./samples/menu/mouse_click/menu_mouse_click_test
|
||||
make -C samples/menu/mouse_click clean
|
||||
|
||||
- name: Build and run menu_network_settings_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The NFS Network Settings entry opened an empty "null"
|
||||
# browser: the label its deferred list is pushed with had no
|
||||
# row in msg_hash_lbl.h, so it resolved to "null" and the
|
||||
# push found nothing. The harness resolves the SMB and NFS
|
||||
# labels, opens Settings > Network and both screens through
|
||||
# the real dispatch, and checks the Quick Menu no longer
|
||||
# carries the two entries.
|
||||
samples/menu/network_settings/build.sh
|
||||
./samples/menu/network_settings/menu_network_settings_test
|
||||
make -C samples/menu/network_settings clean
|
||||
|
||||
- name: Build and run resolution_reset_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Start on the Resolution entry reinits and sets the video
|
||||
# mode at the output size; it must keep the window state the
|
||||
# frontend is in rather than take a windowed desktop session
|
||||
# full screen. Shares the non-Qt build made above.
|
||||
samples/menu/resolution_reset/build.sh
|
||||
./samples/menu/resolution_reset/resolution_reset_test
|
||||
make -C samples/menu/resolution_reset clean
|
||||
|
||||
- name: Build and run packed_rows_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Settings rows that each own one half of a packed settings_t
|
||||
# word - the custom viewport's origin and size, the window
|
||||
# size pair - driven through their display strings, a right
|
||||
# press and the dropdown list. Each row has to show and set
|
||||
# its own axis and leave its partner as it stands. Shares the
|
||||
# non-Qt build made above.
|
||||
samples/settings/packed_rows/build.sh
|
||||
./samples/settings/packed_rows/packed_rows_test
|
||||
make -C samples/settings/packed_rows clean
|
||||
|
||||
- name: Build and run setting_command_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# A press on a settings row whose command reinitialises the
|
||||
# video driver has to bring the driver up once, on the first
|
||||
# press and on every later one, whether or not the row
|
||||
# applies its command by itself. Shares the non-Qt build
|
||||
# made above.
|
||||
samples/menu/setting_command/build.sh
|
||||
./samples/menu/setting_command/setting_command_test
|
||||
make -C samples/menu/setting_command clean
|
||||
|
||||
- name: Hot function budget
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Code size and stack frame of the functions that run every
|
||||
# frame, against a checked-in reference: a change that doubles
|
||||
# either passes every lane in the suite and shows up only as a
|
||||
# slower frame on someone's machine. Uses the release objects
|
||||
# this job already built.
|
||||
.github/workflows/scripts/hot-function-budget.sh
|
||||
|
||||
- name: Lock budget
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Lock acquisitions on the paths meant to take none, or a
|
||||
# counted few, against tools/lock_acquire_budget.ref: a lock
|
||||
# put back on a per-frame path passes every lane and shows up
|
||||
# only as a slower frame. Same release objects as above; this
|
||||
# build has no Vulkan, so the Vulkan entries report SKIP.
|
||||
tools/lock_acquire_budget.sh
|
||||
|
||||
- name: Wait budget
|
||||
run: |
|
||||
# Main-thread waits on the video thread, per file, against
|
||||
# tools/wait_budget.ref: a count that only comes down.
|
||||
tools/wait_budget.sh
|
||||
|
||||
- name: Build and run threaded_video_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The threaded video wrapper against the real runloop, on the
|
||||
# same non-Qt menu build: the runtime toggle, reinit under the
|
||||
# wrapper, the command mailbox, presenter repeats, and the
|
||||
# font init/free marshalling - the last of which is where a
|
||||
# deferred font free unbound the video thread's GL context on
|
||||
# X11 and left every frame after it black. This build has no
|
||||
# allocator sanitizer, so it is also the one job where the
|
||||
# frame-path heap lane runs: it counts heap calls over three
|
||||
# hundred frames, threaded and not, and the frame path makes
|
||||
# none.
|
||||
samples/gfx/threaded_video/build.sh
|
||||
./samples/gfx/threaded_video/threaded_video_test 3
|
||||
make -C samples/gfx/threaded_video clean
|
||||
|
||||
- name: Build and run content_load_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The content load as a chain of main-thread tasks, against the
|
||||
# real runloop on the same non-Qt menu build: frames presented
|
||||
# between stages, one load at a time, a core's reinit deferred
|
||||
# to the load's driver stage, the dummy-core fallback, a
|
||||
# hardware-render request carried across the driver rebuild,
|
||||
# the task queue surviving the load, and the close waiting out
|
||||
# a save state from the frame loop.
|
||||
samples/tasks/content_load/build.sh
|
||||
./samples/tasks/content_load/content_load_test
|
||||
make -C samples/tasks/content_load clean
|
||||
|
||||
- name: Build and run video_filter_menu_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The menu's Video Filter and Video Filter Enable rows get the
|
||||
# driver the frames they make - a chosen filter's scale and
|
||||
# format, the core's or the filter's format as Enable turns it
|
||||
# off and on: told in place to a driver that takes it
|
||||
# (set_frame_format), set up again otherwise, and nothing at
|
||||
# all when the frames do not change.
|
||||
samples/gfx/video_filter_menu/build.sh
|
||||
./samples/gfx/video_filter_menu/video_filter_menu_test
|
||||
# Under the threaded wrapper too: a filter swapped without
|
||||
# waiting for the video thread, the old one freed behind the
|
||||
# frames staged with it
|
||||
HARNESS_THREADED=1 ./samples/gfx/video_filter_menu/video_filter_menu_test
|
||||
make -C samples/gfx/video_filter_menu clean
|
||||
|
||||
- name: Build and run core_info_page_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The running core's information - its current-core entry,
|
||||
# Core Information in the Information menu and the page
|
||||
# itself - comes from its info file, once it is up and again
|
||||
# after the drivers are set up again under it.
|
||||
samples/menu/core_info_page/build.sh
|
||||
./samples/menu/core_info_page/core_info_page_test
|
||||
make -C samples/menu/core_info_page clean
|
||||
|
||||
- name: Build and run load_content_filter_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Load Content with no core lists every file an installed core
|
||||
# or a built-in player opens, however long the installed cores'
|
||||
# extensions run together.
|
||||
samples/menu/load_content_filter/build.sh
|
||||
./samples/menu/load_content_filter/load_content_filter_test
|
||||
make -C samples/menu/load_content_filter clean
|
||||
|
||||
- name: Build and run explore_build_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The Explore index built in steps: one item per step hashes
|
||||
# the same as the build in one go, and the explore task returns
|
||||
# unfinished across checks with Threaded Tasks off.
|
||||
samples/menu/explore_build/build.sh
|
||||
./samples/menu/explore_build/explore_build_test
|
||||
make -C samples/menu/explore_build clean
|
||||
|
||||
- name: Frame command progress through the real runloop
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
make -C samples/network/command_frames check
|
||||
make -C samples/network/command_frames clean
|
||||
|
||||
- name: Structured HDR queries through the real frontend
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
make -j$(nproc)
|
||||
python3 samples/gfx/hdr_metadata/live.py --retroarch ./retroarch --log-dir /tmp/hdr-metadata-live
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,130 +0,0 @@
|
||||
name: CI fullscreen media menu
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
workflow_dispatch:
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
rgui-media:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: ffmpeg
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
matrix:
|
||||
threads: [enable, disable]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Configure C89 frontend
|
||||
run: ./configure --disable-qt --disable-vulkan --disable-wayland --disable-x11 --disable-opengl --disable-opengl1 --disable-opengl_core --disable-ffmpeg --disable-cheevos --enable-webmplayer --${{ matrix.threads }}-threads
|
||||
- name: Build shipping frontend
|
||||
run: make -j2 C89_BUILD=1
|
||||
- name: Generate movie fixture
|
||||
run: ffmpeg -v error -y -f lavfi -i testsrc2=size=320x240:rate=30 -f lavfi -i sine=frequency=440:sample_rate=48000 -t 3 -c:v libx264 -preset ultrafast -pix_fmt yuv420p -c:a aac -shortest samples/menu/rgui_media/fixture.mp4
|
||||
- name: Real RGUI framebuffer and playback controls
|
||||
run: python3 samples/menu/rgui_media/run.py --c89 samples/menu/rgui_media/fixture.mp4
|
||||
- name: Real MaterialUI file-browser playback controls
|
||||
run: python3 samples/menu/rgui_media/run.py --c89 --driver materialui samples/menu/rgui_media/fixture.mp4
|
||||
- name: Real XMB file-browser playback controls
|
||||
run: python3 samples/menu/rgui_media/run.py --c89 --driver xmb samples/menu/rgui_media/fixture.mp4
|
||||
- name: Real Ozone file-browser playback controls
|
||||
run: python3 samples/menu/rgui_media/run.py --c89 --driver ozone samples/menu/rgui_media/fixture.mp4
|
||||
- name: External movies and internal image activation across all menus
|
||||
run: |
|
||||
ffmpeg -v error -y -f lavfi -i color=c=orange:size=32x32 -frames:v 1 -threads 1 samples/menu/rgui_media/fixture.png
|
||||
for driver in rgui materialui xmb ozone; do
|
||||
python3 samples/menu/rgui_media/run.py --c89 --external --driver "$driver" samples/menu/rgui_media/fixture.mp4
|
||||
python3 samples/menu/rgui_media/run.py --c89 --external --driver "$driver" samples/menu/rgui_media/fixture.png
|
||||
python3 samples/menu/rgui_media/run.py --c89 --browser-image --driver "$driver" samples/menu/rgui_media/fixture.png
|
||||
done
|
||||
- name: Natural MP4 folder playback and file controls across all menus
|
||||
run: |
|
||||
for driver in rgui materialui xmb ozone; do
|
||||
python3 samples/menu/rgui_media/run.py --c89 --continuous --fullscreen-settings --require-cadence --driver "$driver" samples/menu/rgui_media/fixture.mp4
|
||||
python3 samples/menu/rgui_media/run.py --c89 --continuous-error --driver "$driver" samples/menu/rgui_media/fixture.mp4
|
||||
done
|
||||
- name: Desktop refresh source lifecycle across all menus
|
||||
run: |
|
||||
for driver in rgui materialui xmb ozone; do
|
||||
python3 samples/menu/rgui_media/run.py --c89 --desktop-refresh --driver "$driver" samples/menu/rgui_media/fixture.mp4
|
||||
done
|
||||
- name: Generate WebM transport fixtures
|
||||
run: |
|
||||
ffmpeg -v error -y -f lavfi -i testsrc2=size=320x240:rate=30 -f lavfi -i sine=frequency=440:sample_rate=48000 -t 3 -c:v libvpx -deadline realtime -cpu-used 8 -g 30 -auto-alt-ref 0 -c:a libopus -shortest samples/menu/rgui_media/fixture-opus.webm
|
||||
ffmpeg -v error -y -f lavfi -i testsrc2=size=320x240:rate=30 -f lavfi -i sine=frequency=440:sample_rate=48000 -t 3 -c:v libvpx-vp9 -g 30 -auto-alt-ref 0 -c:a libvorbis -shortest samples/menu/rgui_media/fixture-vorbis.webm
|
||||
- name: Real WebM controls across all four menus
|
||||
run: |
|
||||
for driver in rgui materialui xmb ozone; do
|
||||
python3 samples/menu/rgui_media/run.py --c89 --driver "$driver" samples/menu/rgui_media/fixture-opus.webm
|
||||
python3 samples/menu/rgui_media/run.py --c89 --driver "$driver" samples/menu/rgui_media/fixture-vorbis.webm
|
||||
done
|
||||
- name: Natural WebM folder playback across all menus
|
||||
run: |
|
||||
for driver in rgui materialui xmb ozone; do
|
||||
python3 samples/menu/rgui_media/run.py --c89 --continuous --fullscreen-settings --require-cadence --driver "$driver" samples/menu/rgui_media/fixture-vorbis.webm
|
||||
python3 samples/menu/rgui_media/run.py --c89 --continuous-error --driver "$driver" samples/menu/rgui_media/fixture-vorbis.webm
|
||||
done
|
||||
|
||||
window-toggle-media:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
APT_PKGS: ffmpeg xvfb xauth libgl1-mesa-dev libx11-dev libxext-dev libxrandr-dev
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
- name: Configure C89 GL frontend
|
||||
run: ./configure --disable-qt --disable-vulkan --disable-wayland --disable-ffmpeg --disable-cheevos --enable-webmplayer
|
||||
- name: Build shipping frontend
|
||||
run: make -j2 C89_BUILD=1
|
||||
- name: Generate moving VP8 fixture
|
||||
run: ffmpeg -v error -y -f lavfi -i "testsrc2=size=320x240:rate=30,hue=h=90*t" -t 3 -c:v libvpx -deadline realtime -cpu-used 8 -g 90 -auto-alt-ref 0 samples/menu/rgui_media/window-toggle.webm
|
||||
- name: Fullscreen window transitions retain movie pixels and seeking
|
||||
run: |
|
||||
for driver in rgui materialui xmb ozone; do
|
||||
for threaded in '' --threaded; do
|
||||
xvfb-run -a python3 samples/menu/rgui_media/run.py --c89 --window-toggle --video-driver gl --driver "$driver" $threaded samples/menu/rgui_media/window-toggle.webm
|
||||
done
|
||||
done
|
||||
@@ -1,144 +0,0 @@
|
||||
name: CI Visual C++ 6 project (stand-in compiler)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
msvc6-standin:
|
||||
name: The Visual C++ 6 project's sources, defines and libraries, on mingw held to old C
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: --no-install-recommends gcc-mingw-w64-i686 g++-mingw-w64-i686 gcc-mingw-w64-x86-64 wine64 pulseaudio xvfb
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 15
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Compile and link what pkg/msvc/msvc-6 builds
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Visual C++ 6 cannot be fetched here, so nothing built its
|
||||
# project. This reads the project file - sources, defines,
|
||||
# libraries - and builds the same with a 32-bit mingw
|
||||
# compiler under old-C rules, at Windows NT 4.0's API, and
|
||||
# links it. See the script for what that does and does not
|
||||
# catch.
|
||||
tools/msvc6_standin_check.sh
|
||||
|
||||
- name: The DXGI bridge as Visual C++ 2005 and 2010 build it
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Their SDKs have no dxgi1_5.h or d3d12.h; the griffin builds
|
||||
# for them still compile and link the bridge.
|
||||
tools/dxgi_bridge_old_sdk_check.sh
|
||||
|
||||
- name: Run the waveout audio driver on a wave output device (Wine)
|
||||
working-directory: samples/audio/waveout
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The audio driver the Visual C++ 6 project uses: the
|
||||
# multimedia library's wave output, which is all a Windows
|
||||
# with no DirectX has. Run for real against a device - a
|
||||
# silent one, from a sound server started here - and held to
|
||||
# what the audio interface says of a driver. With no device
|
||||
# the test only skips, which checks nothing: that is a
|
||||
# failure here.
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true; pulseaudio --kill >/dev/null 2>&1 || true' EXIT
|
||||
pulseaudio --start --exit-idle-time=-1
|
||||
pactl load-module module-null-sink sink_name=ci >/dev/null
|
||||
pactl set-default-sink ci
|
||||
WINE=$(command -v wine64 || command -v wine || echo /usr/lib/wine/wine64)
|
||||
make clean && make -j$(nproc) all
|
||||
WINEDEBUG=-all timeout 300 make check WINE="$WINE" | tee waveout.log
|
||||
grep -q "PASS waveout_test" waveout.log
|
||||
make clean
|
||||
rm -f waveout.log
|
||||
|
||||
- name: Run the plain Win32 input driver against a window (Wine)
|
||||
working-directory: samples/input/win32_input
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The input driver the Visual C++ 6 project uses: keys from
|
||||
# the window's messages, the mouse from where the cursor is.
|
||||
# Run against a real window: its key map, keys down and up,
|
||||
# nothing down with another window in front, the mouse's
|
||||
# place and motion. A part it had to skip - no window, or one
|
||||
# that would not come to the front - checks nothing, and is a
|
||||
# failure here.
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
WINE=$(command -v wine64 || command -v wine || echo /usr/lib/wine/wine64)
|
||||
make clean && make -j$(nproc) all
|
||||
WINEDEBUG=-all timeout 300 make check WINE="$WINE" | tee win32_input.log
|
||||
grep -q "PASS win32_input_test" win32_input.log
|
||||
if grep -q "^\[skip\]" win32_input.log; then
|
||||
echo "a part of the test was skipped"
|
||||
exit 1
|
||||
fi
|
||||
make clean
|
||||
rm -f win32_input.log
|
||||
|
||||
- name: Run the winmm joypad driver against stand-in joystick calls (Wine)
|
||||
working-directory: samples/input/winmm_joypad
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The joypad driver the Visual C++ 6 project uses: the
|
||||
# multimedia library's joystick calls. No controller can be
|
||||
# scripted here, so the calls and the clock are the test's:
|
||||
# axes across the controller's own ranges, thirty-two
|
||||
# buttons, the hat's eight ways, the RetroPad mask, a
|
||||
# controller pulled out and plugged in, and the controllers
|
||||
# that are not there not asked at every poll.
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
WINE=$(command -v wine64 || command -v wine || echo /usr/lib/wine/wine64)
|
||||
make clean && make -j$(nproc) all
|
||||
WINEDEBUG=-all timeout 300 make check WINE="$WINE" | tee winmm_joypad.log
|
||||
grep -q "PASS winmm_joypad_test" winmm_joypad.log
|
||||
make clean
|
||||
rm -f winmm_joypad.log
|
||||
@@ -1,282 +0,0 @@
|
||||
name: CI Linux network clients
|
||||
|
||||
# The built-in TLS, SMB2/3 and NFSv3 clients against real servers:
|
||||
# openssl s_server, Samba, unfs3, nfs-ganesha and a MIT KDC on the runner, natively, as Windows
|
||||
# builds under Wine, under ASan + UBSan + LSan, plus libFuzzer over the
|
||||
# parsers. Its own job so the libretro-common unit-test job keeps its
|
||||
# short budget.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
network-clients:
|
||||
name: TLS, SMB and NFS clients against local servers
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: --no-install-recommends build-essential clang gcc-mingw-w64-x86-64 openssl samba libtirpc-dev flex bison autoconf automake wine wine64 nfs-ganesha nfs-ganesha-vfs krb5-kdc krb5-admin-server krb5-user winbind samba-dsdb-modules samba-ad-provision samba-vfs-modules acl smbclient tshark
|
||||
timeout-minutes: 45
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Preseed tshark
|
||||
# dumpcap asks whether to be setuid: no, runs are root
|
||||
run: echo "wireshark-common wireshark-common/install-setuid boolean false" | sudo debconf-set-selections
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 25
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Built-in TLS client against a local openssl server
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# net_socket_ssl_retro.c end to end: every cipher suite, both
|
||||
# curves, RSA / P-256 / P-384 certificates under a CA made on
|
||||
# the spot, verify required / optional / disabled, and the
|
||||
# refusals that must happen (wrong hostname, untrusted CA). An
|
||||
# IP address matches only an iPAddress SAN entry, never the
|
||||
# same address written as a DNS name.
|
||||
samples/network/tls_retro/local_server_test.sh
|
||||
# The same tool cross-linked for Windows: the sample's link
|
||||
# line has to carry Winsock, which nothing on Linux checks.
|
||||
make -C samples/network/tls_retro clean
|
||||
|
||||
|
||||
- name: Built-in SMB2/3 client against a local smbd
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# net_smb2.c end to end against Samba on the loopback: every
|
||||
# dialect 2.0.2 to 3.1.1 with signing mandatory, AES-CCM and
|
||||
# AES-GCM sealing required, and a refused logon. Root for
|
||||
# port 445; the script itself skips without smbd.
|
||||
sudo samples/network/smb_retro/local_samba_test.sh
|
||||
# and with Kerberos against a Samba AD DC provisioned on the
|
||||
# spot, NTLM disabled on it so only a ticket can log in
|
||||
sudo samples/network/smb_retro/local_ad_dc_test.sh
|
||||
sudo make -C samples/network/smb_retro clean
|
||||
|
||||
- name: Embedded MCP server over the loopback
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# network/mcp_server.c as it ships, in front of a stub command
|
||||
# table: the handshake, the tool list and its hints, answers now
|
||||
# and later, the JSON-RPC errors, the HTTP gate (method, path,
|
||||
# Origin, the bearer token it will not start without), an
|
||||
# oversized body, a request in pieces, and teardown with a
|
||||
# request waiting
|
||||
make -C samples/network/mcp_server clean
|
||||
make -C samples/network/mcp_server SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 \
|
||||
make -C samples/network/mcp_server check
|
||||
make -C samples/network/mcp_server clean
|
||||
|
||||
- name: GET_LOG's ring, written from four threads while read
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
make -C samples/runloop/log_ring clean
|
||||
make -C samples/runloop/log_ring SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 \
|
||||
make -C samples/runloop/log_ring check
|
||||
make -C samples/runloop/log_ring clean
|
||||
|
||||
- name: Command options and speed setters
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
make -C samples/network/command_options clean
|
||||
make -C samples/network/command_options SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=halt_on_error=1 \
|
||||
make -C samples/network/command_options check
|
||||
make -C samples/network/command_options clean
|
||||
|
||||
|
||||
- name: Windows builds under Wine
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# The MinGW builds run, not just link: the crypto and keychain
|
||||
# suites, then the three server matrices with the Windows tools
|
||||
# talking to the same local openssl, Samba and unfs3.
|
||||
export WINEDEBUG=-all WINEPREFIX=$RUNNER_TEMP/wineprefix
|
||||
# the tools below are run through wine, so it must be there
|
||||
command -v wine >/dev/null
|
||||
# One wineserver for the whole step. Ubuntu's wrapper starts
|
||||
# it with -p0: it exits with each tool and the next tool
|
||||
# starts another. A tool that starts while the last server
|
||||
# is still on its way out is cut off by it before main()
|
||||
# ("wine client error:0: recvmsg: Connection reset by peer")
|
||||
# and the lane fails with nothing wrong in the tree. The
|
||||
# first process brings up Wine's services, which keep its
|
||||
# output for as long as they live, so it is given none.
|
||||
mkdir -p "$WINEPREFIX"
|
||||
wineserver -p
|
||||
trap 'wineserver -k || true; sudo -E env HOME=/root WINEPREFIX=/tmp/wineprefix-root wineserver -k || true' EXIT
|
||||
wine cmd /c exit > /dev/null 2>&1 < /dev/null
|
||||
make -C libretro-common -f Makefile.test win32-wine-check
|
||||
# the MCP server on Winsock
|
||||
make -C samples/network/mcp_server clean
|
||||
make -C samples/network/mcp_server compiler=x86_64-w64-mingw32-gcc
|
||||
(cd samples/network/mcp_server && wine ./mcp_server_test.exe)
|
||||
make -C samples/network/mcp_server clean
|
||||
make -C samples/network/command_options check compiler=x86_64-w64-mingw32-gcc RUNNER=wine
|
||||
make -C samples/network/command_options clean
|
||||
export CC=x86_64-w64-mingw32-gcc RUNNER=wine EXE=.exe
|
||||
make -C samples/network/tls_retro clean
|
||||
samples/network/tls_retro/local_server_test.sh
|
||||
make -C samples/network/tls_retro clean
|
||||
make -C samples/network/smb_retro clean
|
||||
# smbd needs root for port 445, and Wine refuses both a prefix
|
||||
# owned by someone else and creating one inside a directory it
|
||||
# does not own ($RUNNER_TEMP belongs to the runner user), so the
|
||||
# root run gets a prefix under /tmp with root's own HOME
|
||||
sudo -E env HOME=/root WINEPREFIX=/tmp/wineprefix-root sh -c 'mkdir -p "$WINEPREFIX" && wineserver -p'
|
||||
sudo -E env HOME=/root WINEPREFIX=/tmp/wineprefix-root wineboot -u > /dev/null 2>&1 < /dev/null
|
||||
sudo -E env HOME=/root WINEPREFIX=/tmp/wineprefix-root samples/network/smb_retro/local_samba_test.sh
|
||||
sudo -E env HOME=/root WINEPREFIX=/tmp/wineprefix-root samples/network/smb_retro/local_ad_dc_test.sh
|
||||
sudo make -C samples/network/smb_retro clean
|
||||
make -C samples/network/nfs_retro clean
|
||||
samples/network/nfs_retro/local_unfs3_test.sh
|
||||
make -C samples/network/nfs_retro clean
|
||||
sudo -E env HOME=/root WINEPREFIX=/tmp/wineprefix-root samples/network/nfs_retro/local_ganesha_test.sh
|
||||
sudo make -C samples/network/nfs_retro clean
|
||||
sudo -E env HOME=/root WINEPREFIX=/tmp/wineprefix-root samples/network/nfs_retro/local_read_plus_test.sh
|
||||
sudo make -C samples/network/nfs_retro clean
|
||||
make -C samples/network/krb5_retro clean
|
||||
samples/network/krb5_retro/local_kdc_test.sh
|
||||
make -C samples/network/krb5_retro clean
|
||||
|
||||
|
||||
- name: Fuzz the network parsers
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# libFuzzer over the X.509 parser and the TLS, SMB and NFS
|
||||
# clients' receive paths (a listener in the harness answers the
|
||||
# client with the fuzzer's input), under ASan + UBSan, from a
|
||||
# seed corpus recorded off real servers. Any crash, timeout or
|
||||
# leak artifact fails the step.
|
||||
make -C libretro-common/test/fuzz fuzz-run FUZZ_SECONDS=30
|
||||
if ls libretro-common/test/fuzz/crash-* libretro-common/test/fuzz/leak-* libretro-common/test/fuzz/timeout-* >/dev/null 2>&1; then
|
||||
echo "fuzzer artifacts found"; exit 1
|
||||
fi
|
||||
make -C libretro-common/test/fuzz clean
|
||||
|
||||
|
||||
- name: Network client matrices under ASan + UBSan + LSan
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# The three server matrices again, with the clients built under
|
||||
# the sanitizers: every code path a real server drives, checked
|
||||
# for memory errors, undefined behaviour and leaks. UBSan found
|
||||
# a NULL memcpy in the SHA-2 stream updates on the SHA-384 PRF
|
||||
# path the first time this ran.
|
||||
export CFLAGS="-O1 -g1 -fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
export LDFLAGS="-fsanitize=address,undefined"
|
||||
export ASAN_OPTIONS=detect_leaks=1:strict_string_checks=1
|
||||
export UBSAN_OPTIONS=print_stacktrace=1
|
||||
make -C samples/network/tls_retro clean
|
||||
samples/network/tls_retro/local_server_test.sh
|
||||
make -C samples/network/tls_retro clean
|
||||
make -C samples/network/smb_retro clean
|
||||
sudo -E samples/network/smb_retro/local_samba_test.sh
|
||||
sudo -E samples/network/smb_retro/local_ad_dc_test.sh
|
||||
make -C samples/network/smb_retro clean
|
||||
make -C samples/network/nfs_retro clean
|
||||
samples/network/nfs_retro/local_unfs3_test.sh
|
||||
make -C samples/network/nfs_retro clean
|
||||
sudo -E samples/network/nfs_retro/local_ganesha_test.sh
|
||||
sudo make -C samples/network/nfs_retro clean
|
||||
sudo -E samples/network/nfs_retro/local_read_plus_test.sh
|
||||
sudo make -C samples/network/nfs_retro clean
|
||||
make -C samples/network/krb5_retro clean
|
||||
samples/network/krb5_retro/local_kdc_test.sh
|
||||
make -C samples/network/krb5_retro clean
|
||||
|
||||
|
||||
- name: Built-in NFSv3 client against unfs3
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# net_nfs3.c end to end against a user-space NFSv3 server built
|
||||
# from unfs3's repository (Ubuntu no longer packages it), on
|
||||
# fixed ports without a portmapper: mount, write, read, seek,
|
||||
# stat, mkdir, rename, truncate, list, unlink, refused export.
|
||||
samples/network/nfs_retro/local_unfs3_test.sh
|
||||
# NFSv4.0 (one COMPOUND per operation, no portmapper or MOUNT,
|
||||
# pseudo-filesystem export) against nfs-ganesha from apt
|
||||
sudo -E samples/network/nfs_retro/local_ganesha_test.sh
|
||||
# NFSv4.2 READ_PLUS against a fake server reporting the holes
|
||||
# the filesystem really holds, its replies checked by
|
||||
# Wireshark's own dissector
|
||||
sudo make -C samples/network/nfs_retro clean
|
||||
sudo -E samples/network/nfs_retro/local_read_plus_test.sh
|
||||
# and its Windows link line, cross-linked
|
||||
sudo make -C samples/network/nfs_retro clean
|
||||
CC=x86_64-w64-mingw32-gcc make -C samples/network/nfs_retro nfs_test
|
||||
make -C samples/network/nfs_retro clean
|
||||
CC=x86_64-w64-mingw32-gcc make -C samples/network/tls_retro tls_fetch
|
||||
make -C samples/network/tls_retro clean
|
||||
|
||||
- name: Built-in Kerberos client against a MIT KDC
|
||||
shell: bash
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: |
|
||||
set -eu
|
||||
# net_krb5.c against krb5kdc on a fixed port: AS with and
|
||||
# without PA-ENC-TIMESTAMP, TGS for a cifs/ service with the
|
||||
# ticket checked against the service's keytab key, wrong
|
||||
# password and unknown service refused.
|
||||
samples/network/krb5_retro/local_kdc_test.sh
|
||||
make -C samples/network/krb5_retro clean
|
||||
CC=x86_64-w64-mingw32-gcc make -C samples/network/krb5_retro krb5_test
|
||||
make -C samples/network/krb5_retro clean
|
||||
@@ -1,123 +0,0 @@
|
||||
name: CI Linux without pkg-config
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
no-pkg-config:
|
||||
name: Configure and build with pkg-config unavailable
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: --no-install-recommends build-essential zlib1g-dev libfreetype-dev libdrm-dev libasound2-dev libpulse-dev libpipewire-0.3-dev libdbus-1-dev libwayland-dev libwayland-bin libxkbcommon-dev libdecor-0-dev libssl-dev qt6-base-dev qt6-base-dev-tools
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 15
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Configure
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# PKG_CONF_PATH=none makes configure behave as it does on a
|
||||
# system with no pkg-config binary: every check_val falls
|
||||
# back to a plain link test and takes its cflags from the
|
||||
# include directories it is given. A library that links but
|
||||
# whose headers are not on the include path must end up
|
||||
# disabled, never enabled with empty cflags.
|
||||
PKG_CONF_PATH=none ./configure --enable-dbus
|
||||
grep -q '^HAVE_PIPEWIRE = 1' config.mk
|
||||
grep -q '^HAVE_PIPEWIRE_STABLE = 1' config.mk
|
||||
grep '^PIPEWIRE_CFLAGS = ' config.mk | grep -q -- '-I/usr/include/pipewire-0.3'
|
||||
grep '^PIPEWIRE_CFLAGS = ' config.mk | grep -q -- '-I/usr/include/spa-0.2'
|
||||
# Found without pkg-config: D-Bus by its headers, one of them
|
||||
# under the library directory; Wayland by its libraries and the
|
||||
# scanner's own version; Qt through qmake -query.
|
||||
for have in DBUS WAYLAND WAYLAND_SCANNER LIBDECOR OPENSSL QT QT6; do
|
||||
grep -q "^HAVE_$have = 1" config.mk \
|
||||
|| { echo "::error::HAVE_$have not found without pkg-config"; exit 1; }
|
||||
done
|
||||
grep '^DBUS_CFLAGS = ' config.mk | grep -q -- '-I/usr/include/dbus-1.0'
|
||||
grep '^DBUS_CFLAGS = ' config.mk | grep -q -- 'dbus-1.0/include'
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
make -j"$(nproc)"
|
||||
test -x ./retroarch
|
||||
test -f obj-unix/release/audio/drivers/pipewire.o
|
||||
test -f obj-unix/release/camera/drivers/pipewire.o
|
||||
test -f obj-unix/release/gfx/common/dbus_common.o
|
||||
test -f obj-unix/release/gfx/common/wayland_common.o
|
||||
test -f obj-unix/release/ui/drivers/ui_qt.o
|
||||
|
||||
- name: The run-time libdbus mirror matches libdbus
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# gfx/common/dbus_runtime.h mirrors libdbus's public structs and
|
||||
# constants so RetroArch can load it without its headers; the
|
||||
# D-Bus CFLAGS configure found above lead to the real ones.
|
||||
make -C samples/frontend/dbus_runtime check \
|
||||
DBUS_CFLAGS="$(sed -n 's/^DBUS_CFLAGS = //p' config.mk)"
|
||||
|
||||
- name: A package forced by name fails when nothing can find it
|
||||
shell: bash
|
||||
run: |
|
||||
set -u
|
||||
# rsound is found only through pkg-config. Asked for by name with
|
||||
# no pkg-config, configure must stop and say so rather than
|
||||
# quietly build without it.
|
||||
if PKG_CONF_PATH=none ./configure --enable-rsound > forced.log 2>&1; then
|
||||
cat forced.log
|
||||
echo "::error::--enable-rsound without pkg-config configured instead of failing"
|
||||
exit 1
|
||||
fi
|
||||
grep -q 'Forced to build with package rsound, but pkg-config was not found' forced.log \
|
||||
|| { cat forced.log; echo "::error::configure failed for another reason"; exit 1; }
|
||||
# A forced package with a library check behind it still configures.
|
||||
PKG_CONF_PATH=none ./configure --enable-pulse > forced.log 2>&1 \
|
||||
|| { cat forced.log; echo "::error::--enable-pulse failed without pkg-config"; exit 1; }
|
||||
grep -q '^HAVE_PULSE = 1' config.mk
|
||||
@@ -1,323 +0,0 @@
|
||||
name: CI OpenXR (stand-in runtime, desktop headset path)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
openxr-input:
|
||||
name: OpenXR input and shared units against a stand-in runtime
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: pkg-config libegl-dev libgl-dev libx11-dev
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Run input/common/input_openxr.c against a stand-in runtime
|
||||
working-directory: samples/input/openxr_input
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# The headset's controllers, the desktop's and the Quest's, as
|
||||
# they ship, against a runtime and a frontend the test stands
|
||||
# in for: what the actions give the RetroPad, Touch's menu
|
||||
# button, the laser on a frame and on the menu, rumble, and
|
||||
# nothing held when the runtime has nothing to give.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
|
||||
./openxr_input_test | tee openxr_input.log
|
||||
grep -q "PASS openxr_input_test" openxr_input.log
|
||||
make clean
|
||||
rm -f openxr_input.log
|
||||
|
||||
- name: Run the shared OpenXR units against a stand-in runtime
|
||||
working-directory: samples/openxr/core
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# The Makefile leaves the desktop GL host's tests out where
|
||||
# these are not found, and the run still passes.
|
||||
pkg-config --exists egl x11 gl
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
|
||||
./openxr_core_test | tee openxr_core.log
|
||||
grep -q "PASS openxr_core_test" openxr_core.log
|
||||
make clean
|
||||
rm -f openxr_core.log
|
||||
|
||||
- name: Run the shared OpenXR units under TSan
|
||||
working-directory: samples/openxr/core
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# The XR thread, the tick waiters and the lock gaps.
|
||||
pkg-config --exists egl x11 gl
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
./openxr_core_test | tee openxr_core.log
|
||||
grep -q "PASS openxr_core_test" openxr_core.log
|
||||
make clean
|
||||
rm -f openxr_core.log
|
||||
|
||||
openxr-haptics:
|
||||
name: Desktop haptic results (Linux sanitizers, Windows build)
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: gcc-mingw-w64-x86-64
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Run desktop haptics against scripted runtime results
|
||||
working-directory: samples/input/openxr_haptics
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
make clean
|
||||
make SANITIZER=address,undefined check
|
||||
make clean
|
||||
make SANITIZER=thread check
|
||||
make clean
|
||||
make CC=x86_64-w64-mingw32-gcc all
|
||||
make clean
|
||||
|
||||
openxr-loader-threads:
|
||||
name: OpenXR loader under concurrent use (TSan, ASan+UBSan)
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Run deps/openxr's loader from several threads
|
||||
working-directory: samples/openxr/loader_threads
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The loader shares its runtime, active instance, recorder and
|
||||
# messenger tables and property set between threads with no
|
||||
# lock. Threads enumerate, create, reinitialize and log against
|
||||
# a stand-in runtime while the main thread cycles instances and
|
||||
# messengers; a race or a use-after-free in any of it fails.
|
||||
make clean
|
||||
make SANITIZER=thread check
|
||||
make clean
|
||||
make SANITIZER=address,undefined check
|
||||
make clean
|
||||
|
||||
openxr-desktop:
|
||||
name: Desktop headset output with the in-tree loader
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential pkg-config libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libx11-dev libxext-dev libxrandr-dev libxinerama-dev libxxf86vm-dev libxv-dev libxkbcommon-dev libwayland-dev wayland-protocols libdrm-dev libgbm-dev libasound2-dev libpulse-dev libudev-dev libusb-1.0-0-dev libvulkan-dev libdbus-1-dev zlib1g-dev
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Build RetroArch with OpenXR
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# OpenXR is opt-in; the vendored Khronos loader is built into
|
||||
# the tree, so nothing has to be installed. Qt has to go: the
|
||||
# menu harness below replaces main(), which lives in ui_qt.o
|
||||
# with Qt enabled.
|
||||
./configure --disable-qt --enable-openxr
|
||||
grep -q '^HAVE_OPENXR = 1' config.mk
|
||||
make -j$(nproc)
|
||||
# Vulkan's headset host and the desktop GL drivers', side by
|
||||
# side.
|
||||
test -f obj-unix/release/gfx/common/vulkan_openxr.o
|
||||
test -f obj-unix/release/gfx/common/gl_openxr.o
|
||||
test -f obj-unix/release/gfx/common/openxr_binding_gl.o
|
||||
|
||||
- name: Build and run stereo_headset_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The Stereo 3D & Screens list, with Headset Output off and
|
||||
# on under each driver that has a headset path, against the
|
||||
# shipping menu objects.
|
||||
samples/menu/stereo_headset/build.sh
|
||||
./samples/menu/stereo_headset/stereo_headset_test
|
||||
make -C samples/menu/stereo_headset clean
|
||||
|
||||
- name: Run the headset end-to-end runner's own tests
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# samples/openxr/e2e/run.py needs a runtime and a GPU; its
|
||||
# case selection and its OpenGL lanes do not.
|
||||
python3 -m unittest discover -s samples/openxr/e2e -p 'test_*.py'
|
||||
|
||||
- name: Build the OpenXR test layer and the video_views core
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The API layer the Monado end-to-end check records through,
|
||||
# against the vendored headers, and the core it drives.
|
||||
make -C samples/openxr/test_layer clean && make -C samples/openxr/test_layer -j$(nproc) all
|
||||
test -f samples/openxr/test_layer/libxr_test_layer.so
|
||||
make -C samples/cores/video_views clean && make -C samples/cores/video_views -j$(nproc) all
|
||||
test -f samples/cores/video_views/video_views_libretro.so
|
||||
make -C samples/openxr/test_layer clean
|
||||
make -C samples/cores/video_views clean
|
||||
|
||||
openxr-desktop-gl:
|
||||
name: Desktop headset output on OpenGL alone, without Vulkan
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential pkg-config libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libx11-dev libxext-dev libxrandr-dev libxinerama-dev libxxf86vm-dev libxv-dev libxkbcommon-dev libwayland-dev wayland-protocols libdrm-dev libgbm-dev libasound2-dev libpulse-dev libudev-dev libusb-1.0-0-dev libdbus-1-dev zlib1g-dev
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 10
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Build RetroArch with OpenXR and no Vulkan
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The gl and glcore drivers' headset output has to configure,
|
||||
# build and link without Vulkan.
|
||||
./configure --disable-qt --enable-openxr --disable-vulkan
|
||||
grep -q '^HAVE_OPENXR = 1' config.mk
|
||||
grep -q '^HAVE_VULKAN = 0' config.mk
|
||||
make -j$(nproc)
|
||||
test -f obj-unix/release/gfx/common/openxr_frame.o
|
||||
test -f obj-unix/release/gfx/common/gl_openxr.o
|
||||
test ! -e obj-unix/release/gfx/common/vulkan_openxr.o
|
||||
|
||||
- name: Build and run stereo_headset_test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Headset Output under glcore and gl, with no vulkan driver
|
||||
# to list it under.
|
||||
samples/menu/stereo_headset/build.sh
|
||||
./samples/menu/stereo_headset/stereo_headset_test
|
||||
make -C samples/menu/stereo_headset clean
|
||||
@@ -1,223 +0,0 @@
|
||||
name: CI Linux overlay on screen
|
||||
|
||||
# The one overlay test that looks at the screen. It builds a real
|
||||
# retroarch with X11 and OpenGL, runs it under Xvfb on Mesa's software
|
||||
# rasteriser with an input overlay enabled, threaded video off and then
|
||||
# on, grabs the screen and checks the overlay is where its config puts
|
||||
# it and nowhere else. It then checks the menu's mouse cursor with an
|
||||
# overlay up: a page of "nul" buttons (an LED overlay) must leave the
|
||||
# cursor to the menu, a page that takes input must not. Last, with the
|
||||
# overlay LED driver on, it checks that only LED images are hidden and
|
||||
# that a hidden one stays hidden while its button is held.
|
||||
#
|
||||
# Every stubbed overlay test passed while an enabled overlay covered the
|
||||
# whole screen (2026-09-19). Nothing that stubs the driver, or builds
|
||||
# the pack by hand, can see that; this can.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'input/input_driver.c'
|
||||
- 'input/input_overlay*'
|
||||
- 'tasks/task_overlay.c'
|
||||
- 'led/drivers/led_overlay.c'
|
||||
- 'gfx/gfx_surface.*'
|
||||
- 'gfx/gfx_surface_player.*'
|
||||
- 'libretro-common/formats/video_player.c'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'gfx/drivers/gl2.c'
|
||||
- 'menu/menu_driver.c'
|
||||
- 'input/drivers/x11_input.c'
|
||||
- 'samples/input/overlay_on_screen/**'
|
||||
- 'input/input_driver_choice.c'
|
||||
- 'gfx/drivers_context/x_ctx.c'
|
||||
- 'gfx/common/x11_common.c'
|
||||
- 'samples/input/x11_smoke/**'
|
||||
- 'samples/input/windows_wine_smoke/smoke_core.c'
|
||||
- '.github/workflows/Linux-overlay-on-screen.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'input/input_driver.c'
|
||||
- 'input/input_overlay*'
|
||||
- 'tasks/task_overlay.c'
|
||||
- 'led/drivers/led_overlay.c'
|
||||
- 'gfx/gfx_surface.*'
|
||||
- 'gfx/gfx_surface_player.*'
|
||||
- 'libretro-common/formats/video_player.c'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'gfx/drivers/gl2.c'
|
||||
- 'menu/menu_driver.c'
|
||||
- 'input/drivers/x11_input.c'
|
||||
- 'samples/input/overlay_on_screen/**'
|
||||
- 'input/input_driver_choice.c'
|
||||
- 'gfx/drivers_context/x_ctx.c'
|
||||
- 'gfx/common/x11_common.c'
|
||||
- 'samples/input/x11_smoke/**'
|
||||
- 'samples/input/windows_wine_smoke/smoke_core.c'
|
||||
- '.github/workflows/Linux-overlay-on-screen.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Only pull requests cancel a superseded run. On master every push
|
||||
# gets its own group (keyed by the commit), so a burst of pushes queues
|
||||
# instead of cancelling the run for the commit before it.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
overlay-on-screen:
|
||||
name: Run retroarch under Xvfb and look at the overlay
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential zlib1g-dev ccache python3 xvfb x11-apps xdotool libgl1-mesa-dri libx11-dev libx11-xcb-dev libxcb1-dev libxext-dev libxtst6 libxxf86vm-dev libxrandr-dev libxinerama-dev libgl-dev libegl-dev
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build RetroArch (X11 + OpenGL, the rest off)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# What draws the overlay has to be real: X11, the gl driver,
|
||||
# the menu, threads. Everything else is build time.
|
||||
./configure --disable-qt --disable-wayland --disable-sdl \
|
||||
--disable-sdl2 --disable-ffmpeg --disable-vulkan \
|
||||
--disable-pulse --disable-discord \
|
||||
--disable-networking --disable-cheevos \
|
||||
--disable-glslang --disable-slang \
|
||||
--disable-spirv_cross --disable-xmb \
|
||||
--disable-materialui --disable-ozone \
|
||||
--disable-7zip --disable-flac \
|
||||
--disable-audiomixer --disable-translate \
|
||||
--disable-accessibility --disable-crtswitchres \
|
||||
--disable-langextra --disable-libretrodb \
|
||||
--disable-video_filter --disable-dsp_filter
|
||||
make -j$(nproc)
|
||||
ccache -s
|
||||
|
||||
- name: Run overlay_on_screen_test (threaded video off, then on)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Two solid magenta squares on a full-screen page. Each must
|
||||
# be where the config puts it, the middle of the screen must
|
||||
# not be overlay, and the overlay must cover about the area of
|
||||
# its two squares. With "does this desc have an image" asked
|
||||
# of pixels that had just been released, no desc's geometry
|
||||
# was set and the overlay covered 100% of the screen, in both
|
||||
# modes.
|
||||
timeout 180 python3 samples/input/overlay_on_screen/overlay_on_screen_test.py ./retroarch
|
||||
|
||||
- name: Run overlay_apng_on_screen_test (an animated image plays and loops, threaded off and on)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
timeout 180 python3 samples/input/overlay_on_screen/overlay_apng_on_screen_test.py ./retroarch
|
||||
|
||||
- name: Run overlay_apng_press_on_screen_test (a two-frame image shows its pressed frame, threaded off and on)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
timeout 180 python3 samples/input/overlay_on_screen/overlay_apng_press_on_screen_test.py ./retroarch
|
||||
|
||||
- name: Run statistics_on_screen_test (threaded video off, then on)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# This build has no video filters, and the statistics have
|
||||
# to show all the same: they are drawn with the OSD font,
|
||||
# which reaches the video state through a binding video init
|
||||
# makes whatever the build leaves out.
|
||||
timeout 180 python3 samples/gfx/statistics_on_screen/statistics_on_screen_test.py ./retroarch
|
||||
|
||||
- name: Run overlay_menu_mouse_test (display and input packs, threaded off and on)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The menu switched its mouse off whenever any overlay was
|
||||
# alive, so an LED overlay - nothing on it to press - left a
|
||||
# fullscreen desktop user with no menu cursor. A pack of
|
||||
# "nul" buttons must now show the cursor where the pointer is
|
||||
# moved; the same pack bound to "a" must still not.
|
||||
timeout 180 python3 samples/input/overlay_on_screen/overlay_menu_mouse_test.py ./retroarch
|
||||
|
||||
- name: Run overlay_led_hidden_test (mapped and named LED packs, threaded off and on)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# With the overlay LED driver on and Up held through XTEST: an
|
||||
# image at a ledN_map slot, "nul" or a control, stays hidden,
|
||||
# as does one named with _led, and a pack that names its LEDs
|
||||
# is not mapped.
|
||||
timeout 300 python3 samples/input/overlay_on_screen/overlay_led_hidden_test.py ./retroarch
|
||||
|
||||
- name: Run the X11 input scenarios (keys pressed in the window)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The same build, on a virtual display of its own, with the
|
||||
# X11 input driver: keys are pressed in the window and a small
|
||||
# core says in the log what reached it - before and after a
|
||||
# fullscreen toggle restarts the video driver, with threaded
|
||||
# video and without. See samples/input/x11_smoke/run.sh.
|
||||
timeout 600 samples/input/x11_smoke/run.sh
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,105 +0,0 @@
|
||||
name: CI Linux pace shadow [debug harness]
|
||||
|
||||
# The pace decision - which sources hold the loop each iteration - is
|
||||
# one pure function, runloop_pace_decide() in runloop.h, that every
|
||||
# path of runloop_iterate() defers to. It began life shadowing the
|
||||
# paths' own scattered decisions with a debug assertion that the two
|
||||
# agreed; this job was created to run that assertion in CI, and it
|
||||
# never fired, which is what let the paths defer.
|
||||
#
|
||||
# What the job still does: builds with DEBUG=1 under ASan and UBSan,
|
||||
# so every retro_assert in the wrapper, the ring and the runloop is
|
||||
# live, and runs the threaded-video harness through it - threaded and
|
||||
# unthreaded, menu open and closed, display pacing on, the runtime
|
||||
# toggles - then the pacing sample, whose menu table pins the decision
|
||||
# row by row. The release harness job cannot see an assertion; this
|
||||
# one can.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
linux-pace-shadow:
|
||||
name: Debug build, harness with assertions live
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
|
||||
env:
|
||||
APT_PKGS: build-essential libxkbcommon-dev libx11-xcb-dev xvfb x11-utils zlib1g-dev libfreetype6-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev libavcodec-dev libsdl2-dev libsdl-image1.2-dev libxml2-dev yasm
|
||||
# Line tables are all a sanitizer report needs. configure and
|
||||
# make take these in place of DEBUG=1's -O0 -g, adding their own.
|
||||
CFLAGS: -O0 -g1
|
||||
CXXFLAGS: -O0 -g1
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Configure
|
||||
# Non-Qt, as the harness requires (with Qt, main() lives in
|
||||
# ui_qt.o). Menu enabled: the menu lanes are half the point.
|
||||
run: |
|
||||
./configure \
|
||||
--disable-qt \
|
||||
--disable-discord \
|
||||
--disable-cheevos \
|
||||
--disable-networking \
|
||||
--disable-ffmpeg
|
||||
|
||||
- name: Build with DEBUG=1 and -fsanitize=address,undefined
|
||||
run: |
|
||||
make -j$(getconf _NPROCESSORS_ONLN) SANITIZER=address,undefined DEBUG=1
|
||||
|
||||
- name: Run the threaded-video harness with assertions live
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# SAN=address is the harness's default and links exactly the
|
||||
# build above; CYCLES=2 runs each toggling lane twice.
|
||||
SAN=address CYCLES=2 make -C samples/gfx/threaded_video check
|
||||
make -C samples/gfx/threaded_video clean
|
||||
|
||||
- name: Run the pacing sample (the menu table)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
make -C samples/runloop/pacing check
|
||||
make -C samples/runloop/pacing clean
|
||||
@@ -1,45 +0,0 @@
|
||||
name: CI QNX input drivers (stand-in SDK)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
qnx-standin:
|
||||
name: QNX input drivers compile against stand-ins for the SDK
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Compile qnx_input.c and qnx_joypad.c
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The BlackBerry 10 SDK cannot be fetched here, so nothing
|
||||
# built the QNX port and its input driver stopped compiling
|
||||
# unseen. This compiles the two input files - declarations
|
||||
# and syntax, nothing linked or run - against stand-ins for
|
||||
# the SDK's headers. See the script for what that does and
|
||||
# does not catch.
|
||||
tools/qnx_standin_check.sh
|
||||
@@ -1,85 +0,0 @@
|
||||
name: CI Linux Qt companion (persistence)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
qt-companion-persist:
|
||||
# Builds a Qt-enabled RetroArch with the null video/audio/input
|
||||
# drivers and runs tools/companion_qt_persist_test.sh: the desktop
|
||||
# companion's window geometry and dock layout must reach
|
||||
# retroarch.cfg when RetroArch quits with the companion window still
|
||||
# open, and a saved layout must restore and re-save identically.
|
||||
#
|
||||
# The shader stacks are disabled explicitly: with no OpenGL/Vulkan
|
||||
# dev packages on the runner this is a Qt build with NO shader stack
|
||||
# at all, and it links (the shader-preset editor and the companion
|
||||
# core's shader accessors are compiled out). That is deliberate - it
|
||||
# is the one configuration the other jobs never build.
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential pkg-config zlib1g-dev qt6-base-dev libgl-dev
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
- name: Configure
|
||||
run: |
|
||||
./configure --enable-qt --disable-x11 --disable-wayland \
|
||||
--disable-opengl --disable-opengles --disable-vulkan \
|
||||
--disable-sdl2 --disable-sdl --disable-alsa --disable-pulse \
|
||||
--disable-ffmpeg --disable-networking --disable-cheevos \
|
||||
--disable-discord --disable-cdrom --disable-flac --disable-mpv \
|
||||
--disable-libusb --disable-udev --disable-v4l2 --disable-freetype \
|
||||
--disable-caca --disable-sixel --disable-microphone --disable-ssl \
|
||||
--disable-bluetooth --disable-wifi --disable-oss --disable-jack \
|
||||
--disable-roar --disable-al --disable-xvideo --disable-kms \
|
||||
--disable-egl --disable-dispmanx --disable-videocore \
|
||||
--disable-crtswitchres --disable-update_cores --disable-hid \
|
||||
--disable-dbus --disable-glsl --disable-slang --disable-cg \
|
||||
--disable-glslang --disable-spirv_cross
|
||||
- name: Build
|
||||
run: make -j$(getconf _NPROCESSORS_ONLN)
|
||||
- name: Companion persistence regression
|
||||
timeout-minutes: 10
|
||||
run: tools/companion_qt_persist_test.sh
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,264 +0,0 @@
|
||||
name: CI Linux samples/cores
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'cores/libretro-ffmpeg/**'
|
||||
- 'libretro-common/queues/**'
|
||||
- 'libretro-common/include/retro_spsc.h'
|
||||
- 'libretro-common/include/retro_atomic.h'
|
||||
- 'camera/drivers/**'
|
||||
- 'samples/camera/**'
|
||||
- 'samples/cores/**'
|
||||
- '.github/workflows/Linux-samples-cores.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'cores/libretro-ffmpeg/**'
|
||||
- 'libretro-common/queues/**'
|
||||
- 'libretro-common/include/retro_spsc.h'
|
||||
- 'libretro-common/include/retro_atomic.h'
|
||||
- 'camera/drivers/**'
|
||||
- 'samples/camera/**'
|
||||
- 'samples/cores/**'
|
||||
- '.github/workflows/Linux-samples-cores.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
samples-cores:
|
||||
name: Build and run samples/cores
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential pkg-config ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libv4l-dev libasound2-dev ccache libavdevice-dev libavfilter-dev libpipewire-0.3-dev
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build and run camera ffmpeg_live_test (plain, ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/camera/ffmpeg_live
|
||||
run: |
|
||||
set -eu
|
||||
# The camera driver against lavfi: built with its input
|
||||
# format set to libavfilter, a filter graph is the device and
|
||||
# the whole pipeline runs with no camera attached - avformat
|
||||
# opens the source, the poll thread reads, the decoder
|
||||
# decodes, swscale converts and poll() takes the newest
|
||||
# finished frame.
|
||||
#
|
||||
# The cases are the ones the threading has to get right and
|
||||
# that no eyeball on a webcam would show: start and stop
|
||||
# repeatedly, stop while the thread is mid-frame, free
|
||||
# without stopping, poll before starting, a source that
|
||||
# does not exist, a poll that must show the last frame
|
||||
# decoded, and a slow poll the thread must not wait on. Leak
|
||||
# checking is on: a packet or plane kept per frame or per
|
||||
# start is a leak report.
|
||||
make clean && make -j$(nproc) all
|
||||
./ffmpeg_live_test
|
||||
echo "[pass] ffmpeg_live_test"
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
|
||||
timeout 600 ./ffmpeg_live_test
|
||||
echo "[pass] ffmpeg_live_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1:suppressions=../../cores/ffmpeg_audio_pipe/tsan.supp \
|
||||
timeout 600 ./ffmpeg_live_test
|
||||
echo "[pass] ffmpeg_live_test (TSan)"
|
||||
|
||||
- name: Build and run camera pipewire_poll_test (plain, ASan + UBSan)
|
||||
shell: bash
|
||||
working-directory: samples/camera/pipewire_poll
|
||||
run: |
|
||||
set -eu
|
||||
# The pipewire camera driver's poll against a scripted
|
||||
# stream, the pw_stream calls link-wrapped: an empty queue
|
||||
# returns at once, and every buffer the poll takes - valid,
|
||||
# corrupted or without CPU data - is queued back. The check
|
||||
# target bounds the run: a poll that waits for a frame is
|
||||
# the failure.
|
||||
make clean check
|
||||
echo "[pass] pipewire_poll_test"
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
|
||||
timeout 60 ./pipewire_poll_test
|
||||
echo "[pass] pipewire_poll_test (ASan)"
|
||||
|
||||
- name: Build and run ffmpeg_sweep_test (plain, ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/cores/ffmpeg_sweep
|
||||
run: |
|
||||
set -eu
|
||||
# Breadth where ffmpeg_audio_pipe_test has depth: eight clips
|
||||
# across containers, video and audio codecs, rates, channel
|
||||
# counts and the one-sided cases, each loaded, run, seeked
|
||||
# both ways, reset and unloaded in one process - so the
|
||||
# second load is what finds what the first unload left
|
||||
# behind - then files that are truncated, stubbed, noise,
|
||||
# empty or absent, then teardown while the decode thread is
|
||||
# still working.
|
||||
#
|
||||
# With leak detection: every load and unload in it, the
|
||||
# decoder probing included, must give back its codec
|
||||
# contexts and hardware devices. The libav* TSan
|
||||
# suppressions are the audio-pipe lane's, for the same
|
||||
# reason.
|
||||
make clean && make -j$(nproc) all
|
||||
./ffmpeg_sweep_test
|
||||
echo "[pass] ffmpeg_sweep_test"
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 900 ./ffmpeg_sweep_test
|
||||
echo "[pass] ffmpeg_sweep_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1:suppressions=../ffmpeg_audio_pipe/tsan.supp \
|
||||
timeout 900 ./ffmpeg_sweep_test
|
||||
echo "[pass] ffmpeg_sweep_test (TSan)"
|
||||
# The standalone core's own makefiles: a link with
|
||||
# --no-undefined is the check their source lists are whole,
|
||||
# and a dry run with GL (no GL headers here) the check that
|
||||
# the GL build's list resolves. The sample's objects share
|
||||
# paths with the core's libretro-common ones: cleaned first.
|
||||
make clean
|
||||
make -n -C ../../../cores/libretro-ffmpeg OPENGL=1 >/dev/null
|
||||
make -C ../../../cores/libretro-ffmpeg -j2 OPENGL=0 HAVE_SSA=0
|
||||
make -C ../../../cores/libretro-ffmpeg clean OPENGL=0 HAVE_SSA=0
|
||||
echo "[pass] standalone ffmpeg core links"
|
||||
|
||||
- name: Build and run ffmpeg_finished_wait_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/cores/ffmpeg_finished_wait
|
||||
run: |
|
||||
set -eu
|
||||
# The main thread's wait for a finished video slot ends when
|
||||
# the decode thread does, at the end of a clip, instead of
|
||||
# holding retro_run() on a slot nothing will finish.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=print_stacktrace=1 \
|
||||
timeout 60 ./ffmpeg_finished_wait_test
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1:suppressions=../ffmpeg_audio_pipe/tsan.supp \
|
||||
timeout 60 ./ffmpeg_finished_wait_test
|
||||
echo "[pass] ffmpeg_finished_wait_test"
|
||||
|
||||
- name: Build and run ffmpeg_audio_pipe_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/cores/ffmpeg_audio_pipe
|
||||
run: |
|
||||
set -eu
|
||||
# cores/libretro-ffmpeg/ffmpeg_core.c as a libretro host would
|
||||
# drive it: a generated clip (tone under a test pattern), 5 s
|
||||
# of frames checked for the audio frame count and a tone in
|
||||
# every batch, then R1/L1 seeks both ways - the decode-thread
|
||||
# / main-thread handshake around the audio ring - and a
|
||||
# teardown mid-stream, all on a watchdog. Needs the ffmpeg
|
||||
# CLI to generate the clip. Leak detection off: libavutil's
|
||||
# own HW-device probing allocates and keeps a few objects.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x ffmpeg_audio_pipe_test
|
||||
ASAN_OPTIONS=detect_leaks=0:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 300 \
|
||||
./ffmpeg_audio_pipe_test
|
||||
echo "[pass] ffmpeg_audio_pipe_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
# The libav* libraries are uninstrumented, so TSan cannot see
|
||||
# the atomics that order an AVBufferRef's reference count and
|
||||
# reports the allocation and the release as a race. Only
|
||||
# those libraries are suppressed; a race in the core's own
|
||||
# code is still reported.
|
||||
TSAN_OPTIONS=halt_on_error=1:suppressions=tsan.supp \
|
||||
timeout 300 ./ffmpeg_audio_pipe_test
|
||||
echo "[pass] ffmpeg_audio_pipe_test (TSan)"
|
||||
|
||||
- name: Build and run videoproc_audio_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/cores/videoproc_audio
|
||||
run: |
|
||||
set -eu
|
||||
# cores/libretro-video-processor's ALSA capture handle between
|
||||
# the frontend's audio thread, which keeps calling the core's
|
||||
# audio callback, and the main thread opening and closing the
|
||||
# device under it: no read on a closed handle - a close that
|
||||
# lands mid-read included - and no lock taken by the callback.
|
||||
# The device is ALSA's null PCM; the capture read is a
|
||||
# stand-in.
|
||||
make clean && make -j$(nproc) all
|
||||
timeout 120 ./videoproc_audio_test
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
|
||||
timeout 120 ./videoproc_audio_test
|
||||
echo "[pass] videoproc_audio_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./videoproc_audio_test
|
||||
echo "[pass] videoproc_audio_test (TSan)"
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,286 +0,0 @@
|
||||
name: CI Linux samples/formats
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
samples-formats:
|
||||
name: Build and run samples/formats
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential ffmpeg clang ccache
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build and run dts_lpcm_test (plain, ASan + UBSan)
|
||||
shell: bash
|
||||
working-directory: samples/formats/dts_lpcm
|
||||
run: |
|
||||
set -eu
|
||||
# The DTS frame layer and the LPCM codec against ffmpeg.
|
||||
#
|
||||
# rdts reads frames, it does not decode them, so what is
|
||||
# checked is that every frame is found where ffmpeg's
|
||||
# encoder put it, that the rate and the arrangement agree
|
||||
# with ffprobe's reading of the same file, and that a stream
|
||||
# byte-swapped or packed fourteen bits to the word reads
|
||||
# back to the same core - which is what a receiver and a
|
||||
# decoder are handed.
|
||||
#
|
||||
# rlpcm does decode, and is bit-exact: the samples go out
|
||||
# through ffmpeg's own converters and come back the same, at
|
||||
# 16 and 24 bits and both byte orders, and what rlpcm writes
|
||||
# back is the bytes it read. 20-bit has no ffmpeg format to
|
||||
# compare against - two samples to five bytes is a disc
|
||||
# packing - so it is checked against itself, and the DVD and
|
||||
# Blu-ray headers against their field layouts. The
|
||||
# audio_transfer arm is driven too: chunked reads against
|
||||
# the codec's own output, the compressed frontier, and
|
||||
# seeks, which for constant-size frames land exactly.
|
||||
#
|
||||
# And the pass-through route, which is what a format with no
|
||||
# decoder is for: every frame repacked to the plain core,
|
||||
# put in the IEC 61937 burst its sample count calls for, and
|
||||
# read back out of that burst byte for byte.
|
||||
make clean && make -j$(nproc) all
|
||||
./dts_lpcm_test
|
||||
echo "[pass] dts_lpcm_test"
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 ./dts_lpcm_test
|
||||
echo "[pass] dts_lpcm_test (ASan)"
|
||||
|
||||
- name: Build and run image_decode_fuzz_test (ASan + UBSan + LSan)
|
||||
shell: bash
|
||||
working-directory: samples/formats/image_decode_fuzz
|
||||
run: |
|
||||
set -eu
|
||||
# Malformed-input sweep for the BMP, TGA, DDS and WebP decoders in
|
||||
# libretro-common/formats. All three take dimensions and
|
||||
# layout from a header the file supplies and size their
|
||||
# output from it, which is where this kind of arithmetic
|
||||
# goes wrong, and none of the four had any test at all.
|
||||
# (WebP is told its buffer length, so it is the least
|
||||
# exposed of them; its chunk walk still trusts sizes that
|
||||
# came out of the file.)
|
||||
#
|
||||
# It found one on its first run: rbmp_proc_reset() gated the
|
||||
# free of output_image on phase != RBMP_PHASE_IDLE, but
|
||||
# rbmp_begin() allocates that surface before it sets any
|
||||
# phase and returns false between the two for a palette
|
||||
# header claiming a bits-per-pixel other than 4 or 8. Every
|
||||
# such image leaked the surface, reachable from any
|
||||
# malformed or hostile BMP. Leak detection is therefore
|
||||
# switched on explicitly here rather than left to the
|
||||
# default.
|
||||
#
|
||||
# The sweep truncates each seed at every length and sets
|
||||
# every header byte to each of six interesting values,
|
||||
# including the ones that make dimensions enormous. The
|
||||
# count of inputs that decode successfully is asserted
|
||||
# inside the test, so a sweep where the seeds stopped being
|
||||
# accepted would fail rather than exercise only the reject
|
||||
# paths and report a pass. That count is kept per format, not
|
||||
# just in total, so one decoder quietly ceasing to accept its
|
||||
# seed cannot hide behind the other three.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x image_decode_fuzz_test
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1 \
|
||||
timeout 120 ./image_decode_fuzz_test
|
||||
echo "[pass] image_decode_fuzz_test"
|
||||
|
||||
- name: Build and run image_avail_test (ASan + UBSan + LSan)
|
||||
shell: bash
|
||||
working-directory: samples/formats/image_avail
|
||||
run: |
|
||||
set -eu
|
||||
# Partial-buffer ("avail-aware") still decoding for TGA and
|
||||
# BMP, checked
|
||||
# against the whole-buffer decode that has always been
|
||||
# there: every fixture is decoded once with the file fully
|
||||
# resident and again with the frontier raised a few bytes at
|
||||
# a time, and the two surfaces must be bit-identical.
|
||||
#
|
||||
# The oracle is the decoder itself, so this catches the
|
||||
# failures that do not crash: a wall mistaken for EOF (the
|
||||
# decode pads the rest of the surface and reports success),
|
||||
# an RLE run re-emitted after a stall, a cursor resumed off
|
||||
# by a pixel. It found all three of those on its first runs
|
||||
# while TGA was being converted.
|
||||
#
|
||||
# BMP rows are bottom-up, so a prefix of the file is the
|
||||
# bottom of the image and a stall resumed on the wrong row
|
||||
# shows up as a vertically displaced surface rather than as
|
||||
# noise. The 4bpp and 8bpp fixtures put the wall inside the
|
||||
# palette as well.
|
||||
#
|
||||
# Steps of 1, 3 and 7 bytes put the wall inside every field,
|
||||
# inside RLE packets and mid-pixel for both 24bpp and 32bpp;
|
||||
# 1024 is a realistic read granularity. A truncated file
|
||||
# must still settle rather than wait forever, which is the
|
||||
# one case where stopping at the frontier and stopping at
|
||||
# the end of the data have to be told apart.
|
||||
#
|
||||
# One set of checks replays task_image's real call sequence
|
||||
# rather than an order this test invented - set_buffer_ptr,
|
||||
# then set_avail BEFORE each process(), then set_avail
|
||||
# ((size_t)-1) the instant the read completes, which for a
|
||||
# small file is before any process() has run - at four read
|
||||
# granularities. Inventing the order instead of replaying
|
||||
# it is exactly how the blank-BMP/TGA-thumbnail regression
|
||||
# got past this file: every other check here raised the
|
||||
# frontier only after the first process() call.
|
||||
#
|
||||
# One set of checks drives every avail-aware still decoder -
|
||||
# PNG and JPEG as well as TGA and BMP - through the
|
||||
# image_transfer facade in task_image's order. PNG, JPEG,
|
||||
# WEBM and MP4 clamp the requested frontier in the size
|
||||
# domain because their set_buf_ptr is given the buffer
|
||||
# length; rtga's and rbmp's are not, which is why those two
|
||||
# were the only ones that could turn (size_t)-1 into a
|
||||
# wrapped pointer, and did. A sixth avail-aware decoder
|
||||
# inherits whichever shape it copies, so the check lives
|
||||
# here rather than in anyone's memory.
|
||||
#
|
||||
# It also checks header_ready, the gate the task layer uses
|
||||
# to start a decode early, against the decoder itself: every
|
||||
# prefix it accepts must be one the decoder can actually
|
||||
# begin on, it must accept before the whole file has arrived
|
||||
# (or partial decoding is silently off), and it must be
|
||||
# monotonic in the prefix length.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x image_avail_test
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1 \
|
||||
timeout 120 ./image_avail_test
|
||||
echo "[pass] image_avail_test"
|
||||
|
||||
- name: AV1 picture tools, frame prefixes, tiles and container packets (ASan + UBSan)
|
||||
working-directory: libretro-common/samples/formats/av1
|
||||
run: |
|
||||
make check SANITIZER=address,undefined
|
||||
python3 fixtures.py
|
||||
python3 tile_fixtures.py
|
||||
python3 frame_fixtures.py
|
||||
python3 picture_fixtures.py
|
||||
python3 reference_fixtures.py
|
||||
python3 grain_fixtures.py
|
||||
python3 state_fixtures.py
|
||||
|
||||
- name: Vulkan AV1 parameters against real streams (ASan + UBSan)
|
||||
working-directory: samples/gfx/vulkan_video_caps
|
||||
run: |
|
||||
make av1_params_test SANITIZER=address,undefined
|
||||
python3 av1_fixtures.py
|
||||
|
||||
- name: VP9 sessions and WebM GPU dispatch (ASan + UBSan)
|
||||
working-directory: libretro-common/samples/formats/vp9
|
||||
run: |
|
||||
make check stream-check pixel-check SANITIZER=address,undefined
|
||||
make stack-check CC=gcc
|
||||
make stack-check CC=clang
|
||||
|
||||
- name: Build and run video_hdr_fp16_test (ASan + UBSan + LSan)
|
||||
shell: bash
|
||||
working-directory: samples/formats/video_hdr_fp16
|
||||
run: |
|
||||
set -eu
|
||||
# HDR10 video to linear scRGB half floats: HEVC Main10 in MP4
|
||||
# and VP9 profile 2 in WebM, tagged PQ, decode flat grey onto
|
||||
# the PQ EOTF when asked into the caller's frame; their
|
||||
# SDR-tagged twins, and any stream decoding into its own
|
||||
# canvas, keep the 32-bit paths. Fixtures made with ffmpeg
|
||||
# (libx265, libvpx-vp9) from known 10-bit grey.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1 \
|
||||
timeout 120 ./video_hdr_fp16_test
|
||||
|
||||
- name: Build and run image_tile_gx_test (ASan + UBSan + LSan)
|
||||
shell: bash
|
||||
working-directory: samples/formats/image_tile_gx
|
||||
run: |
|
||||
set -eu
|
||||
# The GameCube/Wii GX RGBA8 tiling the gx driver's overlays
|
||||
# are sampled in, which runs nowhere but on the console. It
|
||||
# is checked against the layout's definition and against
|
||||
# the band conversion it replaced, over every size up to
|
||||
# 70x44 so widths and heights off a multiple of four - where
|
||||
# the source pitch and the tile width part ways - are all
|
||||
# covered.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x image_tile_gx_test
|
||||
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1 \
|
||||
timeout 120 ./image_tile_gx_test
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,391 +0,0 @@
|
||||
name: CI Linux samples/network
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
samples-network:
|
||||
name: Build and run samples/network
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential libmbedtls-dev libbearssl-dev ccache
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build and run webdav_options_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/network/webdav_options
|
||||
run: |
|
||||
set -eu
|
||||
# Includes network/cloud_sync/webdav.c and drives the OPTIONS
|
||||
# capability probe as shipped over real-world header sets. The
|
||||
# probe has to separate a WebDAV server from a plain HTTP
|
||||
# server that answers OPTIONS, and the target it probes is a
|
||||
# collection, on which PUT is not defined (RFC 4918 9.7.1) -
|
||||
# so PUT's absence from Allow must not fail it. The previous
|
||||
# probe did exactly that, rejecting mod_dav and Koofr
|
||||
# (libretro/RetroArch#19486) while accepting a plain nginx
|
||||
# that happened to list PUT. Covers the DAV header, Allow-only
|
||||
# WebDAV methods, HTTP/2 lowercase field names, plain HTTP
|
||||
# with and without PUT, empty and NULL header lists, and
|
||||
# whole-token matching (PROPFINDX must not match PROPFIND).
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x webdav_options_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 60 \
|
||||
./webdav_options_test
|
||||
echo "[pass] webdav_options_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./webdav_options_test
|
||||
echo "[pass] webdav_options_test (TSan)"
|
||||
|
||||
- name: Build and run webdav_reauth_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/network/webdav_reauth
|
||||
run: |
|
||||
set -eu
|
||||
# Includes network/cloud_sync/webdav.c and plays the server
|
||||
# for every request type the driver sends (OPTIONS, GET, PUT,
|
||||
# DELETE, MOVE, MKCOL). A server that keeps answering 401 with
|
||||
# a Digest challenge - a wrong password - must get one retry
|
||||
# and then a reported failure; the driver used to retry every
|
||||
# challenge, so a mistyped password looped the first request
|
||||
# of a sync forever. A single stale-nonce challenge must still
|
||||
# be retried and succeed. A retried PUT must send the file:
|
||||
# it used to re-read it from the end the first attempt left
|
||||
# it at and upload uninitialised memory in place of the save.
|
||||
# A malformed challenge (a value with no closing quote, a
|
||||
# trailing unquoted parameter) must be refused, not crash the
|
||||
# parser or send it reading past the end of the line.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x webdav_reauth_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 60 \
|
||||
./webdav_reauth_test
|
||||
echo "[pass] webdav_reauth_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./webdav_reauth_test
|
||||
echo "[pass] webdav_reauth_test (TSan)"
|
||||
|
||||
- name: Build and run webdav_backup_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/network/webdav_backup
|
||||
run: |
|
||||
set -eu
|
||||
# Includes network/cloud_sync/webdav.c and plays the server,
|
||||
# request by request. With destructive sync off, an upload
|
||||
# must COPY the server's file to deleted/<path>-<time> before
|
||||
# the PUT replaces it - it used to overwrite it in place, so
|
||||
# the setting protected against deletes but not overwrites.
|
||||
# Covers the order (backup first, into an existing deleted/
|
||||
# collection, named as a delete names it), 404 as "nothing to
|
||||
# back up", a failed backup stopping the upload, destructive
|
||||
# sync and the server manifest skipping the backup, and COPY
|
||||
# and PUT each getting their own Digest retry.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x webdav_backup_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 60 \
|
||||
./webdav_backup_test
|
||||
echo "[pass] webdav_backup_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./webdav_backup_test
|
||||
echo "[pass] webdav_backup_test (TSan)"
|
||||
|
||||
- name: Build and run s3_backup_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/network/s3_backup
|
||||
run: |
|
||||
set -eu
|
||||
# Includes network/cloud_sync/s3.c and plays the server,
|
||||
# request by request. The S3 driver never read the
|
||||
# destructive sync setting: deletes removed objects for good
|
||||
# and uploads overwrote them. With it off, both must first
|
||||
# CopyObject the object to deleted/<path>-<time>. Covers the
|
||||
# copy source for virtual-hosted and path-style endpoints,
|
||||
# x-amz-copy-source being signed, 404 as "nothing to keep", a
|
||||
# failed copy (including a 200 with an <Error> body) stopping
|
||||
# the delete or upload, and destructive sync and the server
|
||||
# manifest skipping the copy.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x s3_backup_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 60 \
|
||||
./s3_backup_test
|
||||
echo "[pass] s3_backup_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./s3_backup_test
|
||||
echo "[pass] s3_backup_test (TSan)"
|
||||
|
||||
- name: Build and run smb_backup_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/network/smb_backup
|
||||
run: |
|
||||
set -eu
|
||||
# Includes network/cloud_sync/smb.c and runs it against an
|
||||
# in-memory libsmb2 share (fake_smb.c), checking what the
|
||||
# share holds after each upload. The driver used to truncate
|
||||
# the server file and then write, so a write failing part way
|
||||
# left a truncated save; and with destructive sync off it
|
||||
# overwrote the file without keeping the old copy a delete
|
||||
# keeps. Uploads now go through <path>.rauploading and the
|
||||
# replaced file is kept as <path>-<time> (non-destructive).
|
||||
# Covers a failed write, backup and final rename each leaving
|
||||
# the old file intact with no temporary file left, no backup
|
||||
# for destructive sync, a new file or the manifest, an empty
|
||||
# upload and the configured subdirectory.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x smb_backup_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 60 \
|
||||
./smb_backup_test
|
||||
echo "[pass] smb_backup_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./smb_backup_test
|
||||
echo "[pass] smb_backup_test (TSan)"
|
||||
|
||||
- name: Build and run nfs_backup_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/network/nfs_backup
|
||||
run: |
|
||||
set -eu
|
||||
# Includes network/cloud_sync/nfs.c and runs it against an
|
||||
# in-memory export (fake_nfs.c) keeping net_nfs3.c's status
|
||||
# contract. A download is written beside the local file and
|
||||
# renamed over it once complete; only the server answering
|
||||
# NOENT reads as "not there"; an upload is one RENAME over the
|
||||
# old file, kept as <path>-<time>[-n] with destructive sync
|
||||
# off. Covers failed opens and partial reads leaving the local
|
||||
# save intact, unanswered stat/unlink failing instead of
|
||||
# reporting a missing file or a delete, failed write, backup
|
||||
# and final rename leaving the old file and no temporary, the
|
||||
# manifest skipping the backup, refused over-long names, the
|
||||
# subdirectory and a concurrent MKDIR.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x nfs_backup_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 60 \
|
||||
./nfs_backup_test
|
||||
echo "[pass] nfs_backup_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./nfs_backup_test
|
||||
echo "[pass] nfs_backup_test (TSan)"
|
||||
|
||||
- name: Build and run gdrive_backup_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/network/gdrive_backup
|
||||
run: |
|
||||
set -eu
|
||||
# Includes network/cloud_sync/google_drive.c and plays the
|
||||
# Drive API, request by request. With destructive sync off, a
|
||||
# delete kept the old file (renamed <name>-<time>) but an
|
||||
# upload replaced its content outright. An upload to an
|
||||
# existing file must now files.copy it to that name in the
|
||||
# same folder before the PATCH. Covers the order and the copy
|
||||
# request, a failed copy stopping the upload, a 401 on the
|
||||
# copy and on the PATCH each refreshing the token once (the
|
||||
# PATCH retry repeating only the PATCH, not the backup), and
|
||||
# destructive sync, a new file and the manifest skipping it.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x gdrive_backup_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 60 \
|
||||
./gdrive_backup_test
|
||||
echo "[pass] gdrive_backup_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./gdrive_backup_test
|
||||
echo "[pass] gdrive_backup_test (TSan)"
|
||||
|
||||
- name: Build and run cheevos_login_test (bear ASan+UBSan, bear TSan, mbed ASan+UBSan)
|
||||
shell: bash
|
||||
working-directory: samples/network/cheevos_login
|
||||
run: |
|
||||
set -eu
|
||||
# Regression guard for the RetroAchievements login transport
|
||||
# (libretro/RetroArch#19562, #19457): drives net_http with the
|
||||
# exact login shape cheevos_client.c produces, against a local
|
||||
# mock server that validates every request byte-for-byte, over
|
||||
# plain HTTP and over TLS with the real SSL backend linked in.
|
||||
# Covers: login on a fresh TLS connection, trust-store loading
|
||||
# from a realistic messy CA bundle (BearSSL), keep-alive pool
|
||||
# reuse, one-shot replay of a request on a pooled connection
|
||||
# the server closed while idle, and no replay once response
|
||||
# bytes have been seen. Each TLS backend's non-blocking send
|
||||
# must push a 12 MiB body past a server that stops reading for
|
||||
# a second without ever blocking, and deliver every byte; and
|
||||
# net_http must send the same upload a slice per update, plain
|
||||
# and over TLS - it used to go out in one blocking send, a call
|
||||
# of a second or more (spinning at 100% CPU on a plain socket).
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x cheevos_login_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 timeout 120 \
|
||||
make check
|
||||
echo "[pass] cheevos_login_test (BearSSL, ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 180 make check
|
||||
echo "[pass] cheevos_login_test (BearSSL, TSan)"
|
||||
make clean SSL_BACKEND=mbed SANITIZER=address,undefined && make -j$(nproc) all SSL_BACKEND=mbed SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 timeout 120 \
|
||||
make check SSL_BACKEND=mbed
|
||||
echo "[pass] cheevos_login_test (mbedTLS, ASan)"
|
||||
# The built-in client, RetroArch's default backend.
|
||||
make clean SSL_BACKEND=retro SANITIZER=address,undefined && make -j$(nproc) all SSL_BACKEND=retro SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 timeout 120 \
|
||||
make check SSL_BACKEND=retro
|
||||
echo "[pass] cheevos_login_test (built-in TLS, ASan)"
|
||||
# The runner's libmbedtls-dev is 2.28, which has no TLS 1.3,
|
||||
# so the leg above cannot see either TLS 1.3 failure. Mbed
|
||||
# TLS 3.6.0 is the one release that shows both: it fails
|
||||
# every handshake unless psa_crypto_init() was called, and it
|
||||
# reports session tickets from mbedtls_ssl_read(). Library
|
||||
# only, ~20 s to build. A download that still fails after
|
||||
# the retries skips the leg rather than failing the job.
|
||||
mbed_ver=3.6.0
|
||||
mbed_sha=3ecf94fcfdaacafb757786a01b7538a61750ebd85c4b024f56ff8ba1490fcd38
|
||||
mbed_tar="$RUNNER_TEMP/mbedtls-$mbed_ver.tar.bz2"
|
||||
if curl -fsSL --retry 3 --retry-delay 5 --max-time 120 -o "$mbed_tar" \
|
||||
"https://github.com/Mbed-TLS/mbedtls/releases/download/v$mbed_ver/mbedtls-$mbed_ver.tar.bz2"; then
|
||||
echo "$mbed_sha $mbed_tar" | sha256sum -c -
|
||||
tar -xjf "$mbed_tar" -C "$RUNNER_TEMP"
|
||||
make -C "$RUNNER_TEMP/mbedtls-$mbed_ver" -j"$(nproc)" lib >/dev/null
|
||||
make clean SSL_BACKEND=mbed SANITIZER=address,undefined && make -j$(nproc) all SSL_BACKEND=mbed SANITIZER=address,undefined \
|
||||
MBEDTLS_DIR="$RUNNER_TEMP/mbedtls-$mbed_ver"
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 timeout 120 \
|
||||
make check SSL_BACKEND=mbed
|
||||
echo "[pass] cheevos_login_test (mbedTLS $mbed_ver TLS 1.3, ASan)"
|
||||
else
|
||||
echo "::warning::Mbed TLS $mbed_ver download failed; TLS 1.3 leg skipped"
|
||||
fi
|
||||
|
||||
- name: Build and run net_http_semantics_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/network/net_http_semantics
|
||||
run: |
|
||||
set -eu
|
||||
# HTTP/1.1 semantics of libretro-common/net/net_http.c against
|
||||
# an in-process scripted server on 127.0.0.1, which logs which
|
||||
# connection every request arrived on. Covers GET 200 framing
|
||||
# and pool reuse, and responses without a body: HEAD, 204 and
|
||||
# 304 on keep-alive used to sit waiting for a close that never
|
||||
# came, a 1xx other than 100 was taken as the final status,
|
||||
# and a 101 or stray bytes after a bodyless response left the
|
||||
# socket in the pool. Connection and Transfer-Encoding are
|
||||
# read as lists ("Keep-Alive, Close", "gzip, chunked"),
|
||||
# HTTP/1.0 without keep-alive is not pooled, and a length
|
||||
# after "chunked" does not reframe the body. Redirects: an
|
||||
# absolute-path Location used to go out as "GET //foo", a
|
||||
# 302 loop was followed forever (now 8 hops), a streamed PUT
|
||||
# redirected by a 307 is rewound and resent whole, and a 3xx
|
||||
# body no longer lands in the caller's sink. Bounds: a header
|
||||
# block (1xx blocks included) over 64 KiB and a chunk size
|
||||
# with no hex digits fail instead of growing the buffer or
|
||||
# passing as the last chunk, a Content-Length buffer never
|
||||
# grows past the body, and a pooled connection that dies
|
||||
# after the status line is not replayed. A URL shorter than
|
||||
# its scheme is rejected without an overread. Unit matrix for
|
||||
# net_http_url_join() and net_http_urldecode(), including
|
||||
# buffer bounds and in-place decoding; redirects resolved
|
||||
# through it ("../", "?q", "//host", fragments dropped,
|
||||
# %20 left encoded). The response header block: lookup and
|
||||
# iteration, the legacy string_list accessor, and 64 header
|
||||
# lines costing no per-line allocations. A Content-Length or
|
||||
# "chunked" on a 1xx block does not frame the final response.
|
||||
# A followed 3xx's body is dropped as it arrives, not
|
||||
# buffered to its Content-Length, and bytes past a body's
|
||||
# Content-Length end the connection, not the transfer.
|
||||
# Every case has a
|
||||
# deadline, so a hang fails the case instead of the job.
|
||||
# net_http is lock-free by design (DNS cache and pool owned by
|
||||
# the driving thread, resolvers publish with an atomic store);
|
||||
# keep it that way.
|
||||
if grep -nE '\b(slock|scond)_[a-z_]+\(' ../../../libretro-common/net/net_http.c; then
|
||||
echo "::error title=net_http lock::net_http.c must not take locks"
|
||||
exit 1
|
||||
fi
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 timeout 120 \
|
||||
./net_http_semantics_test
|
||||
echo "[pass] net_http_semantics_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 300 ./net_http_semantics_test
|
||||
echo "[pass] net_http_semantics_test (TSan)"
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,201 +0,0 @@
|
||||
name: CI Linux samples/record
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'record/**'
|
||||
- 'gfx/common/videotoolbox_encode*.h'
|
||||
- 'libretro-common/queues/**'
|
||||
- 'libretro-common/include/retro_spsc.h'
|
||||
- 'libretro-common/include/retro_atomic.h'
|
||||
- 'samples/record/**'
|
||||
- '.github/workflows/Linux-samples-record.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'record/**'
|
||||
- 'gfx/common/videotoolbox_encode*.h'
|
||||
- 'libretro-common/queues/**'
|
||||
- 'libretro-common/include/retro_spsc.h'
|
||||
- 'libretro-common/include/retro_atomic.h'
|
||||
- 'samples/record/**'
|
||||
- '.github/workflows/Linux-samples-record.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
samples-record:
|
||||
name: Build and run samples/record
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: mingw-w64 wine build-essential pkg-config ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev ccache
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Build and run ffmpeg_pipeline_test (ASan + UBSan, TSan)
|
||||
shell: bash
|
||||
working-directory: samples/record/ffmpeg_pipeline
|
||||
run: |
|
||||
set -eu
|
||||
# record/drivers/record_ffmpeg.c end to end: frames whose
|
||||
# pixels encode their number, plus audio, pushed from the
|
||||
# test thread while the driver's encoder thread drains the
|
||||
# attr/video/audio rings; the file is decoded back and every
|
||||
# frame checked in order and pixel-exact. Covers the rings
|
||||
# under contention, the full-queue wait, and the drain after
|
||||
# the encoder thread is joined. Needs libavcodec with
|
||||
# libx264rgb (Ubuntu's has it).
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x ffmpeg_pipeline_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 300 \
|
||||
./ffmpeg_pipeline_test
|
||||
echo "[pass] ffmpeg_pipeline_test (ASan)"
|
||||
make clean SANITIZER=thread && make -j$(nproc) all SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 300 ./ffmpeg_pipeline_test
|
||||
echo "[pass] ffmpeg_pipeline_test (TSan)"
|
||||
# The same run on a video ring that cannot be mirrored, as on
|
||||
# a platform without a double mapping: frames that straddle
|
||||
# the wrap go through the encoder side's scratch copy.
|
||||
make clean SANITIZER=address,undefined PLAIN_RING=1 && make -j$(nproc) all SANITIZER=address,undefined PLAIN_RING=1
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 300 \
|
||||
./ffmpeg_pipeline_test
|
||||
echo "[pass] ffmpeg_pipeline_test (plain ring, ASan)"
|
||||
|
||||
- name: Native overlapped file output
|
||||
working-directory: samples/record/file_win32
|
||||
run: |
|
||||
set -eu
|
||||
make clean && make check SANITIZER=address,undefined
|
||||
make clean && make check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
|
||||
make clean
|
||||
|
||||
- name: Native MP4 mux (ASan + UBSan, mingw-w64)
|
||||
shell: bash
|
||||
working-directory: samples/record/mp4_mux
|
||||
run: |
|
||||
set -eu
|
||||
make clean && make -j$(nproc) check SANITIZER=address,undefined
|
||||
make clean && make -j$(nproc) check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
|
||||
make clean
|
||||
|
||||
- name: GPU PCM output pipeline (ASan + UBSan, TSan, mingw-w64)
|
||||
working-directory: samples/record/gpu_av_output
|
||||
run: |
|
||||
set -eu
|
||||
make clean && make -j$(nproc) check SANITIZER=address,undefined
|
||||
make clean && make thread_test session_test SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./thread_test
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./session_test
|
||||
make clean && make -j$(nproc) check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
|
||||
make clean
|
||||
|
||||
- name: GPU recording dispatcher (ASan + UBSan, TSan, mingw-w64)
|
||||
working-directory: samples/record/gpu_dispatch
|
||||
run: |
|
||||
set -eu
|
||||
make clean && make check SANITIZER=address,undefined
|
||||
make clean && make dispatch_test session_integration SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./dispatch_test
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./session_integration
|
||||
make clean && make check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
|
||||
make clean
|
||||
|
||||
- name: Native recording frontend clock and PCM (ASan + UBSan, mingw-w64)
|
||||
working-directory: samples/record/nvenc_frontend
|
||||
run: |
|
||||
set -eu
|
||||
make clean && make check SANITIZER=address,undefined
|
||||
make clean && make check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
|
||||
make clean
|
||||
|
||||
# The Apple API stand-in checks ownership/configuration only. Native
|
||||
# compilation and hardware encode run in MacOS-videotoolbox-encode.yml.
|
||||
- name: VideoToolbox encode callback and session contracts
|
||||
working-directory: samples/record/videotoolbox_encode
|
||||
run: |
|
||||
set -eu
|
||||
make clean && make check thread_test worker_thread_test audio_thread_test av_session_thread_test SANITIZER=address,undefined
|
||||
./thread_test
|
||||
./worker_thread_test
|
||||
./audio_thread_test
|
||||
./av_session_thread_test
|
||||
make clean && make thread_test worker_thread_test audio_thread_test av_session_thread_test SANITIZER=thread
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./thread_test
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./worker_thread_test
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./audio_thread_test
|
||||
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./av_session_thread_test
|
||||
make clean && make check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
|
||||
make clean
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,145 +0,0 @@
|
||||
name: CI Linux samples/settings
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
samples-settings:
|
||||
name: Build and run samples/settings
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential ccache
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Enable ccache
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
echo "/usr/lib/ccache" >> "$GITHUB_PATH"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
|
||||
- name: Settings definitions keep their keys and defaults
|
||||
run: |
|
||||
set -eu
|
||||
python3 tools/settings_check_test.py
|
||||
python3 tools/settings_check.py table --check tools/settings_table.reference
|
||||
python3 tools/settings_check.py unity
|
||||
|
||||
- name: Settings lists have room for what they are given
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# configuration.c builds each list of settings into an array
|
||||
# of a fixed size. One setting too many for its list wrote
|
||||
# past the end of the array, and RetroArch died of heap
|
||||
# corruption at startup: two per-port string settings did it
|
||||
# to the string list. The lists now refuse what they have no
|
||||
# room for; this counts, in the preprocessed source and for
|
||||
# each build profile, what every list is given against the
|
||||
# size it is allocated with, so that the next one is found
|
||||
# here.
|
||||
timeout 300 tools/check.sh tools/settings_capacity_check.c
|
||||
echo "[pass] settings_capacity_check"
|
||||
|
||||
- name: Build and run pipeline_migration_test (ASan + UBSan)
|
||||
shell: bash
|
||||
working-directory: samples/settings/pipeline_migration
|
||||
run: |
|
||||
set -eu
|
||||
# The audio_threaded_pipeline config migration. The setting
|
||||
# briefly held off/automatic/on and was saved as a number; it
|
||||
# is a bool again, and a bool is always saved as "true" or
|
||||
# "false", so a bare digit on the key is the older three-way
|
||||
# value. config_get_bool() reads its automatic (1) as an
|
||||
# explicit on, which forced the pipeline on for users who
|
||||
# never chose it. Pins each stored digit against both
|
||||
# defaults, and pins that "true", "false", absent, empty and
|
||||
# multi-character values are untouched. The rule under test
|
||||
# is restated from config_load_file(), which needs most of the
|
||||
# frontend to run; a change to one must be made in the other.
|
||||
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
|
||||
test -x pipeline_migration_test
|
||||
ASAN_OPTIONS=detect_leaks=1:detect_stack_use_after_return=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 timeout 60 \
|
||||
./pipeline_migration_test
|
||||
echo "[pass] pipeline_migration_test (ASan)"
|
||||
|
||||
- name: Build and run cli_override_rows_test (ASan + UBSan)
|
||||
shell: bash
|
||||
working-directory: samples/settings/cli_override_rows
|
||||
run: |
|
||||
set -eu
|
||||
# Each command-line override (--log-file, --check-frames,
|
||||
# --port) must pin its own setting's row: config_save_file()
|
||||
# skips the row carrying a set override, so on another row it
|
||||
# dropped that setting and saved the command-line value.
|
||||
make clean && make check SANITIZER=address,undefined
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,104 +0,0 @@
|
||||
name: CI Linux samples [nothing else runs these]
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
samples-unclaimed:
|
||||
name: Samples no other job runs
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
APT_PKGS: build-essential gcc-mingw-w64-x86-64 wine64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
# Up front, bounded, for the samples cross-built with mingw-w64 and
|
||||
# run under Wine: installed inside the loop, a mirror that stalled
|
||||
# held the job, silent, until its 30 minutes ran out
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 15
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Run them
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# A sample that builds and runs, and that no workflow names,
|
||||
# is a test nobody runs: font_lifecycle sat that way while
|
||||
# its expectation drifted away from the font driver it was
|
||||
# written against. This job takes whatever is left over -
|
||||
# the list is computed, so a new sample joins it by existing
|
||||
# rather than by being remembered.
|
||||
#
|
||||
# Samples that need a library the runner does not carry
|
||||
# (SDL, FFmpeg, libusb) are skipped: their own workflows
|
||||
# install what they need. mingw-w64 and Wine come from the
|
||||
# install step, for the samples cross-built and run under Wine.
|
||||
fails=0
|
||||
for mk in $(find samples libretro-common/samples -name Makefile | sort); do
|
||||
dir=$(dirname "$mk")
|
||||
name=$(basename "$dir")
|
||||
(cd "$dir" && make -n check >/dev/null 2>&1) || continue
|
||||
if grep -rqlF "$name" .github/workflows/ 2>/dev/null; then
|
||||
continue
|
||||
fi
|
||||
if grep -qiE 'sdl|ffmpeg|libav|libusb' "$mk"; then
|
||||
echo "-- skip $dir (needs a library this job does not install)"
|
||||
continue
|
||||
fi
|
||||
echo "== $dir"
|
||||
if (cd "$dir" && make clean >/dev/null 2>&1 \
|
||||
&& ASAN_OPTIONS=detect_leaks=1:allocator_may_return_null=1 \
|
||||
UBSAN_OPTIONS=print_stacktrace=1 \
|
||||
timeout 300 make SANITIZER=address,undefined check); then
|
||||
echo " ok"
|
||||
else
|
||||
echo " FAIL $dir"
|
||||
fails=$((fails + 1))
|
||||
fi
|
||||
(cd "$dir" && make clean >/dev/null 2>&1) || true
|
||||
done
|
||||
if [ "$fails" -ne 0 ]; then
|
||||
echo "$fails sample(s) failed"
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,74 +0,0 @@
|
||||
name: CI Linux state_manager + runahead tests
|
||||
|
||||
# The rewind codec and ring, and the run-ahead core-copy protocol,
|
||||
# driven directly by harnesses that include or extract the shipping
|
||||
# code: samples/state_rewind and samples/runahead. Plain, then under
|
||||
# ASan and UBSan with halt_on_error.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- state_manager.c
|
||||
- state_manager.h
|
||||
- runahead.c
|
||||
- runahead.h
|
||||
- runloop.h
|
||||
- samples/state_rewind/**
|
||||
- samples/runahead/**
|
||||
- tasks/task_nbio_slice.c
|
||||
- tasks/tasks_internal.h
|
||||
- libretro-common/queues/task_queue.c
|
||||
- .github/workflows/Linux-state-runahead-tests.yml
|
||||
pull_request:
|
||||
branches: [master]
|
||||
paths:
|
||||
- state_manager.c
|
||||
- state_manager.h
|
||||
- runahead.c
|
||||
- runahead.h
|
||||
- runloop.h
|
||||
- samples/state_rewind/**
|
||||
- samples/runahead/**
|
||||
- tasks/task_nbio_slice.c
|
||||
- tasks/tasks_internal.h
|
||||
- libretro-common/queues/task_queue.c
|
||||
- .github/workflows/Linux-state-runahead-tests.yml
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
unit:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
- name: state_rewind
|
||||
run: make -C samples/state_rewind clean check
|
||||
- name: runahead
|
||||
run: make -C samples/runahead clean check
|
||||
|
||||
sanitize:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
ASAN_OPTIONS: abort_on_error=1:detect_leaks=1:print_stacktrace=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
- name: state_rewind (ASan + UBSan)
|
||||
run: make -C samples/state_rewind clean check SANITIZER=address,undefined
|
||||
- name: runahead (ASan + UBSan)
|
||||
run: make -C samples/runahead clean check SANITIZER=address,undefined
|
||||
@@ -1,98 +0,0 @@
|
||||
name: CI Linux TSan [threaded-video harness]
|
||||
|
||||
# The threaded-video harness under ThreadSanitizer. Linux-tsan-threaded-
|
||||
# video.yml builds with TSan and runs RetroArch headless with the
|
||||
# wrapper on, which is one configuration; the harness has a lane for
|
||||
# each thing the wrapper does - the runtime toggle, reinit under the
|
||||
# wrapper, the command mailbox, presenter repeats and their display
|
||||
# phase, the second ring waiter, the re-entrant frame, the call on the
|
||||
# waiting thread, display pacing, the zero-copy loan, the hardware
|
||||
# ring's bookkeeping - and runs each against the shipping objects with
|
||||
# nothing stubbed. It is where the send/wait race in the waiter call
|
||||
# was found, under TSan, on a developer's machine: this job is what
|
||||
# keeps that class of bug found in CI instead. Null drivers, no
|
||||
# display, no SDL, so no suppression file is needed; the harness sets
|
||||
# halt_on_error itself, so any report fails the job.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
linux-tsan-harness:
|
||||
name: TSan build, the threaded-video harness
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
|
||||
env:
|
||||
APT_PKGS: build-essential libxkbcommon-dev libx11-xcb-dev xvfb x11-utils zlib1g-dev libfreetype6-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev libavcodec-dev libsdl2-dev libsdl-image1.2-dev libxml2-dev yasm
|
||||
# Line tables are all a sanitizer report needs. configure and
|
||||
# make take these in place of DEBUG=1's -O0 -g, adding their own.
|
||||
CFLAGS: -O0 -g1
|
||||
CXXFLAGS: -O0 -g1
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Configure
|
||||
# Non-Qt, as the harness requires (with Qt, main() lives in
|
||||
# ui_qt.o). Menu enabled: the menu lanes are half the point.
|
||||
run: |
|
||||
./configure \
|
||||
--disable-qt \
|
||||
--disable-discord \
|
||||
--disable-cheevos \
|
||||
--disable-networking \
|
||||
--disable-ffmpeg
|
||||
|
||||
- name: Build with DEBUG=1 and -fsanitize=thread
|
||||
run: |
|
||||
make -j$(getconf _NPROCESSORS_ONLN) SANITIZER=thread DEBUG=1
|
||||
|
||||
- name: Run the threaded-video harness under TSan
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# SAN=thread links exactly the build above; CYCLES=2 runs
|
||||
# each toggling lane twice. The harness's own TSAN_OPTIONS
|
||||
# halt on the first report.
|
||||
SAN=thread CYCLES=2 make -C samples/gfx/threaded_video check
|
||||
make -C samples/gfx/threaded_video clean
|
||||
@@ -1,65 +0,0 @@
|
||||
name: CI Linux TSan [sample suites]
|
||||
|
||||
# The threaded sample suites no other lane runs under ThreadSanitizer.
|
||||
# Their own steps build them under ASan, which cannot see a race: an
|
||||
# unordered access between two threads passes there and is only found
|
||||
# by a developer running TSan by hand. tools/tsan-samples.sh builds each
|
||||
# suite in tools/tsan-samples.list with SANITIZER=thread and runs it with
|
||||
# halt_on_error, so any report fails the job; the list says what is left
|
||||
# out and why.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
linux-tsan-samples:
|
||||
name: TSan, the threaded sample suites
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential zlib1g-dev libasound2-dev libsdl1.2-dev libsdl2-dev libwayland-dev ffmpeg
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Build and run each suite under TSan
|
||||
run: tools/tsan-samples.sh
|
||||
@@ -1,172 +0,0 @@
|
||||
name: CI Linux TSan [Threaded video]
|
||||
|
||||
# Builds RetroArch with -fsanitize=thread and runs it headless with
|
||||
# video_threaded = "true", which is the configuration none of the other
|
||||
# jobs cover and the only one where the video thread exists at all.
|
||||
#
|
||||
# Why a separate job from Linux-asan-ubsan.yml: ASan and TSan cannot be
|
||||
# linked into the same binary, and the ASan job deliberately runs
|
||||
# unthreaded (video_threaded = "false") because its purpose is memory
|
||||
# errors on the simplest path. Threading bugs are invisible there --
|
||||
# the second thread is never created.
|
||||
#
|
||||
# What this reaches that nothing else does: the video thread wrapper's
|
||||
# command and frame handoff, every driver frame() call running off the
|
||||
# main thread, and the state the runloop and the video thread share --
|
||||
# window title, alive/focus/presentable, viewport and statistics. Two
|
||||
# real races were found this way and fixed (the window title handoff,
|
||||
# and the runloop asking a context for presentability while the video
|
||||
# thread rebuilt its swapchain); this job is what keeps them fixed.
|
||||
#
|
||||
# Soft-fail for now, like the ASan job's smoke tier was on its first
|
||||
# iterations: TSan reports races inside libSDL2 itself that RetroArch
|
||||
# neither causes nor can fix (see the suppression file written below),
|
||||
# and the baseline wants a few green runs before it gates.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
linux-tsan-threaded-video:
|
||||
name: Build with TSan and run with threaded video
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential libxkbcommon-dev libx11-xcb-dev xvfb x11-utils zlib1g-dev libfreetype6-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev libavcodec-dev libsdl2-dev libsdl-image1.2-dev libxml2-dev yasm
|
||||
timeout-minutes: 45
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Configure
|
||||
# Same trimmed surface as the ASan job, for the same reason:
|
||||
# a finding should be a RetroArch bug rather than noise from a
|
||||
# vendored subsystem. --enable-sdl2 is explicit because the run
|
||||
# below selects sdl2, and a silent fallback to another driver
|
||||
# would quietly stop exercising the threaded path this job is
|
||||
# for.
|
||||
run: |
|
||||
./configure \
|
||||
--disable-menu \
|
||||
--disable-discord \
|
||||
--disable-cheevos \
|
||||
--disable-networking \
|
||||
--enable-sdl2
|
||||
|
||||
- name: Build with -fsanitize=thread
|
||||
run: |
|
||||
make -j$(getconf _NPROCESSORS_ONLN) SANITIZER=thread
|
||||
test -x retroarch
|
||||
file retroarch
|
||||
|
||||
- name: Run headless with video_threaded = true
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
Xvfb :99 -screen 0 640x480x24 &
|
||||
for i in $(seq 1 15); do
|
||||
if DISPLAY=:99 xdpyinfo >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# A 1x1 PNG for the imageviewer core, as in the ASan job.
|
||||
python3 - <<'PY'
|
||||
import binascii, struct
|
||||
def chunk(t, d):
|
||||
c = t + d
|
||||
return struct.pack(">I", len(d)) + c + struct.pack(">I", binascii.crc32(c))
|
||||
png = b"\x89PNG\r\n\x1a\n"
|
||||
png += chunk(b"IHDR", struct.pack(">IIBBBBB", 1, 1, 8, 2, 0, 0, 0))
|
||||
png += chunk(b"IDAT", b"\x08\xd7\x63\xf8\xcf\xc0\x00\x00\x03\x01\x01\x00\x18\xdd\x8d\xb0")
|
||||
png += chunk(b"IEND", b"")
|
||||
open("/tmp/test.png", "wb").write(png)
|
||||
PY
|
||||
|
||||
# Races inside libSDL2 itself: no RetroArch frame appears on
|
||||
# either access, so there is nothing here to fix. Suppressed
|
||||
# by object so a real race in our own SDL-facing code is
|
||||
# still reported.
|
||||
cat > /tmp/tsan.supp <<'EOF'
|
||||
race:libSDL2-2.0.so
|
||||
EOF
|
||||
|
||||
mkdir -p /tmp/tsan-cfg
|
||||
cat > /tmp/tsan-cfg/retroarch.cfg <<EOF
|
||||
video_driver = "sdl2"
|
||||
audio_driver = "null"
|
||||
video_threaded = "true"
|
||||
video_fullscreen = "false"
|
||||
video_windowed_fullscreen = "false"
|
||||
EOF
|
||||
|
||||
set +e
|
||||
DISPLAY=:99 \
|
||||
TSAN_OPTIONS="halt_on_error=0 history_size=4 suppressions=/tmp/tsan.supp" \
|
||||
timeout 300 ./retroarch \
|
||||
-c /tmp/tsan-cfg/retroarch.cfg \
|
||||
-L cores/libretro-imageviewer/image_core.so \
|
||||
/tmp/test.png \
|
||||
--max-frames=400 \
|
||||
--verbose \
|
||||
> /tmp/tsan.out 2> /tmp/tsan.err
|
||||
rc=$?
|
||||
set -e
|
||||
|
||||
echo "exit=${rc}"
|
||||
echo "=== stderr (last 200) ==="
|
||||
tail -200 /tmp/tsan.err || true
|
||||
|
||||
# The video thread has to have existed, or the run proved
|
||||
# nothing at all and a green result would be misleading.
|
||||
if ! grep -q "ra-video\|[Tt]hreaded video" /tmp/tsan.out /tmp/tsan.err; then
|
||||
echo "[WARN] no sign of the video thread; the threaded path may not have run"
|
||||
fi
|
||||
|
||||
n=$(grep -c "WARNING: ThreadSanitizer" /tmp/tsan.err || true)
|
||||
echo "ThreadSanitizer reports: ${n}"
|
||||
if [ "${n}" -gt 0 ]; then
|
||||
echo ""
|
||||
echo "[INFO] ThreadSanitizer finding(s):"
|
||||
grep "SUMMARY: ThreadSanitizer" /tmp/tsan.err || true
|
||||
fi
|
||||
@@ -1,131 +0,0 @@
|
||||
name: CI Linux Vulkan resize
|
||||
|
||||
# The Vulkan driver through changes of the swapchain's size, run for
|
||||
# real: a retroarch built with Vulkan and X11, on a virtual display
|
||||
# with Mesa's software Vulkan driver, has its window resized four
|
||||
# times, with the menu closed and open.
|
||||
#
|
||||
# When a swapchain is replaced for nothing but its size, the driver
|
||||
# rebuilds the framebuffers on its images and keeps the rest - the
|
||||
# pipelines, render passes, samplers, pools, buffers and frame
|
||||
# textures it used to destroy and build again each time. This holds
|
||||
# that every size change takes that path, that the picture afterwards
|
||||
# is pixel for pixel the one a full rebuild draws, and that the
|
||||
# Vulkan validation layers have nothing to say about either. Then
|
||||
# the same with a two-pass shader preset: the shader chain, which used
|
||||
# to reflect and compile every pass again on each swapchain change, is
|
||||
# kept when only the size changed, and its picture is the one a full
|
||||
# rebuild draws. See samples/gfx/vulkan_resize/run.sh.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'gfx/drivers/vulkan.c'
|
||||
- 'gfx/common/vulkan_common.*'
|
||||
- 'gfx/drivers_context/x_vk_ctx.c'
|
||||
- 'gfx/drivers_shader/shader_vulkan.*'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'samples/gfx/vulkan_resize/**'
|
||||
- 'samples/input/windows_wine_smoke/smoke_core.c'
|
||||
- '.github/workflows/Linux-vulkan-resize.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'gfx/drivers/vulkan.c'
|
||||
- 'gfx/common/vulkan_common.*'
|
||||
- 'gfx/drivers_context/x_vk_ctx.c'
|
||||
- 'gfx/drivers_shader/shader_vulkan.*'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'samples/gfx/vulkan_resize/**'
|
||||
- 'samples/input/windows_wine_smoke/smoke_core.c'
|
||||
- '.github/workflows/Linux-vulkan-resize.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Only pull requests cancel a superseded run. On master every push
|
||||
# gets its own group (keyed by the commit), so a burst of pushes queues
|
||||
# instead of cancelling the run for the commit before it.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
linux-vulkan-resize:
|
||||
name: Run retroarch on software Vulkan and resize its window
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential ccache xvfb xdotool x11-apps python3 libx11-dev libx11-xcb-dev libxcb1-dev libxext-dev libxxf86vm-dev libxinerama-dev libxrandr-dev libxv-dev libudev-dev zlib1g-dev libvulkan-dev mesa-vulkan-drivers vulkan-validationlayers
|
||||
timeout-minutes: 40
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Build retroarch with Vulkan and X11
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
ccache -M 500M
|
||||
ccache -z
|
||||
# (--enable-vulkan makes configure look for the Vulkan
|
||||
# loader to link against: libvulkan-dev above)
|
||||
./configure --disable-qt --enable-vulkan --enable-x11 \
|
||||
--disable-wayland --disable-sdl2 --disable-pulse \
|
||||
--disable-alsa --disable-ffmpeg --disable-discord
|
||||
make -j$(nproc) CC="ccache gcc" CXX="ccache g++"
|
||||
ccache -s
|
||||
test -x retroarch
|
||||
|
||||
- name: Resize the window on both paths
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
timeout 600 samples/gfx/vulkan_resize/run.sh
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,146 +0,0 @@
|
||||
name: CI Linux Wayland input
|
||||
|
||||
# RetroArch's Wayland input path, run for real: a retroarch built with
|
||||
# Wayland and OpenGL is run under Weston - itself a window on a virtual
|
||||
# X display, drawing in software - keys are pressed and the pointer is
|
||||
# moved in it, and its log is read. It runs the small core of
|
||||
# samples/input/windows_wine_smoke, which writes to the log what
|
||||
# reaches it.
|
||||
#
|
||||
# What it holds: that the seat's events - keyboard, pointer - are
|
||||
# handled on the frontend's thread and nowhere else, with threaded
|
||||
# video and without. They are on an event queue of their own that only
|
||||
# the input driver's poll dispatches; on the one queue there used to
|
||||
# be, the video thread dispatched them as well. And that keys, the
|
||||
# pointer, a fullscreen toggle and the keyboard focus leaving and
|
||||
# coming back all still work that way. See
|
||||
# samples/input/wayland_smoke/run.sh.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'input/input_driver.c'
|
||||
- 'input/input_driver.h'
|
||||
- 'input/drivers/wayland_input.c'
|
||||
- 'input/common/wayland_common.*'
|
||||
- 'gfx/common/wayland_common.*'
|
||||
- 'gfx/drivers_context/wayland_ctx.c'
|
||||
- 'gfx/drivers_context/wayland_vk_ctx.c'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'samples/input/wayland_smoke/**'
|
||||
- 'samples/input/windows_wine_smoke/smoke_core.c'
|
||||
- '.github/workflows/Linux-wayland-input.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'input/input_driver.c'
|
||||
- 'input/input_driver.h'
|
||||
- 'input/drivers/wayland_input.c'
|
||||
- 'input/common/wayland_common.*'
|
||||
- 'gfx/common/wayland_common.*'
|
||||
- 'gfx/drivers_context/wayland_ctx.c'
|
||||
- 'gfx/drivers_context/wayland_vk_ctx.c'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'samples/input/wayland_smoke/**'
|
||||
- 'samples/input/windows_wine_smoke/smoke_core.c'
|
||||
- '.github/workflows/Linux-wayland-input.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Only pull requests cancel a superseded run. On master every push
|
||||
# gets its own group (keyed by the commit), so a burst of pushes queues
|
||||
# instead of cancelling the run for the commit before it.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
linux-wayland-input:
|
||||
name: Run retroarch under Weston and press keys
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential ccache weston xvfb xdotool x11-apps libwayland-dev wayland-protocols libxkbcommon-dev libdecor-0-dev libegl1-mesa-dev libgl1-mesa-dev libgl1-mesa-dri libudev-dev
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Build retroarch with Wayland and OpenGL (the rest off)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
# What the test runs has to be real: the Wayland context and
|
||||
# input driver, OpenGL, the menu, threads. Everything else is
|
||||
# build time.
|
||||
./configure --disable-qt --disable-x11 --enable-wayland \
|
||||
--disable-sdl --disable-sdl2 --disable-ffmpeg \
|
||||
--disable-vulkan --disable-pulse --disable-discord \
|
||||
--disable-networking --disable-cheevos \
|
||||
--disable-glslang --disable-slang \
|
||||
--disable-spirv_cross --disable-xmb \
|
||||
--disable-materialui --disable-ozone \
|
||||
--disable-7zip --disable-flac \
|
||||
--disable-audiomixer --disable-translate \
|
||||
--disable-accessibility --disable-crtswitchres \
|
||||
--disable-langextra --disable-libretrodb \
|
||||
--disable-video_filter --disable-dsp_filter
|
||||
make -j$(nproc) CC="ccache gcc" CXX="ccache g++"
|
||||
ccache -s
|
||||
test -x retroarch
|
||||
|
||||
- name: Run the scenarios under Weston
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
timeout 600 samples/input/wayland_smoke/run.sh
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,79 +0,0 @@
|
||||
name: CI builtin media player
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'cores/libretro-media/**'
|
||||
- 'samples/cores/webm_player/**'
|
||||
- 'libretro-common/samples/formats/audio_transfer/**'
|
||||
- 'libretro-common/formats/**'
|
||||
- 'libretro-common/include/formats/**'
|
||||
- '.github/workflows/Linux-webm-player.yml'
|
||||
pull_request:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'cores/libretro-media/**'
|
||||
- 'samples/cores/webm_player/**'
|
||||
- 'libretro-common/samples/formats/audio_transfer/**'
|
||||
- 'libretro-common/formats/**'
|
||||
- 'libretro-common/include/formats/**'
|
||||
- '.github/workflows/Linux-webm-player.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
player:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
APT_PKGS: build-essential ffmpeg gcc-mingw-w64-x86-64 wine64
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
# Bounded, with the main archive tried when the mirror stalls: a
|
||||
# plain apt-get install stalled on it took the job's 15 minutes
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 15
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
- name: Generate media
|
||||
working-directory: samples/cores/webm_player
|
||||
run: python3 mkfixtures.py
|
||||
- name: Metadata-only demuxed audio setup
|
||||
run: |
|
||||
make -j2 -C libretro-common/samples/formats/audio_transfer check-empty SANITIZER=address,undefined SAMPLE_OBJDIR=obj-player-meta
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
- name: Run the builtin core without FFmpeg
|
||||
working-directory: samples/cores/webm_player
|
||||
run: |
|
||||
set -eu
|
||||
make -j2 check SANITIZER=address,undefined SAMPLE_OBJDIR=obj-ci-asan TARGET=webm_player_ci_asan
|
||||
make -j2 check AUDIO=0 SAMPLE_OBJDIR=obj-noaudio TARGET=webm_player_noaudio SANITIZER=address,undefined
|
||||
make -j2 check MP4=0 SAMPLE_OBJDIR=obj-webm TARGET=webm_player_webm SANITIZER=address,undefined
|
||||
make -j2 check THREADS=0 SAMPLE_OBJDIR=obj-nothreads TARGET=webm_player_nothreads SANITIZER=address,undefined
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=1
|
||||
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||
- name: Windows core host
|
||||
working-directory: samples/cores/webm_player
|
||||
run: |
|
||||
set -eu
|
||||
make -j2 check CC=x86_64-w64-mingw32-gcc OS=Windows_NT EXE=.exe SAMPLE_OBJDIR=obj-win RUNNER=wine
|
||||
@@ -1,56 +0,0 @@
|
||||
name: CI Linux (i686)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-i386-ubuntu:xenial-gcc9
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- name: Check Out Repo
|
||||
uses: taiki-e/checkout-action@v1
|
||||
|
||||
- name: Configure Build
|
||||
run: |
|
||||
./configure --disable-qt --enable-xdelta
|
||||
|
||||
- name: Include order
|
||||
run: |
|
||||
# The tree's own headers are found before same-named ones in the
|
||||
# system include dirs configure or pkg-config put on the line.
|
||||
sh tools/include_order_check.sh
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -j$(getconf _NPROCESSORS_ONLN) info all
|
||||
|
||||
- name: Stack frame sweep
|
||||
run: |
|
||||
set -eu
|
||||
# Every stack frame in the graphics objects against the
|
||||
# ceiling in CODING-GUIDELINES. It runs here rather than with
|
||||
# the other checks because this is the job that builds the
|
||||
# drivers: the menu harness turns OpenGL, Vulkan and the rest
|
||||
# off for its own reasons, and the frames this sweep is for
|
||||
# live in exactly those files.
|
||||
.github/workflows/scripts/stack-frame-sweep.sh
|
||||
@@ -1,104 +0,0 @@
|
||||
name: CI Windows (MSVC)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
# These jobs run smoke tests to ensure that MSVC-specific builds work properly.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
|
||||
msvc:
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
matrix:
|
||||
version: [UWP, 2019, 2022]
|
||||
configuration: [Debug, Release]
|
||||
platform: [x64]
|
||||
exclude:
|
||||
- version: UWP
|
||||
configuration: Debug
|
||||
include:
|
||||
- version: UWP
|
||||
configuration: ReleaseAngle
|
||||
platform: x64
|
||||
# Qt and Cg builds are excluded for now
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
|
||||
- name: Compile RA
|
||||
working-directory: "${{github.workspace}}/pkg/msvc${{ matrix.version == 'UWP' && '-uwp' || ''}}"
|
||||
run: |
|
||||
msbuild -p:"Configuration=${{matrix.configuration}}" -p:"Platform=${{matrix.platform}}" .\RetroArch-msvc${{matrix.version}}.sln
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
shell: powershell
|
||||
run: echo "sha8=$('${{github.sha}}'.Substring(0,8))" >> $env:GITHUB_OUTPUT
|
||||
# https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: retroarch-${{matrix.version}}-${{matrix.configuration}}-${{matrix.platform}}-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
${{ matrix.version != 'UWP' }}:
|
||||
pkg/msvc/${{matrix.platform}}/${{matrix.configuration}}/RetroArch-msvc${{matrix.version}}.exe
|
||||
${{ matrix.version == 'UWP' }}:
|
||||
pkg/msvc-uwp/AppPackages/RetroArch-msvcUWP
|
||||
|
||||
msvc2026:
|
||||
runs-on: windows-2025
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
matrix:
|
||||
version: [UWP, 2026]
|
||||
configuration: [Debug, Release]
|
||||
platform: [x64]
|
||||
exclude:
|
||||
- version: UWP
|
||||
configuration: Debug
|
||||
include:
|
||||
- version: UWP
|
||||
configuration: ReleaseAngle
|
||||
platform: x64
|
||||
# Qt and Cg builds are excluded for now
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Compile RA
|
||||
working-directory: "${{github.workspace}}/pkg/msvc${{ matrix.version == 'UWP' && '-uwp' || ''}}"
|
||||
run: |
|
||||
msbuild -p:"Configuration=${{matrix.configuration}}" -p:"Platform=${{matrix.platform}}" .\RetroArch-msvc${{matrix.version}}.sln
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
shell: powershell
|
||||
run: echo "sha8=$('${{github.sha}}'.Substring(0,8))" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: retroarch-${{matrix.version}}-vs2026-${{matrix.configuration}}-${{matrix.platform}}-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
${{ matrix.version != 'UWP' }}:
|
||||
pkg/msvc/${{matrix.platform}}/${{matrix.configuration}}/RetroArch-msvc${{matrix.version}}.exe
|
||||
${{ matrix.version == 'UWP' }}:
|
||||
pkg/msvc-uwp/AppPackages/RetroArch-msvcUWP
|
||||
@@ -1,100 +0,0 @@
|
||||
name: CI Windows (MSYS2)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
msys2-build-test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Existing x64 builds
|
||||
- sys: MINGW64
|
||||
runner: windows-latest
|
||||
- sys: UCRT64
|
||||
runner: windows-latest
|
||||
- sys: CLANG64
|
||||
runner: windows-latest
|
||||
|
||||
# New ARM64 build (native Windows on ARM)
|
||||
# MSYS2's runtime runs emulated on these runners, so configure
|
||||
# runs its checks one at a time here instead of in parallel
|
||||
# background workers.
|
||||
- sys: CLANGARM64
|
||||
runner: windows-11-arm
|
||||
qb_jobs: 1
|
||||
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 90
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.sys }}
|
||||
update: true
|
||||
|
||||
- name: Install packages
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
# A mirror that stalls or rate-limits (HTTP 429) fails pacman's
|
||||
# whole transaction; what it fetched stays in the cache, so a
|
||||
# retry fetches only the rest, one file at a time after a
|
||||
# growing wait so a shared runner's rate limit can clear.
|
||||
# A package that fails its checksum is deleted, but pacman
|
||||
# fetches it again from the same first mirror, so each retry
|
||||
# also moves every mirror list's first server to the end.
|
||||
# Runtime updates belong to setup-msys2 above, which can restart
|
||||
# its shell. These retries install dependencies only.
|
||||
p=$MINGW_PACKAGE_PREFIX
|
||||
pkgs="base-devel git $p-gettext $p-gobject-introspection
|
||||
$p-graphite2 $p-p11-kit $p-qt6-base $p-x264 $p-cc"
|
||||
for i in 1 2 3 4 5; do
|
||||
pacman -S --noconfirm --needed $pkgs && exit 0
|
||||
[ $i = 5 ] && break
|
||||
echo "package install failed (attempt $i); retrying in $((30 * i))s, next mirror, serial downloads"
|
||||
sed -i -e '/^#*ParallelDownloads/d' -e '/^\[options\]/a ParallelDownloads = 1' /etc/pacman.conf
|
||||
for m in /etc/pacman.d/mirrorlist.*; do
|
||||
awk '/^Server/ && !s { s = $0; next } { print } END { if (s) print s }' "$m" > "$m.tmp" && mv "$m.tmp" "$m"
|
||||
done
|
||||
sleep $((30 * i))
|
||||
done
|
||||
exit 1
|
||||
|
||||
- name: Configure and build RetroArch
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
echo "Building RetroArch in ${{ matrix.sys }} on ${{ matrix.runner }}"
|
||||
QB_JOBS=${{ matrix.qb_jobs }} ./configure
|
||||
make -j"$(nproc)" info all
|
||||
|
||||
- name: Collect DLLs and binaries
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
echo "Collecting DLLs and binaries"
|
||||
rm -rf dist
|
||||
mkdir -p dist
|
||||
cp retroarch.exe dist/
|
||||
ldd retroarch.exe | grep "$MINGW_PREFIX" | awk '{print $3}' | xargs -I {} cp {} dist/ || true
|
||||
|
||||
- name: Archive build artifacts
|
||||
if: success()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: retroarch-${{ matrix.sys }}
|
||||
path: dist/
|
||||
@@ -1,141 +0,0 @@
|
||||
name: CI macOS PowerPC (cross)
|
||||
|
||||
# Builds the macOS (Cocoa + OpenGL) frontend for 32-bit PowerPC with a
|
||||
# GCC 14 cross compiler on Linux, against the 10.5 SDK, once for a
|
||||
# 10.4 deployment target and once for 10.5. This is the
|
||||
# compiler-compatibility leg for the Apple code: no clang, no ARC, no
|
||||
# blocks, no GCD, and nothing newer than Leopard in the SDK. Whatever
|
||||
# the Xcode 3 / PowerPC project would reject, this rejects first.
|
||||
#
|
||||
# Toolchain: VariantXYZ's GCC 14.2 powerpc-apple-darwin8 image (GCC
|
||||
# with the Objective-C front end, cctools-port ld/as, dsymutil), see
|
||||
# https://github.com/VariantXYZ/gcc-powerpc-apple-darwin8.
|
||||
#
|
||||
# The audit step lists every import the binary makes that the 10.4u
|
||||
# SDK does not export; for the 10.4 target that list must be empty,
|
||||
# which is what makes the binary launch on Tiger.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
TARGET: powerpc-apple-darwin8
|
||||
SDKROOT: /usr/local/MacOSX10.5.sdk
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
container:
|
||||
image: ghcr.io/variantxyz/gcc-powerpc-apple-darwin8:build-gcc-14.2-MacOSXSDK10.5
|
||||
options: --user root
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
deployment_target: ["10.4", "10.5"]
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.deployment_target }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
$TARGET-gcc --version | head -n 1
|
||||
./configure --host=$TARGET \
|
||||
--disable-qt --disable-sdl --disable-sdl2 --disable-ffmpeg \
|
||||
--disable-x11 --disable-wayland --disable-egl \
|
||||
--disable-pulse --disable-alsa --disable-jack --disable-oss \
|
||||
--disable-udev --disable-v4l2 --disable-libusb \
|
||||
--disable-freetype --disable-flac --disable-discord \
|
||||
--disable-translate --disable-microphone --disable-avf \
|
||||
--disable-mfi --disable-slang --disable-spirv_cross \
|
||||
--disable-glslang --disable-crtswitchres --disable-al \
|
||||
--disable-cdrom
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ matrix.deployment_target }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-${{ matrix.deployment_target }}-
|
||||
|
||||
- name: Set up ccache
|
||||
run: |
|
||||
# Best effort: without ccache, ccache-make.sh runs plain make.
|
||||
command -v ccache > /dev/null || {
|
||||
s=$(command -v sudo || true)
|
||||
for i in 1 2 3; do
|
||||
$s timeout 90 apt-get -yq update \
|
||||
-o Acquire::Retries=3 -o Acquire::http::Timeout=30 &&
|
||||
$s timeout 120 apt-get -yq install --no-install-recommends \
|
||||
ccache > /dev/null && break
|
||||
echo "installing ccache failed (attempt $i); retrying in 10s"
|
||||
sleep 10
|
||||
done
|
||||
}
|
||||
echo "CCACHE_DIR=$GITHUB_WORKSPACE/.ccache" >> "$GITHUB_ENV"
|
||||
echo "CCACHE_MAXSIZE=250M" >> "$GITHUB_ENV"
|
||||
if command -v ccache > /dev/null; then
|
||||
CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" ccache -z
|
||||
fi
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
bash .github/workflows/scripts/ccache-make.sh ARCH=ppc -j$(getconf _NPROCESSORS_ONLN)
|
||||
file retroarch
|
||||
$TARGET-otool -l retroarch | grep -A2 LC_VERSION_MIN_MACOSX
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv || ccache -s
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ matrix.deployment_target }}-${{ github.sha }}
|
||||
|
||||
- name: Audit imports against the 10.4u SDK
|
||||
if: matrix.deployment_target == '10.4'
|
||||
run: |
|
||||
set -e
|
||||
cd /usr/local
|
||||
wget -q https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX10.4u.sdk.tar.xz
|
||||
tar xJf MacOSX10.4u.sdk.tar.xz && rm MacOSX10.4u.sdk.tar.xz
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
SDK4=/usr/local/MacOSX10.4u.sdk
|
||||
$TARGET-nm -u retroarch | sed 's/^ *//' | sort -u > undef.txt
|
||||
( find $SDK4/usr/lib -name '*.dylib' ; \
|
||||
find $SDK4/System/Library/Frameworks -type f -path '*/Versions/*' ! -path '*/Headers/*' ! -path '*/Resources/*' ) \
|
||||
| while read -r lib; do $TARGET-nm -g -arch ppc "$lib" 2>/dev/null | awk 'NF==3 {print $3} NF==2 {print $2}'; done \
|
||||
| sort -u > sdk4.txt
|
||||
echo "Imports absent from the 10.4u SDK:"
|
||||
comm -23 undef.txt sdk4.txt | grep -v '^_OBJC_CLASS_\$_\|^\.objc_class_name_' | tee missing.txt
|
||||
test ! -s missing.txt
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: RetroArch-macOS-ppc-${{ matrix.deployment_target }}-${{ steps.slug.outputs.sha8 }}
|
||||
path: retroarch
|
||||
@@ -1,193 +0,0 @@
|
||||
name: CI VideoToolbox hardware encode
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- '.github/workflows/MacOS-videotoolbox-encode.yml'
|
||||
- 'gfx/common/videotoolbox_encode*.h'
|
||||
- 'libretro-common/formats/h265/rh265_sps_crop.c'
|
||||
- 'libretro-common/include/formats/rh265_sps_crop.h'
|
||||
- 'record/drivers/record_metal.*'
|
||||
- 'record/record_driver.*'
|
||||
- 'gfx/drivers/metal.m'
|
||||
- 'Makefile.common'
|
||||
- 'griffin/griffin*'
|
||||
- 'record/record_gpu_capture_metal.*'
|
||||
- 'record/record_gpu_session_metal.*'
|
||||
- 'record/record_gpu_dispatch_metal.*'
|
||||
- 'record/record_gpu_worker_vt*'
|
||||
- 'record/record_audio_queue.*'
|
||||
- 'record/record_avfoundation_worker*'
|
||||
- 'record/record_avfoundation_session*'
|
||||
- 'record/record_mux_avfoundation.*'
|
||||
- 'record/shaders/capture_metal.*'
|
||||
- 'record/shaders/generate_metal.py'
|
||||
- 'samples/record/videotoolbox_encode/**'
|
||||
- 'samples/record/metal_frontend/**'
|
||||
- 'libretro-common/include/retro_atomic.h'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/MacOS-videotoolbox-encode.yml'
|
||||
- 'gfx/common/videotoolbox_encode*.h'
|
||||
- 'libretro-common/formats/h265/rh265_sps_crop.c'
|
||||
- 'libretro-common/include/formats/rh265_sps_crop.h'
|
||||
- 'record/drivers/record_metal.*'
|
||||
- 'record/record_driver.*'
|
||||
- 'gfx/drivers/metal.m'
|
||||
- 'Makefile.common'
|
||||
- 'griffin/griffin*'
|
||||
- 'record/record_gpu_capture_metal.*'
|
||||
- 'record/record_gpu_session_metal.*'
|
||||
- 'record/record_gpu_dispatch_metal.*'
|
||||
- 'record/record_gpu_worker_vt*'
|
||||
- 'record/record_audio_queue.*'
|
||||
- 'record/record_avfoundation_worker*'
|
||||
- 'record/record_avfoundation_session*'
|
||||
- 'record/record_mux_avfoundation.*'
|
||||
- 'record/shaders/capture_metal.*'
|
||||
- 'record/shaders/generate_metal.py'
|
||||
- 'samples/record/videotoolbox_encode/**'
|
||||
- 'samples/record/metal_frontend/**'
|
||||
- 'libretro-common/include/retro_atomic.h'
|
||||
workflow_dispatch:
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
encode:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install independent test decoder
|
||||
run: command -v ffmpeg >/dev/null && command -v ffprobe >/dev/null || brew install ffmpeg
|
||||
- name: Native encoder and Metal device inventory
|
||||
if: ${{ !cancelled() }}
|
||||
run: ENCODER_DEVICE_ARTIFACT="$RUNNER_TEMP/metal-vt-devices.json" python3 samples/record/videotoolbox_encode/device_run.py
|
||||
- name: Portable ownership and failure contracts
|
||||
working-directory: samples/record/videotoolbox_encode
|
||||
run: make check thread_test worker_thread_test audio_thread_test av_session_thread_test && ./thread_test && ./worker_thread_test && ./audio_thread_test && ./av_session_thread_test
|
||||
- name: Native hardware encoder and independent pixels
|
||||
run: |
|
||||
rc=0
|
||||
python3 samples/record/videotoolbox_encode/run.py --native || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::Some required hardware encode cases unavailable; native encode acceptance is incomplete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: Native Metal to VideoToolbox queue-worker pipeline
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
rc=0
|
||||
PIPELINE_ARTIFACT_DIR="$RUNNER_TEMP/metal-vt-evidence" python3 samples/record/videotoolbox_encode/pipeline_run.py || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::Native pipeline hardware unavailable; integrated recording acceptance is incomplete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: Independent native Metal capture pixels and ownership
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
rc=0
|
||||
python3 samples/record/videotoolbox_encode/capture_run.py || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::Metal capture device unavailable; native capture acceptance is incomplete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: Native compressed MP4 and AAC worker mux
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
rc=0
|
||||
PIPELINE_ARTIFACT_DIR="$RUNNER_TEMP/metal-vt-mux-evidence" python3 samples/record/videotoolbox_encode/pipeline_run.py --mux || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::Native mux hardware unavailable; A/V acceptance is incomplete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: Native owned recording session
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
rc=0
|
||||
PIPELINE_ARTIFACT_DIR="$RUNNER_TEMP/metal-vt-session-evidence" python3 samples/record/videotoolbox_encode/pipeline_run.py --session || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::Native owned session hardware unavailable; controller acceptance is incomplete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: Native renderer-device cold recording startup
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
rc=0
|
||||
PIPELINE_ARTIFACT_DIR="$RUNNER_TEMP/metal-vt-cold-evidence" python3 samples/record/videotoolbox_encode/pipeline_run.py --cold || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::Renderer-device encoder unavailable; cold startup acceptance is incomplete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: Native dedicated recording dispatcher
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
rc=0
|
||||
PIPELINE_ARTIFACT_DIR="$RUNNER_TEMP/metal-vt-dispatch-evidence" python3 samples/record/videotoolbox_encode/pipeline_run.py --dispatch || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::Dispatcher hardware unavailable; recording dispatch acceptance is incomplete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: Preserve native pipeline evidence
|
||||
if: ${{ !cancelled() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: metal-vt-pipeline-evidence
|
||||
path: |
|
||||
${{ runner.temp }}/metal-vt-evidence
|
||||
${{ runner.temp }}/metal-vt-mux-evidence
|
||||
${{ runner.temp }}/metal-vt-session-evidence
|
||||
${{ runner.temp }}/metal-vt-cold-evidence
|
||||
${{ runner.temp }}/metal-vt-dispatch-evidence
|
||||
${{ runner.temp }}/metal-vt-devices.json
|
||||
if-no-files-found: warn
|
||||
|
||||
frontend-build:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 40
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Configure native Metal recording frontend
|
||||
run: |
|
||||
set -eu
|
||||
./configure --enable-metal --enable-avf --enable-threads --enable-configfile --enable-webmplayer \
|
||||
--disable-qt --disable-ffmpeg --disable-discord --disable-cheevos \
|
||||
--disable-networking --disable-sdl2 --disable-sdl --disable-translate \
|
||||
--disable-update_cores --disable-update_assets --disable-online_updater \
|
||||
--disable-cdrom --disable-7zip --disable-ssl
|
||||
for feature in HAVE_METAL HAVE_AVF HAVE_THREADS HAVE_CONFIGFILE HAVE_WEBMPLAYER; do
|
||||
grep -Eq "^#define $feature 1" config.h
|
||||
done
|
||||
- name: Build and link real frontend with native recording enabled
|
||||
run: |
|
||||
set -eu
|
||||
make -j"$(sysctl -n hw.ncpu)" MINVERFLAGS="-mmacosx-version-min=$(sw_vers -productVersion)"
|
||||
test -x retroarch
|
||||
nm retroarch | grep '_record_metal_gpu_capture'
|
||||
|
||||
- name: Independent real frontend GPU recording
|
||||
run: |
|
||||
set -eu
|
||||
command -v ffmpeg >/dev/null && command -v ffprobe >/dev/null || brew install ffmpeg
|
||||
cc -dynamiclib -std=gnu89 -Ilibretro-common/include samples/record/metal_frontend/core.c -o "$RUNNER_TEMP/metal-record-core.dylib" -lm
|
||||
python3 samples/record/metal_frontend/run.py --retroarch ./retroarch --core "$RUNNER_TEMP/metal-record-core.dylib" --output-dir "$RUNNER_TEMP/metal-frontend-recordings"
|
||||
- uses: actions/upload-artifact@v6
|
||||
if: always()
|
||||
with:
|
||||
name: metal-frontend-recordings
|
||||
path: ${{ runner.temp }}/metal-frontend-recordings
|
||||
if-no-files-found: warn
|
||||
|
||||
frontend-contracts:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Source-clock capture and backpressure under sanitizers
|
||||
run: make -C samples/record/metal_frontend check SANITIZER=address,undefined
|
||||
@@ -1,121 +0,0 @@
|
||||
name: CI VideoToolbox HEVC and Metal
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- '.github/workflows/MacOS-videotoolbox-hevc.yml'
|
||||
- 'samples/gfx/videotoolbox_hevc/**'
|
||||
- 'samples/gfx/videotoolbox_vp9/**'
|
||||
- 'samples/gfx/videotoolbox_av1/**'
|
||||
- 'gfx/common/videotoolbox_av1*.h'
|
||||
- 'gfx/common/videotoolbox_vp9*.h'
|
||||
- 'gfx/common/vp9_color.h'
|
||||
- 'libretro-common/include/formats/rvp9*.h'
|
||||
- 'libretro-common/include/formats/rwebm*.h'
|
||||
- 'libretro-common/formats/vp9/**'
|
||||
- 'libretro-common/formats/webm/**'
|
||||
- 'samples/gfx/metal_frame/**'
|
||||
- 'gfx/common/videotoolbox_hevc*.h'
|
||||
- 'gfx/common/metal_frame*.h'
|
||||
- 'gfx/common/metal_video_decoder_driver.h'
|
||||
- 'gfx/common/metal_decoder_snapshot.h'
|
||||
- 'gfx/drivers/metal.m'
|
||||
- 'gfx/drivers/metal.h'
|
||||
- 'gfx/drivers/metal_shaders/Shaders.metal'
|
||||
- 'gfx/video_driver.h'
|
||||
- 'gfx/video_defines.h'
|
||||
- 'libretro-common/formats/h265/**'
|
||||
- 'libretro-common/formats/video_player.c'
|
||||
- 'libretro-common/samples/formats/video_player/**'
|
||||
- 'libretro-common/rthreads/**'
|
||||
- 'libretro-common/include/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/MacOS-videotoolbox-hevc.yml'
|
||||
- 'samples/gfx/videotoolbox_hevc/**'
|
||||
- 'samples/gfx/videotoolbox_vp9/**'
|
||||
- 'samples/gfx/videotoolbox_av1/**'
|
||||
- 'gfx/common/videotoolbox_av1*.h'
|
||||
- 'gfx/common/videotoolbox_vp9*.h'
|
||||
- 'gfx/common/vp9_color.h'
|
||||
- 'libretro-common/include/formats/rvp9*.h'
|
||||
- 'libretro-common/include/formats/rwebm*.h'
|
||||
- 'libretro-common/formats/vp9/**'
|
||||
- 'libretro-common/formats/webm/**'
|
||||
- 'samples/gfx/metal_frame/**'
|
||||
- 'gfx/common/videotoolbox_hevc*.h'
|
||||
- 'gfx/common/metal_frame*.h'
|
||||
- 'gfx/common/metal_video_decoder_driver.h'
|
||||
- 'gfx/common/metal_decoder_snapshot.h'
|
||||
- 'gfx/drivers/metal.m'
|
||||
- 'gfx/drivers/metal.h'
|
||||
- 'gfx/drivers/metal_shaders/Shaders.metal'
|
||||
- 'gfx/video_driver.h'
|
||||
- 'gfx/video_defines.h'
|
||||
- 'libretro-common/formats/h265/**'
|
||||
- 'libretro-common/formats/video_player.c'
|
||||
- 'libretro-common/samples/formats/video_player/**'
|
||||
- 'libretro-common/rthreads/**'
|
||||
- 'libretro-common/include/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
videotoolbox-hevc:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Player cold hardware startup and cancellation
|
||||
run: |
|
||||
for threads in 0 1; do
|
||||
make -C libretro-common/samples/formats/video_player clean all THREADS="$threads" SANITIZER=address,undefined
|
||||
libretro-common/samples/formats/video_player/video_player_test
|
||||
done
|
||||
- name: VideoToolbox VP9 configuration conformance (no device claim)
|
||||
run: |
|
||||
make -C samples/gfx/videotoolbox_vp9 check CC=clang SANITIZER=address,undefined
|
||||
CC=clang python3 samples/gfx/videotoolbox_vp9/run.py --native
|
||||
- name: VideoToolbox VP9 native pixels, Metal playback and retained output
|
||||
run: |
|
||||
rc=0
|
||||
CC=clang python3 samples/gfx/videotoolbox_vp9/run.py --native --pixels --pipeline || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::VP9 hardware or Metal device unavailable; native VP9 playback acceptance remains incomplete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: VideoToolbox AV1 configuration and ownership (no decoder device claim)
|
||||
run: |
|
||||
make -C samples/gfx/videotoolbox_av1 check CC=clang SANITIZER=address,undefined
|
||||
CC=clang python3 samples/gfx/videotoolbox_av1/run.py --native-format
|
||||
- name: VideoToolbox AV1 hardware pixels, keyframe seeks and retained images
|
||||
run: |
|
||||
if ! command -v ffmpeg >/dev/null ||
|
||||
! ffmpeg -hide_banner -encoders 2>/dev/null | grep ' libaom-av1 ' >/dev/null; then
|
||||
brew install ffmpeg-full
|
||||
export PATH="$(brew --prefix ffmpeg-full)/bin:$PATH"
|
||||
fi
|
||||
ffmpeg -hide_banner -encoders 2>/dev/null | grep ' libaom-av1 '
|
||||
rc=0
|
||||
CC=clang python3 samples/gfx/videotoolbox_av1/run.py --native-pixels --pipeline || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::AV1 hardware unavailable; native AV1 decode acceptance remains incomplete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: VideoToolbox HEVC hardware decode and pixel ownership
|
||||
run: |
|
||||
rc=0
|
||||
python3 samples/gfx/videotoolbox_hevc/run.py --native --metal || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::HEVC hardware decode or Metal shared events unavailable; native bridge check did not complete"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
- name: Metal movie import, history and GPU pixel acceptance
|
||||
if: ${{ !cancelled() }}
|
||||
run: python3 samples/gfx/metal_frame/run.py --native
|
||||
@@ -1,143 +0,0 @@
|
||||
name: CI macOS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Cocoa companion harness on Apple's AppKit
|
||||
run: |
|
||||
set -o pipefail
|
||||
# The same harness the Linux job runs under GNUstep, built with
|
||||
# Apple's clang against the real Cocoa framework and run on the
|
||||
# runner's window server: key-window arbitration after closing the
|
||||
# companion, the grid, the tables, the dialogs - as AppKit does them.
|
||||
tools/companion_cocoa_test_macos.sh 2>&1 | grep -v "^$"
|
||||
|
||||
- name: Metal texture behaviour the surface, overlay and lent-framebuffer paths assume
|
||||
run: |
|
||||
set -o pipefail
|
||||
# The driver's Metal paths have only ever been compiled. This
|
||||
# asserts the two behaviours they are built on, on the runner's
|
||||
# real device: a texture replaced in place while GPU work that
|
||||
# samples it is in flight - the animated preview's steady
|
||||
# state, and the one path with no fence check or DO_NOT_WAIT to
|
||||
# drop a frame with - and an overlay page holding textures the
|
||||
# pack owns, where a page switch must not take them with it.
|
||||
#
|
||||
# 77 means the runner exposed no Metal device; the sample says
|
||||
# so rather than passing quietly.
|
||||
cd samples/gfx/metal_texture_update
|
||||
make check; rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::no Metal device on this runner; the check did not run"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
|
||||
- name: Retained Metal frame lease on the native GPU
|
||||
run: |
|
||||
rc=0
|
||||
python3 samples/gfx/metal_frame/run.py --native || rc=$?
|
||||
if [ "$rc" = 77 ]; then
|
||||
echo "::warning::Metal shared events unavailable; lease GPU check did not run"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
|
||||
- name: iCloud Drive cloud sync driver
|
||||
run: |
|
||||
set -o pipefail
|
||||
# Includes network/cloud_sync/icloud_drive.m, with the iCloud
|
||||
# container redirected to a temporary directory. Cloud sync
|
||||
# waits for every request to report exactly once: a read whose
|
||||
# local file could not be created never reported (the sync
|
||||
# hung), and a cloud file that could not be loaded or a local
|
||||
# file that could not be read reported twice. With iCloud
|
||||
# unavailable, read and delete reported success. Also covers
|
||||
# the ordinary read, missing file, upload and delete paths.
|
||||
cd samples/network/icloud_drive
|
||||
make clean check SANITIZER=address,undefined
|
||||
|
||||
- name: iCloud (CloudKit) cloud sync driver
|
||||
run: |
|
||||
set -o pipefail
|
||||
# Includes network/cloud_sync/icloud.m, with CloudKit replaced by
|
||||
# an in-memory database (+[CKContainer defaultContainer] is
|
||||
# overridden in a category; real CKRecord/CKAsset/CKQuery). A
|
||||
# read whose local file could not be written, or whose record
|
||||
# held no readable data, reported success; an upload whose
|
||||
# lookup failed created a duplicate record; a delete reported
|
||||
# success before its deletes were sent, whatever became of
|
||||
# them; and non-destructive sync was ignored. Checks each case,
|
||||
# that deletes and uploads keep <path>-<time> with destructive
|
||||
# sync off (and not for destructive sync or the manifest), and
|
||||
# that every request reports exactly once.
|
||||
cd samples/network/icloud_cloudkit
|
||||
make clean check SANITIZER=address,undefined
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
set -o pipefail
|
||||
xcodebuild -workspace pkg/apple/RetroArch.xcworkspace -scheme RetroArch -config Release -xcconfig pkg/apple/GitHubCI.xcconfig -derivedDataPath build
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: RetroArch-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
build/Build/Products/Release
|
||||
|
||||
# The threaded-video harness on the Metal driver: the real frontend
|
||||
# under Cocoa's own main (see samples/gfx/threaded_video/harness_cocoa.m),
|
||||
# every lane the Vulkan and D3D legs run, on the runner's GPU. A
|
||||
# Makefile build, since the harness links the tree's objects.
|
||||
metal-harness:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Match the runner's library deployment target
|
||||
run: echo "MACOSX_DEPLOYMENT_TARGET=$(sw_vers -productVersion)" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Configure and build (Makefile, no Qt)
|
||||
run: |
|
||||
set -o pipefail
|
||||
./configure --disable-qt --disable-ffmpeg --disable-discord --disable-cheevos \
|
||||
--disable-networking --disable-sdl2 --disable-sdl --disable-translate \
|
||||
--disable-update_cores --disable-update_assets --disable-online_updater \
|
||||
--disable-cdrom --disable-7zip --disable-ssl 2>&1 | tail -5
|
||||
make -j$(sysctl -n hw.ncpu) MINVERFLAGS="-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET" GFX_INSTRUMENT=1 2>&1 | grep -E "error|warning: unused" || true
|
||||
test -x retroarch
|
||||
|
||||
- name: Harness on Metal (RGB565 core, then XRGB8888)
|
||||
env:
|
||||
# Hosted macOS timers cannot reliably meet the synthetic 120 Hz grid.
|
||||
HARNESS_SKIP_PHASE_GRID: '1'
|
||||
run: |
|
||||
set -o pipefail
|
||||
SAN=none GFX_INSTRUMENT=1 DRIVER=metal CYCLES=1 make -C samples/gfx/threaded_video MINVERFLAGS="-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET" check-driver
|
||||
HARNESS_CORE_XRGB8888=1 SAN=none GFX_INSTRUMENT=1 DRIVER=metal CYCLES=1 make -C samples/gfx/threaded_video MINVERFLAGS="-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET" check-driver
|
||||
@@ -1,44 +0,0 @@
|
||||
name: CI Miyoo ARM32
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-dingux:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -j$(getconf _NPROCESSORS_ONLN) -f Makefile.miyoo clean
|
||||
make -j$(getconf _NPROCESSORS_ONLN) -f Makefile.miyoo info all
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: retroarch_miyoo_arm32${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
retroarch
|
||||
@@ -1,136 +0,0 @@
|
||||
name: CI msg_hash packed tables
|
||||
|
||||
# intl/msg_hash_<lang>.h is generated as two objects that are paired by
|
||||
# position: the blob struct holds every row as one run of NUL-terminated
|
||||
# strings, and ids[] names the enum each row belongs to.
|
||||
# msg_hash_strtab_index_build() walks the blob once and hands row N to
|
||||
# ids[N].
|
||||
#
|
||||
# Nothing in the C ties them together. Both objects are well formed on
|
||||
# their own, and the sizeof() contiguity check inside the header only
|
||||
# measures the blob against itself, so a row removed from one side and
|
||||
# left on the other compiles clean everywhere and renames every row
|
||||
# after it at runtime. The menu then shows real translated strings
|
||||
# belonging to other entries - which is what #19534 reported, in every
|
||||
# language at once. English is unaffected, because msg_hash_us.c is a
|
||||
# switch rather than a packed table, so no English-language test, manual
|
||||
# or automated, can see it either.
|
||||
#
|
||||
# 5d0f721 did exactly that: retiring audio_block_frames took
|
||||
# MENU_ENUM_LABEL_VALUE_AUDIO_BLOCK_FRAMES and its sublabel out of ids[]
|
||||
# in twenty-nine headers and left the two blob members behind. From the
|
||||
# audio device row onward every language was off by one or two.
|
||||
#
|
||||
# The check re-derives the pairing from the member names - json2h.py
|
||||
# names each member after the djb2 hash of the key its row was emitted
|
||||
# for - and compares it against ids[] row for row, under the guards. It
|
||||
# reads the files rather than building them, so it covers every
|
||||
# language and every #ifdef configuration at once, which no build job
|
||||
# does. intl/json2h.py runs the same check on its own output before
|
||||
# writing, so this is the lane that catches a header edited by hand.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
msg-hash-packed-check:
|
||||
name: blob and ids[] pairing
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Checker self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Fixture pass: a consistent table is clean, 5d0f721's shape
|
||||
# (a row dropped from ids[] only) is caught, so is its mirror,
|
||||
# a member one byte wider than its string, a guard present on
|
||||
# one side only, and a contiguity constant left stale.
|
||||
#
|
||||
# The fixtures are built by the checker rather than lifted
|
||||
# from intl/, so this reports the same thing whether or not
|
||||
# the shipped headers currently pass - it is measuring the
|
||||
# checker, not the tree.
|
||||
tools/check.sh tools/msg_hash_packed_check.c --selftest
|
||||
|
||||
- name: Tree check
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Every packed header: row N's member name must be what the
|
||||
# key in ids[N] hashes to and carry the same guard, each
|
||||
# member must be exactly its string plus the NUL (or exactly
|
||||
# the chunk, for a non-final chunk of a split row), no row may
|
||||
# hold an embedded NUL, and the sizeof() check must still add
|
||||
# up to the members it guards.
|
||||
tools/check.sh tools/msg_hash_packed_check.c
|
||||
|
||||
- name: Format parity self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Fixture pass: matching conversions are clean, a conversion
|
||||
# lost, invented, retyped or reordered positionally is caught,
|
||||
# and a percent sign in prose - English's "50% of this value",
|
||||
# Hungarian's "50%-a", a doubled %% - is not mistaken for one.
|
||||
# The format-site scan is measured too: it must see a format
|
||||
# argument taken from the table directly and through a local,
|
||||
# and must not see a string that is copied, passed as a value,
|
||||
# or split on a placeholder rather than formatted.
|
||||
tools/check.sh tools/msg_hash_format_check.c --selftest
|
||||
|
||||
- name: Format parity tree check
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Every translated row against its English source: the same
|
||||
# conversions in the same order wherever English has any, no
|
||||
# positional %n$ anywhere, and no conversion invented in a row
|
||||
# that is used as a format string and has none in English.
|
||||
# That last set is measured from the call sites rather than
|
||||
# assumed from the namespace: ninety rows reach a printf-family
|
||||
# format argument today and twenty-nine of them are not MSG_*.
|
||||
tools/check.sh tools/msg_hash_format_check.c
|
||||
|
||||
- name: Label macros current
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# msg_hash_lbl_str.h names each label's member of the packed
|
||||
# label blob and is generated from the same rows the blob is
|
||||
# built from; a row added, renamed or guarded without rerunning
|
||||
# the generator would leave a macro pointing at a stale or
|
||||
# missing member, or fall back to a literal that duplicates
|
||||
# the blob's bytes. Regenerating must be a no-op.
|
||||
python3 tools/gen_lbl_str.py
|
||||
git diff --exit-code -- msg_hash_lbl_str.h
|
||||
|
||||
- name: Sublabel map sorted
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The sublabel binder looks rows up by binary search; a row
|
||||
# out of order is never found and its entry loses its
|
||||
# sublabel without any build failing.
|
||||
python3 tools/sublabel_map_check.py --selftest
|
||||
python3 tools/sublabel_map_check.py
|
||||
@@ -1,57 +0,0 @@
|
||||
name: CI Overlapping-buffer copies
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
overlap-copy-check:
|
||||
name: Overlapping dst/src in copy calls
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Checker self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Fixture pass: exact-alias strlcpy and overlapping memcpy
|
||||
# element shifts are flagged, memmove is not, unguarded
|
||||
# param->param copy helpers called with aliased buffers are
|
||||
# flagged while alias-guarded helpers are not, the
|
||||
# allowlist suppresses audited same-base copies but can
|
||||
# never suppress an exact alias, and stale allowlist
|
||||
# entries are reported.
|
||||
tools/check.sh tools/overlap_copy_check.c --selftest
|
||||
|
||||
- name: Tree check
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# strlcpy resolves to the fortified __strlcpy_chk on macOS,
|
||||
# which aborts on ANY dst/src overlap (bd79aee: typing into
|
||||
# the OSK crashed with EXC_BREAKPOINT), and overlapping
|
||||
# memcpy is UB everywhere (e942ee2: leaderboard element
|
||||
# shift). The portable strlcpy fallback tolerates aliasing
|
||||
# on Linux/Windows, so nothing else in CI can catch this
|
||||
# class before it ships to Mac users. Audited-intentional
|
||||
# same-buffer copies live in tools/overlap_copy_allow.list.
|
||||
tools/check.sh tools/overlap_copy_check.c
|
||||
@@ -1,50 +0,0 @@
|
||||
name: CI PS2
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-ps2:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
make -f Makefile.ps2.salamander -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.ps2.salamander -j$(getconf _NPROCESSORS_ONLN) release
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.ps2 -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.ps2 -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 info release
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: RA-PS2-dummy-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
raboot.elf
|
||||
retroarchps2.elf
|
||||
@@ -1,50 +0,0 @@
|
||||
name: CI PS3/PSL1GHT
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-psl1ght:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
make -f Makefile.psl1ght.salamander -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.psl1ght.salamander -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.psl1ght -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.psl1ght -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 info all
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: RA-psl1ght-dummy-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
retroarch_psl1ght_salamander.elf
|
||||
retroarch_psl1ght.elf
|
||||
@@ -1,70 +0,0 @@
|
||||
name: CI PS4/ORBIS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
# The image is Alpine 3.15, whose musl cannot load the runner's
|
||||
# Node 24, so JavaScript actions run on the host and only the
|
||||
# build steps run inside the image.
|
||||
env:
|
||||
ORBIS_IMAGE: reallibretroretroarch/libretro-build-orbis:latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
# Authenticated pulls avoid the shared per-IP anonymous rate limit;
|
||||
# without the secrets (fork pull requests) the pull stays anonymous
|
||||
- name: Log in to Docker Hub
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
run: |
|
||||
if [ -n "$DOCKERHUB_USERNAME" ] && [ -n "$DOCKERHUB_TOKEN" ]; then
|
||||
echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
|
||||
fi
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
docker run --rm --user root -v "$PWD":/src -w /src "$ORBIS_IMAGE" bash -c '
|
||||
set -e
|
||||
apk add ncurses-dev make bash python2
|
||||
apk add libintl icu-dev wget
|
||||
wget https://dot.net/v1/dotnet-install.sh && chmod 755 dotnet-install.sh && ./dotnet-install.sh -c 3.0 --install-dir ~/cli
|
||||
export PATH=~/cli:$PATH # .net cli
|
||||
make -f Makefile.orbis -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 info all
|
||||
clang --version
|
||||
orbis-ld --version
|
||||
'
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bin-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
retroarch_orbis.elf
|
||||
retroarch_orbis.oelf
|
||||
retroarch_orbis.self
|
||||
@@ -1,56 +0,0 @@
|
||||
name: CI PSP
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-psp:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Compile bootstrap
|
||||
run: |
|
||||
cd bootstrap/psp1/kernel_functions_prx
|
||||
make -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
make -f Makefile.psp1.salamander -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.psp1.salamander -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.psp1 -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.psp1 -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: RA-PSP-dummy-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
kernel_functions.prx
|
||||
EBOOT.PBP
|
||||
@@ -1,91 +0,0 @@
|
||||
name: CI PSVita
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-vita:latest-20260905
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
make -f Makefile.vita.salamander -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.vita.salamander -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Set up ccache
|
||||
run: |
|
||||
# Best effort: without ccache, ccache-make.sh runs plain make.
|
||||
command -v ccache > /dev/null || {
|
||||
s=$(command -v sudo || true)
|
||||
for i in 1 2 3; do
|
||||
$s timeout 90 apt-get -yq update \
|
||||
-o Acquire::Retries=3 -o Acquire::http::Timeout=30 &&
|
||||
$s timeout 120 apt-get -yq install --no-install-recommends \
|
||||
ccache > /dev/null && break
|
||||
echo "installing ccache failed (attempt $i); retrying in 10s"
|
||||
sleep 10
|
||||
done
|
||||
}
|
||||
echo "CCACHE_DIR=$GITHUB_WORKSPACE/.ccache" >> "$GITHUB_ENV"
|
||||
echo "CCACHE_MAXSIZE=250M" >> "$GITHUB_ENV"
|
||||
if command -v ccache > /dev/null; then
|
||||
CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" ccache -z
|
||||
fi
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.vita -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
bash .github/workflows/scripts/ccache-make.sh -f Makefile.vita -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 HAVE_VITAGLES=1 info all
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv || ccache -s
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: RA-PSVita-dummy-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
eboot.bin
|
||||
@@ -1,57 +0,0 @@
|
||||
name: CI prune caches
|
||||
|
||||
# Every master push saves a ccache per job under a key ending in the
|
||||
# commit, and only the newest of each is ever restored. The older ones
|
||||
# fill the repository's cache store, which then evicts the newest cache
|
||||
# of any workflow that has not run for a few hours. This keeps only the
|
||||
# newest entry for each job and branch.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
schedule:
|
||||
- cron: '23 * * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
prune:
|
||||
name: Delete superseded caches
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Delete all but the newest cache of each job
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
set -eu
|
||||
# Only ccache keys ending in a commit, with the commit cut off;
|
||||
# jq does it, as some mawk versions have no {n} in a regex.
|
||||
gh api --paginate \
|
||||
"repos/$REPO/actions/caches?per_page=100&sort=created_at&direction=desc" \
|
||||
--jq '.actions_caches[]
|
||||
| select(.key | test("^ccache-.*-[0-9a-f]{40}$"))
|
||||
| [.id, .ref, (.key | sub("-[0-9a-f]{40}$"; "")), .size_in_bytes]
|
||||
| @tsv' \
|
||||
> caches.tsv
|
||||
# Newest first: a cache is superseded once a newer one of the
|
||||
# same key on the same branch has been seen. A cache saved
|
||||
# while paging can list one twice, so each id counts once.
|
||||
awk -F '\t' '!ids[$1]++ && seen[$2 FS $3]++ { print $1 "\t" $4 }' \
|
||||
caches.tsv > prune.tsv
|
||||
awk -F '\t' '{ n++; s += $2 } END {
|
||||
printf "%d commit-keyed ccaches, %d superseded (%.2f GB)\n",
|
||||
NR0, n, s / 1e9 }' \
|
||||
NR0="$(wc -l < caches.tsv)" prune.tsv
|
||||
cut -f1 prune.tsv | while read -r id; do
|
||||
gh api -X DELETE "repos/$REPO/actions/caches/$id" > /dev/null || \
|
||||
echo "could not delete cache $id (gone already?)"
|
||||
done
|
||||
@@ -1,94 +0,0 @@
|
||||
name: CI RGUI pixel format
|
||||
|
||||
# RGUI draws into a 16bpp framebuffer, so every menu colour, wallpaper
|
||||
# and thumbnail pixel passes through one of the argb32_to_* converters
|
||||
# in menu/drivers/rgui.c. Each one quantises the four 8-bit channels
|
||||
# to its target widths and ORs them into their fields, with the widths
|
||||
# and the shifts written by hand on separate lines - seven formats,
|
||||
# fourteen driver idents, and a dithered twin of each.
|
||||
#
|
||||
# Nothing else in CI can see a mistake there. The formats are
|
||||
# per-platform: rgb565 belongs to sdl_dingux, sdl_rs90 and xvideo, and
|
||||
# no runner boots a 565 menu, so a converter can be wrong for months
|
||||
# while every desktop build renders perfectly. It is not a build
|
||||
# break either - a width that outgrows its shift just ORs into the
|
||||
# neighbouring field, silently.
|
||||
#
|
||||
# c6b66c9 did exactly that: it widened green in argb32_to_rgb565 from
|
||||
# 5 bits to 6 but left the packing at (g << 6), where 6-bit green
|
||||
# needs (g << 5). Green's top bit landed on red's LSB, the green
|
||||
# field became (g & 31) << 1, and green wrapped hard at half scale -
|
||||
# mid grey rendered as (139, 0, 131). It shipped, and came back as
|
||||
# #19469, bisected by hand on an Anbernic RG300X.
|
||||
#
|
||||
# The check lifts the marked pixel format conversion block out of
|
||||
# rgui.c and compiles it on its own against two stubs, so it tests the
|
||||
# real shipped converters and the real dispatch table. Field layouts
|
||||
# are measured from the converters, not hardcoded, so a new format
|
||||
# gets checked the moment its row is added to rgui_pixel_format_map.
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'menu/drivers/rgui.c'
|
||||
- 'tools/rgui_pixfmt_check.c'
|
||||
- 'tools/rgui_pixfmt_harness.inc'
|
||||
- 'tools/check_common.h'
|
||||
- 'tools/check.sh'
|
||||
- '.github/workflows/RGUI-Pixel-Format-Check.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'menu/drivers/rgui.c'
|
||||
- 'tools/rgui_pixfmt_check.c'
|
||||
- 'tools/rgui_pixfmt_harness.inc'
|
||||
- 'tools/check_common.h'
|
||||
- 'tools/check.sh'
|
||||
- '.github/workflows/RGUI-Pixel-Format-Check.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
rgui-pixfmt-check:
|
||||
name: RGUI 8-bit to 16bpp conversion contract
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Checker self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Fixture pass: the corrected 6-bit green packed at <<5
|
||||
# passes, c6b66c9's same green packed at <<6 is caught as a
|
||||
# red/green overlap, and a table row wired to another
|
||||
# format's dithered twin is caught as a reach mismatch.
|
||||
#
|
||||
# Both green fixtures are made by forcing the packing shift
|
||||
# either way, so the self-test reports the same thing
|
||||
# whether or not the tree is currently fixed - it is
|
||||
# measuring the checker, not the tree.
|
||||
tools/check.sh tools/rgui_pixfmt_check.c --selftest --cc gcc
|
||||
|
||||
- name: Tree check
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Per driver ident, and for the unknown-ident fallback: the
|
||||
# bits each input channel can change must be disjoint from
|
||||
# every other channel's and contiguous; 0 and 255 must give
|
||||
# an empty and a full field; the field must be monotonic in
|
||||
# the input; and the dithered twin must cover the same bits
|
||||
# and stay within one level of the plain converter.
|
||||
tools/check.sh tools/rgui_pixfmt_check.c --cc gcc
|
||||
@@ -1,44 +0,0 @@
|
||||
name: CI RS90 Odbeta MIPS32
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-dingux:odbeta
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -j$(getconf _NPROCESSORS_ONLN) -f Makefile.rs90 clean
|
||||
make -j$(getconf _NPROCESSORS_ONLN) -f Makefile.rs90 info all
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: retroarch_rs90_mips32${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
retroarch_rs90_odbeta.opk
|
||||
@@ -1,114 +0,0 @@
|
||||
name: CI removed struct members
|
||||
|
||||
# When a struct member goes away, the compiler finds every reader it
|
||||
# compiles. The readers it does not compile are the ones no Linux box
|
||||
# sees - the Objective-C drivers above all, and anything behind a
|
||||
# platform #ifdef - so each of those is found by whichever job builds
|
||||
# that platform, one round trip at a time.
|
||||
#
|
||||
# window_position_x and window_position_y went that way. Packing the
|
||||
# pair into one word updated the Win32 and SDL3 users, which is what a
|
||||
# grep of the .c and .h files turns up; ui_cocoa.m kept reading both
|
||||
# and took out the macOS job and both PowerPC cross jobs at once. Those
|
||||
# three are among the slowest jobs in the tree, and the answer they
|
||||
# eventually gave was four lines in one file.
|
||||
#
|
||||
# tools/packed_field_check.py does not cover this. It knows the six
|
||||
# names a size or origin pair is spelled with, and window_position_x is
|
||||
# not one of them; on the broken tree it printed 1184 lines, none of
|
||||
# them ui_cocoa.m. The question here is not what a member is called,
|
||||
# it is whether anything still reaches for one the change took away.
|
||||
#
|
||||
# So this lane reads the change rather than the tree's vocabulary: the
|
||||
# members a push or a pull request removes, minus the ones something
|
||||
# still declares, against every reader in every language the tree is
|
||||
# written in. It reads files rather than building them, so one job
|
||||
# covers what the platform jobs between them would only find one at a
|
||||
# time.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
removed-member-check:
|
||||
name: readers of a removed member
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
# Both ends of the range have to be present, and a pull
|
||||
# request's base can be behind by any amount.
|
||||
fetch-depth: 0
|
||||
# The history without its file contents: the diff fetches
|
||||
# the few it reads. A fifth of the clone.
|
||||
filter: blob:none
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Checker self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Fixture pass: a member removed along with its readers is
|
||||
# clean, one left behind in a language no lane here compiles
|
||||
# is caught, and a member that merely moved, one whose name
|
||||
# another struct still declares, one that was renamed, one
|
||||
# named only in a comment or a log string, one declared in a
|
||||
# declarator list, and a name too common to reason about are
|
||||
# each left alone.
|
||||
#
|
||||
# The fixtures are handed to the checker directly rather than
|
||||
# taken from the tree, so this reports the same thing whether
|
||||
# or not the tree currently passes - it measures the checker.
|
||||
tools/check.sh tools/removed_member_check.c --selftest
|
||||
|
||||
- name: Range check
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# A pull request is measured against its base; a push against
|
||||
# what was there before it. A force push or a first push
|
||||
# leaves 'before' as zeroes, and a merge has more than one
|
||||
# parent, so fall back to the first parent in either case.
|
||||
if [ -n "${PR_BASE:-}" ]; then
|
||||
base="$PR_BASE"; head="$PR_HEAD"
|
||||
else
|
||||
base="${EVENT_BEFORE:-}"; head="$GITHUB_SHA"
|
||||
case "$base" in
|
||||
''|*[!0]*) ;;
|
||||
*) base= ;;
|
||||
esac
|
||||
if [ -z "$base" ] || ! git cat-file -e "$base^{commit}" 2>/dev/null; then
|
||||
base="$(git rev-parse "$head^" 2>/dev/null || true)"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$base" ]; then
|
||||
echo "no base commit to compare against; nothing to check"
|
||||
exit 0
|
||||
fi
|
||||
echo "range: $base..$head"
|
||||
# Every struct member the range removes, minus the ones the
|
||||
# tree still declares somewhere, against every .c .h .m .mm
|
||||
# .cpp .hpp and .inc reader of one.
|
||||
tools/check.sh tools/removed_member_check.c --range "$base..$head"
|
||||
env:
|
||||
PR_BASE: ${{ github.event.pull_request.base.sha }}
|
||||
PR_HEAD: ${{ github.event.pull_request.head.sha }}
|
||||
EVENT_BEFORE: ${{ github.event.before }}
|
||||
@@ -1,44 +0,0 @@
|
||||
name: CI RetroFW MIPS32
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-dingux:odbeta
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -j$(getconf _NPROCESSORS_ONLN) -f Makefile.retrofw clean
|
||||
make -j$(getconf _NPROCESSORS_ONLN) -f Makefile.retrofw info all
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: retroarch_retrofw_mips32${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
retroarch_retrofw.opk
|
||||
@@ -1,44 +0,0 @@
|
||||
name: CI Sample object directories
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
sample-objdir-check:
|
||||
name: Every sample builds its objects in its own directory
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Checker self-test
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
tools/check.sh tools/sample_objdir_check.c --selftest
|
||||
|
||||
- name: Tree check
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# unity_identity once linked the ASan objects mic_handshake
|
||||
# left beside the shared sources.
|
||||
tools/check.sh tools/sample_objdir_check.c
|
||||
@@ -1,55 +0,0 @@
|
||||
name: CI Generate Source Only Tarball
|
||||
|
||||
# Trigger whenever a release and/or is created
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
push:
|
||||
tags:
|
||||
- "v*.*"
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: build
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: archive
|
||||
id: archive
|
||||
run: |
|
||||
VERSION=${GITHUB_REF##*/}
|
||||
test -z "$VERSION" && VERSION=${{ github.event.release.tag_name }}
|
||||
VERSION=$(printf "%s\n" "$VERSION" | sed 's/^v//')
|
||||
PKGNAME="retroarch-sourceonly-$VERSION"
|
||||
mkdir -p /tmp/$PKGNAME
|
||||
mv * /tmp/$PKGNAME
|
||||
mv /tmp/$PKGNAME .
|
||||
rm -rf $PKGNAME/pkg || true
|
||||
rm -rf $PKGNAME/deps/glslang/glslang/Test || true
|
||||
rm -rf $PKGNAME/deps/SPIRV-Cross/reference || true
|
||||
rm -rf $PKGNAME/gfx/include/userland || true
|
||||
find $PKGNAME/ -type f -name '*.a' -delete || true
|
||||
find $PKGNAME/ -type f -name '*.lib' -delete || true
|
||||
find $PKGNAME/ -type f -name '*.dylib' -delete || true
|
||||
find $PKGNAME/ -type f -name '*.so.*' -delete || true
|
||||
find $PKGNAME/ -type f -name '*.dll' -delete || true
|
||||
TARBALL=$PKGNAME.tar.xz
|
||||
tar cJf $TARBALL $PKGNAME
|
||||
echo "tarball=$TARBALL" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: upload tarball
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: ${{ steps.archive.outputs.tarball }}
|
||||
@@ -1,86 +0,0 @@
|
||||
name: CI Switch/libnx
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-libnx-devkitpro:v4-10-0
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Set up ccache
|
||||
run: |
|
||||
# Best effort: without ccache, ccache-make.sh runs plain make.
|
||||
command -v ccache > /dev/null || {
|
||||
s=$(command -v sudo || true)
|
||||
for i in 1 2 3; do
|
||||
$s timeout 90 apt-get -yq update \
|
||||
-o Acquire::Retries=3 -o Acquire::http::Timeout=30 &&
|
||||
$s timeout 120 apt-get -yq install --no-install-recommends \
|
||||
ccache > /dev/null && break
|
||||
echo "installing ccache failed (attempt $i); retrying in 10s"
|
||||
sleep 10
|
||||
done
|
||||
}
|
||||
echo "CCACHE_DIR=$GITHUB_WORKSPACE/.ccache" >> "$GITHUB_ENV"
|
||||
echo "CCACHE_MAXSIZE=250M" >> "$GITHUB_ENV"
|
||||
if command -v ccache > /dev/null; then
|
||||
CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" ccache -z
|
||||
fi
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.libnx -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
bash .github/workflows/scripts/ccache-make.sh -f Makefile.libnx -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv || ccache -s
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: RA-libnx-dummy-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
retroarch_switch.nro
|
||||
@@ -1,82 +0,0 @@
|
||||
name: CI Wii
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: devkitpro/devkitppc:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@v1
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
make -f Makefile.wii.salamander -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.wii.salamander -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Set up ccache
|
||||
run: |
|
||||
# Best effort: without ccache, ccache-make.sh runs plain make.
|
||||
command -v ccache > /dev/null || {
|
||||
s=$(command -v sudo || true)
|
||||
for i in 1 2 3; do
|
||||
$s timeout 90 apt-get -yq update \
|
||||
-o Acquire::Retries=3 -o Acquire::http::Timeout=30 &&
|
||||
$s timeout 120 apt-get -yq install --no-install-recommends \
|
||||
ccache > /dev/null && break
|
||||
echo "installing ccache failed (attempt $i); retrying in 10s"
|
||||
sleep 10
|
||||
done
|
||||
}
|
||||
echo "CCACHE_DIR=$GITHUB_WORKSPACE/.ccache" >> "$GITHUB_ENV"
|
||||
echo "CCACHE_MAXSIZE=250M" >> "$GITHUB_ENV"
|
||||
if command -v ccache > /dev/null; then
|
||||
CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" ccache -z
|
||||
fi
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.wii -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
bash .github/workflows/scripts/ccache-make.sh -f Makefile.wii -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 info all
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv || ccache -s
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: .ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
name: CI WiiU
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-wiiu:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@v1
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
make -f Makefile.wiiu -j$(getconf _NPROCESSORS_ONLN) SALAMANDER_BUILD=1 clean
|
||||
make -f Makefile.wiiu -j$(getconf _NPROCESSORS_ONLN) SALAMANDER_BUILD=1
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.wiiu -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.wiiu -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 info all
|
||||
@@ -1,164 +0,0 @@
|
||||
name: CI Windows ARM64 (MSVC)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag:
|
||||
description: Existing release tag to build (empty builds the selected ref)
|
||||
type: string
|
||||
default: ''
|
||||
publish_release:
|
||||
description: Upload the ARM64 package to the existing release
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || inputs.release_tag || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
msvc:
|
||||
runs-on: windows-11-arm
|
||||
timeout-minutes: 90
|
||||
outputs:
|
||||
release_tag: ${{ steps.source.outputs.release_tag }}
|
||||
strategy:
|
||||
matrix:
|
||||
version: [2022]
|
||||
configuration: [Debug, Release]
|
||||
platform: [ARM64]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ github.event.release.tag_name || inputs.release_tag || github.ref }}
|
||||
|
||||
- name: Record and verify the source revision
|
||||
id: source
|
||||
shell: pwsh
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.release_tag }}
|
||||
PUBLISH_RELEASE: ${{ github.event_name == 'release' || inputs.publish_release == true }}
|
||||
run: |
|
||||
$revision = git rev-parse HEAD
|
||||
if ($LASTEXITCODE) { throw 'Could not resolve the source revision.' }
|
||||
"revision=$revision" >> $env:GITHUB_OUTPUT
|
||||
if ($env:PUBLISH_RELEASE -eq 'true' -and !$env:RELEASE_TAG) {
|
||||
throw 'Publishing requires an existing release tag.'
|
||||
}
|
||||
if ($env:RELEASE_TAG) {
|
||||
$tagRevision = git rev-parse --verify "refs/tags/$($env:RELEASE_TAG)^{commit}"
|
||||
if ($LASTEXITCODE -or $tagRevision -ne $revision) {
|
||||
throw 'The checkout is not the requested release tag.'
|
||||
}
|
||||
}
|
||||
"release_tag=$env:RELEASE_TAG" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
|
||||
- name: Compile RA
|
||||
working-directory: "${{ github.workspace }}/pkg/msvc"
|
||||
run: |
|
||||
msbuild -p:"Configuration=${{ matrix.configuration }}" -p:"Platform=${{ matrix.platform }}" .\RetroArch-msvc${{ matrix.version }}.sln
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
shell: pwsh
|
||||
env:
|
||||
SOURCE_REVISION: ${{ steps.source.outputs.revision }}
|
||||
run: echo "sha8=$($env:SOURCE_REVISION.Substring(0,8))" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: retroarch-${{ matrix.version }}-${{ matrix.configuration }}-${{ matrix.platform }}-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
pkg/msvc/${{ matrix.platform }}/${{ matrix.configuration }}/RetroArch-msvc${{ matrix.version }}.exe
|
||||
|
||||
- name: Checkout packaging tools from the workflow revision
|
||||
if: matrix.configuration == 'Release'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ github.workflow_sha }}
|
||||
path: .arm64-packaging
|
||||
sparse-checkout: pkg/msvc/packaging
|
||||
|
||||
- name: Checkout pinned Ozone assets
|
||||
if: matrix.configuration == 'Release'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: libretro/retroarch-assets
|
||||
ref: 73106363e14e34c08a5854b4cfbc29f184e3b783
|
||||
path: .arm64-assets
|
||||
sparse-checkout: |
|
||||
ozone
|
||||
pkg
|
||||
fonts
|
||||
|
||||
- name: Checkout pinned core information
|
||||
if: matrix.configuration == 'Release'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: libretro/libretro-super
|
||||
ref: 0532bd63ce3072f50ca4f4ada40d42aef565bd3f
|
||||
path: .arm64-info
|
||||
sparse-checkout: dist/info
|
||||
|
||||
- name: Verify and package ARM64 frontend
|
||||
if: matrix.configuration == 'Release'
|
||||
shell: pwsh
|
||||
env:
|
||||
SOURCE_REVISION: ${{ steps.source.outputs.revision }}
|
||||
run: |
|
||||
./.arm64-packaging/pkg/msvc/packaging/package-arm64.ps1 `
|
||||
-Executable ./pkg/msvc/ARM64/Release/RetroArch-msvc2022.exe `
|
||||
-SourceDirectory . -AssetsDirectory ./.arm64-assets -InfoDirectory ./.arm64-info `
|
||||
-OutputDirectory ./arm64-dist -SourceRevision $env:SOURCE_REVISION `
|
||||
-Repository $env:GITHUB_REPOSITORY `
|
||||
-AssetsRevision 73106363e14e34c08a5854b4cfbc29f184e3b783 `
|
||||
-InfoRevision 0532bd63ce3072f50ca4f4ada40d42aef565bd3f
|
||||
|
||||
- name: Upload ARM64 release package
|
||||
if: matrix.configuration == 'Release'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: retroarch-windows-arm64-package
|
||||
path: |
|
||||
arm64-dist/RetroArch-WinARM64.zip
|
||||
arm64-dist/RetroArch-WinARM64.zip.sha256
|
||||
if-no-files-found: error
|
||||
|
||||
upload-release:
|
||||
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.publish_release == true)
|
||||
needs: msvc
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: retroarch-windows-arm64-package
|
||||
path: arm64-dist
|
||||
|
||||
- name: Attach ARM64 package to the existing release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
RELEASE_TAG: ${{ needs.msvc.outputs.release_tag }}
|
||||
run: |
|
||||
gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" > /dev/null
|
||||
gh release upload "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --clobber \
|
||||
arm64-dist/RetroArch-WinARM64.zip arm64-dist/RetroArch-WinARM64.zip.sha256
|
||||
@@ -1,64 +0,0 @@
|
||||
name: CI Windows i686 (MXE)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-mxe-win32-cross:gcc16
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@v1
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
export MOC=/usr/lib/mxe/usr/i686-w64-mingw32.shared/qt5/bin/moc
|
||||
CC="ccache i686-w64-mingw32.shared-gcc" \
|
||||
CXX="ccache i686-w64-mingw32.shared-g++" \
|
||||
./configure --host=i686-w64-mingw32.shared
|
||||
make clean
|
||||
make -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,100 +0,0 @@
|
||||
name: CI Windows (memmap area)
|
||||
|
||||
# The fastmem window's reservation has two implementations and a Windows
|
||||
# runner only ever exercises one of them. From Windows 10 1803 the area is
|
||||
# a placeholder that mapping splits and unmapping coalesces; below that --
|
||||
# back to Windows 2000 -- it is one reservation per allocation-granularity
|
||||
# slot, released and mapped over one slot at a time. Every hosted runner is
|
||||
# far past 1803, so the legacy path never runs unless it is asked for, and
|
||||
# MEMSHM_AREA_FORCE_LEGACY is how it is asked for.
|
||||
#
|
||||
# It is worth running because its failures are quiet. A placeholder split
|
||||
# that loses a range, or a slot released and not put back, does not crash:
|
||||
# it maps the wrong memory, or maps nothing and lets a later map land
|
||||
# somewhere else. A core with a guest RAM behind that reads and writes the
|
||||
# wrong addresses.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'libretro-common/memmap/**'
|
||||
- 'libretro-common/include/memmap.h'
|
||||
- 'libretro-common/samples/memmap/**'
|
||||
- '.github/workflows/Windows-memmap-area.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'libretro-common/memmap/**'
|
||||
- 'libretro-common/include/memmap.h'
|
||||
- 'libretro-common/samples/memmap/**'
|
||||
- '.github/workflows/Windows-memmap-area.yml'
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
area:
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# The path this runner takes on its own.
|
||||
- name: placeholders
|
||||
defines: ''
|
||||
# And the one every Windows before 10 1803 takes.
|
||||
- name: legacy
|
||||
defines: '-DMEMSHM_AREA_FORCE_LEGACY'
|
||||
name: ${{ matrix.name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Report the runner's Windows build
|
||||
shell: powershell
|
||||
run: |
|
||||
$v = [System.Environment]::OSVersion.Version
|
||||
Write-Host "Windows $($v.Major).$($v.Minor) build $($v.Build)"
|
||||
if ($v.Build -lt 17134) {
|
||||
Write-Host "::notice::Runner predates 10 1803; the placeholder job tests the legacy path too"
|
||||
}
|
||||
|
||||
# vcvarsall through vswhere, which ships with every Visual Studio and
|
||||
# needs no third-party action: this repo uses only
|
||||
# microsoft/setup-msbuild, and one job is not a reason to add
|
||||
# another dependency to the supply chain.
|
||||
- name: Build the area sample
|
||||
shell: cmd
|
||||
run: |
|
||||
for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set VSPATH=%%i
|
||||
if not defined VSPATH exit /b 1
|
||||
call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cd libretro-common\samples\memmap\memshm_area_test
|
||||
cl /nologo /W3 /WX /I..\..\..\include ${{ matrix.defines }} ^
|
||||
memshm_area_test.c ..\..\..\memmap\memmap.c ^
|
||||
/Fe:memshm_area_test.exe
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
# The sample's own exit code covers the assertions. This also fails
|
||||
# a run that reported no area at all: that is a pass for a platform
|
||||
# which cannot have one, and a silent no-op on a runner that can.
|
||||
- name: Run it, and fail if the area was skipped
|
||||
shell: powershell
|
||||
run: |
|
||||
cd libretro-common\samples\memmap\memshm_area_test
|
||||
$out = & .\memshm_area_test.exe | Out-String
|
||||
Write-Host $out
|
||||
if ($out -match 'skipped') {
|
||||
Write-Error "no area on a runner that must be able to provide one"
|
||||
exit 1
|
||||
}
|
||||
if ($out -notmatch 'memshm area: ok') {
|
||||
Write-Error "the sample did not report ok"
|
||||
exit 1
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
name: CI Windows raw input under Wine
|
||||
|
||||
# The Windows build's raw input path, run for real. The other winraw
|
||||
# tests take the drivers apart and stand in for the frontend around
|
||||
# them; this one cross-builds retroarch.exe with mingw-w64, runs it
|
||||
# under Wine on a virtual display with the GDI video driver, the raw
|
||||
# input driver and the raw input joypad driver, presses keys in its
|
||||
# window and reads its log.
|
||||
#
|
||||
# It runs a small core that writes to the log what reaches it. Five
|
||||
# scenarios, each: two keys, a fullscreen toggle (which restarts the
|
||||
# GDI video driver), the two keys again, quit with Escape - and in each
|
||||
# the core must have seen its button and its key events before the
|
||||
# restart and after it. Read by the poll and kept across the restart
|
||||
# (the default); restarted with the video driver
|
||||
# (RETROARCH_INPUT_KEEP=0); threaded video off; the raw driver as it
|
||||
# was before any of this (RETROARCH_RAWINPUT_POLL=0); and DirectInput.
|
||||
# In all of those the window is left up across both restarts and
|
||||
# taken back; two more destroy it with the driver as before
|
||||
# (RETROARCH_WINDOW_KEEP=0) and leave it up without taking it (=2).
|
||||
# Those use the GDI video driver. Two more use OpenGL on Wine's
|
||||
# software rasteriser: the fullscreen toggle restyling the window in
|
||||
# place, and - with that turned off - restarting on the kept window.
|
||||
# See samples/input/windows_wine_smoke/run.sh.
|
||||
#
|
||||
# Wine is not Windows: what this holds is that the frontend, the pump,
|
||||
# the two drivers and the driver restart fit together, on every commit
|
||||
# that touches them. What only Windows answers - whether its raw input
|
||||
# reaches a window on a thread without the focus, what a real
|
||||
# controller sends - was tried by hand when the path was made.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'input/input_driver.c'
|
||||
- 'input/input_driver.h'
|
||||
- 'input/input_driver_choice.c'
|
||||
- 'input/drivers/winraw_input.c'
|
||||
- 'input/drivers/winraw_mouse_pending.h'
|
||||
- 'input/drivers/winraw_mouse_buttons.h'
|
||||
- 'input/drivers_joypad/winraw_joypad.c'
|
||||
- 'gfx/common/win32_common.c'
|
||||
- 'gfx/common/win32_msg_route.h'
|
||||
- 'gfx/common/win32_ime.h'
|
||||
- 'samples/input/win32_ime/**'
|
||||
- 'gfx/display_servers/dispserv_win32.c'
|
||||
- 'gfx/drivers/gdi_gfx.c'
|
||||
- 'gfx/drivers_context/wgl_ctx.c'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'ui/drivers/ui_win32.c'
|
||||
- 'retroarch.c'
|
||||
- 'runloop.c'
|
||||
- 'samples/input/windows_wine_smoke/**'
|
||||
- '.github/workflows/Windows-wine-input.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'input/input_driver.c'
|
||||
- 'input/input_driver.h'
|
||||
- 'input/input_driver_choice.c'
|
||||
- 'input/drivers/winraw_input.c'
|
||||
- 'input/drivers/winraw_mouse_pending.h'
|
||||
- 'input/drivers/winraw_mouse_buttons.h'
|
||||
- 'input/drivers_joypad/winraw_joypad.c'
|
||||
- 'gfx/common/win32_common.c'
|
||||
- 'gfx/common/win32_msg_route.h'
|
||||
- 'gfx/common/win32_ime.h'
|
||||
- 'samples/input/win32_ime/**'
|
||||
- 'gfx/display_servers/dispserv_win32.c'
|
||||
- 'gfx/drivers/gdi_gfx.c'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'ui/drivers/ui_win32.c'
|
||||
- 'retroarch.c'
|
||||
- 'runloop.c'
|
||||
- 'samples/input/windows_wine_smoke/**'
|
||||
- '.github/workflows/Windows-wine-input.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Only pull requests cancel a superseded run. On master every push
|
||||
# gets its own group (keyed by the commit), so a burst of pushes queues
|
||||
# instead of cancelling the run for the commit before it.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
windows-wine-input:
|
||||
name: Run retroarch.exe under Wine and press keys
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential ccache gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 wine64 xvfb xdotool libgl1-mesa-dri
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Build and run win32_ime_test under Wine
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The window has its input context (the IME) only while a line
|
||||
# of text is open: gfx/common/win32_ime.h, driven from another
|
||||
# thread as the frontend does, the window asked on its own.
|
||||
Xvfb :97 -screen 0 640x480x24 > /dev/null 2>&1 &
|
||||
trap 'kill $! 2>/dev/null; wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
export DISPLAY=:97
|
||||
make -C samples/input/win32_ime check
|
||||
make -C samples/input/win32_ime clean
|
||||
|
||||
- name: Build and run winusb_hid_test under Wine
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The WinUSB HID driver with the real pad handlers and a
|
||||
# stand-in for winusb.dll: a DualShock 3 started by HID class
|
||||
# requests on the control pipe, the newest report its reader
|
||||
# has had taken at the poll, its Bluetooth address read and
|
||||
# set, and a pad that goes or a driver that stops letting the
|
||||
# reader go.
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
make -C samples/input/winusb_hid check
|
||||
make -C samples/input/winusb_hid clean
|
||||
|
||||
- name: Build retroarch.exe with mingw-w64 (GDI and raw input, the rest off)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
# What the test runs has to be real: the Win32 window code,
|
||||
# the GDI and OpenGL drivers, the raw input drivers, the
|
||||
# menu, threads. Everything else is build time.
|
||||
./configure --host=x86_64-w64-mingw32 \
|
||||
--disable-qt --disable-vulkan --disable-ffmpeg \
|
||||
--disable-networking --disable-cheevos \
|
||||
--disable-glslang --disable-slang \
|
||||
--disable-spirv_cross --disable-xmb \
|
||||
--disable-materialui --disable-ozone \
|
||||
--disable-7zip --disable-flac \
|
||||
--disable-audiomixer --disable-translate \
|
||||
--disable-accessibility --disable-langextra \
|
||||
--disable-libretrodb --disable-discord \
|
||||
--disable-d3d9 --disable-d3d10 --disable-d3d11 \
|
||||
--disable-d3d12 --disable-sdl \
|
||||
--disable-sdl2 --disable-video_filter \
|
||||
--disable-dsp_filter --disable-crtswitchres
|
||||
make -j$(nproc) CC="ccache x86_64-w64-mingw32-gcc" \
|
||||
CXX="ccache x86_64-w64-mingw32-g++"
|
||||
ccache -s
|
||||
test -f retroarch.exe
|
||||
|
||||
- name: Run the scenarios under Wine
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Stop wineserver on exit so it cannot hold the step's output
|
||||
# open.
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
timeout 900 samples/input/windows_wine_smoke/run.sh
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,239 +0,0 @@
|
||||
name: CI Windows menus under Wine
|
||||
|
||||
# Ozone, XMB, MaterialUI and RGUI as each Direct3D driver and both GL
|
||||
# drivers draw them. Cross-builds retroarch.exe with mingw-w64, starts
|
||||
# it with no content under Wine on a virtual display for each menu on
|
||||
# each driver, reads the screen once it holds still and compares it
|
||||
# with D3D11's block by block. A solid quad sampling the wrong texture
|
||||
# (d3d9_hlsl's batched quads read the font atlas) or a gradient split
|
||||
# along the other diagonal (both D3D9 drivers' single quads) moves
|
||||
# whole blocks; the drivers' own text and edge differences do not.
|
||||
# See samples/gfx/menu_wine/run.py. Then a core writes its frames into
|
||||
# the framebuffer d3d9_hlsl lends it - still, cropped, and through the
|
||||
# driver growing its textures - checked against D3D11's copy
|
||||
# (samples/gfx/menu_wine/swfb.py).
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'gfx/drivers/d3d*.c'
|
||||
- 'gfx/drivers/gl2.c'
|
||||
- 'gfx/drivers/gl3.c'
|
||||
- 'gfx/drivers/d3d_shaders/**'
|
||||
- 'gfx/common/d3d*'
|
||||
- 'gfx/common/gl*'
|
||||
- 'gfx/gfx_display.*'
|
||||
- 'gfx/font_driver.*'
|
||||
- 'gfx/font_layout.h'
|
||||
- 'gfx/drivers_font/**'
|
||||
- 'gfx/drivers_font_renderer/**'
|
||||
- 'menu/drivers/**'
|
||||
- 'menu/menu_driver.*'
|
||||
- 'samples/gfx/menu_wine/**'
|
||||
- 'samples/gfx/d3d12_menu_mapping/**'
|
||||
- 'samples/gfx/threaded_video/harness_core.c'
|
||||
- 'samples/gfx/d3d9_ex/**'
|
||||
- '.github/workflows/Windows-wine-menu.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'gfx/drivers/d3d*.c'
|
||||
- 'gfx/drivers/gl2.c'
|
||||
- 'gfx/drivers/gl3.c'
|
||||
- 'gfx/drivers/d3d_shaders/**'
|
||||
- 'gfx/common/d3d*'
|
||||
- 'gfx/common/gl*'
|
||||
- 'gfx/gfx_display.*'
|
||||
- 'gfx/font_driver.*'
|
||||
- 'gfx/font_layout.h'
|
||||
- 'gfx/drivers_font/**'
|
||||
- 'gfx/drivers_font_renderer/**'
|
||||
- 'menu/drivers/**'
|
||||
- 'menu/menu_driver.*'
|
||||
- 'samples/gfx/menu_wine/**'
|
||||
- 'samples/gfx/d3d12_menu_mapping/**'
|
||||
- 'samples/gfx/threaded_video/harness_core.c'
|
||||
- 'samples/gfx/d3d9_ex/**'
|
||||
- '.github/workflows/Windows-wine-menu.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
windows-wine-menu:
|
||||
name: Menus on D3D8, D3D9, D3D10, D3D11, D3D12 and GL under Wine
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
APT_PKGS: build-essential ccache gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 mingw-w64-tools wine64 xvfb xauth imagemagick libgl1-mesa-dri mesa-vulkan-drivers libvulkan1 autoconf automake libtool flex bison pkg-config libvulkan-dev spirv-headers python3
|
||||
timeout-minutes: 90
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Build vkd3d's shader compiler for Windows
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
v="$RUNNER_TEMP/vkd3d"
|
||||
git clone -q --depth 1 --branch vkd3d-2.1 \
|
||||
https://gitlab.winehq.org/wine/vkd3d.git "$v"
|
||||
cd "$v"
|
||||
./autogen.sh > /dev/null
|
||||
mkdir -p inc lib build
|
||||
ln -s /usr/include/vulkan inc/vulkan
|
||||
ln -s /usr/include/vk_video inc/vk_video
|
||||
ln -s /usr/include/spirv inc/spirv
|
||||
printf 'LIBRARY vulkan-1.dll\nEXPORTS\nvkGetInstanceProcAddr\n' \
|
||||
> lib/vulkan-1.def
|
||||
x86_64-w64-mingw32-dlltool -d lib/vulkan-1.def \
|
||||
-l lib/libvulkan-1.a
|
||||
cd build
|
||||
../configure -q --host=x86_64-w64-mingw32 --disable-tests \
|
||||
--disable-demos WIDL=x86_64-w64-mingw32-widl \
|
||||
CPPFLAGS="-I$v/inc" LDFLAGS="-L$v/lib"
|
||||
make -j$(nproc) > /dev/null
|
||||
cp .libs/libvkd3d-utils-1.dll "$GITHUB_WORKSPACE/D3DCompiler_47.dll"
|
||||
cp .libs/libvkd3d-shader-1.dll .libs/libvkd3d-1.dll \
|
||||
"$GITHUB_WORKSPACE/"
|
||||
|
||||
- name: Build retroarch.exe with mingw-w64 (D3D8, D3D9, D3D10, D3D11, D3D12, GL)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
ccache -M 250M
|
||||
./configure --host=x86_64-w64-mingw32 \
|
||||
--disable-qt --disable-vulkan --disable-ffmpeg \
|
||||
--disable-cheevos --disable-discord --enable-d3d8 \
|
||||
--disable-sdl --disable-sdl2
|
||||
make -j$(nproc) CC="ccache x86_64-w64-mingw32-gcc" \
|
||||
CXX="ccache x86_64-w64-mingw32-g++"
|
||||
ccache -s
|
||||
for f in libstdc++-6.dll libgcc_s_seh-1.dll; do
|
||||
cp "$(ls /usr/lib/gcc/x86_64-w64-mingw32/*-win32/$f | head -n 1)" .
|
||||
done
|
||||
|
||||
- name: Menus on every driver, compared with D3D11 (Wine, Xvfb, llvmpipe)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
export LIBGL_ALWAYS_SOFTWARE=1
|
||||
WINEDEBUG=-all timeout 120 xvfb-run -a sh -c 'wineboot -i && wineserver -w'
|
||||
python3 samples/gfx/menu_wine/run.py ./retroarch.exe \
|
||||
"$RUNNER_TEMP/menu-wine" d3d11 d3d10 d3d12 d3d9_hlsl d3d8 gl glcore
|
||||
|
||||
- name: D3D12 menu component mapping on the GPU (Wine)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
export LIBGL_ALWAYS_SOFTWARE=1
|
||||
CC=x86_64-w64-mingw32-gcc RUNNER=wine \
|
||||
xvfb-run -a python3 samples/gfx/d3d12_menu_mapping/run.py
|
||||
CC=x86_64-w64-mingw32-gcc RUNNER=wine REQUIRE_D3D11=1 \
|
||||
xvfb-run -a python3 samples/gfx/d3d_failure_paths/gpu.py
|
||||
CC=x86_64-w64-mingw32-gcc RUNNER=wine REQUIRE_D3D11=1 \
|
||||
xvfb-run -a python3 samples/gfx/d3d_failure_paths/lend_gpu.py
|
||||
|
||||
- name: A core writing into the framebuffer d3d9_hlsl lends it (Wine)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
(cd samples/gfx/threaded_video && x86_64-w64-mingw32-gcc -O1 \
|
||||
-shared -I../../../libretro-common/include -I../../../gfx/include \
|
||||
-o ../../../harness_core.dll harness_core.c)
|
||||
python3 samples/gfx/menu_wine/swfb.py ./retroarch.exe \
|
||||
./harness_core.dll "$RUNNER_TEMP/menu-wine/swfb" d3d9_hlsl
|
||||
|
||||
- name: D3D9 textures and frame memory on a Direct3D9Ex device and a plain one (Wine)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
# What reached the GPU, read back: the managed pool before Ex,
|
||||
# default-pool textures with system-memory twins on it, and the
|
||||
# frames it reads where they lie; then a device in the flip
|
||||
# model, its frame latency and d3d9_present's ways to wait
|
||||
make -C samples/gfx/d3d9_ex check
|
||||
|
||||
- name: d3d9_hlsl with Direct3D 9Ex Presentation, and without Ex (Wine)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
# The window in the flip model and the frame latency taken on
|
||||
# Ex, the same screens; as before where there is no Ex
|
||||
export SWFB_D3D9EX_PRESENT=2
|
||||
python3 samples/gfx/menu_wine/swfb.py ./retroarch.exe \
|
||||
./harness_core.dll "$RUNNER_TEMP/menu-wine/swfb-present" d3d9_hlsl
|
||||
RETROARCH_D3D9EX=0 python3 samples/gfx/menu_wine/swfb.py \
|
||||
./retroarch.exe ./harness_core.dll \
|
||||
"$RUNNER_TEMP/menu-wine/swfb-present-legacy" d3d9_hlsl
|
||||
|
||||
- name: d3d9_hlsl without Direct3D9Ex, as a system without it has (Wine)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
export RETROARCH_D3D9EX=0
|
||||
python3 samples/gfx/menu_wine/run.py ./retroarch.exe \
|
||||
"$RUNNER_TEMP/menu-wine/legacy" d3d11 d3d9_hlsl
|
||||
python3 samples/gfx/menu_wine/swfb.py ./retroarch.exe \
|
||||
./harness_core.dll "$RUNNER_TEMP/menu-wine/swfb-legacy" d3d9_hlsl
|
||||
|
||||
- name: Preserve screens on failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows-wine-menu-screens
|
||||
path: |
|
||||
${{ runner.temp }}/menu-wine/**/*.png
|
||||
${{ runner.temp }}/menu-wine/**/*.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Save ccache
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,181 +0,0 @@
|
||||
name: CI Windows views under Wine
|
||||
|
||||
# Views on the GDI, D3D8, D3D9 HLSL, D3D10, D3D11 and D3D12 drivers, end
|
||||
# to end: retroarch.exe cross-built with mingw-w64 runs the video_views
|
||||
# test core under Wine, on a virtual display through Mesa's software
|
||||
# rasterisers (D3D12 on Wine's vkd3d over lavapipe), and
|
||||
# samples/cores/video_views/e2e/run.py checks the screen in each stereo
|
||||
# mode, from the core's software frames and its D3D11 and D3D12
|
||||
# textures, with the menu laid out per eye and the pointer over it.
|
||||
# Wine's own shader compiler can't take the drivers' HLSL, so vkd3d's,
|
||||
# from its release, is put in as D3DCompiler_47.dll.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'gfx/common/d3d9_*'
|
||||
- 'gfx/drivers/gdi_gfx.c'
|
||||
- 'gfx/common/gdi_defines.h'
|
||||
- 'gfx/drivers/d3d8.c'
|
||||
- 'gfx/drivers/d3d9hlsl.c'
|
||||
- 'gfx/drivers/d3d10.c'
|
||||
- 'gfx/drivers/d3d11.c'
|
||||
- 'gfx/drivers/d3d12.c'
|
||||
- 'gfx/drivers/d3d_shaders/views_sm*.hlsl.h'
|
||||
- 'gfx/video_views.*'
|
||||
- 'gfx/video_views_draw.h'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'samples/cores/video_views/**'
|
||||
- '.github/workflows/Windows-wine-views.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'gfx/common/d3d9_*'
|
||||
- 'gfx/drivers/gdi_gfx.c'
|
||||
- 'gfx/common/gdi_defines.h'
|
||||
- 'gfx/drivers/d3d8.c'
|
||||
- 'gfx/drivers/d3d9hlsl.c'
|
||||
- 'gfx/drivers/d3d10.c'
|
||||
- 'gfx/drivers/d3d11.c'
|
||||
- 'gfx/drivers/d3d12.c'
|
||||
- 'gfx/drivers/d3d_shaders/views_sm*.hlsl.h'
|
||||
- 'gfx/video_views.*'
|
||||
- 'gfx/video_views_draw.h'
|
||||
- 'gfx/video_driver.c'
|
||||
- 'gfx/video_thread_wrapper.*'
|
||||
- 'samples/cores/video_views/**'
|
||||
- '.github/workflows/Windows-wine-views.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
windows-wine-views:
|
||||
name: Views on GDI, D3D8, D3D9, D3D10, D3D11 and D3D12 under Wine
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
APT_PKGS: build-essential ccache gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 mingw-w64-tools wine64 xvfb xauth imagemagick libgl1-mesa-dri mesa-vulkan-drivers libvulkan1 autoconf automake libtool flex bison pkg-config libvulkan-dev spirv-headers python3
|
||||
timeout-minutes: 150
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install dependencies
|
||||
timeout-minutes: 20
|
||||
run: sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Build vkd3d's shader compiler for Windows
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
v="$RUNNER_TEMP/vkd3d"
|
||||
git clone -q --depth 1 --branch vkd3d-2.1 \
|
||||
https://gitlab.winehq.org/wine/vkd3d.git "$v"
|
||||
cd "$v"
|
||||
./autogen.sh > /dev/null
|
||||
# Its headers from the host; vulkan-1.dll is loaded at run
|
||||
# time, so an import library naming it does.
|
||||
mkdir -p inc lib build
|
||||
ln -s /usr/include/vulkan inc/vulkan
|
||||
ln -s /usr/include/vk_video inc/vk_video
|
||||
ln -s /usr/include/spirv inc/spirv
|
||||
printf 'LIBRARY vulkan-1.dll\nEXPORTS\nvkGetInstanceProcAddr\n' \
|
||||
> lib/vulkan-1.def
|
||||
x86_64-w64-mingw32-dlltool -d lib/vulkan-1.def \
|
||||
-l lib/libvulkan-1.a
|
||||
cd build
|
||||
../configure -q --host=x86_64-w64-mingw32 --disable-tests \
|
||||
--disable-demos WIDL=x86_64-w64-mingw32-widl \
|
||||
CPPFLAGS="-I$v/inc" LDFLAGS="-L$v/lib"
|
||||
make -j$(nproc) > /dev/null
|
||||
cp .libs/libvkd3d-utils-1.dll "$GITHUB_WORKSPACE/D3DCompiler_47.dll"
|
||||
cp .libs/libvkd3d-shader-1.dll .libs/libvkd3d-1.dll \
|
||||
"$GITHUB_WORKSPACE/"
|
||||
|
||||
- name: Build retroarch.exe with mingw-w64 (D3D8, D3D9, D3D10, D3D11, D3D12, slang)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
ccache -M 250M
|
||||
./configure --host=x86_64-w64-mingw32 \
|
||||
--disable-qt --disable-vulkan --disable-ffmpeg \
|
||||
--disable-cheevos --disable-discord --enable-d3d8 \
|
||||
--disable-sdl --disable-sdl2
|
||||
make -j$(nproc) CC="ccache x86_64-w64-mingw32-gcc" \
|
||||
CXX="ccache x86_64-w64-mingw32-g++"
|
||||
ccache -s
|
||||
# The C and C++ runtimes it was linked against
|
||||
for f in libstdc++-6.dll libgcc_s_seh-1.dll; do
|
||||
cp "$(ls /usr/lib/gcc/x86_64-w64-mingw32/*-win32/$f | head -n 1)" .
|
||||
done
|
||||
make -C samples/cores/video_views DLL=1 CC=x86_64-w64-mingw32-gcc
|
||||
|
||||
- name: Views on GDI, D3D8, D3D9, D3D10, D3D11 and D3D12, end to end (Wine, Xvfb, llvmpipe, lavapipe)
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
trap 'wineserver -k >/dev/null 2>&1 || true' EXIT
|
||||
export LIBGL_ALWAYS_SOFTWARE=1
|
||||
export VK_DRIVER_FILES=/usr/share/vulkan/icd.d/lvp_icd.json
|
||||
# Initialize the prefix with a display and wait for setup to finish.
|
||||
WINEDEBUG=-all timeout 120 xvfb-run -a sh -c 'wineboot -i && wineserver -w'
|
||||
RA_E2E_WINE=1 python3 samples/cores/video_views/e2e/run.py \
|
||||
./retroarch.exe "$RUNNER_TEMP/views-e2e" gdi d3d8 d3d9_hlsl d3d10 d3d11 d3d12
|
||||
# And d3d9_hlsl on the device of a system without Direct3D9Ex
|
||||
RETROARCH_D3D9EX=0 RA_E2E_WINE=1 python3 samples/cores/video_views/e2e/run.py \
|
||||
./retroarch.exe "$RUNNER_TEMP/views-e2e-legacy" d3d9_hlsl
|
||||
|
||||
- name: Preserve views logs on failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows-wine-views-logs
|
||||
path: ${{ runner.temp }}/views-e2e/**/*.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,64 +0,0 @@
|
||||
name: CI Windows x64 (MXE)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-mxe-win64-cross:gcc16
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@v1
|
||||
|
||||
- name: Restore ccache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
ccache-${{ github.workflow }}-${{ github.job }}-
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
export CCACHE_DIR="$HOME/.ccache"
|
||||
echo "CCACHE_DIR=$CCACHE_DIR" >> "$GITHUB_ENV"
|
||||
ccache -M 250M
|
||||
ccache -z
|
||||
export MOC=/usr/lib/mxe/usr/x86_64-w64-mingw32.shared/qt5/bin/moc
|
||||
CC="ccache x86_64-w64-mingw32.shared-gcc" \
|
||||
CXX="ccache x86_64-w64-mingw32.shared-g++" \
|
||||
./configure --host=x86_64-w64-mingw32.shared
|
||||
make clean
|
||||
make -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: ccache statistics
|
||||
if: ${{ !cancelled() }}
|
||||
continue-on-error: true
|
||||
run: ccache -sv
|
||||
|
||||
- name: Save ccache
|
||||
# Only master's pushes keep a cache: pull requests restore
|
||||
# master's, so one push does not evict the next one's.
|
||||
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
|
||||
@@ -1,49 +0,0 @@
|
||||
# Download translations from Crowdin and push to GitHub
|
||||
|
||||
name: Crowdin Daily Workflow
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # every day at midnight
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
permissions:
|
||||
contents: write # for Git to git push
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Setup Java JDK
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 18
|
||||
distribution: zulu
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
- name: Crowdin Sync
|
||||
shell: bash
|
||||
env:
|
||||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
||||
run: |
|
||||
cd intl
|
||||
python3 -m pip install requests PyYAML
|
||||
python3 crowdin_sync.py "$CROWDIN_API_KEY"
|
||||
git config user.name github-actions
|
||||
git config user.email [email protected]
|
||||
git add .
|
||||
if git diff --cached --quiet; then
|
||||
echo "No translation changes to commit."
|
||||
else
|
||||
git commit -m "Fetch translations from Crowdin"
|
||||
git push
|
||||
fi
|
||||
@@ -1,41 +0,0 @@
|
||||
# Upload sources to Crowdin for translation
|
||||
|
||||
name: Crowdin Workflow
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'intl/*_us.h'
|
||||
- 'intl/*_us.json'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Setup Java JDK
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 18
|
||||
distribution: zulu
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
- name: Crowdin Sync
|
||||
shell: bash
|
||||
env:
|
||||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
||||
run: |
|
||||
cd intl
|
||||
python3 crowdin_sync.py "$CROWDIN_API_KEY"
|
||||
@@ -1,89 +0,0 @@
|
||||
name: CI iOS 6 (armv7)
|
||||
|
||||
# The iOS 6 build - RetroArch_iOS6.xcodeproj's defines, ARC, armv7,
|
||||
# a 6.0 deployment target - compiled against the iOS 9.3 SDK, the last
|
||||
# that takes a 6.0 floor. No runner Xcode can build armv7 or anything
|
||||
# below iOS 12 any more, so this runs clang on Linux against the SDK's
|
||||
# headers, as the PowerPC leg does for old macOS. Every warning is an
|
||||
# error: anything newer than iOS 6 has to be behind a runtime check,
|
||||
# and -Wunguarded-availability is what says so.
|
||||
#
|
||||
# The checking is .github/workflows/scripts/ios-legacy-check.sh, which
|
||||
# runs by hand the same way; this job fetches the SDK headers for it.
|
||||
#
|
||||
# SDK: theos/sdks, pinned to a commit; only the headers are checked out.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
SDKS_COMMIT: 0222fd5413cf4b9af096f37b4621afa2688572f7
|
||||
SDK: iPhoneOS9.3.sdk
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
APT_PKGS: clang-18
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: Apt cache key
|
||||
id: apt
|
||||
run: sh .github/workflows/scripts/apt-cache-key.sh "$APT_PKGS"
|
||||
|
||||
- name: Restore apt cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
restore-keys: ${{ steps.apt.outputs.prefix }}
|
||||
|
||||
- name: Install clang
|
||||
timeout-minutes: 10
|
||||
run: |
|
||||
sh .github/workflows/scripts/apt-install.sh $APT_PKGS
|
||||
clang-18 --version | head -n 1
|
||||
|
||||
- name: Save apt cache
|
||||
if: env.APT_CACHE_SAVE == '1'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ~/.apt-cache
|
||||
key: ${{ steps.apt.outputs.key }}
|
||||
|
||||
- name: Fetch the iOS SDK headers
|
||||
run: |
|
||||
set -e
|
||||
git init -q "$RUNNER_TEMP/sdks"
|
||||
cd "$RUNNER_TEMP/sdks"
|
||||
git remote add origin https://github.com/theos/sdks.git
|
||||
git config core.sparseCheckout true
|
||||
printf '%s\n' \
|
||||
"/$SDK/usr/include/" \
|
||||
"/$SDK/System/Library/Frameworks/*/Headers/" \
|
||||
"/$SDK/System/Library/Frameworks/*/Frameworks/*.framework/Headers/" \
|
||||
> .git/info/sparse-checkout
|
||||
git fetch -q --depth 1 --filter=blob:none origin "$SDKS_COMMIT"
|
||||
git checkout -q FETCH_HEAD
|
||||
du -sh "$SDK"
|
||||
|
||||
- name: iOS 6.0
|
||||
run: CC=clang-18 .github/workflows/scripts/ios-legacy-check.sh "$RUNNER_TEMP/sdks/$SDK" 6.0
|
||||
Loaded 100 of 13591 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user