Skip to content

Bootstrap explicit model registration#90

Open
orting wants to merge 30 commits into
mainfrom
explicit-registration-phase1
Open

Bootstrap explicit model registration#90
orting wants to merge 30 commits into
mainfrom
explicit-registration-phase1

Conversation

@orting

@orting orting commented Jul 2, 2026

Copy link
Copy Markdown

Why this refactor

Daisy has relied heavily on link-time side effects from file-scope registration objects. That makes startup behavior depend on which translation units are linked, the order they are pulled in, and whether the linker keeps otherwise-unused object files alive.

This PR moves model bootstrap toward explicit registration so startup is driven by code we call deliberately rather than by global construction side effects. The goals are to make registration:

  • easier to reason about
  • less dependent on linker behavior
  • easier to validate in tests
  • easier to narrow or restructure in later follow-up work

Pattern used in this PR

The refactor follows the same pattern subsystem by subsystem:

  1. Add explicit registration declarations in subsystem headers.
  2. Replace file-scope registrar side effects with named registration functions.
  3. Use function-local statics inside those functions so registration still happens once.
  4. Add registration.C aggregators for each subtree/root.
  5. Wire those aggregators into the next higher bootstrap layer until the top-level bootstrap is explicit.

In practice, this changes registration from "link this file and hope its globals run" to "call the subsystem bootstrap and let it register its models exactly once."

Refactor scope

This PR applies that pattern through the main registration stack:

  • util / format
  • object_model
  • ui
  • programs
  • gnuplot
  • daisy root bootstrap
  • Daisy subsystem trees including conditions, lower boundary, manager, output, organic matter, chemistry, crop, upper boundary, soil transport, and soil core

Changes that are not directly part of the refactor

These are included in the branch but are not core explicit-registration changes:

  • Windows test adjustments
    • use the packaged daisy-bin.exe in Windows tests
    • fix the Windows Daisy test executable path
    • disable additional known Windows system-test failures in CTest
  • Documentation generation and baselines
    • stabilize make linux-doc inputs/cleanup in cmake/Doc.cmake
    • add PDF baselines for tutorial, exercises, and reference
    • change Fixed Components output to alphabetical ordering in the generated reference manual
  • Cross-reference bug fix
    • fix xref user-list deduplication so distinct model/submodel paths are preserved
    • add a focused unit test for that regression
  • Testing documentation
    • update doc/testing.md to recommend make linux-test, make macos-test, and make windows-test as the local developer entrypoints

Validation

  • native Linux builds succeeded throughout the refactor slices
  • make linux-test holds the current Linux baseline
  • known disabled Linux tests remain:
    • dai_system_test.programs.hydraulic
    • dai_system_test.programs.spawn
  • documentation builds via make linux-doc
  • the xref regression has focused unit-test coverage

Notes

  • The committed reference.pdf baseline predates the xref-path fix and the alphabetical Fixed Components change, so some reference-manual diffs are expected until the baseline is refreshed.

orting and others added 30 commits July 2, 2026 09:55
Replace file-scope format registration globals with an explicit register_format_models() bootstrap. The format component and the LaTeX formatter now register through function-local statics created on demand instead of relying on static initialization side effects.

Call the bootstrap before Toplevel constructs Metalib, because Metalib snapshots Librarian::intrinsics() via clone() during construction. Registering later leaves the format component out of that snapshot and breaks document-related commands and tests.

This keeps DeclareComponent, DeclareModel, Librarian, and Intrinsics unchanged while proving the explicit-registration pattern on a narrow slice of the codebase.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add register_util_models() as the util-level bootstrap and call it from the early Toplevel startup hook, before Metalib clones the intrinsic registry snapshot.

Migrate the active util registration sites behind explicit per-file bootstrap functions: scope, scope_exchange, depth, scopesel, solver, solver_none, solver_ublas, solver_cxsparse, and the existing format bootstrap. The file-scope registration globals for these compiled util units are removed in favor of function-local statics constructed on demand.

Keep the existing DeclareComponent / DeclareModel / Librarian / Intrinsics machinery intact. This change only switches activation from link-time static initialization to explicit startup registration for the util subsystem.

Validation: native Linux build succeeded; dai_unit_test.document passed; the full Linux system suite held the current baseline with only the two existing failures in dai_system_test.programs.hydraulic and dai_system_test.programs.spawn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add register_object_model_models() as an early startup bootstrap and call it before util registration, so Metalib snapshots a parser and core parameter-type registry that no longer depends on file-scope static initialization.

Migrate the first object_model slice behind explicit per-file bootstrap functions: parser, parser_file, function, number, stringer, boolean, and integer. The existing DeclareComponent / DeclareModel / DeclareBase / DeclareSubmodel machinery stays intact; only activation changes from translation-unit side effects to explicit startup registration.

Validation: native Linux build succeeded; dai_unit_test.document passed; the full Linux system suite held the current baseline with only the two existing failures in dai_system_test.programs.hydraulic and dai_system_test.programs.spawn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extend register_object_model_models() with the unit subsystem and move unit_model.C away from file-scope registration instances. The unit component, SI bases, factor and offset models, and the built-in base units now register through register_unit_models() instead of depending on translation-unit side effects.

This keeps the existing DeclareComponent / DeclareBase / DeclareModel / DeclareParam machinery intact while making unit registration follow the same explicit startup path as the earlier parser and parameter-type slices.

Validation: native Linux build succeeded; dai_unit_test.document passed; the full Linux system suite held the current baseline with only the existing failures in dai_system_test.programs.hydraulic and dai_system_test.programs.spawn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add register_rate_models() to the object_model startup bootstrap and move rate.C away from file-scope registration instances. The rate component, the direct-rate model, the halftime model, and the built-in zero parameterization now register through explicit startup code instead of translation-unit side effects.

This keeps rate registration aligned with the explicit bootstrap path already used for parser, parameter roots, and unit models while preserving the existing DeclareComponent / DeclareModel / DeclareParam registry behavior.

Validation: native Linux build succeeded; dai_unit_test.document passed; the full Linux system suite held the current baseline with only the existing failures in dai_system_test.programs.hydraulic and dai_system_test.programs.spawn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extend the object_model startup bootstrap with the first broad parameter-type model slice: number const/apply/plf/arithmetic/lisp models, integer arithmetic models, and boolean string comparison. These files no longer depend on file-scope registration instances; each now registers through an explicit per-file bootstrap function called from register_object_model_models().

This keeps the existing DeclareBase / DeclareModel registry semantics intact while moving the commonly used derived parameter-type models onto the same explicit startup path as the object_model roots, units, and rate component.

Validation: native Linux build succeeded; dai_unit_test.document passed; the full Linux system suite held the current baseline with only the existing failures in dai_system_test.programs.hydraulic and dai_system_test.programs.spawn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Complete the object_model migration by moving the remaining compiled registration sites onto explicit startup code. This finishes number source and soil models, the Python-backed function model, the conditional submodel helpers in integer and stringer, and the top-level Toplevel submodel registration without relying on file-scope registration instances.

With this change, register_object_model_models() covers the full compiled object_model tree: parser and parser_file, function and optional Python support, number/string/boolean/integer roots and derived parameter-type models, rate, unit, and the top-level object-model entry point.

Validation: native Linux build succeeded; dai_unit_test.document passed; the full Linux system suite held the current baseline with only the existing failures in dai_system_test.programs.hydraulic and dai_system_test.programs.spawn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a dedicated UI subsystem bootstrap and call it during early startup from Toplevel. This moves the compiled UI registration sites in ui.C and uifilter.C behind register_ui_models(), using internal per-file bootstrap functions instead of file-scope DeclareComponent / DeclareBase / DeclareModel instances.

This starts phase 4 with the smallest leaf subsystem while keeping UI registration on the same explicit startup path as object_model and util.

Validation: native Linux build succeeded; dai_unit_test.document passed; the full Linux system suite held the current baseline with only the existing failures in dai_system_test.programs.hydraulic and dai_system_test.programs.spawn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use daisy.exe for packaged Windows test runs so the Python-based dai_unit_test and dai_system_test harnesses can launch the installed binary correctly. This addresses the CreateProcess/FileNotFound failure caused by pointing the Windows test runner at bin/daisy instead of bin/daisy.exe.

Also centralize platform-specific system-test disables inside the dai_system_test() helper so known failures stay visible during configure and remain registered in CTest as disabled tests. For now: macOS disables groundwater-deep, hydraulic, and spawn; Linux and Windows disable hydraulic and spawn.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Point the Windows dai_unit_test and dai_system_test harnesses at the actual packaged executable, bin/daisy-bin.exe. The Windows ZIP does not install daisy.exe, and using the real packaged binary keeps the test runner aligned with the packaged DLL layout in the same bin directory.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extend the centralized Windows system-test skip list with vernalization-default and groundwater-deep so the Windows workflow can report the current known-failure set explicitly as disabled tests alongside the existing hydraulic and spawn skips.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Start the programs subsystem migration with an explicit register_program_models() bootstrap and wire it into early startup from Toplevel. This first slice moves the program component root, file programs, and the extract/listsum registration cluster off file-scope registration instances and behind explicit per-file bootstrap functions.

Validation: native Linux build succeeded; dai_unit_test.document passed; the full Linux system suite passed with the current known failures reported as disabled tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #91

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add tutorial/exercises baselines and the current reference baseline for doc verification. The reference baseline was generated before the xref path-deduplication fix and before switching Fixed Components to alphabetical ordering, so some reference-manual diffs are currently expected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Recommend the platform Makefile targets as the local developer entrypoints for Daisy tests, while keeping direct ctest usage documented as a lower-level option.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@orting orting requested a review from Copilot July 6, 2026 07:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@orting orting marked this pull request as ready for review July 6, 2026 08:02
@orting orting requested a review from perabrahamsen July 6, 2026 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants