Fix Text effect font-cache race to allow deterministic renders (#6959) #3957
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Windows xLights CI | |
| on: | |
| push: | |
| branches: [ master ] | |
| paths-ignore: | |
| - '.github/workflows/*.yml' | |
| - '.github/ISSUE_TEMPLATE/*.md' | |
| - 'build_scripts/**' | |
| - 'ci_scripts/**' | |
| - 'cmudict/**' | |
| - 'documentation/**' | |
| - 'download/**' | |
| - 'resources/**' | |
| - 'lib/windows/**' | |
| - 'lib/windows64/**' | |
| - 'songs/**' | |
| - 'TipOfDay/**' | |
| - 'xlDo/**' | |
| - '*.md' | |
| - '*.yml' | |
| - '*.txt' | |
| - '*.docx' | |
| - 'README.*' | |
| pull_request: | |
| branches: [ master ] | |
| paths-ignore: | |
| - '.github/workflows/*.yml' | |
| - '.github/ISSUE_TEMPLATE/*.md' | |
| - 'build_scripts/**' | |
| - 'ci_scripts/**' | |
| - 'cmudict/**' | |
| - 'documentation/**' | |
| - 'download/**' | |
| - 'resources/**' | |
| - 'songs/**' | |
| - 'TipOfDay/**' | |
| - 'xlDo/**' | |
| - '*.md' | |
| - '*.yml' | |
| - '*.txt' | |
| - '*.docx' | |
| - 'README.*' | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| runs-on: windows-2022 | |
| env: | |
| WX_VERSION: xlights_2026.13 | |
| SCCACHE_GHA_ENABLED: "true" | |
| steps: | |
| - name: Checkout xLights | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: 'true' | |
| - name: Setup MSVC dev environment | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| with: | |
| arch: x64 | |
| - name: install ISPC | |
| uses: ispc/install-ispc-action@main | |
| with: | |
| version: 1.31.0 | |
| # glslc (Vulkan SDK Bin) compiles the .comp compute kernels to SPIR-V | |
| # headers via the Xlights.vcxproj CompileVulkanShaders pre-build target | |
| # (x64). The action exports VULKAN_SDK so that target's PowerShell script | |
| # finds glslc; without it the msbuild step fails at the pre-build event. | |
| - name: Install Vulkan SDK | |
| uses: jakoch/install-vulkan-sdk-action@v1 | |
| with: | |
| install_runtime: false | |
| cache: true | |
| - name: Setup sccache | |
| uses: mozilla-actions/sccache-action@v0.0.9 | |
| - name: Configure sccache | |
| shell: bash | |
| run: | | |
| # If the GHA cache backend is unreachable (transient outage, auth | |
| # hiccup, etc.), fall back to local-disk caching instead of failing | |
| # the entire build. Local cache won't persist between runs but at | |
| # least compiles succeed. | |
| if ! sccache --zero-stats; then | |
| echo "::warning::sccache GHA backend unavailable; falling back to local disk" | |
| echo "SCCACHE_GHA_ENABLED=" >> "$GITHUB_ENV" | |
| sccache --stop-server 2>/dev/null || true | |
| fi | |
| - name: Create sccache-cl wrapper | |
| shell: pwsh | |
| run: | | |
| $wrapperDir = "${{ runner.temp }}\sccache-wrapper" | |
| New-Item -ItemType Directory -Force -Path $wrapperDir | Out-Null | |
| # MSBuild invokes CLToolExe with cl-style args. The wrapper prepends | |
| # cl.exe as the first positional arg so sccache knows which compiler | |
| # to wrap. MSBuild's MultiToolTask drops the wrapped compiler's own | |
| # stdout/stderr, so a bad compile would otherwise show up as just | |
| # "cl.bat exited with code 2" with no diagnostic. Capture all of | |
| # cl.exe's output to a per-TU log file and re-emit it from the | |
| # wrapper's own streams (type) so the actual error text — and the | |
| # source file that broke — always reach the build log. | |
| # | |
| # The log name is derived from the source basename (the last arg), | |
| # NOT from %RANDOM%: MultiToolTask spawns many cl.bat at once and | |
| # %RANDOM% is seeded from the clock, so same-tick launches collide on | |
| # one filename. A locked-file redirect then aborts the line before | |
| # sccache runs and the .obj is never produced. Source basenames are | |
| # unique here (all objs share one flat /Fo dir), so this can't race. | |
| # Plain setlocal (no delayed expansion) avoids corrupting any arg | |
| # that contains '!'. | |
| @' | |
| @echo off | |
| setlocal | |
| :findsrc | |
| set "SRC=%~1" | |
| shift | |
| if not "%~1"=="" goto findsrc | |
| for %%F in ("%SRC%") do set "BASE=%%~nF" | |
| if not defined BASE set "BASE=%RANDOM%" | |
| set "CLLOG=%TEMP%\sccache-cl-%BASE%.log" | |
| sccache.exe cl.exe %* > "%CLLOG%" 2>&1 | |
| set "RC=%ERRORLEVEL%" | |
| type "%CLLOG%" | |
| if not "%RC%"=="0" ( | |
| echo cl.bat FAILED ^(rc=%RC%^) for %SRC% 1>&2 | |
| type "%CLLOG%" 1>&2 | |
| ) | |
| del "%CLLOG%" 2>nul | |
| exit /b %RC% | |
| '@ | Set-Content -Encoding Ascii "$wrapperDir\cl.bat" | |
| echo "SCCACHE_WRAPPER_DIR=$wrapperDir" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 | |
| - name: Write sccache MSBuild overrides | |
| shell: pwsh | |
| working-directory: xLights | |
| run: | | |
| @' | |
| <Project> | |
| <PropertyGroup> | |
| <ScanSourceForModuleDependencies>false</ScanSourceForModuleDependencies> | |
| <BuildStlModules>false</BuildStlModules> | |
| </PropertyGroup> | |
| <ItemDefinitionGroup> | |
| <ClCompile> | |
| <DebugInformationFormat>OldStyle</DebugInformationFormat> | |
| <MultiProcessorCompilation>false</MultiProcessorCompilation> | |
| <ScanSourceForModuleDependencies>false</ScanSourceForModuleDependencies> | |
| </ClCompile> | |
| </ItemDefinitionGroup> | |
| </Project> | |
| '@ | Set-Content -Encoding UTF8 Directory.Build.targets | |
| # Clone wxWidgets inside the workspace so actions/cache can reach it | |
| # (actions/cache rejects paths with '..'). A junction at ..\wxWidgets\ | |
| # keeps the xLights vcxproj's sibling-directory expectation working. | |
| - name: Download wxWidgets | |
| shell: pwsh | |
| run: | | |
| git clone --depth=1 --shallow-submodules --recurse-submodules ` | |
| -b $env:WX_VERSION https://github.com/xLightsSequencer/wxWidgets wxWidgets | |
| New-Item -ItemType Junction -Path "..\wxWidgets" ` | |
| -Target "$((Resolve-Path wxWidgets).Path)" | Out-Null | |
| - name: Cache wxWidgets | |
| id: cache-wx | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| wxWidgets/lib/vc_x64_lib | |
| wxWidgets/include | |
| key: ${{ runner.os }}-wx-${{ env.WX_VERSION }} | |
| - name: Build wxWidgets | |
| if: steps.cache-wx.outputs.cache-hit != 'true' | |
| working-directory: wxWidgets | |
| run: msbuild /m .\build\msw\wx_vc17.sln /p:Configuration="Release" /p:Platform="x64" | |
| - name: xLights | |
| working-directory: xLights | |
| shell: pwsh | |
| run: | | |
| Write-Host "cl.exe: $((Get-Command cl.exe -ErrorAction SilentlyContinue).Source)" | |
| Write-Host "sccache: $((Get-Command sccache.exe -ErrorAction SilentlyContinue).Source)" | |
| Write-Host "wrapper: $env:SCCACHE_WRAPPER_DIR\cl.bat" | |
| msbuild /m:10 xLights.sln ` | |
| /p:Configuration="Release" /p:Platform="x64" ` | |
| /p:CLToolExe=cl.bat /p:CLToolPath="$env:SCCACHE_WRAPPER_DIR" ` | |
| /p:TrackFileAccess=false ` | |
| /p:UseMultiToolTask=true | |
| - name: sccache stats | |
| run: sccache --show-stats | |
| - name: Upload xLights Exe | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: xLights_Exe | |
| path: 'xLights\x64\Release\**' | |
| retention-days: 7 |