Skip to content

Commit 3b771b2

Browse files
Zero warnings: dish-windows (#89)
## Summary The dish-windows part of the fleet-wide zero-warnings, zero-suppressions pass. Every warning the three CI lanes printed on `main` (Windows CI, CodeQL, Security) is fixed at its cause, every first-party `(void)` discard and `NOLINT` is gone, the clang-tidy sweep now blocks, and the tests build under `/WX` like the rest of the code. ## What was fixed, by category **Compiler warnings (214 lines on the last `main` run of Windows CI, 9 in CodeQL)** - `C5287` x 18 (9 per configuration): the cgutman ENet fork ORs an `ENetProtocolCommand` with an `ENetProtocolFlag` in nine places. `cmake/enet-msvc-c5287.patch` adds the `enet_uint8` casts the compiler asks for (the assigned field is an `enet_uint8` already, so the runtime bytes do not change) and `cmake/PatchEnet.cmake` applies it as the FetchContent patch step, recognising an already patched tree because ExternalProject re-runs the step on every update. Documented in `THIRD_PARTY.md`; the `.patch` is pinned to LF in `.gitattributes`. - `D9025` x 181 ("overriding '/Zi' with '/Z7'", every TU of `dish_core` and `Dish` in Debug): the sentry block's raw `/Z7` sat on top of the `/Zi` CMake bakes into the Debug flags. With CMake 3.25 (CMP0141) the format is a target property, so `MSVC_DEBUG_INFORMATION_FORMAT=Embedded` replaces the flag instead of overriding it. Same flags as before on every target and configuration. The CMake floor moves from 3.21 to 3.25 (CMakeLists, presets, README). - `C4244` x 4: the two ranged-for loops over brace lists in the tests iterate a `std::array` of the element type. **clang-tidy findings (20 on `main`, plus 1 that clang-tidy 22 adds)** - `modernize-return-braced-init-list` x 7, `bugprone-misplaced-widening-cast` x 5, `cert-err34-c` x 2 (`std::from_chars` replaces `atoi`), `bugprone-exception-escape` x 3 and `performance-unnecessary-copy-initialization` x 1 in `MoonlightSession` (the lambdas capture non-const movable copies through init-captures, so the closures' implicit special members move instead of copy), `readability-inconsistent-declaration-parameter-name` x 1, `performance-no-automatic-move` x 1, `bugprone-throwing-static-initialization` x 1 (`kFallbackUniqueId` is a `constexpr QStringView`). - `main.cpp`: the two pre-logger stderr lines go through `QTextStream(stderr)`, the same bytes `fprintf` wrote, with no result to discard (`cert-err33-c`) and no iostream failure path for `bugprone-exception-escape` to report on `main`. **Discards and suppressions removed (first-party)** - 32 `(void)` discards: replaced by logging where the result carries information (`dish.update.staging`, `dish.update.download`, `dish.update`), by a returned value (`publishMotion`), by unnamed parameters (`UsbDeviceGateway`), and in tests by assertions where the value is known or plain calls where only the absence of a throw is under test. - 4 `NOLINT`s: the two empty catch blocks in the audio engines' destructors now log through `dish.audio`; `SDLGamepadBridge.h` includes `SDL_events.h` instead of forward-declaring SDL's reserved-identifier struct tags. - `_CRT_SECURE_NO_WARNINGS` and `_WINSOCK_DEPRECATED_NO_WARNINGS` dropped from `dish_warnings`: both configurations build clean without them. - `-Wno-unused-command-line-argument` dropped from the tidy script: the sweep reads a copy of the compile database with `/Zc:preprocessor` removed (clang-cl's preprocessor conforms already, so the flag is meaningless to it and its driver reported it as unused). Every other MSVC flag clang-cl understands, so nothing is silenced. - `/wd4702` on the whole `Dish` target narrowed to the qmlcachegen-generated units it exists for (see "Left in place" below). **Gates** - `scripts/check-tidy.ps1` passes `--warnings-as-errors='*'` on the command line, the way `linux-ci.yml` gates its sweep, so findings fail CI while the fleet-canonical `.clang-tidy` (`WarningsAsErrors: ''`) stays unforked. The script takes `-Files`, and the pre-commit hook runs it over the staged sources in CI's file set, so a finding stops the commit before it would stop the PR. - Tests link `dish_strict` (`/WX`); Catch2's FetchContent declaration takes `SYSTEM` (CMake 3.25) so its headers are external includes under `-external:W0`. - `codeql.yml`: the analyze step loses `continue-on-error` and `upload: failure-only`, as its own comment said to do once the repository went public (code scanning is active, 0 open alerts). `CODEQL_OVERLAY_DATABASE_MODE=none` declares the mode the action fell back to on every run after warning that a traced build cannot use overlay analysis. - `_security.yml`: dependency review loses its `continue-on-error` for the same reason. That exposed the truth: the action fails with "Dependency review is not supported on this repository. Please ensure that Dependency graph is enabled", so it had never reviewed anything here. `security.yml` now passes `dependency_review_enabled: false` with the precondition spelled out (see below). `CONTRIBUTING.md`, `SECURITY.md` and the PR template follow. - `lukka/run-vcpkg` v11.5 -> v11.6 in all three workflows: it runs on Node 24, which ends the "Node.js 20 is deprecated" notice for that action. Nothing in its behaviour changed between the tags. ## qmllint: the last lowered level, closed The one item this pass had left open. `scripts/check-qml.ps1` ran `qmllint` with `--unqualified info` because `App` was a runtime context property, so all 386 `App.x` reads in the QML tree came back as `Unqualified access`, 278 diagnostics, and the category could not gate anything. That level is back at its default, and `qmllint` over all 68 tracked QML files now reports nothing, in any category, at every category's default level. No `// qmllint disable`, no pragma, no other level touched. `App` is a `Dish.Chrome` singleton now, spelled exactly as before in QML. `AppViewModel` and the two role models stay in `dish_core`, which links no Qml so the tests can keep exercising them without the Quick stack, so they cannot carry `QML_ELEMENT` themselves; `src/qml/chrome/ForeignTypes.h` declares their QML identities from the `Dish` target with `QML_FOREIGN` instead, and `qt_extract_metatypes(dish_core)` is what lets `qmltyperegistrar` read their meta-objects and expand those declarations into the module's generated `qmltypes`. That header is the whole of the new C++: 67 lines, no logic. Runtime behaviour is unchanged. `App` is registered by instance in `QmlEntryPoint` exactly as `ChromeBridge`, `Theme` and `Tokens` already are, for the reason those three already document: this target's LTCG strips the generated `QQmlModuleRegistration` initializer, so a declarative-only name would never reach the engine. The foreign declaration's `create()` returns that same instance, so it cannot matter which of the two registrations the engine resolves, and an explicit `CppOwnership` keeps the engine from deleting a stack object. One QML file changed, by one line: `shared/BindingDraft.qml` reads `App` and was the only one of the 68 not already importing `Dish.Chrome` for `Theme` and `Tokens`. Verified past the linter, because the registration-stripping risk lives in the shipping configuration: the Debug tree's 2229 tests pass, and the Release build with LTCG, staged through `scripts/stage-bundle.ps1` and launched from a scratch directory by `scripts/test-portable-bundle.ps1`, stays up with an otherwise empty stderr. A singleton that failed to resolve would print a binding error for every page that reads it, and that gate reads stderr. `docs/QML_CONTRACT.md`, `docs/QML_UI_KIT.md` and `CONTRIBUTING.md` no longer describe a gap that is not there. ## Left in place, with the reason - `/wd4702` on the qmlcachegen-generated `*_qml.cpp` units only. MSVC's optimizer reports unreachable code inside Qt's own `QJSEngine` and `QVariant` templates (their `if constexpr` early returns) when the AOT-compiled QML instantiates them; it fires in Release with and without LTCG, and Qt 6.9 still has the pattern. `C4702` is a back-end warning, which `/external:W0` cannot reach: Microsoft documents this under `/external`, "Limitations", and names `/wd47XX` as the remedy. The only alternatives change the shipped binary (`NO_CACHEGEN`, or `/Od` for those units), so the option stays, scoped to the generated files; `main.cpp`, the crash handler and the bridges keep `C4702` live. - Dependency review: it needs the repository's Dependency graph, a setting under Settings, Code security that I could not change (the permission was denied, rightly). Enable it, flip `dependency_review_enabled` to `true` in `security.yml`, and the job blocks from then on. - The `::warning::` the OSV-Scanner job prints on every run ("found no package sources"): OSV-Scanner has no support for `vcpkg.json`, so the job scans nothing in this repository; the shared security workflow deliberately reports that rather than hiding it. Worth a fleet-level decision (feed it an SBOM, or skip the job here), not a unilateral change in this PR. - `ilammy/msvc-dev-cmd` still declares Node 20 (no release targets Node 24), so its half of the deprecation notice remains; replacing the action with a vswhere/vcvars import step is out of scope here. - The release lane's best-effort `continue-on-error` steps (Sentry symbol upload, Sentry release, Grype SARIF upload) are deliberate release semantics and were not touched. - `N warnings generated.` lines in the clang-tidy step's log are clang's count of findings in Qt's and the STL's headers, which the header filter drops; they are not findings. ## Judgment calls recorded - CMake floor 3.21 -> 3.25 (November 2022): needed for CMP0141 and FetchContent `SYSTEM`; the CI image and the documented local setup are far newer. - `dish.audio` (not `dish.audio.teardown`) for the new logging category, following the `dish.<area>` convention of the existing categories. - The RTSP `CSeq` parse accepts only a whole-value integer; `atoi` used to return the digit prefix of a malformed value. Nothing but the tests reads the field. - The pre-commit hook now blocks on tidy findings (it used to be advisory), matching the CI gate; it only ever ran when `core.hooksPath` points at `.githooks`. ## Verification - `cmake --preset debug` (fresh tree) + `cmake --build --parallel 8`: 637 steps, 0 warnings. `ctest --parallel --output-on-failure`: 2227/2227 passed. - `cmake --preset release` from a wiped `build-release` (fresh ENet population, patch applied: 2 + 6 + 1 casts in `host.c`, `peer.c`, `protocol.c`) + build of `Dish` and `dish_setup_image`: 346 steps, 0 warnings, LTCG link included. The already populated debug tree was patched in place on the next reconfigure, and the reverse check leaves a patched tree alone. - `scripts/check-tidy.ps1`: `clang-tidy: OK (100 files)`, 0 findings, under the gate. - `scripts/check-format.ps1` (clang-format 22.1.4): OK (495 files). - `scripts/check-qml.ps1`: OK (68 files). - No em-dashes in any added text; every diff is line-level (CRLF files kept their endings). ## Review follow-ups (three commits on the same branch) - `tests/test_moonlight_rtsp.cpp`: two cases pin the edges that `std::from_chars` changed. A trimmed, whole-integer `CSeq` still counts (padding, tabs, `INT_MAX`, a negative); a digit prefix with trailing text, a leading `+`, an empty value or an overflow leaves the default, where `atoi` answered the prefix or had no defined answer. `server_port` reads the digit run after the key whatever follows it (`\r`, `;`, letters); a space or sign directly after the key, or a run that does not fit an `int`, is no port. - `CMakeLists.txt` + `CONTRIBUTING.md`: the D9025 fix only held for a fresh tree. CMake fills `CMAKE_<LANG>_FLAGS_<CONFIG>` once, so a `build/` configured before the 3.25 floor keeps `/Zi` in its cached Debug flags, and on that tree the Embedded property put `/Z7` on top of it again (verified in place: 3.21-configured tree, reconfigured after the bump, D9025 back). The configure now refuses such a tree with the one-time remedy, delete its `CMakeCache.txt`. A fresh tree passes in Debug, Release and RelWithDebInfo; CI trees are fresh on every run (only the vcpkg binary cache persists), so nothing changes there. - `tests/CrtAssertToStderr.cpp`: the last `[[maybe_unused]]` in first-party code is gone; the hook object exists for its constructor, which no compiler here warns about. Re-verified on the final tip: Debug build 0 warnings, `ctest` 2229/2229 (2227 + the two new cases), `check-tidy.ps1` OK (100 files, and the gate was shown to fail on a planted finding), `check-format.ps1` OK (495), `check-qml.ps1` OK (68). --------- Co-authored-by: Emir Hasanbegovic <1190336+emir-hasanbegovic@users.noreply.github.com>
1 parent 7cb8c2c commit 3b771b2

56 files changed

Lines changed: 664 additions & 227 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.gitattributes‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*.sh text eol=lf
1616
*.py text eol=lf
1717

18+
# Fed to `git apply` by cmake/PatchEnet.cmake; one byte-exact form everywhere.
19+
*.patch text eol=lf
20+
1821
# cmd.exe mis-parses `goto` / `call` labels in an LF-only batch file.
1922
# PowerShell tolerates LF, but every Windows editor and signer expects CRLF.
2023
*.bat text eol=crlf

‎.githooks/pre-commit‎

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/env bash
22
# Reformats staged C/C++ sources in place with clang-format and re-stages
3-
# them, then runs clang-tidy advisory-only. Skips either tool if it is not
4-
# installed; CI enforces both in strict mode. Runs under Git for Windows'
5-
# bundled bash, no WSL needed.
3+
# them, then runs CI's clang-tidy gate over the staged sources in its file
4+
# set. Skips either tool if it is not installed; CI enforces both. Runs under
5+
# Git for Windows' bundled bash, no WSL needed.
66
#
77
# This file must stay LF-terminated: a CRLF checkout makes the kernel look
88
# for an interpreter named "bash\r" and the hook silently never runs.
@@ -30,22 +30,27 @@ else
3030
echo "⚠ clang-format not installed — skipping (winget install LLVM.LLVM)"
3131
fi
3232

33-
# ── clang-tidy (advisory) ────────────────────────────────────────────────
34-
# Advisory to match CI: .clang-tidy's WarningsAsErrors='' is authoritative,
35-
# so a stylistic finding must not block a commit.
33+
# ── clang-tidy ───────────────────────────────────────────────────────────
34+
# scripts/check-tidy.ps1 is the gate CI runs (its flags, its compile database
35+
# view, findings fail); here it takes only the staged files in CI's set
36+
# (src/**/*.cpp outside src/UI/), so a finding stops the commit before it
37+
# would stop the pull request.
3638
if command -v clang-tidy >/dev/null 2>&1; then
3739
# build/ is the debug preset's binaryDir (CMakePresets.json), the same
3840
# tree CI lints against.
3941
if [ -f build/compile_commands.json ]; then
4042
cpp_files=()
4143
while IFS= read -r f; do
4244
case "$f" in
43-
*.cpp) cpp_files+=("$f") ;;
45+
src/UI/*) ;;
46+
src/*.cpp) cpp_files+=("$f") ;;
4447
esac
4548
done <<<"$staged"
4649
if [ "${#cpp_files[@]}" -gt 0 ]; then
47-
echo "▶ clang-tidy -p build (${#cpp_files[@]} file(s))"
48-
clang-tidy -p build --quiet "${cpp_files[@]}" || true
50+
echo "▶ clang-tidy (${#cpp_files[@]} file(s))"
51+
files_csv=$(IFS=,; echo "${cpp_files[*]}")
52+
powershell.exe -NoProfile -ExecutionPolicy Bypass \
53+
-File scripts/check-tidy.ps1 -BuildDir build -Files "$files_csv"
4954
fi
5055
else
5156
echo "⚠ build/compile_commands.json missing — run scripts/build.ps1 debug"

‎.github/pull_request_template.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
## CI gates
1515

1616
`windows-ci.yml` runs these on every pull request, in this order. Tick what you
17-
ran locally. Everything except `clang-tidy` fails the build.
17+
ran locally. Every one of them fails the build.
1818

1919
- [ ] **`clang-format --dry-run --Werror`** over `src/` and `tests/`. CI pins
2020
clang-format **22.1.4** from PyPI. Version 18 and version 22 disagree on
2121
braced-init lists, so a different local version will flap.
2222
`pipx install clang-format==22.1.4`
2323
- [ ] **Debug build** configured with `-DDISH_BUILD_TESTS=ON
2424
-DDISH_REQUIRE_TRANSLATIONS=ON`, warnings clean (`/WX` is on for
25-
first-party code)
25+
first-party code, tests included)
2626
- [ ] **`ctest --output-on-failure --parallel`** passes
2727
- [ ] **`qmllint`** clean over every tracked `src/qml/*.qml`. Must run after the
2828
build, because the `Dish.Chrome` qmldir and qmltypes are generated into the
@@ -37,9 +37,10 @@ ran locally. Everything except `clang-tidy` fails the build.
3737
`cmake --build <build-dir> --target update_translations`, then commit the
3838
changed `.ts` files. A new `%n` plural also needs its singular and plural
3939
written into `translations/dish_en.ts` by hand.
40-
- [ ] **`clang-tidy -p build`** over `src/*.cpp` excluding `src/UI/*`, against the
41-
same Debug tree. Advisory: `.clang-tidy` sets `WarningsAsErrors: ''` and
42-
the step does not fail. Read the findings anyway.
40+
- [ ] **`scripts/check-tidy.ps1`** (`clang-tidy` over `src/*.cpp` excluding
41+
`src/UI/*`, against the same Debug tree). Findings fail the step: it
42+
passes `--warnings-as-errors='*'`, the way `dish-linux` gates its sweep,
43+
while the fleet-canonical `.clang-tidy` keeps `WarningsAsErrors: ''`.
4344
- [ ] **Release build** configures and builds
4445

4546
`scripts\build.ps1 debug test` reproduces the build and test steps. The security

‎.github/workflows/_security.yml‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,9 @@ jobs:
206206
- name: Checkout
207207
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
208208

209-
# Needs Advanced Security, which a private repo does not have; the step
210-
# is advisory until then. Drop continue-on-error once public.
209+
# Blocking: the repository is public, so the dependency graph this
210+
# action reads is available.
211211
- name: Review changed dependencies
212-
continue-on-error: true
213212
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
214213
with:
215214
fail-on-severity: high

‎.github/workflows/codeql.yml‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ jobs:
4343
# provider is backed by the actions/cache step below; windows-ci.yml
4444
# uses the same key, so the two lanes share archives.
4545
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}\vcpkg-bincache,readwrite
46+
# Overlay (incremental) analysis needs build-mode none; this lane traces
47+
# a real MSVC build, so the action would try, warn that it cannot, and
48+
# fall back to a full database on every run. Declaring the mode it ends
49+
# up in anyway keeps the init step's log clean.
50+
CODEQL_OVERLAY_DATABASE_MODE: none
4651

4752
steps:
4853
- name: Checkout
@@ -89,7 +94,7 @@ jobs:
8994
vcpkg-bin-${{ runner.os }}-
9095
9196
- name: Set up vcpkg
92-
uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5
97+
uses: lukka/run-vcpkg@b1a0dd252f06b9e25b3c022a9a03bd7a427fb6a2 # v11.6
9398
with:
9499
vcpkgGitCommitId: ${{ env.VCPKG_COMMITID }}
95100

@@ -115,8 +120,7 @@ jobs:
115120
with:
116121
languages: ${{ matrix.language }}
117122
# security-extended without security-and-quality: the quality suite
118-
# tripled the query count for maintainability findings that, like
119-
# everything here pre-GHAS, surface only in the logs.
123+
# tripled the query count for maintainability findings.
120124
queries: security-extended
121125

122126
# 4 = the windows-2022 runner's vCPU count; Ninja's cores+2 default
@@ -127,12 +131,10 @@ jobs:
127131
shell: pwsh
128132
run: cmake --build build-release --parallel 4 --target Dish
129133

134+
# Blocking, and the SARIF is uploaded: the repository is public, so code
135+
# scanning is available and the findings land as alerts instead of only
136+
# in this log.
130137
- name: Perform CodeQL analysis
131-
# SARIF upload needs Advanced Security, which a private repo does not
132-
# have. Findings still surface in the logs. Drop continue-on-error and
133-
# `upload: failure-only` once the repo is public.
134-
continue-on-error: true
135138
uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
136139
with:
137140
category: "/language:${{ matrix.language }}"
138-
upload: failure-only

‎.github/workflows/release.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ on:
3838
# actions/checkout @ v7.0.1 → 3d3c42e5aac5ba805825da76410c181273ba90b1
3939
# ilammy/msvc-dev-cmd @ v1.13.0 → 0b201ec74fa43914dc39ae48a89fd1d8cb592756
4040
# jurplel/install-qt-action @ v4.3.1 → 48d3ad6db93f3627c8ee7a0454bc6f3744f7e730
41-
# lukka/run-vcpkg @ v11.5 → 5e0cab206a5ea620130caf672fce3e4a6b5666a1
41+
# lukka/run-vcpkg @ v11.6 → b1a0dd252f06b9e25b3c022a9a03bd7a427fb6a2
4242
# actions/upload-artifact @ v7.0.1 → 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
4343
# actions/download-artifact @ v8.0.1 → 3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
4444
# softprops/action-gh-release @ v3.0.2 → 3d0d9888cb7fd7b750713d6e236d1fcb99157228
@@ -178,7 +178,7 @@ jobs:
178178
cache: true
179179

180180
- name: Set up vcpkg + install dependencies
181-
uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5
181+
uses: lukka/run-vcpkg@b1a0dd252f06b9e25b3c022a9a03bd7a427fb6a2 # v11.6
182182
with:
183183
vcpkgGitCommitId: ${{ env.VCPKG_COMMITID }}
184184

‎.github/workflows/security.yml‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ jobs:
2929
osv_scan_paths: |
3030
.
3131
gitleaks_enabled: true
32-
dependency_review_enabled: true
32+
# Off until the repository's Dependency graph is switched on (Settings,
33+
# Code security). dependency-review-action reads that graph and fails
34+
# without it, so on this repository the job has never reviewed anything.
35+
# Flip to true once the setting is on; the job then blocks.
36+
dependency_review_enabled: false
3337
action_pin_lint_enabled: true
3438
allowlist_expiry_enabled: true

‎.github/workflows/windows-ci.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ jobs:
8585
vcpkg-bin-${{ runner.os }}-
8686
8787
- name: Set up vcpkg + install dependencies
88-
uses: lukka/run-vcpkg@5e0cab206a5ea620130caf672fce3e4a6b5666a1 # v11.5
88+
uses: lukka/run-vcpkg@b1a0dd252f06b9e25b3c022a9a03bd7a427fb6a2 # v11.6
8989
with:
9090
vcpkgGitCommitId: ${{ env.VCPKG_COMMITID }}
9191

‎CMakeLists.txt‎

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
cmake_minimum_required(VERSION 3.21)
1+
# 3.25 for two things the warning-free build rests on: CMP0141, which hands the
2+
# MSVC debug-information format to a target property instead of baking /Zi into
3+
# the Debug flags (so a /Z7 target no longer overrides it, D9025), and the SYSTEM
4+
# option of FetchContent_Declare, which keeps /W4 /WX off Catch2's headers.
5+
cmake_minimum_required(VERSION 3.25)
26
project(Dish
37
VERSION 2.1.0
48
DESCRIPTION "Dish Windows client for the Satellite gamepad-over-LAN protocol"
59
# C is enabled for the vendored ENet fork (Moonlight control stream), whose
610
# backend is pure C; everything first-party is C++.
711
LANGUAGES C CXX)
812

9-
set(CMAKE_CXX_STANDARD 17)
13+
# C++20, in step with dish-linux (where it retires the pedantic warning on
14+
# Qt's zero-argument streaming log macros).
15+
set(CMAKE_CXX_STANDARD 20)
1016
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1117
set(CMAKE_CXX_EXTENSIONS OFF)
1218

@@ -37,9 +43,10 @@ if(DISH_ENABLE_LTO AND CMAKE_BUILD_TYPE STREQUAL "Release")
3743
endif()
3844
endif()
3945

40-
# dish_warnings is applied everywhere including tests; dish_strict adds
41-
# /WX (-Werror) and is applied only to first-party code, so Catch2's headers
42-
# can't fail the build.
46+
# dish_warnings carries the warning set, dish_strict adds /WX (-Werror). Both
47+
# apply to every first-party target, tests included; third-party headers stay
48+
# out of their reach as SYSTEM (external) includes, Catch2's via the SYSTEM
49+
# option in tests/CMakeLists.txt.
4350
add_library(dish_warnings INTERFACE)
4451
add_library(dish_strict INTERFACE)
4552

@@ -52,11 +59,7 @@ if(MSVC)
5259
target_compile_definitions(dish_warnings INTERFACE
5360
UNICODE _UNICODE
5461
WIN32_LEAN_AND_MEAN
55-
NOMINMAX
56-
# Silences the "use the secure version" nags for POSIX-style calls
57-
# inside Qt and libsodium.
58-
_CRT_SECURE_NO_WARNINGS
59-
_WINSOCK_DEPRECATED_NO_WARNINGS)
62+
NOMINMAX)
6063
if(DISH_ENABLE_WARNINGS)
6164
target_compile_options(dish_strict INTERFACE /WX)
6265
endif()
@@ -116,7 +119,15 @@ FetchContent_Declare(
116119
enet
117120
GIT_REPOSITORY https://github.com/cgutman/enet.git
118121
GIT_TAG 44c85e16279553d9c052e572bcbfcd745fb74abf
119-
SOURCE_SUBDIR _dish_no_such_subdir)
122+
SOURCE_SUBDIR _dish_no_such_subdir
123+
# Nine `command | flag` ORs of two different enum types, which current
124+
# MSVC reports as C5287 (level 1, so at any warning level), get the
125+
# explicit casts it asks for. Applied once, at fetch time; see
126+
# cmake/PatchEnet.cmake and THIRD_PARTY.md.
127+
PATCH_COMMAND ${CMAKE_COMMAND}
128+
-DENET_SOURCE_DIR=<SOURCE_DIR>
129+
-DPATCH_FILE=${CMAKE_CURRENT_SOURCE_DIR}/cmake/enet-msvc-c5287.patch
130+
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/PatchEnet.cmake)
120131
FetchContent_MakeAvailable(enet)
121132

122133
if(NOT enet_SOURCE_DIR OR NOT EXISTS "${enet_SOURCE_DIR}/callbacks.c")
@@ -563,6 +574,15 @@ target_link_libraries(dish_core
563574
dish_warnings
564575
dish_strict)
565576

577+
# AppViewModel and the two role models live here, but their QML identities are
578+
# declared from the Dish target (src/qml/chrome/ForeignTypes.h). qmltyperegistrar
579+
# can only expand a QML_FOREIGN declaration when it can read the foreign class's
580+
# meta-object, which reaches it as a --foreign-types argument: this call writes
581+
# dish_core's metatypes .json and puts it on Dish's SOURCES through the
582+
# INTERFACE_SOURCES genex that qt_add_qml_module's QT_CONSUMES_METATYPES enables.
583+
# Without it the App singleton lands in the qmltypes with no properties at all.
584+
qt_extract_metatypes(dish_core)
585+
566586
# --- UI executable ---
567587
set(DISH_UI_SOURCES
568588
src/UI/CrashHandler.h
@@ -589,12 +609,33 @@ if(sentry_FOUND)
589609
endif()
590610
set_target_properties(Dish PROPERTIES OUTPUT_NAME dish)
591611
target_link_libraries(Dish PRIVATE dish_core Qt6::Gui Qt6::Svg dish_warnings dish_strict)
592-
# Debug information for the symbol upload in release.yml. /Z7 keeps it in the
593-
# objects, /DEBUG:FULL writes dish.pdb beside dish.exe, and neither the install
594-
# image nor the portable bundle picks a .pdb up, so nothing shipped carries it.
612+
# Debug information for the symbol upload in release.yml. Embedded (/Z7) keeps
613+
# it in the objects, /DEBUG:FULL writes dish.pdb beside dish.exe, and neither
614+
# the install image nor the portable bundle picks a .pdb up, so nothing shipped
615+
# carries it. The format goes through the CMP0141 target property rather than a
616+
# raw /Z7, so the Debug configuration's own /Zi is replaced instead of overridden
617+
# on the command line (cl reports that as D9025 on every translation unit).
595618
if(sentry_FOUND AND MSVC)
596-
target_compile_options(dish_core PRIVATE /Z7)
597-
target_compile_options(Dish PRIVATE /Z7)
619+
# CMake fills CMAKE_<LANG>_FLAGS_<CONFIG> once, when a tree is first
620+
# configured, and a tree configured before 3.25 became the floor keeps the
621+
# /Zi the older default put there. The property would then add /Z7 on top of
622+
# it, which is D9025 back on every unit of these two targets, so such a tree
623+
# is refused with the one-time remedy instead of built with the warning.
624+
foreach(_dish_config IN LISTS CMAKE_CONFIGURATION_TYPES CMAKE_BUILD_TYPE)
625+
string(TOUPPER "${_dish_config}" _dish_config)
626+
foreach(_dish_lang C CXX)
627+
set(_dish_flags_var CMAKE_${_dish_lang}_FLAGS_${_dish_config})
628+
if("${${_dish_flags_var}}" MATCHES "[-/]Z[iI]( |$)")
629+
message(FATAL_ERROR
630+
"${_dish_flags_var} is \"${${_dish_flags_var}}\": its /Zi would be "
631+
"overridden by the /Z7 dish_core and Dish carry as a target property "
632+
"(D9025 on every translation unit). This build tree was configured before "
633+
"CMake 3.25 became the floor; delete ${CMAKE_BINARY_DIR}/CMakeCache.txt "
634+
"and configure again.")
635+
endif()
636+
endforeach()
637+
endforeach()
638+
set_target_properties(dish_core Dish PROPERTIES MSVC_DEBUG_INFORMATION_FORMAT Embedded)
598639
target_link_options(Dish PRIVATE /DEBUG:FULL /OPT:REF /OPT:ICF)
599640
endif()
600641
# CrashHandler.cpp: dbghelp writes the minidump and symbolizes the stack;
@@ -613,7 +654,9 @@ target_sources(Dish PRIVATE
613654
src/qml/chrome/ThemeBridge.h
614655
src/qml/chrome/ThemeBridge.cpp
615656
src/qml/chrome/TokensBridge.h
616-
src/qml/chrome/TokensBridge.cpp)
657+
src/qml/chrome/TokensBridge.cpp
658+
# QML_FOREIGN declarations for dish_core's view-model types; see the header.
659+
src/qml/chrome/ForeignTypes.h)
617660

618661
# DISH_KIT_QML_FILES: the canonical design-kit file list, kept in its own
619662
# file so the kit reads as a unit rather than as lines lost in this one.
@@ -663,10 +706,18 @@ qt_add_qml_module(Dish
663706
# so their directory has to be on the include path for it to compile.
664707
target_include_directories(Dish PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/qml/chrome)
665708

666-
# C4702 (unreachable code) fires inside Qt's own headers from the TUs
667-
# qmlcachegen generates, and dish_strict's /WX makes it fatal.
709+
# The AOT-compiled QML (qmlcachegen's *_qml.cpp, attached to Dish by
710+
# qt_add_qml_module above) instantiates Qt's own QJSEngine / QVariant templates,
711+
# whose `if constexpr` early returns leave code MSVC's optimizer reports as
712+
# unreachable (C4702) inside qjsengine.h, qvariant.h and qmetatype.h. That is a
713+
# back-end warning, which -external:W0 does not reach (documented under
714+
# /external, "Limitations"), so /wd47XX is the compiler's own remedy for it.
715+
# Scoped to the generated units only: every first-party unit in this target
716+
# keeps C4702 live.
668717
if(MSVC)
669-
target_compile_options(Dish PRIVATE /wd4702)
718+
get_target_property(_dish_qmlcache_sources Dish SOURCES)
719+
list(FILTER _dish_qmlcache_sources INCLUDE REGEX "/\\.rcc/qmlcache/")
720+
set_source_files_properties(${_dish_qmlcache_sources} PROPERTIES COMPILE_OPTIONS /wd4702)
670721
endif()
671722

672723
target_link_libraries(Dish PRIVATE

‎CMakePresets.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"version": 3,
3-
"cmakeMinimumRequired": { "major": 3, "minor": 21, "patch": 0 },
3+
"cmakeMinimumRequired": { "major": 3, "minor": 25, "patch": 0 },
44
"configurePresets": [
55
{
66
"name": "debug",

0 commit comments

Comments
 (0)