Skip to content

Commit 040e1cb

Browse files
alex-spataruclaude
andcommitted
build(windows): fix clang-cl side-by-side manifest; use VS clang-cl
Root cause of the Windows "side-by-side configuration is incorrect" startup failure: lld-link embeds an application manifest whose requestedExecutionLevel carries a namespace-prefixed ms_asmv1:level attribute, which the Windows SxS parser rejects (it requires an unprefixed level), so activation-context generation fails before main(). Confirmed via the Application event log. - Add app/deploy/windows/serial-studio.manifest and a POST_BUILD mt.exe step (clang-cl only, before signing) that overwrites the malformed manifest with a correct one. Verified locally: the patched binary starts. - Prefer the VS-bundled clang-cl (matched to the MSVC toolset and Qt's msvc2022_64) over the runner's standalone LLVM. Keep windows-latest, since windows-2022 lacks a clang toolchain. - ci: add a Linux arm64 entry to the test matrix (os field shares the Linux setup steps), so the arm64 build is verified instead of build->publish only. - ci: drop the temporary Windows diagnostics + instrumented-exe upload and the windeployqt attempts now that the real cause is fixed. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
1 parent 6a67e31 commit 040e1cb

3 files changed

Lines changed: 54 additions & 39 deletions

File tree

.github/workflows/ci.yml

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,13 @@ jobs:
11071107
with:
11081108
arch: x64
11091109

1110+
- name: '🛠 Use Microsoft (VS-bundled) clang-cl'
1111+
run: |
1112+
$clangDir = Join-Path $env:VCINSTALLDIR 'Tools\Llvm\x64\bin'
1113+
if (-not (Test-Path (Join-Path $clangDir 'clang-cl.exe'))) { throw "VS clang-cl not found at $clangDir" }
1114+
Add-Content -Path $env:GITHUB_PATH -Value $clangDir
1115+
& (Join-Path $clangDir 'clang-cl.exe') --version
1116+
11101117
- name: '⚙️ Download prebuilt gRPC'
11111118
run: |
11121119
gh release download v${{env.GRPC_VERSION}} `
@@ -1139,36 +1146,8 @@ jobs:
11391146
- name: '🚧 Build application (instrumented)'
11401147
run: cmake --build build --config Release -j $env:NUMBER_OF_PROCESSORS
11411148

1142-
# Diagnostics for the side-by-side startup failure: which clang-cl was picked (the runner has
1143-
# several LLVM installs) and the exe's direct DLL imports. The exe + its build-tree DLLs are
1144-
# uploaded as a workflow artifact (not a release asset) for local dependency/sxstrace analysis.
1145-
- name: '🔬 Inspect instrumented binary (debug)'
1146-
continue-on-error: true
1147-
run: |
1148-
Write-Host "clang-cl resolved to: $((Get-Command clang-cl).Source)"
1149-
clang-cl --version
1150-
Write-Host "--- dumpbin /dependents ---"
1151-
dumpbin /dependents "build/app/${{env.EXECUTABLE}}.exe"
1152-
Write-Host "--- embedded manifest (side-by-side dependencies) ---"
1153-
mt.exe -nologo -inputresource:"build/app/${{env.EXECUTABLE}}.exe;#1" -out:app.manifest
1154-
if (Test-Path app.manifest) { Get-Content app.manifest } else { Write-Host "(no embedded manifest)" }
1155-
1156-
- name: '📤 Upload instrumented exe (debug, not released)'
1157-
uses: actions/upload-artifact@v5
1158-
with:
1159-
name: windows-instrumented-debug
1160-
retention-days: 3
1161-
path: |
1162-
build/app/${{env.EXECUTABLE}}.exe
1163-
build/app/*.dll
1164-
1165-
# The GUI-subsystem exe can't write to the console, so the benchmark reports into benchmark.txt
1166-
# and hard-exits after flushing it + the PGO profile (skipping a teardown that hangs on Windows).
1167-
# windeployqt bundles Qt + the MSVC runtime next to the bare build-tree exe so it actually starts
1168-
# (fixes the side-by-side error); the WaitForExit timeout is a runaway guard.
11691149
- name: '🏋️ PGO training run (hotpath)'
11701150
run: |
1171-
windeployqt --compiler-runtime --no-translations "build/app/${{env.EXECUTABLE}}.exe"
11721151
$p = Start-Process -FilePath "build/app/${{env.EXECUTABLE}}.exe" `
11731152
-ArgumentList '--headless','--benchmark-hotpath','--min-fps','1' `
11741153
-WorkingDirectory $PWD -PassThru -NoNewWindow
@@ -1197,11 +1176,8 @@ jobs:
11971176
- name: '🚧 Build application (PGO optimized)'
11981177
run: cmake --build build --config Release -j $env:NUMBER_OF_PROCESSORS
11991178

1200-
# Gate on HOTPATH_PASS in benchmark.txt (written before the hard exit) rather than the process
1201-
# exit code, so a residual teardown hang that the timeout kills still yields a verdict.
12021179
- name: '🚦 Hotpath throughput gate (256 kHz)'
12031180
run: |
1204-
windeployqt --compiler-runtime --no-translations "build/app/${{env.EXECUTABLE}}.exe"
12051181
$p = Start-Process -FilePath "build/app/${{env.EXECUTABLE}}.exe" `
12061182
-ArgumentList '--headless','--benchmark-hotpath','--min-fps','256000' `
12071183
-WorkingDirectory $PWD -PassThru -NoNewWindow
@@ -1374,24 +1350,33 @@ jobs:
13741350

13751351
test:
13761352
name: '🧪 Test (${{ matrix.label }})'
1377-
needs: [build-linux, build-macos, build-windows]
1353+
needs: [build-linux, build-linux-arm64, build-macos, build-windows]
13781354
permissions:
13791355
contents: read
13801356
strategy:
13811357
fail-fast: false
13821358
matrix:
13831359
include:
13841360
- label: Linux
1361+
os: linux
13851362
runs-on: ubuntu-24.04
13861363
asset: Linux-x64.AppImage
13871364
broker: true
13881365
marker_expr: "not destructive and not dos and not audio"
1366+
- label: Linux-arm64
1367+
os: linux
1368+
runs-on: ubuntu-24.04-arm
1369+
asset: Linux-arm64.AppImage
1370+
broker: true
1371+
marker_expr: "not destructive and not dos and not audio"
13891372
- label: macOS
1373+
os: macos
13901374
runs-on: macos-latest
13911375
asset: macOS.dmg
13921376
broker: true
13931377
marker_expr: "not destructive and not dos and not audio"
13941378
- label: Windows
1379+
os: windows
13951380
runs-on: windows-latest
13961381
asset: Windows-Portable
13971382
broker: false
@@ -1422,7 +1407,7 @@ jobs:
14221407
name: ${{env.ARTIFACT}}
14231408

14241409
- name: '📦 Prepare binary (Linux AppImage)'
1425-
if: matrix.label == 'Linux'
1410+
if: matrix.os == 'linux'
14261411
run: |
14271412
sudo apt-get update
14281413
sudo apt-get install -y libegl1 libgl1 libopengl0 libasound2-dev fontconfig \
@@ -1432,38 +1417,38 @@ jobs:
14321417
echo "SS_RUN=$PWD/squashfs-root/AppRun" >> "$GITHUB_ENV"
14331418
14341419
- name: '📦 Prepare binary (macOS .app)'
1435-
if: matrix.label == 'macOS'
1420+
if: matrix.os == 'macos'
14361421
run: |
14371422
hdiutil attach "$ARTIFACT" -nobrowse -mountpoint /tmp/ssdmg
14381423
cp -R "/tmp/ssdmg/${{env.APPLICATION}}.app" .
14391424
hdiutil detach /tmp/ssdmg
14401425
echo "SS_RUN=$PWD/${{env.APPLICATION}}.app/Contents/MacOS/${{env.EXECUTABLE}}" >> "$GITHUB_ENV"
14411426
14421427
- name: '📦 Prepare binary (Windows portable)'
1443-
if: matrix.label == 'Windows'
1428+
if: matrix.os == 'windows'
14441429
run: |
14451430
7z x "${ARTIFACT}.zip" -oapp_win >/dev/null
14461431
EXE=$(find app_win -name "${{env.EXECUTABLE}}.exe" | head -1)
14471432
echo "SS_RUN=$PWD/$EXE" >> "$GITHUB_ENV"
14481433
14491434
- name: '🦟 Start Mosquitto (Linux)'
1450-
if: matrix.label == 'Linux'
1435+
if: matrix.os == 'linux'
14511436
run: |
14521437
sudo systemctl stop mosquitto || true
14531438
printf 'listener 1883 127.0.0.1\nallow_anonymous true\npersistence false\n' > /tmp/mosq.conf
14541439
mosquitto -d -c /tmp/mosq.conf
14551440
for i in $(seq 1 15); do (echo > /dev/tcp/127.0.0.1/1883) >/dev/null 2>&1 && break; sleep 1; done
14561441
14571442
- name: '🦟 Start Mosquitto (macOS)'
1458-
if: matrix.label == 'macOS'
1443+
if: matrix.os == 'macos'
14591444
run: |
14601445
brew install mosquitto
14611446
printf 'listener 1883 127.0.0.1\nallow_anonymous true\npersistence false\n' > /tmp/mosq.conf
14621447
"$(brew --prefix mosquitto)/sbin/mosquitto" -d -c /tmp/mosq.conf
14631448
for i in $(seq 1 15); do (echo > /dev/tcp/127.0.0.1/1883) >/dev/null 2>&1 && break; sleep 1; done
14641449
14651450
- name: '🎙 Set up ALSA loopback (Linux)'
1466-
if: matrix.label == 'Linux'
1451+
if: matrix.os == 'linux'
14671452
run: |
14681453
sudo apt-get install -y "linux-modules-extra-$(uname -r)" || true
14691454
sudo modprobe snd-aloop || true
@@ -1493,7 +1478,7 @@ jobs:
14931478
-v --tb=short --timeout=60 --junit-xml=test-results.xml
14941479
14951480
- name: '🎙 Run audio loopback tests (Linux, non-blocking)'
1496-
if: matrix.label == 'Linux'
1481+
if: matrix.os == 'linux'
14971482
continue-on-error: true
14981483
env:
14991484
QT_QPA_PLATFORM: offscreen

app/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,15 @@ target_link_libraries(
10031003
target_link_openssl(${PROJECT_EXECUTABLE})
10041004
target_link_mimalloc(${PROJECT_EXECUTABLE})
10051005

1006+
if(WIN32 AND MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
1007+
add_custom_command(TARGET ${PROJECT_EXECUTABLE} POST_BUILD
1008+
COMMAND mt.exe -nologo
1009+
-manifest "${CMAKE_CURRENT_SOURCE_DIR}/deploy/windows/serial-studio.manifest"
1010+
"-outputresource:$<TARGET_FILE:${PROJECT_EXECUTABLE}>;#1"
1011+
COMMENT "Fixing clang-cl application manifest (side-by-side)"
1012+
VERBATIM)
1013+
endif()
1014+
10061015
if(BUILD_COMMERCIAL)
10071016
target_link_libraries(${PROJECT_EXECUTABLE} PUBLIC usb-1.0)
10081017
target_link_libraries(${PROJECT_EXECUTABLE} PUBLIC hidapi::hidapi)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
3+
<assemblyIdentity type="win32" name="com.serial-studio.Serial-Studio-Pro" version="1.0.0.0" processorArchitecture="*"/>
4+
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
5+
<security>
6+
<requestedPrivileges>
7+
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
8+
</requestedPrivileges>
9+
</security>
10+
</trustInfo>
11+
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
12+
<application>
13+
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
14+
</application>
15+
</compatibility>
16+
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
17+
<asmv3:windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
18+
<ws2:longPathAware>true</ws2:longPathAware>
19+
</asmv3:windowsSettings>
20+
</asmv3:application>
21+
</assembly>

0 commit comments

Comments
 (0)