Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ __pycache__/
packages/
AppPackages/
BundleArtifacts/
platform/windows/obj/

# OS
.DS_Store
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## Unreleased

- Ship the Windows runtime source list as a machine-consumable property
sheet. `platform/windows/rivet-runtime-sources.props` is now the single
author of the host library's `<ClCompile>` set — `rivet-host.vcxproj`
imports it, and hosts that still compile Rivet sources directly (the
transitional path until #238 ships prebuilt static libraries) import the
same file instead of hand-copying entries that rot: adding a runtime
translation unit previously broke every downstream Windows host at link
time (the podlens `valid_utf8` LNK2001). A guard test keeps the props in
step with `runtime/CMakeLists.txt`, and `platform/windows/README.md`
documents both consumption contracts.

- Fix generated C++ bounded-wait RPCs so each promise yields exactly one
future, reused for both the timeout wait and the result read. Void RPCs now
also fulfill their promise after decoding a successful response; previously
Expand Down
72 changes: 72 additions & 0 deletions platform/windows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Windows platform

WinUI 3 / C++/WinRT host and native adapters. Products consume Rivet through
one of the two contracts below; both compile the same authoritative source
list, so they can never disagree about what the Windows host library
contains.

## Packaged consumption (primary)

Reference the released library projects and link `rivet::host` — this is what
`raco rivet new` scaffolds and what the host template
([host/RivetHost.vcxproj](host/RivetHost.vcxproj)) ships:

```xml
<ItemGroup>
<ProjectReference
Include="$(RIVET_ROOT)\platform\windows\rivet-host.vcxproj"
Properties="RivetRuntimeLibrary=MultiThreadedDLL" />
</ItemGroup>
```

The `Properties=` facet forwards the downstream CRT choice (MSVC rejects
mixed `RuntimeLibrary` across a static link, LNK2038). Rivet never appears in
your `<ClCompile>` list; adding a Rivet translation unit upstream cannot
break your build. `raco rivet build` supplies `RIVET_ROOT` and
`RIVET_RACKET_INCLUDE`.

## Transitional vendored sources

Until prebuilt static libraries are published for every channel (#238), a
host that compiles Rivet sources directly must import the shared property
sheet instead of re-listing sources:

```xml
<Import
Project="$(RivetRoot)\platform\windows\rivet-runtime-sources.props" />
```

The props file is the single author of the `<ClCompile>` set;
[rivet-host.vcxproj](rivet-host.vcxproj) imports the same file, and
`rivet/tests/host-package-linkage.rkt` keeps it in step with
`runtime/CMakeLists.txt`. When Rivet adds a runtime translation unit, a
props re-sync is a file update, not a hunt through hand-copied
`<ClCompile>` lines (see issue #280 and the podlens `valid_utf8` LNK2001).

Override `RivetSourceRoot` when the import happens from a checkout rooted
somewhere other than two levels above the props file:

```xml
<PropertyGroup>
<RivetSourceRoot>C:\path\to\rivet\</RivetSourceRoot>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(RivetSourceRoot)runtime\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
```

Importers supply their own include directories, `/utf-8`, CRT selection, and
the Windows App SDK / C++/WinRT NuGet packages — the props intentionally
carries the source list only.

## Layout

- `device/` — device identity, session service, and Schannel transport
- `runtime/` — Racket embedding backend and Win32 pipe transport
- `system/` — WinRT system service adapter
- `update/` — installer handoff and lifecycle helpers
- `chart/` — `rivet-chart.vcxproj` chart control (optional, referenced
separately)
- `host/` — the scaffolded WinUI executable template
22 changes: 5 additions & 17 deletions platform/windows/rivet-host.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,23 +93,11 @@
<PackageReference Include="Microsoft.WindowsAppSDK" Version="$(RivetWinAppSDKVersion)" />
<PackageReference Include="Microsoft.Windows.CppWinRT" Version="$(RivetCppWinRTVersion)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(RIVET_ROOT)\platform\windows\device\device_identity.cpp" />
<ClCompile Include="$(RIVET_ROOT)\platform\windows\device\device_listener.cpp" />
<ClCompile Include="$(RIVET_ROOT)\platform\windows\device\device_session_service.cpp" />
<ClCompile Include="$(RIVET_ROOT)\platform\windows\device\schannel_transport.cpp" />
<ClCompile Include="$(RIVET_ROOT)\platform\windows\runtime\backend.cpp" />
<ClCompile Include="$(RIVET_ROOT)\platform\windows\runtime\win32_pipe_transport.cpp" />
<ClCompile Include="$(RIVET_ROOT)\platform\windows\system\system_services.cpp" />
<ClCompile Include="$(RIVET_ROOT)\platform\windows\update\update_handoff.cpp" />
<ClCompile Include="$(RIVET_ROOT)\runtime\src\device_session.cpp" />
<ClCompile Include="$(RIVET_ROOT)\runtime\src\device_session_host.cpp" />
<ClCompile Include="$(RIVET_ROOT)\runtime\src\discovery_advertisement.cpp" />
<ClCompile Include="$(RIVET_ROOT)\runtime\src\protocol.cpp" />
<ClCompile Include="$(RIVET_ROOT)\runtime\src\sha256.cpp" />
<ClCompile Include="$(RIVET_ROOT)\runtime\src\utf8.cpp" />
<ClCompile Include="$(RIVET_ROOT)\runtime\src\x509_spki.cpp" />
</ItemGroup>
<!-- The authoritative ClCompile set lives in rivet-runtime-sources.props
(issue #280): this build and every vendored-source host must consume
the same list, so a new translation unit cannot ship without reaching
downstream Windows hosts. -->
<Import Project="$(MSBuildThisFileDirectory)rivet-runtime-sources.props" />
<ItemGroup>
<ClInclude Include="$(RIVET_ROOT)\platform\windows\device\device_identity.hpp" />
<ClInclude Include="$(RIVET_ROOT)\platform\windows\device\device_listener.hpp" />
Expand Down
42 changes: 42 additions & 0 deletions platform/windows/rivet-runtime-sources.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Authoritative Windows runtime source list (issue #280).

This property sheet is the machine-consumable replacement for
hand-copied <ClCompile> lists. rivet-host.vcxproj imports it, so
Rivet's own build and every downstream consumer share one list and a
new translation unit can no longer silently miss a vendored host the
way the podlens valid_utf8 LNK2001 did. The guard test in
rivet/tests/host-package-linkage.rkt keeps this list in step with
runtime/CMakeLists.txt.

Transitional hosts that compile Rivet sources directly import this
file instead of re-listing sources:

<Import
Project="$(RivetRoot)\platform\windows\rivet-runtime-sources.props" />

Override RivetSourceRoot when importing from a checkout rooted
elsewhere. Products on the packaged-consumption path (#238) do not
need this file: they reference rivet-host.vcxproj directly. -->
<PropertyGroup>
<RivetSourceRoot Condition="'$(RivetSourceRoot)' == ''">$([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)..\..'))</RivetSourceRoot>
</PropertyGroup>
<ItemGroup Label="RivetRuntimeSources">
<ClCompile Include="$(RivetSourceRoot)platform\windows\device\device_identity.cpp" />
<ClCompile Include="$(RivetSourceRoot)platform\windows\device\device_listener.cpp" />
<ClCompile Include="$(RivetSourceRoot)platform\windows\device\device_session_service.cpp" />
<ClCompile Include="$(RivetSourceRoot)platform\windows\device\schannel_transport.cpp" />
<ClCompile Include="$(RivetSourceRoot)platform\windows\runtime\backend.cpp" />
<ClCompile Include="$(RivetSourceRoot)platform\windows\runtime\win32_pipe_transport.cpp" />
<ClCompile Include="$(RivetSourceRoot)platform\windows\system\system_services.cpp" />
<ClCompile Include="$(RivetSourceRoot)platform\windows\update\update_handoff.cpp" />
<ClCompile Include="$(RivetSourceRoot)runtime\src\device_session.cpp" />
<ClCompile Include="$(RivetSourceRoot)runtime\src\device_session_host.cpp" />
<ClCompile Include="$(RivetSourceRoot)runtime\src\discovery_advertisement.cpp" />
<ClCompile Include="$(RivetSourceRoot)runtime\src\protocol.cpp" />
<ClCompile Include="$(RivetSourceRoot)runtime\src\sha256.cpp" />
<ClCompile Include="$(RivetSourceRoot)runtime\src\utf8.cpp" />
<ClCompile Include="$(RivetSourceRoot)runtime\src\x509_spki.cpp" />
</ItemGroup>
</Project>
35 changes: 35 additions & 0 deletions rivet/tests/host-package-linkage.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

(require rackunit
racket/file
racket/list
racket/runtime-path
racket/string)

Expand All @@ -23,6 +24,13 @@
(file->string
(build-path repository-root "platform" "windows"
"rivet-host.vcxproj")))
(define windows-source-props
(file->string
(build-path repository-root "platform" "windows"
"rivet-runtime-sources.props")))
(define runtime-cmake
(file->string
(build-path repository-root "runtime" "CMakeLists.txt")))
(define windows-host-template
(file->string
(build-path repository-root "platform" "windows" "host"
Expand Down Expand Up @@ -59,6 +67,33 @@
(format "obj\\~a\\</MSBuildProjectExtensionsPath>" project-name))
(format "~a must have an isolated NuGet assets directory" project-name)))

;; The Windows runtime source list has exactly one author (issue #280): the
;; props file that vendored hosts import. Re-listing sources in the vcxproj
;; would reintroduce the roting hand copies behind the podlens LNK2001.
(check-true (string-contains? windows-host "rivet-runtime-sources.props")
"rivet-host.vcxproj must import the shared runtime source props")
(check-false (string-contains? windows-host "<ClCompile Include=")
"rivet-host.vcxproj must not re-list sources beside the props")

;; Every shared runtime unit CMake compiles into rivet_protocol — minus the
;; chart unit that rivet-chart.lib owns on Windows — must appear in the props,
;; so adding a translation unit without reaching vendored Windows hosts fails
;; here instead of at a downstream link (the utf8.cpp LNK2001 class).
(define cmake-runtime-units
(filter-map
(lambda (line)
(define unit-match
(regexp-match #px"^\\s*src/([A-Za-z0-9_]+\\.cpp)\\s*$" line))
(and unit-match (second unit-match)))
(string-split runtime-cmake "\n")))
(check-true (pair? cmake-runtime-units)
"runtime/CMakeLists.txt must still declare rivet_protocol sources")
(for ([unit (in-list cmake-runtime-units)]
#:unless (string=? unit "chart_batch.cpp"))
(check-true
(string-contains? windows-source-props (format "runtime\\src\\~a" unit))
(format "rivet-runtime-sources.props must compile the shared unit ~a" unit)))

(check-true
(string-contains? windows-host-template
"'$(RivetSelfContained)'=='true'\">MultiThreaded")
Expand Down
8 changes: 7 additions & 1 deletion rivet/tests/windows-update-handoff.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
(define project
(file->string
(build-path repository-root "platform" "windows" "rivet-host.vcxproj")))
;; The source list is authored in rivet-runtime-sources.props and imported by
;; the vcxproj (issue #280), so the compile claim is checked against the props.
(define windows-sources
(file->string
(build-path repository-root "platform" "windows"
"rivet-runtime-sources.props")))

(for ([required (in-list '("tasklist /FI"
"msiexec /passive /norestart"
Expand All @@ -26,7 +32,7 @@
(check-true (string-contains? source required)
(format "Windows handoff lost required lifecycle step: ~a"
required)))
(check-true (string-contains? project "update\\update_handoff.cpp")
(check-true (string-contains? windows-sources "update\\update_handoff.cpp")
"the released Windows platform library must compile the handoff")
(check-true (string-contains? project "Debug|ARM64"))
(check-true (string-contains? project "Release|ARM64"))
Loading