Types marked [<ModelType>] get an adaptive counterpart generated by
Adaptify: Surface-Model.fs → Surface-Model.g.fs,
right next to it. The *.g.fs files are not checked in (.gitignore: /src/**/*.g.fs); every
checkout generates them locally.
build.cmd/build.shand therunTests/runAllTests/run-tests/runUiTestsscripts generate whatever is missing or stale before they compile. Nothing to do there.- Building from the IDE or with plain
dotnet build: runadapt.cmd/adapt.shfirst — after a fresh clone or worktree, and after a pull, merge or branch switch that touched a model. When everything is up to date it only checks, in a few seconds. - Changed a
[<ModelType>]: runadapt.cmd/adapt.sh, then build. - New model file
X.fs: add<Compile Include="X.g.fs" />directly afterX.fsin the.fsproj, then runadapt.cmd/adapt.sh. - Never edit a
*.g.fs— change the model and regenerate.
adapt.cmd regenerate the projects with a missing or stale *.g.fs
adapt.cmd --all regenerate every model project
adapt.cmd --check only report; exit code 1 if anything is missing or stale
The first run on a fresh clone takes several minutes (about 5 on a desktop machine): it builds
PRo3D.Base, PRo3D.Core, PRo3D.GIS and PRo3D.SimulatedViews in Release, which the
following Release build then reuses.
Everything lives in utilities/Adapt.fsx; adapt.cmd / adapt.sh, the
Adapt target in Build.fs (a dependency of Compile, CompileDebug, Tests, CopyToElectron
and Publish) and the test scripts all run it.
- Model projects are the
.fsprojfiles undersrc/that list a*.g.fs. They are processed in project-reference order (Base, Core, SimulatedViews, Viewer, Lite, GeometryLab), so no list needs maintaining when a project gains models. - Stale check. Adaptify writes the hash of the model source into the first line of each
*.g.fs(MD5 of the file text, as a Guid). The script recomputes it; a missing file or a different hash marks the project for regeneration. - Generation, per marked project:
dotnet msbuild <proj> -restore -t:ResolveProjectReferences -p:Configuration=Releaserestores the project and builds only its references. Adaptify type-checks the models against the referenced assemblies, so they must exist and be current. The restore matters too: without the project's ownobj/project.assets.jsonAdaptify sees no NuGet references and silently finds no model types (this is what broke the oldadapt.cmdon a fresh clone).dotnet adaptify --lenses --local --force --release <proj>.
- Verification. Adaptify exits with 0 even when it generates nothing, so the stale check
runs again afterwards and the script fails if anything is still missing or stale. To see why,
run
dotnet adaptify --lenses --local --force --release --verbose <proj>.
- Staleness is judged by the model file alone. If the generated code has to change for a reason
outside it — say a type in a referenced project becomes or stops being a
[<ModelType>]— runadapt.cmd --all. --forceregenerates every model file of a project, so that project recompiles once.- An IDE only sees the generated types once they exist; before the first
adaptit reports missing files and unknownAdaptive*types.
Until 20.11.2024 generation ran implicitly through Adaptify.MSBuild; that was too slow for
interactive work, so PRo3D switched to Adaptify's local mode and checked the *.g.fs in. That
made every model change a merge conflict waiting to happen, and the checked-in files drifted:
when they were removed, 3 of the 45 were stale against their sources, and a fourth
(SequencedBookmarks-Model.g.fs) differed from a fresh generation of its unchanged source in
member order - so even untouched models produced diffs depending on who generated them.
Adaptify.MSBuild with LocalAdaptify=true would generate during every build instead, but
version 1.3.7 drops up-to-date files from its cache (Runner.fs), so every second build
regenerates all *.g.fs and recompiles every model project.
Merging develop into such a branch produces modify/delete conflicts on the *.g.fs files.
Resolve them by deleting: git rm <file>.g.fs (the local copy is regenerated by adapt).