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.
This commit is contained in:
@@ -164,7 +164,10 @@ option(DPM_DOCS_PDF "Generate the code reference as PDF (requires LaTeX)" ON)
|
|||||||
|
|
||||||
find_package(Doxygen)
|
find_package(Doxygen)
|
||||||
if(DOXYGEN_FOUND)
|
if(DOXYGEN_FOUND)
|
||||||
set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/docs)
|
# Doxygen and LaTeX both work in scratch space under docs/tmp. The
|
||||||
|
# finished document is copied up into docs/, so the directory a user
|
||||||
|
# opens holds documentation and nothing else.
|
||||||
|
set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/docs/tmp)
|
||||||
set(DOXYGEN_EXTRACT_ALL YES)
|
set(DOXYGEN_EXTRACT_ALL YES)
|
||||||
set(DOXYGEN_EXTRACT_STATIC YES)
|
set(DOXYGEN_EXTRACT_STATIC YES)
|
||||||
set(DOXYGEN_QUIET YES)
|
set(DOXYGEN_QUIET YES)
|
||||||
@@ -185,24 +188,45 @@ if(DOXYGEN_FOUND)
|
|||||||
set(DOXYGEN_GENERATE_LATEX NO)
|
set(DOXYGEN_GENERATE_LATEX NO)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
doxygen_add_docs(docs
|
# OVERVIEW.md becomes the reference's front page, so the generated
|
||||||
|
# document opens on the project description instead of a bare index.
|
||||||
|
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE ${CMAKE_CURRENT_SOURCE_DIR}/docs/OVERVIEW.md)
|
||||||
|
|
||||||
|
doxygen_add_docs(docs-generate
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/docs
|
||||||
COMMENT "Generating code reference with Doxygen"
|
COMMENT "Generating code reference with Doxygen"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# The one target a user builds. Everything below hangs off it, so
|
||||||
|
# `cmake --build <dir> --target docs` produces finished documents.
|
||||||
|
add_custom_target(docs COMMENT "Building the code reference")
|
||||||
|
add_dependencies(docs docs-generate)
|
||||||
|
|
||||||
if(DPM_DOCS_PDF)
|
if(DPM_DOCS_PDF)
|
||||||
find_program(PDFLATEX_EXECUTABLE pdflatex)
|
find_program(PDFLATEX_EXECUTABLE pdflatex)
|
||||||
if(PDFLATEX_EXECUTABLE)
|
if(PDFLATEX_EXECUTABLE)
|
||||||
add_custom_target(docs-pdf
|
add_custom_command(TARGET docs POST_BUILD
|
||||||
COMMAND make -C ${CMAKE_BINARY_DIR}/docs/latex
|
COMMAND make -C ${CMAKE_BINARY_DIR}/docs/tmp/latex
|
||||||
COMMENT "Building PDF code reference"
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${CMAKE_BINARY_DIR}/docs/tmp/latex/refman.pdf
|
||||||
|
${CMAKE_BINARY_DIR}/docs/pdf/dpm-core-${PROJECT_VERSION}.pdf
|
||||||
|
COMMENT "Compiling the PDF reference"
|
||||||
)
|
)
|
||||||
add_dependencies(docs-pdf docs)
|
|
||||||
else()
|
else()
|
||||||
message(WARNING "DPM_DOCS_PDF is ON but pdflatex was not found; the docs-pdf target is unavailable")
|
message(WARNING "DPM_DOCS_PDF is ON but pdflatex was not found; no PDF will be produced")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(DPM_DOCS_HTML)
|
||||||
|
add_custom_command(TARGET docs POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
${CMAKE_BINARY_DIR}/docs/tmp/html
|
||||||
|
${CMAKE_BINARY_DIR}/docs/html
|
||||||
|
COMMENT "Placing the HTML reference"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
# ---------------------------------------------------------------------
|
||||||
|
|||||||
@@ -34,14 +34,16 @@ To point a context elsewhere, pass overrides — every field is optional:
|
|||||||
|
|
||||||
```
|
```
|
||||||
dpm_open_overrides ov = {
|
dpm_open_overrides ov = {
|
||||||
"/path/to/conf.d", /* config_dir: NULL = /etc/dpm/conf.d/ */
|
"/path/to/conf.d",
|
||||||
"/path/to/modules", /* module_path: NULL = config, then default */
|
"/path/to/modules",
|
||||||
"/path/to/root", /* root: target root for package operations */
|
"/path/to/root",
|
||||||
-1 /* log_level: -1 = from config */
|
-1
|
||||||
};
|
};
|
||||||
dpm_ctx* ctx = dpm_open(&ov);
|
dpm_ctx* ctx = dpm_open(&ov);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Leaving `config_dir` NULL selects `/etc/dpm/conf.d/`; leaving `module_path` NULL selects the configured value and then the built-in default; leaving `root` NULL selects `/`; a `log_level` of -1 takes the configured value.
|
||||||
|
|
||||||
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.
|
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
|
## Acquiring and using modules
|
||||||
@@ -58,9 +60,11 @@ libdpm-core.so validates the module completely at load; a handle is returned onl
|
|||||||
|
|
||||||
```
|
```
|
||||||
dpm_module_info info;
|
dpm_module_info info;
|
||||||
dpm_module_info_of(ctx, mod, &info); /* info.name, .version, .description */
|
dpm_module_info_of(ctx, mod, &info);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`info` carries `name`, `version`, and `description`.
|
||||||
|
|
||||||
Deciding whether that version is suitable is yours. libdpm-core.so applies no version criterion of its own — a handle means the module is valid, not that it suits you.
|
Deciding whether that version is suitable is yours. libdpm-core.so applies no version criterion of its own — a handle means the module is valid, not that it suits you.
|
||||||
|
|
||||||
**`dpm_execute`** invokes the module — a command name and arguments:
|
**`dpm_execute`** invokes the module — a command name and arguments:
|
||||||
@@ -77,7 +81,7 @@ This is the only path into module code, and it is the same path the `dpm` binary
|
|||||||
dpm_cursor* cur = dpm_list_modules(ctx);
|
dpm_cursor* cur = dpm_list_modules(ctx);
|
||||||
dpm_module_info info;
|
dpm_module_info info;
|
||||||
while (dpm_cursor_next(cur, &info) == 0) {
|
while (dpm_cursor_next(cur, &info) == 0) {
|
||||||
/* info.name, info.version, info.description */
|
/* each iteration fills info */
|
||||||
}
|
}
|
||||||
dpm_cursor_free(cur);
|
dpm_cursor_free(cur);
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,20 +1,28 @@
|
|||||||
# Generating the Code Reference
|
# Generating the Code Reference
|
||||||
|
|
||||||
When Doxygen is present, the build offers a `docs` target that generates the API and source reference from the documentation comments carried in the headers and sources. Two output formats are available as configure-time options:
|
When Doxygen is present, the build offers a `docs` target that produces the reference from the documentation comments carried in the headers and sources, together with the markdown documents in `docs/`. OVERVIEW.md becomes its front page, and DESIGN.md, MODULES.md, CONSUMERS.md, BUILD.md, and this file follow as chapters ahead of the namespace, class, and file reference.
|
||||||
|
|
||||||
|
One command generates it:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake --build <build-dir> --target docs
|
||||||
|
```
|
||||||
|
|
||||||
|
The finished documents land in `<build-dir>/docs/`:
|
||||||
|
|
||||||
|
```
|
||||||
|
<build-dir>/docs/pdf/dpm-core-<version>.pdf the PDF reference
|
||||||
|
<build-dir>/docs/html/index.html the HTML reference
|
||||||
|
<build-dir>/docs/tmp/ scratch space for the generators
|
||||||
|
```
|
||||||
|
|
||||||
|
Doxygen and LaTeX both work under `docs/tmp/`, and the finished document is copied up into `docs/`. `cmake --build <build-dir> --target clean` removes the whole tree.
|
||||||
|
|
||||||
|
Two output formats are available as configure-time options:
|
||||||
|
|
||||||
- **`-DDPM_DOCS_PDF`** (default ON) — PDF reference, via Doxygen's native LaTeX output; requires `pdflatex` and `makeindex`
|
- **`-DDPM_DOCS_PDF`** (default ON) — PDF reference, via Doxygen's native LaTeX output; requires `pdflatex` and `makeindex`
|
||||||
- **`-DDPM_DOCS_HTML`** (default OFF) — HTML reference
|
- **`-DDPM_DOCS_HTML`** (default OFF) — HTML reference
|
||||||
|
|
||||||
Generate and compile the PDF reference:
|
|
||||||
|
|
||||||
```
|
|
||||||
cmake --build <build-dir> --target docs-pdf
|
|
||||||
```
|
|
||||||
|
|
||||||
The PDF lands at `<build-dir>/docs/latex/refman.pdf`.
|
|
||||||
|
|
||||||
With `DPM_DOCS_HTML` enabled at configure time, the `docs` target additionally produces the HTML reference in `<build-dir>/docs/html`:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
cmake -B <build-dir> -DDPM_DOCS_HTML=ON
|
cmake -B <build-dir> -DDPM_DOCS_HTML=ON
|
||||||
cmake --build <build-dir> --target docs
|
cmake --build <build-dir> --target docs
|
||||||
|
|||||||
@@ -40,9 +40,10 @@ extern "C" {
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the public API visible. The library is compiled with hidden
|
* @brief Marks the public API visible
|
||||||
* default symbol visibility; these functions are its entire exported
|
*
|
||||||
* surface.
|
* The library is compiled with hidden default symbol visibility; the
|
||||||
|
* functions carrying this are its entire exported surface.
|
||||||
*/
|
*/
|
||||||
#ifndef DPM_API
|
#ifndef DPM_API
|
||||||
#define DPM_API __attribute__((visibility("default")))
|
#define DPM_API __attribute__((visibility("default")))
|
||||||
@@ -60,11 +61,25 @@ typedef struct dpm_cursor dpm_cursor;
|
|||||||
/* Log levels */
|
/* Log levels */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Severity levels accepted by dpm_log()
|
||||||
|
*
|
||||||
|
* A message at a level above the context's configured level is dropped.
|
||||||
|
*/
|
||||||
enum {
|
enum {
|
||||||
|
/** Unrecoverable failure. */
|
||||||
DPM_LOG_FATAL = 0,
|
DPM_LOG_FATAL = 0,
|
||||||
|
|
||||||
|
/** Operation failed. */
|
||||||
DPM_LOG_ERROR = 1,
|
DPM_LOG_ERROR = 1,
|
||||||
DPM_LOG_WARN = 2,
|
|
||||||
DPM_LOG_INFO = 3,
|
/** Operation continued, something was wrong. */
|
||||||
|
DPM_LOG_WARN = 2,
|
||||||
|
|
||||||
|
/** Normal reporting; the default level. */
|
||||||
|
DPM_LOG_INFO = 3,
|
||||||
|
|
||||||
|
/** Detail for diagnosing behaviour. */
|
||||||
DPM_LOG_DEBUG = 4
|
DPM_LOG_DEBUG = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,25 +88,45 @@ enum {
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides for dpm_open(). Any field may be left NULL (or -1 for
|
* @brief Overrides for dpm_open()
|
||||||
* log_level) to accept configuration-file values and built-in defaults.
|
*
|
||||||
* Every field here is exposed as a dpm CLI flag.
|
* Any field may be left NULL (or -1 for log_level) to accept
|
||||||
|
* configuration-file values and built-in defaults. Every field here is
|
||||||
|
* exposed as a flag on the dpm binary.
|
||||||
*/
|
*/
|
||||||
typedef struct dpm_open_overrides {
|
typedef struct dpm_open_overrides {
|
||||||
const char* config_dir; /* NULL = /etc/dpm/conf.d/ */
|
/** NULL selects /etc/dpm/conf.d/. */
|
||||||
const char* module_path; /* NULL = config value, then built-in */
|
const char* config_dir;
|
||||||
const char* root; /* NULL = "/" (target root for pkg ops) */
|
|
||||||
int log_level; /* -1 = config value; else DPM_LOG_* */
|
/** NULL selects the configured value, then the built-in default. */
|
||||||
|
const char* module_path;
|
||||||
|
|
||||||
|
/** NULL selects "/", the target root for package operations. */
|
||||||
|
const char* root;
|
||||||
|
|
||||||
|
/** -1 selects the configured value; otherwise a DPM_LOG_* level. */
|
||||||
|
int log_level;
|
||||||
} dpm_open_overrides;
|
} dpm_open_overrides;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Module information (enumeration results) */
|
/* Module information (enumeration results) */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief What the library read from a module at load
|
||||||
|
*
|
||||||
|
* Filled by dpm_module_info_of() and by dpm_cursor_next(). The string
|
||||||
|
* pointers remain valid until the context is closed.
|
||||||
|
*/
|
||||||
typedef struct dpm_module_info {
|
typedef struct dpm_module_info {
|
||||||
const char* name; /* module name (filename minus .so) */
|
/** Module name, its filename minus .so. */
|
||||||
const char* version; /* module's own X.Y.Z */
|
const char* name;
|
||||||
const char* description; /* one-line description */
|
|
||||||
|
/** The module's own X.Y.Z. */
|
||||||
|
const char* version;
|
||||||
|
|
||||||
|
/** One-line description. */
|
||||||
|
const char* description;
|
||||||
} dpm_module_info;
|
} dpm_module_info;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -285,17 +320,28 @@ DPM_API const char* dpm_last_error(dpm_ctx* ctx);
|
|||||||
/* Module contract (implemented by modules, called by libdpm-core) */
|
/* Module contract (implemented by modules, called by libdpm-core) */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Every module exports, as extern "C":
|
* @page module_contract The module contract
|
||||||
*
|
*
|
||||||
* int dpm_module_execute(dpm_ctx* ctx, const char* command,
|
* A module is one .so in the module directory. It includes
|
||||||
* int argc, char** argv);
|
* <dpm/core.h>, links -ldpm-core, and exports three reserved symbols as
|
||||||
* const char* dpm_module_version(void);
|
* extern "C":
|
||||||
* const char* dpm_module_description(void);
|
*
|
||||||
|
* @code
|
||||||
|
* int dpm_module_execute(dpm_ctx* ctx, const char* command,
|
||||||
|
* int argc, char** argv);
|
||||||
|
* const char* dpm_module_version(void);
|
||||||
|
* const char* dpm_module_description(void);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @section module_contract_surface The functional surface
|
||||||
*
|
*
|
||||||
* dpm_module_execute is the module's entire functional surface; its
|
* dpm_module_execute is the module's entire functional surface; its
|
||||||
* capabilities are addressed by command string, so a module publishes
|
* capabilities are addressed by command string, so a module publishes
|
||||||
* no headers, struct layouts, or symbols to anything that calls it.
|
* no headers, struct layouts, or symbols to anything that calls it.
|
||||||
|
* NULL or an empty command behaves as the module's help command.
|
||||||
|
*
|
||||||
|
* @section module_contract_version Version compatibility
|
||||||
*
|
*
|
||||||
* A module determines for itself whether it can work with the library
|
* A module determines for itself whether it can work with the library
|
||||||
* it is running against: dpm_core_version() reports the running
|
* it is running against: dpm_core_version() reports the running
|
||||||
@@ -303,8 +349,12 @@ DPM_API const char* dpm_last_error(dpm_ctx* ctx);
|
|||||||
* module is built against the system-installed libdpm-core.so and is
|
* module is built against the system-installed libdpm-core.so and is
|
||||||
* responsible for being correct against it.
|
* responsible for being correct against it.
|
||||||
*
|
*
|
||||||
|
* @section module_contract_validation Validation
|
||||||
|
*
|
||||||
* The library refuses to load any module that does not validate
|
* The library refuses to load any module that does not validate
|
||||||
* completely (see the DPM specification: load-time enforcement).
|
* completely: every reserved symbol resolves, and the version and
|
||||||
|
* description probes return well-formed values. A module that loads is
|
||||||
|
* fully valid.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -32,22 +32,33 @@
|
|||||||
|
|
||||||
/** @brief A libdpm-core context: configuration, logging, module registry */
|
/** @brief A libdpm-core context: configuration, logging, module registry */
|
||||||
struct dpm_ctx {
|
struct dpm_ctx {
|
||||||
|
/** Directory the .conf files were read from. */
|
||||||
std::string config_dir;
|
std::string config_dir;
|
||||||
|
|
||||||
|
/** Directory modules are loaded from. */
|
||||||
std::string module_path;
|
std::string module_path;
|
||||||
|
|
||||||
|
/** Target root for package operations. */
|
||||||
std::string root;
|
std::string root;
|
||||||
|
|
||||||
int log_level = DPM_LOG_INFO;
|
/** Messages above this level are dropped. */
|
||||||
bool write_to_log = false;
|
int log_level = DPM_LOG_INFO;
|
||||||
|
|
||||||
|
/** Whether to append messages to log_file. */
|
||||||
|
bool write_to_log = false;
|
||||||
|
|
||||||
|
/** Path of the log file. */
|
||||||
std::string log_file;
|
std::string log_file;
|
||||||
|
|
||||||
/* config[module][section][key] = value */
|
/** Configuration store, addressed as config[module][section][key]. */
|
||||||
std::map<std::string,
|
std::map<std::string,
|
||||||
std::map<std::string,
|
std::map<std::string,
|
||||||
std::map<std::string, std::string>>> config;
|
std::map<std::string, std::string>>> config;
|
||||||
|
|
||||||
/* validated modules, keyed by name; loaded at most once per ctx */
|
/** Validated modules keyed by name; each is loaded at most once. */
|
||||||
std::map<std::string, std::unique_ptr<dpm_module>> modules;
|
std::map<std::string, std::unique_ptr<dpm_module>> modules;
|
||||||
|
|
||||||
|
/** Reason for the most recent failure. */
|
||||||
std::string last_error;
|
std::string last_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -30,16 +30,28 @@
|
|||||||
|
|
||||||
/** @brief A loaded, fully validated module */
|
/** @brief A loaded, fully validated module */
|
||||||
struct dpm_module {
|
struct dpm_module {
|
||||||
|
/** Module name, its filename minus .so. */
|
||||||
std::string name;
|
std::string name;
|
||||||
void* handle = nullptr;
|
|
||||||
|
/** The dlopen handle. */
|
||||||
|
void* handle = nullptr;
|
||||||
|
|
||||||
|
/** dpm_module_version() as read at load. */
|
||||||
std::string version;
|
std::string version;
|
||||||
|
|
||||||
|
/** dpm_module_description() as read at load. */
|
||||||
std::string description;
|
std::string description;
|
||||||
|
|
||||||
|
/** Resolved dpm_module_execute; the only path into module code. */
|
||||||
int (*execute)(dpm_ctx*, const char*, int, char**) = nullptr;
|
int (*execute)(dpm_ctx*, const char*, int, char**) = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief Enumeration cursor over validated modules */
|
/** @brief Enumeration cursor over validated modules */
|
||||||
struct dpm_cursor {
|
struct dpm_cursor {
|
||||||
|
/** One entry per valid module. */
|
||||||
std::vector<dpm_module_info> infos;
|
std::vector<dpm_module_info> infos;
|
||||||
|
|
||||||
|
/** Position of the next entry. */
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -29,11 +29,20 @@
|
|||||||
* @brief Commands supported by the info module
|
* @brief Commands supported by the info module
|
||||||
*/
|
*/
|
||||||
enum Command {
|
enum Command {
|
||||||
CMD_UNKNOWN, /**< Unknown or unsupported command */
|
/** Unknown or unsupported command. */
|
||||||
CMD_HELP, /**< Display help information */
|
CMD_UNKNOWN,
|
||||||
CMD_VERSION, /**< Display libdpm-core and module versions */
|
|
||||||
CMD_SYSTEM, /**< Display system information */
|
/** Display help information. */
|
||||||
CMD_CONFIG, /**< Display configuration information */
|
CMD_HELP,
|
||||||
|
|
||||||
|
/** Display library and module versions. */
|
||||||
|
CMD_VERSION,
|
||||||
|
|
||||||
|
/** Display system information. */
|
||||||
|
CMD_SYSTEM,
|
||||||
|
|
||||||
|
/** Display configuration information. */
|
||||||
|
CMD_CONFIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,65 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* libdpm-core.map — the linker version script for libdpm-core.so
|
* libdpm-core.map — holds libdpm-core.so's exports to the public C API,
|
||||||
|
* so <dpm/core.h> describes the binary exactly and the implementation
|
||||||
|
* behind it stays private.
|
||||||
*
|
*
|
||||||
* Passed to the linker with --version-script; see CMakeLists.txt, which
|
* Passed to the linker with --version-script. `dpm_*` passes the
|
||||||
* also lists it as a link dependency so edits force a relink. It does
|
* functions marked DPM_API in the header, which is where membership is
|
||||||
* two separate jobs.
|
* decided; `local: *` hides the rest, including the template
|
||||||
*
|
* instantiations libstdc++ headers emit with default visibility.
|
||||||
*
|
|
||||||
* 1. It limits the export set.
|
|
||||||
*
|
|
||||||
* `global` names every function declared in <dpm/core.h>. `local: *`
|
|
||||||
* hides everything else, including the template instantiations that
|
|
||||||
* libstdc++ headers emit with default visibility.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* 2. It versions the exports.
|
|
||||||
*
|
|
||||||
* Every symbol here is stamped with the node name: dpm_open becomes
|
|
||||||
* dpm_open@@DPM_CORE_1.0. The linker reads that node off the library a
|
|
||||||
* consumer links against and records it in the consumer's own binary,
|
|
||||||
* and at startup the dynamic linker verifies the library still provides
|
|
||||||
* it.
|
|
||||||
*
|
|
||||||
* That keeps an already-installed module working after the library
|
|
||||||
* changes underneath it, which is what makes updating libdpm-core.so
|
|
||||||
* safe mid-bootstrap.
|
|
||||||
*
|
|
||||||
* A breaking change ships as a new node while the old node keeps its
|
|
||||||
* original definitions, so binaries built against the old node keep
|
|
||||||
* resolving them. Both live in one .so under one soname, preserving the
|
|
||||||
* invariant the routing model depends on: exactly one instance of the
|
|
||||||
* library mapped per process.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Changing this file:
|
|
||||||
*
|
|
||||||
* - A new public function goes into `global` in the same commit that
|
|
||||||
* adds it to <dpm/core.h>.
|
|
||||||
* - A breaking change to an existing function adds a new node above
|
|
||||||
* DPM_CORE_1.0, leaving this node and its definitions intact.
|
|
||||||
*
|
|
||||||
* Newest node first. DPM_CORE_0.1 was never released; it is here as the
|
|
||||||
* shape a retired node takes.
|
|
||||||
*/
|
*/
|
||||||
DPM_CORE_1.0 {
|
{
|
||||||
global:
|
global:
|
||||||
dpm_open;
|
dpm_*;
|
||||||
dpm_close;
|
|
||||||
dpm_require;
|
|
||||||
dpm_module_info_of;
|
|
||||||
dpm_execute;
|
|
||||||
dpm_list_modules;
|
|
||||||
dpm_cursor_next;
|
|
||||||
dpm_cursor_free;
|
|
||||||
dpm_core_version;
|
|
||||||
dpm_config_get;
|
|
||||||
dpm_log;
|
|
||||||
dpm_module_path;
|
|
||||||
dpm_last_error;
|
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
|
||||||
DPM_CORE_0.1 {
|
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user