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>
This commit is contained in:
@@ -92,7 +92,7 @@ typedef struct dpm_module_info {
|
||||
const char* name; /* module name (filename minus .so) */
|
||||
const char* version; /* module's own X.Y.Z */
|
||||
const char* description; /* one-line description */
|
||||
const char* core_min; /* minimum core version it supports */
|
||||
const char* core_min; /* minimum libdpm-core version it supports */
|
||||
} dpm_module_info;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -131,7 +131,7 @@ typedef struct dpm_manifest {
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Creates a core context
|
||||
* @brief Creates a libdpm-core context
|
||||
*
|
||||
* Reads configuration from /etc/dpm/conf.d/ (or the overridden config
|
||||
* directory), resolves the module path (override > config > built-in
|
||||
@@ -148,7 +148,7 @@ typedef struct dpm_manifest {
|
||||
DPM_API dpm_ctx* dpm_open(const dpm_open_overrides* overrides);
|
||||
|
||||
/**
|
||||
* @brief Releases a core context
|
||||
* @brief Releases a libdpm-core context
|
||||
*
|
||||
* Unloads every module handle the context issued, closes log targets,
|
||||
* and frees all memory owned by the context. All handles and strings
|
||||
@@ -170,15 +170,34 @@ DPM_API void dpm_close(dpm_ctx* ctx);
|
||||
* context. Modules are loaded at most once per context; repeated
|
||||
* calls return the same handle.
|
||||
*
|
||||
* @param ctx The core context
|
||||
* Version compatibility is the caller's judgement, not this library's:
|
||||
* read the loaded module's version with dpm_module_info_of() and
|
||||
* decide whether it is acceptable.
|
||||
*
|
||||
* @param ctx The libdpm-core context
|
||||
* @param name The module name (its filename minus .so)
|
||||
* @param min_version Minimum acceptable module version as X.Y.Z;
|
||||
* NULL accepts any version
|
||||
* @return A module handle owned by the context, or NULL on failure
|
||||
* with the precise reason retrievable via dpm_last_error()
|
||||
*/
|
||||
DPM_API dpm_module* dpm_require(dpm_ctx* ctx, const char* name,
|
||||
const char* min_version);
|
||||
DPM_API dpm_module* dpm_require(dpm_ctx* ctx, const char* name);
|
||||
|
||||
/**
|
||||
* @brief Reports what libdpm-core sees in a loaded module
|
||||
*
|
||||
* Fills `out` with the module's name, version, description, and
|
||||
* minimum-libdpm-core version, exactly as they were read at load. No
|
||||
* compatibility conclusion is drawn from these values; the caller
|
||||
* decides whether the version it is looking at is too new or too
|
||||
* old for its purposes.
|
||||
*
|
||||
* @param ctx The libdpm-core context
|
||||
* @param mod A module handle from dpm_require()
|
||||
* @param out Receives the module's information; the string pointers
|
||||
* remain valid until context close
|
||||
* @return 0 on success, nonzero if the module cannot be reported on
|
||||
*/
|
||||
DPM_API int dpm_module_info_of(dpm_ctx* ctx, dpm_module* mod,
|
||||
dpm_module_info* out);
|
||||
|
||||
/**
|
||||
* @brief Returns a module's API table for direct typed calls
|
||||
@@ -188,7 +207,7 @@ DPM_API dpm_module* dpm_require(dpm_ctx* ctx, const char* name,
|
||||
* table struct type for that API and version. The table is valid for
|
||||
* the life of the context.
|
||||
*
|
||||
* @param ctx The core context
|
||||
* @param ctx The libdpm-core context
|
||||
* @param mod A module handle from dpm_require()
|
||||
* @param api_name The API name as declared in the module's manifest
|
||||
* @param table_version The table version to retrieve
|
||||
@@ -205,7 +224,7 @@ DPM_API const void* dpm_get_api(dpm_ctx* ctx, dpm_module* mod,
|
||||
* command, and the argument vector. argv[0] is the command when
|
||||
* argc > 0; semantics beyond that are the module's to define.
|
||||
*
|
||||
* @param ctx The core context
|
||||
* @param ctx The libdpm-core context
|
||||
* @param mod A module handle from dpm_require()
|
||||
* @param command The command name; NULL or empty behaves as the
|
||||
* module's help command
|
||||
@@ -226,7 +245,7 @@ DPM_API int dpm_execute(dpm_ctx* ctx, dpm_module* mod, const char* command,
|
||||
* Scans the module path and validates each candidate .so; failures
|
||||
* are logged and excluded from the results.
|
||||
*
|
||||
* @param ctx The core context
|
||||
* @param ctx The libdpm-core context
|
||||
* @return A cursor over all valid modules, or NULL on an unreadable
|
||||
* module path
|
||||
*/
|
||||
@@ -236,7 +255,7 @@ DPM_API dpm_cursor* dpm_list_modules(dpm_ctx* ctx);
|
||||
* @brief Advances an enumeration cursor
|
||||
*
|
||||
* Fills `out` with the next module's name, version, description, and
|
||||
* minimum-core version; the string pointers remain valid until
|
||||
* minimum-libdpm-core version; the string pointers remain valid until
|
||||
* context close.
|
||||
*
|
||||
* @param cur The cursor from dpm_list_modules()
|
||||
@@ -257,10 +276,10 @@ DPM_API void dpm_cursor_free(dpm_cursor* cur);
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Returns core's own version
|
||||
* @brief Returns libdpm-core's own version
|
||||
*
|
||||
* @return Core's version as a static X.Y.Z string; callable without
|
||||
* a context
|
||||
* @return The libdpm-core version as a static X.Y.Z string; callable
|
||||
* without a context
|
||||
*/
|
||||
DPM_API const char* dpm_core_version(void);
|
||||
|
||||
@@ -268,9 +287,10 @@ DPM_API const char* dpm_core_version(void);
|
||||
* @brief Returns a configuration value from a module's namespace
|
||||
*
|
||||
* A module's configuration namespace is its own .conf file under the
|
||||
* context's configuration directory; "core" names core's own file.
|
||||
* context's configuration directory; the namespace named "core", from
|
||||
* core.conf, is the library's own.
|
||||
*
|
||||
* @param ctx The core context
|
||||
* @param ctx The libdpm-core context
|
||||
* @param module The configuration namespace to read
|
||||
* @param section The section name within the file
|
||||
* @param key The key within the section
|
||||
@@ -286,7 +306,7 @@ DPM_API const char* dpm_config_get(dpm_ctx* ctx, const char* module,
|
||||
* Targets are the console and, when configured, the log file.
|
||||
* Messages above the configured level are dropped.
|
||||
*
|
||||
* @param ctx The core context
|
||||
* @param ctx The libdpm-core context
|
||||
* @param level The severity (DPM_LOG_FATAL through DPM_LOG_DEBUG)
|
||||
* @param message The message to log; NULL is a no-op
|
||||
*/
|
||||
@@ -295,7 +315,7 @@ DPM_API void dpm_log(dpm_ctx* ctx, int level, const char* message);
|
||||
/**
|
||||
* @brief Returns the resolved module directory path
|
||||
*
|
||||
* @param ctx The core context
|
||||
* @param ctx The libdpm-core context
|
||||
* @return The module directory path this context resolved
|
||||
*/
|
||||
DPM_API const char* dpm_module_path(dpm_ctx* ctx);
|
||||
@@ -303,14 +323,14 @@ DPM_API const char* dpm_module_path(dpm_ctx* ctx);
|
||||
/**
|
||||
* @brief Returns the most recent failure recorded on the context
|
||||
*
|
||||
* @param ctx The core context
|
||||
* @param ctx The libdpm-core context
|
||||
* @return A human-readable description of the most recent failure, or
|
||||
* NULL if none; overwritten by the next failing call
|
||||
*/
|
||||
DPM_API const char* dpm_last_error(dpm_ctx* ctx);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Module contract (implemented by modules, called by core) */
|
||||
/* Module contract (implemented by modules, called by libdpm-core) */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
@@ -323,7 +343,8 @@ DPM_API const char* dpm_last_error(dpm_ctx* ctx);
|
||||
* const char* dpm_module_core_min(void);
|
||||
* const dpm_manifest* dpm_module_manifest(void);
|
||||
*
|
||||
* plus one exported table symbol per manifest entry. Core refuses to
|
||||
* plus one exported table symbol per manifest entry. libdpm-core
|
||||
* refuses to
|
||||
* load any module that does not validate completely (see the DPM
|
||||
* specification: load-time enforcement).
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file context.hpp
|
||||
* @brief The core context: configuration, logging, module registry
|
||||
* @brief The libdpm-core context: configuration, logging, module registry
|
||||
*
|
||||
* @copyright Copyright (c) 2026 SILO GROUP LLC
|
||||
* @author Chris Punches <chris.punches@silogroup.org>
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "internal/modules.hpp"
|
||||
|
||||
/** @brief A core context: configuration, logging, and the module registry */
|
||||
/** @brief A libdpm-core context: configuration, logging, module registry */
|
||||
struct dpm_ctx {
|
||||
std::string config_dir;
|
||||
std::string module_path;
|
||||
@@ -56,7 +56,7 @@ namespace dpmcore {
|
||||
/**
|
||||
* @brief Records a failure reason on the context
|
||||
*
|
||||
* @param ctx The core context; NULL is a no-op
|
||||
* @param ctx The libdpm-core context; NULL is a no-op
|
||||
* @param msg The failure description
|
||||
*/
|
||||
void set_error(dpm_ctx* ctx, const std::string& msg);
|
||||
@@ -67,7 +67,7 @@ void set_error(dpm_ctx* ctx, const std::string& msg);
|
||||
* Parses every .conf file in the context's configuration directory
|
||||
* into the context's configuration store.
|
||||
*
|
||||
* @param ctx The core context
|
||||
* @param ctx The libdpm-core context
|
||||
*/
|
||||
void load_config_dir(dpm_ctx* ctx);
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace dpmcore {
|
||||
* Loads the named module's .so from the context's module path and
|
||||
* verifies the complete contract.
|
||||
*
|
||||
* @param ctx The core context
|
||||
* @param ctx The libdpm-core context
|
||||
* @param name The module name
|
||||
* @param reason Receives the refusal reason on failure
|
||||
* @return The validated module (caller owns), or nullptr on failure
|
||||
|
||||
Reference in New Issue
Block a user