Files
dpm-core-ng/CMakeLists.txt
Christopher M. Punches 0291e61fd8 Module records and aliases
Installation records what a module reports about itself. dpm_install_module
opens a module once, writes its version and description to a .meta file in
/var/lib/dpm/metadata/, and records the alternate names it declared in
modules.aliases beside it. dpm_uninstall_module removes both, leaving the
module file in place.

dpm_list_modules reads those records and opens no module. A module with no
record lists with a version of <uninstalled> and still loads when a caller
names it. An unreadable or absent metadata directory costs the listing its
detail and costs nothing else.

Aliases give a module alternate names, declared through the new
dpm_module_aliases contract symbol or added with dpm_add_module_alias. A
name is recorded once: one already serving as an alias, or belonging to an
installed module, is refused rather than repointed. dpm_require matches a
name against the installed modules, then the alias table, then the module
path.

The metadata directory is a fifth override field and the -M flag, and
[modules] metadata in core.conf.

The test suite is four binaries covering context, modules, records, and
aliases, each a ctest case of its own, alongside the CLI cases.
2026-08-24 03:51:39 -04:00

193 lines
7.3 KiB
CMake

cmake_minimum_required(VERSION 3.22)
# libdpm-core.so's version is declared in src/core/version.cpp, the file
# that reports it. The build reads that declaration rather than carrying
# its own copy, so the soname, the artifact filenames, and the version
# the library answers with all derive from one line of source.
file(READ src/core/version.cpp DPM_VERSION_SOURCE)
string(REGEX MATCH "DPM_CORE_VERSION_STR[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+)\""
DPM_VERSION_MATCH "${DPM_VERSION_SOURCE}")
if(NOT CMAKE_MATCH_1)
message(FATAL_ERROR
"No DPM_CORE_VERSION_STR found in src/core/version.cpp")
endif()
project(dpm-core VERSION ${CMAKE_MATCH_1} LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ---------------------------------------------------------------------
# libdpm-core.so — the library (C ABI)
# ---------------------------------------------------------------------
add_library(dpm-core SHARED
src/core/aliases.cpp
src/core/conf.cpp
src/core/context.cpp
src/core/logging.cpp
src/core/metadata.cpp
src/core/modules.cpp
src/core/sanitizers.cpp
src/core/version.cpp
)
target_include_directories(dpm-core PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# The public C API is the library's entire exported surface; internals
# stay hidden. The version script pins the export list and versions the
# symbols.
target_compile_options(dpm-core PRIVATE
-fvisibility=hidden
-fvisibility-inlines-hidden
)
target_link_options(dpm-core PRIVATE
-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/core/libdpm-core.map
)
set_property(TARGET dpm-core APPEND PROPERTY
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/core/libdpm-core.map
)
target_link_libraries(dpm-core PRIVATE ${CMAKE_DL_LIBS})
set_target_properties(dpm-core PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
)
# ---------------------------------------------------------------------
# dpm — the CLI (thin client of libdpm-core)
# ---------------------------------------------------------------------
add_executable(dpm src/cli/dpm.cpp)
target_link_libraries(dpm PRIVATE dpm-core)
set_target_properties(dpm PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
BUILD_RPATH "$ORIGIN/../lib"
)
# ---------------------------------------------------------------------
# info — the bundled module (tests and reports libdpm-core functionality)
# ---------------------------------------------------------------------
add_library(info MODULE
src/bundled-modules/info/info.cpp
src/bundled-modules/info/src/commands.cpp
)
target_include_directories(info PRIVATE src/bundled-modules/info/include)
# The one permitted link dependency: libdpm-core.
target_link_libraries(info PRIVATE dpm-core)
set_target_properties(info PROPERTIES
PREFIX ""
SUFFIX ".so"
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/modules
)
# The module bundles with libdpm-core, so building the CLI builds it too: after a
# clean, running dpm from the build tree finds a module directory that is
# populated. This orders the build only — the CLI does not link the module.
add_dependencies(dpm info)
# ---------------------------------------------------------------------
# Tests
#
# The test targets and cases are defined in tests/CMakeLists.txt. The
# paths they build into are named here, above that directory, so each is
# written once and the clean rule below refers to the same values.
# ---------------------------------------------------------------------
enable_testing()
set(DPM_TEST_DIR ${CMAKE_BINARY_DIR}/tests)
set(DPM_TEST_FIXTURE_DIR ${DPM_TEST_DIR}/fixtures)
set(DPM_TEST_RESULTS_DIR ${CMAKE_BINARY_DIR}/test-results)
# CTest's scratch area is named by its BuildDirectory configuration option.
# Writing it into DartConfiguration.tcl puts it where ctest reads it on every
# invocation — the test target, a bare ctest, and the IDE's test discovery
# alike — rather than only the ones the build drives.
file(WRITE ${CMAKE_BINARY_DIR}/DartConfiguration.tcl
"BuildDirectory: ${DPM_TEST_RESULTS_DIR}\n")
add_subdirectory(tests)
# ---------------------------------------------------------------------
# Documentation
#
# The Doxygen configuration and the 'docs' target are defined in
# docs/CMakeLists.txt. The paths it builds into are named here, above
# that directory, so each is written once and the clean rule below
# refers to the same values.
#
# The subdirectory is given its own binary directory so that CMake's
# scaffolding stays out of the documentation output.
# ---------------------------------------------------------------------
set(DPM_DOCS_DIR ${CMAKE_BINARY_DIR}/docs)
set(DPM_DOCS_TMP_DIR ${DPM_DOCS_DIR}/tmp)
set(DPM_DOCS_PDF_DIR ${DPM_DOCS_DIR}/pdf)
set(DPM_DOCS_HTML_DIR ${DPM_DOCS_DIR}/html)
add_subdirectory(docs ${CMAKE_BINARY_DIR}/docs-build)
# ---------------------------------------------------------------------
# Clean
# ---------------------------------------------------------------------
# clean removes everything the build produced and leaves the configured
# build system in place, so the next build proceeds from the directory
# as it stands.
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES
# Build artifacts.
${CMAKE_BINARY_DIR}/bin
${CMAKE_BINARY_DIR}/lib
${CMAKE_BINARY_DIR}/modules
${DPM_TEST_DIR}
${DPM_DOCS_DIR}
# Test scratch areas.
${DPM_TEST_RESULTS_DIR}
${CMAKE_BINARY_DIR}/Testing
)
# distclean empties the build directory, the generated build system
# included, leaving what a freshly created directory holds: nothing.
#
# It is a terminal operation. Nothing inside the directory can drive a
# build afterwards, so the next step is `cmake -B <dir>` from outside
# it. Use it to prove a change against a tree carrying no state from
# earlier runs.
add_custom_target(distclean
COMMAND ${CMAKE_COMMAND} -E rm -rf
${CMAKE_BINARY_DIR}/bin
${CMAKE_BINARY_DIR}/lib
${CMAKE_BINARY_DIR}/modules
${DPM_TEST_DIR}
${DPM_DOCS_DIR}
${DPM_TEST_RESULTS_DIR}
${CMAKE_BINARY_DIR}/Testing
${CMAKE_BINARY_DIR}/CMakeFiles
${CMAKE_BINARY_DIR}/CMakeCache.txt
${CMAKE_BINARY_DIR}/Makefile
${CMAKE_BINARY_DIR}/cmake_install.cmake
${CMAKE_BINARY_DIR}/CTestTestfile.cmake
${CMAKE_BINARY_DIR}/DartConfiguration.tcl
${CMAKE_BINARY_DIR}/.cmake
${CMAKE_BINARY_DIR}/CMakeDoxyfile.in
${CMAKE_BINARY_DIR}/CMakeDoxygenDefaults.cmake
${CMAKE_BINARY_DIR}/docs-build
COMMENT "Emptying the build directory"
)
# ---------------------------------------------------------------------
# Installation
# ---------------------------------------------------------------------
install(TARGETS dpm RUNTIME DESTINATION bin)
install(TARGETS dpm-core LIBRARY DESTINATION lib)
install(TARGETS info LIBRARY DESTINATION lib/dpm/modules)
install(DIRECTORY include/dpm DESTINATION include)
install(FILES data/core.conf DESTINATION /etc/dpm/conf.d)