A module had one channel back to its caller: the int returned from dpm_module_execute, handed through by dpm_execute. Any detail behind that number could only reach a log, so a caller wanting the reason had to read output rather than ask for it. dpm_set_last_error joins the exported API. A module records its reason on the context handed to its entry point, which belongs to the caller, and the caller reads it back with dpm_get_last_error. The two accessors on the context now say what they do to it: dpm_module_path becomes dpm_get_resolved_module_path, naming the value it reports rather than the setting it came from, and dpm_last_error becomes dpm_get_last_error, pairing with the setter. Path normalization moves to sanitizers.cpp, which holds the conversions that put a value written by a person into the single form the library stores it in.
191 lines
7.2 KiB
CMake
191 lines
7.2 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/conf.cpp
|
|
src/core/context.cpp
|
|
src/core/logging.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)
|