mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-12 13:08:24 -10:00
Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
928d1a0810 | ||
|
|
6919bc9cd7 | ||
|
|
a8c5b1815e | ||
|
|
cf6aab7ad2 | ||
|
|
f0cce58206 | ||
|
|
07ac0685e2 | ||
|
|
e3e1d87705 | ||
|
|
05a483cbe6 | ||
|
|
2c5cde4125 | ||
|
|
5f8bbcd1b6 | ||
|
|
e81d65d51b | ||
|
|
193133d616 | ||
|
|
d2cf7a113b | ||
|
|
4e07070e86 | ||
|
|
4562153839 |
No files matched your search
@@ -0,0 +1,6 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -2,7 +2,6 @@ name: CI 3DS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,14 +12,9 @@ permissions:
|
||||
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
|
||||
@@ -37,3 +31,6 @@ jobs:
|
||||
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
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
@@ -2,7 +2,6 @@ name: CI Android
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
@@ -14,47 +13,23 @@ permissions:
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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
|
||||
./gradlew assembleDebug
|
||||
find . -iname "*.apk" -exec ls -l "{}" \;
|
||||
|
||||
- name: Get short SHA
|
||||
@@ -67,374 +42,3 @@ jobs:
|
||||
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
|
||||
@@ -11,7 +11,6 @@ name: CI Apple
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
@@ -20,10 +19,6 @@ permissions:
|
||||
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.
|
||||
@@ -57,7 +52,6 @@ jobs:
|
||||
netplay-discovery-guard:
|
||||
name: Build graph - netplay mDNS discovery
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -134,7 +128,6 @@ jobs:
|
||||
tvos:
|
||||
name: tvOS build (non-gating)
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
|
||||
@@ -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
|
||||
@@ -11,43 +11,15 @@ on:
|
||||
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: Dependencies
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y build-essential
|
||||
- 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
|
||||
uses: actions/checkout@v3
|
||||
- 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
|
||||
@@ -2,7 +2,6 @@ name: CI DOS/DJGPP
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,67 +12,20 @@ permissions:
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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 }}
|
||||
make -f Makefile.dos -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 info all
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
|
||||
@@ -2,7 +2,6 @@ name: CI Emscripten
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,14 +12,9 @@ permissions:
|
||||
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
|
||||
@@ -32,3 +26,8 @@ jobs:
|
||||
run: |
|
||||
emmake make -f Makefile.emscripten -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
emmake make -f Makefile.emscripten -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)"
|
||||
|
||||
@@ -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
|
||||
@@ -2,7 +2,6 @@ name: CI GameCube
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,65 +12,21 @@ permissions:
|
||||
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
|
||||
image: reallibretroretroarch/libretro-build-devkitpro: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 }}
|
||||
make -f Makefile.ngc -j$(getconf _NPROCESSORS_ONLN) EXTERNAL_LIBOGC=1 GX_PTHREAD_LEGACY=0 HAVE_STATIC_DUMMY=1 info all
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
@@ -14,77 +14,17 @@ permissions:
|
||||
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
|
||||
- name: Dependencies
|
||||
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
|
||||
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install 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
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- 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 }}
|
||||
@@ -21,10 +21,8 @@ name: CI Linux ASan + UBSan [No Menu]
|
||||
# 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
|
||||
# Linux-samples-tasks.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
|
||||
@@ -51,63 +49,37 @@ permissions:
|
||||
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
|
||||
# Mirrors Linux-Headless.yml's apt set so the build matches a
|
||||
# known-good headless configuration. Adds:
|
||||
# xvfb / x11-utils -- virtual X server for the imageviewer
|
||||
# smoke step + xdpyinfo for diagnostics
|
||||
# libsdl2-dev (already in the base set) provides the SDL2
|
||||
# video driver used by that smoke -- see the smoke step's
|
||||
# comment for why SDL2 over xvideo. No sanitizer-specific
|
||||
# packages required; libasan / libubsan ship with the gcc
|
||||
# that ubuntu-latest has installed by default.
|
||||
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
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y \
|
||||
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
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Configure (no menu, no discord/cheevos/networking, sdl2 on)
|
||||
# Trim the build surface for the first iteration so any
|
||||
@@ -400,78 +372,3 @@ jobs:
|
||||
| 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
|
||||
@@ -15,76 +15,20 @@ permissions:
|
||||
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 }})
|
||||
name: Build and run the autoconfig regression suite
|
||||
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
|
||||
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 }}-${{ 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
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y build-essential zlib1g-dev libfreetype6-dev
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Configure (headless, test drivers)
|
||||
run: |
|
||||
@@ -98,36 +42,11 @@ jobs:
|
||||
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
|
||||
run: make -j"$(nproc)"
|
||||
|
||||
- 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 }}
|
||||
./tests-other/test_autoconf.sh ./retroarch
|
||||
@@ -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
@@ -21,65 +21,33 @@ permissions:
|
||||
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
|
||||
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
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y build-essential check pkg-config \
|
||||
zlib1g-dev lcov \
|
||||
gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 wine wine64
|
||||
# mingw and wine are for the Windows A/W configuration matrix
|
||||
# in Makefile.test. libretro-common selects between the ANSI
|
||||
# and the wide Win32 entry points three ways and, until these
|
||||
# were installed, no job built two of them: the ANSI branch
|
||||
# was compiled by nothing, so nothing noticed when it stopped
|
||||
# compiling. wine takes it past a build check - an ANSI build
|
||||
# under wine really does call CreateFileA and
|
||||
# GetFileAttributesA, so the branch is executed rather than
|
||||
# merely parsed. Both are optional to the recipe: without
|
||||
# them it says which tool is missing and passes, so a
|
||||
# contributor's local run is not blocked.
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build and run the unit test suites
|
||||
shell: bash
|
||||
@@ -95,28 +63,10 @@ jobs:
|
||||
# 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 \
|
||||
make -f Makefile.test \
|
||||
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
|
||||
@@ -131,134 +81,7 @@ jobs:
|
||||
# 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"
|
||||
python3 tools/vfs_backend_parity.py
|
||||
|
||||
- name: Check stack frame budget
|
||||
shell: bash
|
||||
@@ -273,169 +96,3 @@ jobs:
|
||||
# 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 }}
|
||||
@@ -15,63 +15,20 @@ permissions:
|
||||
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
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y build-essential zlib1g-dev
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build and run samples
|
||||
shell: bash
|
||||
@@ -201,17 +158,3 @@ jobs:
|
||||
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 }}
|
||||
@@ -15,100 +15,20 @@ permissions:
|
||||
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
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y build-essential
|
||||
|
||||
- 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: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build and run image_decode_fuzz_test (ASan + UBSan + LSan)
|
||||
shell: bash
|
||||
@@ -143,144 +63,8 @@ jobs:
|
||||
# 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
|
||||
make clean 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
|
||||
@@ -2,7 +2,6 @@ name: CI Linux (i686)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,14 +12,9 @@ permissions:
|
||||
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
|
||||
@@ -33,24 +27,11 @@ jobs:
|
||||
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
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
@@ -2,7 +2,6 @@ name: CI Windows (MSVC)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -14,15 +13,10 @@ 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]
|
||||
@@ -37,7 +31,7 @@ jobs:
|
||||
platform: x64
|
||||
# Qt and Cg builds are excluded for now
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
@@ -62,43 +56,3 @@ jobs:
|
||||
${{ 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
|
||||
+32
-39
@@ -2,7 +2,6 @@ name: CI Windows (MSYS2)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -10,10 +9,6 @@ on:
|
||||
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:
|
||||
@@ -29,58 +24,56 @@ jobs:
|
||||
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
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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
|
||||
install: >-
|
||||
base-devel
|
||||
git
|
||||
pacboy: >-
|
||||
gettext:p
|
||||
gobject-introspection:p
|
||||
graphite2:p
|
||||
p11-kit:p
|
||||
qt6:p
|
||||
qt6-3d:p
|
||||
qt6-charts:p
|
||||
qt6-datavis3d:p
|
||||
qt6-imageformats:p
|
||||
qt6-location:p
|
||||
qt6-lottie:p
|
||||
qt6-networkauth:p
|
||||
qt6-quick3dphysics:p
|
||||
qt6-quicktimeline:p
|
||||
qt6-remoteobjects:p
|
||||
qt6-scxml:p
|
||||
qt6-sensors:p
|
||||
qt6-serialbus:p
|
||||
qt6-speech:p
|
||||
qt6-tools:p
|
||||
qt6-translations:p
|
||||
qt6-virtualkeyboard:p
|
||||
qt6-webchannel:p
|
||||
qt6-websockets:p
|
||||
x264:p
|
||||
cc:p
|
||||
|
||||
- name: Configure and build RetroArch
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
echo "Building RetroArch in ${{ matrix.sys }} on ${{ matrix.runner }}"
|
||||
QB_JOBS=${{ matrix.qb_jobs }} ./configure
|
||||
./configure
|
||||
make -j"$(nproc)" info all
|
||||
|
||||
- name: Collect DLLs and binaries
|
||||
|
||||
@@ -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
|
||||
@@ -2,7 +2,6 @@ name: CI macOS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
@@ -11,89 +10,13 @@ permissions:
|
||||
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
|
||||
@@ -108,36 +31,3 @@ jobs:
|
||||
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
|
||||
@@ -2,7 +2,6 @@ name: CI Miyoo ARM32
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,20 +12,15 @@ permissions:
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
|
||||
@@ -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
|
||||
@@ -2,7 +2,6 @@ name: CI PS2
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,20 +12,15 @@ permissions:
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
|
||||
@@ -2,7 +2,6 @@ name: CI PS3/PSL1GHT
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,20 +12,15 @@ permissions:
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
|
||||
@@ -2,7 +2,6 @@ name: CI PS4/ORBIS
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,49 +12,26 @@ permissions:
|
||||
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
|
||||
container:
|
||||
image: reallibretroretroarch/libretro-build-orbis:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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 }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
if [ -n "$DOCKERHUB_USERNAME" ] && [ -n "$DOCKERHUB_TOKEN" ]; then
|
||||
echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
|
||||
fi
|
||||
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
|
||||
|
||||
- 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
|
||||
'
|
||||
export PATH=~/cli:$PATH # .net cli
|
||||
make -f Makefile.orbis -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 info all
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
@@ -68,3 +44,8 @@ jobs:
|
||||
retroarch_orbis.elf
|
||||
retroarch_orbis.oelf
|
||||
retroarch_orbis.self
|
||||
|
||||
- name: Version of binaries
|
||||
run: |
|
||||
clang --version
|
||||
orbis-ld --version
|
||||
@@ -2,7 +2,6 @@ name: CI PSP
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,20 +12,15 @@ permissions:
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Compile bootstrap
|
||||
run: |
|
||||
|
||||
@@ -2,7 +2,6 @@ name: CI PSVita
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,73 +12,25 @@ permissions:
|
||||
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
|
||||
image: reallibretroretroarch/libretro-build-vita:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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 }}
|
||||
|
||||
make -f Makefile.vita -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 HAVE_VITAGLES=1 info all
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
@@ -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
|
||||
@@ -2,7 +2,6 @@ name: CI RS90 Odbeta MIPS32
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,20 +12,15 @@ permissions:
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
|
||||
@@ -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 }}
|
||||
@@ -2,7 +2,6 @@ name: CI RetroFW MIPS32
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,20 +12,15 @@ permissions:
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
|
||||
@@ -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
|
||||
@@ -16,16 +16,12 @@ jobs:
|
||||
build:
|
||||
name: build
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
|
||||
- name: archive
|
||||
id: archive
|
||||
run: |
|
||||
@@ -37,6 +33,7 @@ jobs:
|
||||
mv * /tmp/$PKGNAME
|
||||
mv /tmp/$PKGNAME .
|
||||
rm -rf $PKGNAME/pkg || true
|
||||
rm -rf $PKGNAME/wii/libogc || true
|
||||
rm -rf $PKGNAME/deps/glslang/glslang/Test || true
|
||||
rm -rf $PKGNAME/deps/SPIRV-Cross/reference || true
|
||||
rm -rf $PKGNAME/gfx/include/userland || true
|
||||
|
||||
@@ -2,7 +2,6 @@ name: CI Switch/libnx
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,68 +12,20 @@ permissions:
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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 }}
|
||||
|
||||
make -f Makefile.libnx -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)"
|
||||
|
||||
@@ -2,7 +2,6 @@ name: CI Wii
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,16 +12,11 @@ permissions:
|
||||
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
|
||||
image: reallibretroretroarch/libretro-build-devkitpro:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
@@ -31,52 +25,13 @@ jobs:
|
||||
- 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
|
||||
make -f Makefile.wii.salamander -j$(getconf _NPROCESSORS_ONLN) EXTERNAL_LIBOGC=1 GX_PTHREAD_LEGACY=0
|
||||
|
||||
- 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 }}
|
||||
make -f Makefile.wii -j$(getconf _NPROCESSORS_ONLN) EXTERNAL_LIBOGC=1 GX_PTHREAD_LEGACY=0 HAVE_STATIC_DUMMY=1 info all
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
@@ -2,7 +2,6 @@ name: CI WiiU
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,14 +12,9 @@ permissions:
|
||||
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
|
||||
@@ -37,3 +31,6 @@ jobs:
|
||||
run: |
|
||||
make -f Makefile.wiiu -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.wiiu -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)"
|
||||
@@ -2,22 +2,9 @@ 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
|
||||
@@ -25,16 +12,9 @@ permissions:
|
||||
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]
|
||||
@@ -42,30 +22,7 @@ jobs:
|
||||
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
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
@@ -77,88 +34,11 @@ jobs:
|
||||
|
||||
- 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
|
||||
shell: powershell
|
||||
run: echo "sha8=$('${{ github.sha }}'.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
|
||||
@@ -2,7 +2,6 @@ name: CI Windows i686 (MXE)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,52 +12,23 @@ permissions:
|
||||
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
|
||||
image: reallibretroretroarch/libretro-build-mxe-win32-cross:gcc10
|
||||
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
|
||||
./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 }}
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
@@ -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 }}
|
||||
@@ -2,7 +2,6 @@ name: CI Windows x64 (MXE)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
@@ -13,52 +12,23 @@ permissions:
|
||||
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
|
||||
image: reallibretroretroarch/libretro-build-mxe-win64-cross:gcc10
|
||||
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
|
||||
./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 }}
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
@@ -14,7 +14,6 @@ jobs:
|
||||
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
|
||||
@@ -26,10 +25,7 @@ jobs:
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
uses: actions/checkout@v3
|
||||
- name: Crowdin Sync
|
||||
shell: bash
|
||||
env:
|
||||
|
||||
@@ -16,7 +16,6 @@ permissions:
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Setup Java JDK
|
||||
uses: actions/setup-java@v4
|
||||
@@ -28,10 +27,7 @@ jobs:
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Link with lld
|
||||
run: sh .github/workflows/scripts/use-lld.sh
|
||||
uses: actions/checkout@v3
|
||||
- name: Crowdin Sync
|
||||
shell: bash
|
||||
env:
|
||||
|
||||
@@ -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
|
||||
@@ -2,7 +2,6 @@ name: CI iOS (13)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
@@ -11,14 +10,9 @@ permissions:
|
||||
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
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
name: CI procbarrier tiers
|
||||
|
||||
# retro_procbarrier picks one of several ways to force a memory barrier
|
||||
# on every running thread, and which one depends on the OS and the CPU.
|
||||
# The Linux samples job only ever runs the one its runner picks
|
||||
# (membarrier). This runs every tier each platform has, on a multi-core
|
||||
# runner so the fence checks can actually catch a missing barrier, and
|
||||
# fails if a forced tier quietly fell back to another one.
|
||||
#
|
||||
# Linux x86_64 membarrier, page-flip, signal
|
||||
# Linux arm64 membarrier, signal
|
||||
# Windows x64 FlushProcessWriteBuffers, page-flip
|
||||
# Windows arm64 FlushProcessWriteBuffers
|
||||
# macOS arm64 signal
|
||||
# macOS x86_64 page-flip, signal
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'libretro-common/rthreads/**'
|
||||
- 'libretro-common/include/rthreads/**'
|
||||
- 'libretro-common/include/retro_atomic.h'
|
||||
- 'libretro-common/samples/rthreads/retro_procbarrier_test/**'
|
||||
- 'libretro-common/samples/rthreads/retro_asym_eventcount_test/**'
|
||||
- '.github/workflows/procbarrier-tiers.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'libretro-common/rthreads/**'
|
||||
- 'libretro-common/include/rthreads/**'
|
||||
- 'libretro-common/include/retro_atomic.h'
|
||||
- 'libretro-common/samples/rthreads/retro_procbarrier_test/**'
|
||||
- 'libretro-common/samples/rthreads/retro_asym_eventcount_test/**'
|
||||
- '.github/workflows/procbarrier-tiers.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:
|
||||
posix:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 15
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: linux-x86_64
|
||||
os: ubuntu-latest
|
||||
libs: -lpthread -lrt
|
||||
tiers: natural=membarrier membarrier=membarrier pageflip=page-flip signal=signal
|
||||
- name: linux-arm64
|
||||
os: ubuntu-24.04-arm
|
||||
libs: -lpthread -lrt
|
||||
tiers: natural=membarrier membarrier=membarrier signal=signal
|
||||
- name: macos-arm64
|
||||
os: macos-latest
|
||||
libs: -lpthread
|
||||
tiers: natural=signal signal=signal
|
||||
- name: macos-x86_64
|
||||
os: macos-15-intel
|
||||
libs: -lpthread
|
||||
tiers: natural=page-flip pageflip=page-flip signal=signal
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Build
|
||||
working-directory: libretro-common
|
||||
run: |
|
||||
set -e
|
||||
cc -std=gnu99 -O1 -g1 -Wall -DHAVE_THREADS -Iinclude \
|
||||
samples/rthreads/retro_procbarrier_test/retro_procbarrier_test.c \
|
||||
rthreads/retro_procbarrier.c rthreads/rthreads.c \
|
||||
-o retro_procbarrier_test ${{ matrix.libs }}
|
||||
cc -std=gnu99 -O1 -g1 -Wall -DHAVE_THREADS -Iinclude \
|
||||
samples/rthreads/retro_asym_eventcount_test/retro_asym_eventcount_test.c \
|
||||
rthreads/retro_asym_eventcount.c \
|
||||
rthreads/retro_procbarrier.c rthreads/rthreads.c \
|
||||
-o retro_asym_eventcount_test ${{ matrix.libs }}
|
||||
|
||||
- name: Run every tier
|
||||
working-directory: libretro-common
|
||||
env:
|
||||
REQUIRE_SMP: 1
|
||||
run: |
|
||||
bash samples/rthreads/retro_procbarrier_test/run_tiers.sh \
|
||||
./retro_procbarrier_test ./retro_asym_eventcount_test \
|
||||
${{ matrix.tiers }}
|
||||
|
||||
windows:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 15
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: windows-x64
|
||||
os: windows-2022
|
||||
vcvars: vcvars64.bat
|
||||
tiers: natural=FlushProcessWriteBuffers fpwb=FlushProcessWriteBuffers pageflip=page-flip
|
||||
- name: windows-arm64
|
||||
os: windows-11-arm
|
||||
vcvars: vcvarsarm64.bat
|
||||
tiers: natural=FlushProcessWriteBuffers fpwb=FlushProcessWriteBuffers
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Build
|
||||
shell: cmd
|
||||
working-directory: libretro-common
|
||||
run: |
|
||||
for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -property installationPath`) do set VSPATH=%%i
|
||||
if not defined VSPATH exit /b 1
|
||||
call "%VSPATH%\VC\Auxiliary\Build\${{ matrix.vcvars }}"
|
||||
cl /nologo /W3 /O1 /DHAVE_THREADS /Iinclude ^
|
||||
samples\rthreads\retro_procbarrier_test\retro_procbarrier_test.c ^
|
||||
rthreads\retro_procbarrier.c rthreads\rthreads.c ^
|
||||
/Fe:retro_procbarrier_test.exe
|
||||
if errorlevel 1 exit /b 1
|
||||
cl /nologo /W3 /O1 /DHAVE_THREADS /Iinclude ^
|
||||
samples\rthreads\retro_asym_eventcount_test\retro_asym_eventcount_test.c ^
|
||||
rthreads\retro_asym_eventcount.c ^
|
||||
rthreads\retro_procbarrier.c rthreads\rthreads.c ^
|
||||
/Fe:retro_asym_eventcount_test.exe
|
||||
if errorlevel 1 exit /b 1
|
||||
cl /nologo /W3 /we4013 /O1 /TC /Iinclude ^
|
||||
/DWINAPI_FAMILY=WINAPI_FAMILY_APP /D_WIN32_WINNT=0x0A00 ^
|
||||
/c rthreads\retro_procbarrier.c /Fo:retro_procbarrier_uwp.obj
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
- name: Run every tier
|
||||
shell: bash
|
||||
working-directory: libretro-common
|
||||
env:
|
||||
REQUIRE_SMP: 1
|
||||
run: |
|
||||
bash samples/rthreads/retro_procbarrier_test/run_tiers.sh \
|
||||
./retro_procbarrier_test.exe ./retro_asym_eventcount_test.exe \
|
||||
${{ matrix.tiers }}
|
||||
@@ -16,44 +16,16 @@ permissions:
|
||||
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-c89: # Smoketest build using most restrictive compiler and default options
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APT_PKGS: build-essential libxkbcommon-dev libx11-xcb-dev libvulkan-dev libpipewire-0.3-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
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Dependencies
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install 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
|
||||
- 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
|
||||
uses: actions/checkout@v3
|
||||
- name: Configure
|
||||
run: ./configure
|
||||
- name: Build
|
||||
@@ -61,4 +33,4 @@ jobs:
|
||||
- name: Build Debug
|
||||
run: |
|
||||
make clean # making sure we don't have leftovers from previous build
|
||||
CFLAGS="-O0 -g1" CXXFLAGS="-O0 -g1" make DEBUG=1 GL_DEBUG=1 C89_BUILD=1 info all
|
||||
make DEBUG=1 GL_DEBUG=1 C89_BUILD=1 info all
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/sh
|
||||
# The actions/cache key for apt-install.sh's cache: the packages asked
|
||||
# for and the runner image. Jobs asking for the same packages share an
|
||||
# entry, so the repository's cache holds each set once. A new runner
|
||||
# image makes a new entry, seeded through the prefix by the last one's;
|
||||
# apt-install.sh refreshes what no longer resolves.
|
||||
#
|
||||
# apt-cache-key.sh "PACKAGE..." (writes key= and prefix= to
|
||||
# GITHUB_OUTPUT)
|
||||
set -eu
|
||||
pkgs=$(printf '%s\n' $1 | sort -u | tr '\n' ' ')
|
||||
hash=$(printf '%s' "$pkgs" | sha256sum | cut -c1-16)
|
||||
prefix="apt-${ImageOS:-unknown}-$hash-"
|
||||
key="$prefix${ImageVersion:-unknown}"
|
||||
echo "key=$key" >> "$GITHUB_OUTPUT"
|
||||
echo "prefix=$prefix" >> "$GITHUB_OUTPUT"
|
||||
echo "apt cache key: $key"
|
||||
@@ -1,92 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Installs Ubuntu packages for a CI job, from the job's apt cache when it
|
||||
# has them.
|
||||
#
|
||||
# apt-install.sh [--no-install-recommends] PACKAGE...
|
||||
#
|
||||
# APT_CACHE (default ~/.apt-cache) holds the package lists and the .deb
|
||||
# files of the last install; actions/cache restores it before this runs
|
||||
# and saves it after (see apt-cache-key.sh for the key). With it warm the
|
||||
# packages install without the network: no apt-get update, no download,
|
||||
# only the unpacking. Cold, or when the cached lists no longer resolve
|
||||
# (a new runner image), the lists are refreshed and the packages fetched
|
||||
# into it, under a bound, with the main archive tried when the runner's
|
||||
# mirror stalls - and the cache is marked to be saved again.
|
||||
#
|
||||
# Packages already on the runner are left as they are, and when all of
|
||||
# them are, nothing is done at all.
|
||||
set -eu
|
||||
|
||||
opts=
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
--no-install-recommends) opts="$opts $1"; shift ;;
|
||||
-*) echo "apt-install.sh: unknown option $1"; exit 2 ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
[ $# -gt 0 ] || { echo "apt-install.sh: no packages"; exit 2; }
|
||||
pkgs="$*"
|
||||
cache=${APT_CACHE:-$HOME/.apt-cache}
|
||||
|
||||
if dpkg -s $pkgs >/dev/null 2>&1; then
|
||||
echo "apt-install.sh: all present on the runner; nothing to install."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$cache/archives/partial" "$cache/lists/partial"
|
||||
dirs="-o Dir::Cache::Archives=$cache/archives -o Dir::State::Lists=$cache/lists"
|
||||
net="-o Acquire::Retries=3 -o Acquire::http::Timeout=30"
|
||||
# No package may stop the install to ask a question
|
||||
apt="sudo env DEBIAN_FRONTEND=noninteractive apt-get"
|
||||
|
||||
saved() {
|
||||
# A later plain apt-get install in the job resolves from the same
|
||||
# lists, and the cache action runs as the runner's user
|
||||
sudo cp -a "$cache/lists/." /var/lib/apt/lists/
|
||||
sudo rm -f /var/lib/apt/lists/.complete
|
||||
sudo chown -R "$(id -u):$(id -g)" "$cache"
|
||||
}
|
||||
|
||||
# Warm: everything from the cache
|
||||
if [ -f "$cache/lists/.complete" ] \
|
||||
&& $apt install -y --no-download $dirs $opts $pkgs; then
|
||||
echo "apt-install.sh: installed from the cache."
|
||||
saved
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "apt-install.sh: refreshing the cache."
|
||||
rm -f "$cache/lists/.complete"
|
||||
upd="$net -o Acquire::Languages=none
|
||||
-o Acquire::IndexTargets::deb::CNF::DefaultEnabled=false"
|
||||
for i in 1 2 3; do
|
||||
sudo timeout 120 apt-get update -y $dirs $upd && break
|
||||
[ $i = 3 ] && exit 1
|
||||
echo "apt-get update failed (attempt $i); retrying in 10s"
|
||||
sleep 10
|
||||
done
|
||||
|
||||
# Fetch first, under a bound: a download is safe to stop and resumes, an
|
||||
# install is not. A mirror that stalls is left for the main archive.
|
||||
for i in 1 2 3; do
|
||||
sudo timeout 240 apt-get install -y --download-only $dirs $net $opts $pkgs \
|
||||
&& break
|
||||
[ $i = 3 ] && exit 1
|
||||
echo "package download failed or stalled (attempt $i); retrying from archive.ubuntu.com"
|
||||
for f in /etc/apt/sources.list /etc/apt/sources.list.d/*; do
|
||||
[ -f "$f" ] || continue
|
||||
sudo sed -i -e 's#mirror+file:/etc/apt/apt-mirrors.txt#http://archive.ubuntu.com/ubuntu/#g' \
|
||||
-e 's#http://azure\.archive\.ubuntu\.com/ubuntu#http://archive.ubuntu.com/ubuntu#g' "$f"
|
||||
done
|
||||
sudo timeout 120 apt-get update -y $dirs $upd || true
|
||||
done
|
||||
|
||||
$apt install -y $dirs $net $opts $pkgs
|
||||
# Only what this job installs is kept: the lists, and its own packages
|
||||
sudo touch "$cache/lists/.complete"
|
||||
sudo rm -rf "$cache/archives/partial" "$cache/lists/partial"
|
||||
saved
|
||||
if [ -n "${GITHUB_ENV:-}" ]; then
|
||||
echo "APT_CACHE_SAVE=1" >> "$GITHUB_ENV"
|
||||
fi
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Runs make with its C and C++ compilers wrapped in ccache, for the
|
||||
# platform Makefiles that set CC and CXX themselves. The compilers are
|
||||
# read from the same Makefile and variables, so the wrapped build is
|
||||
# the build CI ran before.
|
||||
# bash .github/workflows/scripts/ccache-make.sh -f Makefile.libnx -j4 all
|
||||
set -euo pipefail
|
||||
if ! command -v ccache > /dev/null; then
|
||||
echo "ccache-make: no ccache, building without it"
|
||||
exec make "$@"
|
||||
fi
|
||||
args=("$@")
|
||||
# The options and variable assignments, without the targets.
|
||||
opts=()
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-f|-C|-I|-o|-W) opts+=("$1" "$2"); shift ;;
|
||||
-*|*=*) opts+=("$1") ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
print() {
|
||||
make "${opts[@]}" --no-print-directory \
|
||||
--eval "ra-print: ; @echo \$($1)" ra-print | tail -n 1
|
||||
}
|
||||
cc=$(print CC)
|
||||
cxx=$(print CXX)
|
||||
if [ -z "$cc" ] || [ -z "$cxx" ]; then
|
||||
echo "ccache-make: could not read CC and CXX" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "ccache-make: CC=$cc CXX=$cxx"
|
||||
exec make "${args[@]}" CC="ccache $cc" CXX="ccache $cxx"
|
||||
File diff suppressed because it is too large.
Load diff
Loaded 100 of 7580 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user