Commit Graph

24 Commits

Author SHA1 Message Date
5230ac8748 Separate clean from distclean
clean removes what the build produced and leaves the configured build
system, so a build following it proceeds without reconfiguring. Deleting
the build system from clean broke that: the target lives in the Makefile
it removes, so nothing in the directory could drive a rebuild afterward.

distclean empties the directory, build system included. It is terminal —
the next step is `cmake -B <dir>` from outside — and it is what proves a
change against a tree carrying no state from earlier runs.
2026-08-16 01:18:55 -04:00
282423d768 Read the version from version.cpp instead of declaring it twice
The library's version reached the build through project(), and reached
the library itself through a separate literal in version.cpp. The two
had to be kept equal by hand; the tests caught drift but the number was
written in both places.

CMakeLists.txt now reads DPM_CORE_VERSION_STR out of the source and
passes it to project(), so the soname, the artifact filenames, the
generated PDF's name, and the value the library reports all derive from
one line. Configuration fails outright if that declaration is missing.

SOVERSION follows PROJECT_VERSION_MAJOR rather than a hardcoded 1.
2026-08-16 01:06:44 -04:00
0fa2205bf6 Annotate exported declarations with DPM_PUBLIC_ABI_EXPORT
The export marker sat in the leading position of each declaration, where
a name reads as part of the return type. It now sits on its own line
above the declaration, where it reads as an annotation on it, and its
name says what it marks: a declaration belonging to the public ABI.
2026-08-16 00:50:06 -04:00
3b7091dc4b Define the documentation build in docs/CMakeLists.txt and collect the prose
The Doxygen configuration, the page list, and the docs target live in
docs/, and the written documents live in docs/PROSE/, leaving the
top-level file with the output paths and the add_subdirectory call.

The subdirectory is given its own binary directory so that CMake's
scaffolding stays out of the documentation output, which holds pdf/ and
html/ and nothing else.

Paths both files need are set once above the call: the child's output
and cleanup and the parent's clean rule refer to the same variables.
2026-08-16 00:37:33 -04:00
64839e3933 Define the tests in tests/CMakeLists.txt
The fixture targets, the test binary, and the six test cases live beside
the sources they build, leaving the top-level file with enable_testing,
the ctest scratch-area write, and the add_subdirectory call.

The paths both files need are set once above that call, so the child's
output directories and the parent's clean rule refer to the same
variables rather than repeating the paths.
2026-08-16 00:29:35 -04:00
dcd8b3fa2c Stop bolding function signatures in the documentation
A signature containing char** argv closed its own bold emphasis early,
which garbled the dpm_execute and dpm_module_execute entries and the
text following them. Signatures are plain code spans now, so a signature
carrying a double asterisk renders like every other one.
2026-08-16 00:21:52 -04:00
cd1e15acec Write down the code style
docs/STYLE.md states the brace and indentation style the codebase
follows: Allman as the base, with the modifications that produce this
project's variant.
2026-08-16 00:06:41 -04:00
303d96ef73 Document the library's implementation
Every function in context.cpp, modules.cpp, and version.cpp carries a
Doxygen block, and the bodies explain the decisions the code alone does
not show: why dlerror is cleared before dlsym rather than testing the
returned address, what RTLD_NOW and RTLD_LOCAL buy, why missing contract
symbols are collected into one report, why a candidate that fails
validation is logged and skipped instead of failing the listing, and why
version parsing tests the first character itself.

Functions declared in a header carry a brief and implementation prose
rather than a second parameter list; Doxygen was reporting duplicate
documentation sections for each of them.

READMEs in include/internal and src/cli state what those directories
hold.
2026-08-16 00:01:22 -04:00
12a4f68025 Indent every scope and put opening braces on the signature line
Namespace and extern "C" bodies are indented a level, so nesting is
visible from the indentation rather than only from the braces. Opening
braces stay on the line that opens the scope, including function
definitions, which previously carried theirs on a line of their own.
2026-08-15 23:47:43 -04:00
9fd7d2f433 Add a README to src/bundled-modules 2026-08-15 23:03:35 -04:00
b641318663 Store the version in version.cpp and group the library under src/core
libdpm-core.so's version was reaching the source as a compile-line
definition, with a fallback in two translation units that would have let
the library build and report 0.0.0 if the build ever stopped supplying
it. The version is a literal in src/core/version.cpp, the file named for
it, alongside dpm_core_version() which returns it and the parser for the
X.Y.Z strings modules report.

The library's sources and its version script move to src/core, leaving
src/cli, src/bundled-modules, and the documentation source beside it.
2026-08-15 22:57:46 -04:00
d3f134aabf Shorten the document titles
The page titles were restating the project name and the artifact names
they cover. They read as Overview, DPM Design, Interaction with
libdpm-core.so, and Building DPM Core and CLI.
2026-08-15 21:31:47 -04:00
11aad23e80 Declare the documentation's structure in a source file
src/documentation.cpp is the documentation loading source: it carries no
code and names each document that the generated reference contains, in
order, by page label. The labels are declared on each markdown file's
first heading. The build configuration lists the files as Doxygen inputs
and nothing more, so the structure of the documentation and the
mechanics of generating it are separate.

The hand-maintained document index at the end of OVERVIEW.md is gone,
along with the last references to markdown files by filename in the
public header. The document list exists in one place.

The docs target clears its output and scratch directories on every run.
Doxygen keeps output files it judges unchanged, so a run over a
populated scratch directory carried pages forward from earlier ones, and
removed sections survived in the generated HTML and PDF after their
source was edited.
2026-08-15 21:26:00 -04:00
cafdeefa11 Describe dpm_module_execute as the entry point, not the whole surface
A module's reported version is consumed: a calling module reads it
through dpm_module_info_of and decides from it whether to issue a
command. Calling dpm_module_execute the module's entire functional
surface contradicted that.

dpm_module_execute is the only entry through which a module performs
work. dpm_module_version and dpm_module_description are what it reports
about itself, read at load and served to consumers, and the contract
page in the public header now says so.
2026-08-15 20:51:44 -04:00
99173d27ea Title-case every page and section heading
DPM is public-facing, and its headings read as titles: capitalized
throughout, with articles, conjunctions, and short prepositions left
lowercase in the middle.

Applies to the markdown documents and to the Doxygen page and section
titles in the public header, so the generated reference matches. One
prose cross-reference in DESIGN.md follows the section it names.
2026-08-15 20:49:29 -04:00
38bd9314cc Release version 1.0.0; keep generated documentation source-derived
The project version moves to 1.0.0, which the library soname, the
reported version, the test expectations, and the generated document
filename all derive from. SOVERSION now matches the major version.

The generated reference is built from the source and its documentation
comments alone. Prose from docs/ was briefly part of the input and is
removed: development notes are written and read on their own, and a
generator that reproduces them adds nothing. The reference opens on a
front page declared in the public header, followed by the module
contract.

One target builds it. Both PDF and HTML are produced by default, the
finished documents land in the build tree under docs/pdf and docs/html,
and the generators work in docs/tmp.

The internal namespace is dpm_core, matching the artifact name as
closely as a C++ identifier permits.
2026-08-15 20:45:47 -04:00
1cd79e79f3 Documentation generation produces consumable output in one command
Building the docs target now generates the reference and leaves finished
documents in the build tree's docs directory: pdf/ holds the compiled
PDF, html/ holds the browsable reference when that format is enabled.
Doxygen and LaTeX work under docs/tmp/, which clean removes along with
the rest of the tree.

The reference has a front page and a structure. The markdown documents
in docs/ are part of the input, OVERVIEW.md becomes the landing page,
and the rest follow as chapters ahead of the namespace, class, and file
reference. The module contract, previously a plain comment block
invisible to Doxygen, is a page in its own right.

Struct and enum members throughout the headers carry documentation, on
their own lines above what they describe.
2026-08-15 20:19:26 -04:00
17acad2b02 Modules determine their own compatibility with the library
A module is built against the system-installed libdpm-core.so and is
responsible for being correct against it. Where it needs to act on the
version it is running under, dpm_core_version() reports that and the
module decides for itself.

dpm_module_core_min() is removed. It was a declaration handed to the
library to enforce on the module's behalf, and enforcement of that kind
belongs nowhere in a library that routes and hosts. The contract is now
three reserved symbols and load validation is two steps: the reserved
symbols resolve, and the version and description probes return
well-formed values.

compare_versions had no remaining caller and is removed; parse_version
stays for the well-formedness probe. The core_too_new fixture went with
the handshake it existed to exercise.
2026-08-15 04:21:58 -04:00
97b39cac6c Route all module interaction through dispatch
A module is addressed by name and command string, and nothing else.
Typed API access handed a caller a pointer into the callee's function
table, which meant compiling against that module's struct layout — a
build-time dependency between modules that the design does not permit.
Removing it also removes the manifest, the table magic constant, and
the table size field, which existed only to describe and validate
those tables.

Load validation is now three steps: reserved contract symbols resolve,
the minimum-version handshake passes, and the version and description
probes return well-formed values. The contract is four reserved
symbols, and a module's interface is the command vocabulary it
documents.

Documentation is brought in line, and artifacts are named exactly:
libdpm-core.so for the library, <dpm/core.h> for the header, the dpm
binary for the command-line tool.
2026-08-15 02:15:18 -04:00
267529bee3 Drop the append-only versioning doctrine; document the version script
Module APIs and the library's exported ABI are versioned and retired
deliberately: a break ships as a new table version or a new symbol
version node, and consumers judge the versions they are handed.

Document src/libdpm-core.map — what it pins, what belongs in it, and
how a generation is retired — and declare DPM_CORE_0.1 as the shape
the next retired node takes.
2026-08-14 02:42:55 -04:00
298f4d5afe Drop the invented layer taxonomy from OVERVIEW.md
The overview had been restructured around a named three-layer model —
user, developer, filesystem — that was never part of the design. The
underlying point stands: a reader must be able to tell whether a given
statement applies to them, and a code-level symbol must never appear in
prose without saying whose vantage point it belongs to.

Sections are now named for the reader they address rather than for a
tier: "Running the dpm binary", "Writing a program against libdpm-core",
"What DPM reads and writes on disk". The remaining uses of "layer" are
the capability-growth layers the design already defines.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 00:48:47 -04:00
c41adc2498 Move version compatibility to the consumer; name libdpm-core explicitly
dpm_require no longer takes a minimum version and applies no version
criterion of its own. A handle now means the module is valid, not that
it suits the caller. dpm_module_info_of is added alongside it, reporting
the name, version, description, and minimum-libdpm-core version read at
load, so a consuming module can judge a dependency's version for itself.
The one rule still enforced is the minimum-version handshake, where
libdpm-core is the host and refuses a module that demands a newer library
than the one running.

dpm_module_info_of joins the version script, so the exported surface is
now fourteen symbols under DPM_CORE_1.0.

Separately, the bare word "core" is gone from prose everywhere. It named
both the command-line tool and the library, so every use forced the
reader to guess which. Text now says "the dpm binary" or "libdpm-core".
Identifiers keep their spelling: libdpm-core, core.h, core.conf, the
"core" configuration namespace, dpm_core_version, core_min, DPM_CORE_1.0,
the dpmcore namespace, test_core, core_api.

Three user-visible strings changed with it: the load-refusal message now
reads "requires libdpm-core >= X, running libdpm-core is Y — update
libdpm-core", and the info module's description and help text name the
library. The test asserting on the refusal text was updated to match.

DESIGN.md's terminology line no longer defines "DPM Core" as the CLI,
which was the source of the ambiguity. OVERVIEW.md is restructured around
the three layers a reader meets DPM at — user, developer, filesystem —
so a code-level symbol never appears without saying whose layer it is.
MODULES.md describes the bundled info module as testing and demonstrating
full DPM system functionality rather than as a reference implementation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 00:38:21 -04:00
da35fe4758 Fix clean target, correct build docs, add overview and docs guide
clean was deleting the generated build system along with the artifacts —
CMakeCache.txt, the makefiles, CMakeFiles/, the CMake file API directory,
and the CTest configuration. That left the build directory unconfigured
after every clean, so an IDE reading its target list from the file API
lost every target until the project was reloaded. clean now removes only
what the build produced.

Also writes CTest's scratch directory into DartConfiguration.tcl so a bare
ctest and IDE test discovery use it too, not just build-driven runs.

BUILD.md no longer lists libdl as a dependency; glibc 2.34 merged it into
libc, so nothing links against it. The code-reference section moves to its
own DOCUMENTATION.md.

The fixture config logged at ERROR while the info module emits its output
at INFO, so the CLI invocation BUILD.md documents exited 0 and printed
nothing. The fixture now logs at INFO and the documented command works as
written.

OVERVIEW.md describes what DPM is, how core routes and validates modules,
and why the architecture takes the shape it does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 23:57:38 -04:00
19cf285cb7 Initial commit: DPM core library, CLI, bundled info module, and tests 2026-08-09 18:00:05 -04:00