Files
dpm-core-ng/docs/CONSUMERS.md

4.5 KiB

Consuming libdpm-core

Programs link libdpm-core to operate the package manager directly: build systems, installers, image builders, system tooling, and foreign-language bindings all use the same library the dpm CLI is built on. A program holding a default context is operating the installed package manager itself — system configuration, system module path, system tree, system locking — identically to invoking the installed dpm command.

Compiling and linking

With core installed, include the public header and link the library:

#include <dpm/core.h>
g++ myprog.cpp -ldpm-core

The header installs to the standard include path and the library to the standard lib path, so no additional flags are required. The interface is a C ABI: every function is extern "C", every type crossing the boundary is a C type, and state passes through opaque handles — callable from C, C++, or any language with C FFI.

The context

All work happens through a context handle:

dpm_ctx* ctx = dpm_open(NULL);
...
dpm_close(ctx);

dpm_open(NULL) reads the system configuration (/etc/dpm/conf.d/), resolves the system module path, and targets the root filesystem. dpm_close releases every handle the context issued; all pointers obtained through the context are invalid after it.

To point a context elsewhere, pass overrides — every field is optional:

dpm_open_overrides ov = {
    "/path/to/conf.d",    /* config_dir:  NULL = /etc/dpm/conf.d/      */
    "/path/to/modules",   /* module_path: NULL = config, then default  */
    "/path/to/root",      /* root: target root for package operations  */
    -1                    /* log_level: -1 = from config               */
};
dpm_ctx* ctx = dpm_open(&ov);

The root override is what makes chroot builds, image assembly, and sysroot management work: package operations act on the given tree instead of the running system. Multiple simultaneous contexts with different roots are legal.

Acquiring and using modules

dpm_require loads a module by name, on demand, with an optional minimum version:

dpm_module* mod = dpm_require(ctx, "mymodule", "1.0.0");

Core validates the module completely at load; a handle is returned only for a fully valid module. NULL means the module is absent, invalid, or below the minimum — dpm_last_error(ctx) carries the precise reason. Modules load at most once per context; repeated calls return the same handle.

dpm_execute drives a module the way the CLI does — a command name and arguments:

int rc = dpm_execute(ctx, mod, "command", argc, argv);

dpm_get_api returns a module's typed function table for direct calls:

const mymodule_api_v1_s* api = (const mymodule_api_v1_s*)dpm_get_api(ctx, mod, "mymodule", 1);

The returned table was validated at load and is usable for the life of the context. NULL means the module does not provide that API at that version.

Enumerating modules

dpm_cursor* cur = dpm_list_modules(ctx);
dpm_module_info info;
while (dpm_cursor_next(cur, &info) == 0) {
    /* info.name, info.version, info.description, info.core_min */
}
dpm_cursor_free(cur);

The cursor covers every valid module in the module path; invalid candidates are excluded and logged.

Services

  • dpm_core_version() — core's version; callable without a context.
  • dpm_config_get(ctx, module, section, key) — a value from a module's configuration namespace, or NULL if unset.
  • dpm_log(ctx, level, message) — writes to the context's configured log targets; levels are DPM_LOG_FATAL through DPM_LOG_DEBUG.
  • dpm_module_path(ctx) — the resolved module directory.
  • dpm_last_error(ctx) — a human-readable description of the most recent failure on the context, or NULL.

Ownership and errors

Strings returned by the library are owned by the context (or by the module that produced them) and remain valid until dpm_close; callers never free them. Functions returning int use 0 for success. Functions returning pointers use NULL for failure, with detail available from dpm_last_error.

Complete example

#include <dpm/core.h>
#include <stdio.h>

int main(void) {
    dpm_ctx* ctx = dpm_open(NULL);
    if (!ctx) {
        fprintf(stderr, "failed to initialize\n");
        return 1;
    }

    dpm_module* mod = dpm_require(ctx, "info", NULL);
    if (!mod) {
        fprintf(stderr, "%s\n", dpm_last_error(ctx));
        dpm_close(ctx);
        return 1;
    }

    int rc = dpm_execute(ctx, mod, "version", 0, NULL);

    dpm_close(ctx);
    return rc;
}