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.
This commit is contained in:
@@ -6,22 +6,22 @@ A DPM module is one shared object in the module directory. libdpm-core loads it,
|
||||
|
||||
Every module exports the following symbols as extern "C". All returned strings must be non-NULL, static or module-owned, and valid for the lifetime of the loaded module; callers never free them.
|
||||
|
||||
**int dpm_module_execute(dpm_ctx\* ctx, const char\* command, int argc, char\*\* argv)**
|
||||
The generic command entry point. `ctx` is the host context that dispatched the call; the module reaches every libdpm-core service (dpm_log, dpm_config_get, dpm_module_path, ...) through it. `command` is the subcommand name, equal to argv[0] when argc > 0. NULL or empty `command` must behave as the module's help command. Returns 0 on success, nonzero on failure. It must be callable immediately after load with no other setup.
|
||||
**`int dpm_module_execute(dpm_ctx* ctx, const char* command, int argc, char** argv)`**
|
||||
The generic command entry point. `ctx` is the host context that dispatched the call; the module reaches every libdpm-core service (`dpm_log`, `dpm_config_get`, `dpm_module_path`, ...) through it. `command` is the subcommand name, equal to argv[0] when argc > 0. NULL or empty `command` must behave as the module's help command. Returns 0 on success, nonzero on failure. It must be callable immediately after load with no other setup.
|
||||
|
||||
**const char\* dpm_module_version(void)**
|
||||
**`const char* dpm_module_version(void)`**
|
||||
The module's own version as an X.Y.Z string. libdpm-core reports this value to consumers, and each consumer decides for itself whether the version suits it.
|
||||
|
||||
**const char\* dpm_module_description(void)**
|
||||
**`const char* dpm_module_description(void)`**
|
||||
A one-line human-readable description, shown in module listings.
|
||||
|
||||
**const char\* dpm_module_core_min(void)**
|
||||
**`const char* dpm_module_core_min(void)`**
|
||||
The minimum libdpm-core version (X.Y.Z) the module supports — the oldest one whose contract and services it was written against. A libdpm-core older than that refuses to load the module, and the refusal message says so.
|
||||
|
||||
**const dpm_manifest\* dpm_module_manifest(void)**
|
||||
**`const dpm_manifest* dpm_module_manifest(void)`**
|
||||
A static table declaring the module's entire functional surface: an entry count and, per entry, the API name, its table version, and the exact exported symbol carrying the table — for example { "mymodule", 1, "mymodule_api_v1" }. Only manifest-declared tables are ever handed to consumers; an API absent from the manifest does not exist, even if its symbol does. A module providing no API tables returns a manifest with a count of zero.
|
||||
|
||||
The dpm_manifest and dpm_manifest_entry types, the table header, and the service declarations all come from the installed public header:
|
||||
The `dpm_manifest` and `dpm_manifest_entry` types, the table header, and the service declarations all come from the installed public header:
|
||||
|
||||
```
|
||||
#include <dpm/core.h>
|
||||
@@ -29,7 +29,7 @@ The dpm_manifest and dpm_manifest_entry types, the table header, and the service
|
||||
|
||||
## API tables
|
||||
|
||||
A module's functions are published to consumers as API tables: one exported symbol per API version (mymodule_api_v1), pointing to a plain C struct of function pointers. Every table opens with a dpm_api_table_header — the DPM_API_TABLE_MAGIC constant, then the table struct's size in bytes as the module compiled it. Later revisions of the same version may append fields at the tail; the size field lets consumers detect what is present.
|
||||
A module's functions are published to consumers as API tables: one exported symbol per API version (`mymodule_api_v1`), pointing to a plain C struct of function pointers. Every table opens with a `dpm_api_table_header` — the `DPM_API_TABLE_MAGIC` constant, then the table struct's size in bytes as the module compiled it. A consumer compares that size against the layout it was built against to see what it has been handed.
|
||||
|
||||
All parameters and return values crossing a table are C types only. State passes through opaque handles; errors are int codes.
|
||||
|
||||
@@ -69,22 +69,22 @@ cmake --build <build-dir>
|
||||
|
||||
libdpm-core is the only DPM link dependency a module ever has. Dependencies on other modules are runtime concerns, resolved through the require/get_api pair — a peer module is never linked and never needs to be present to build.
|
||||
|
||||
A module that depends on a peer is the party that judges the peer's version. Require it, read its reported version with dpm_module_info_of, and decide whether it is too new or too old for the calls you intend to make. libdpm-core reports; it does not rule.
|
||||
A module that depends on a peer is the party that judges the peer's version. Require it, read its reported version with `dpm_module_info_of`, and decide whether it is too new or too old for the calls you intend to make. libdpm-core reports; it does not rule.
|
||||
|
||||
## Running and testing locally
|
||||
|
||||
Load the freshly built module through a locally run dpm without installing anything:
|
||||
Load the freshly built module through a locally run `dpm` without installing anything:
|
||||
|
||||
```
|
||||
dpm --module-path <build-dir> mymodule <command>
|
||||
```
|
||||
|
||||
libdpm-core runs the full validation sequence on every load, so a contract mistake surfaces here, immediately and itemized, rather than after installation. The --config-dir flag points the module's configuration namespace at local files during development, and --root directs package operations at a scratch tree.
|
||||
libdpm-core runs the full validation sequence on every load, so a contract mistake surfaces here, immediately and itemized, rather than after installation. The `--config-dir` flag points the module's configuration namespace at local files during development, and `--root` directs package operations at a scratch tree.
|
||||
|
||||
## Installing
|
||||
|
||||
Modules install to lib/dpm/modules under the install prefix (/usr/lib/dpm/modules on a distribution install). libdpm-core discovers the module on its next scan; no registration step exists beyond the file being present and valid.
|
||||
Modules install to `lib/dpm/modules` under the install prefix (`/usr/lib/dpm/modules` on a distribution install). libdpm-core discovers the module on its next scan; no registration step exists beyond the file being present and valid.
|
||||
|
||||
## A working example
|
||||
|
||||
The info module bundled with the dpm binary and libdpm-core, at src/bundled-modules/info/, tests and demonstrates full DPM system functionality, and in doing so shows the contract, an API table, and this build structure in working form.
|
||||
The info module bundled with the `dpm` binary and libdpm-core, at `src/bundled-modules/info/`, tests and demonstrates full DPM system functionality, and in doing so shows the contract, an API table, and this build structure in working form.
|
||||
|
||||
Reference in New Issue
Block a user