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.
262 lines
10 KiB
CMake
262 lines
10 KiB
CMake
cmake_minimum_required(VERSION 3.22)
|
|
project(dpm-core VERSION 0.1.0 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/context.cpp
|
|
src/modules.cpp
|
|
src/version.cpp
|
|
)
|
|
|
|
target_include_directories(dpm-core PUBLIC
|
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
$<INSTALL_INTERFACE:include>
|
|
)
|
|
|
|
target_compile_definitions(dpm-core PRIVATE
|
|
DPM_CORE_VERSION_STR="${PROJECT_VERSION}"
|
|
)
|
|
|
|
# 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/libdpm-core.map
|
|
)
|
|
set_property(TARGET dpm-core APPEND PROPERTY
|
|
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/libdpm-core.map
|
|
)
|
|
|
|
target_link_libraries(dpm-core PRIVATE ${CMAKE_DL_LIBS})
|
|
|
|
set_target_properties(dpm-core PROPERTIES
|
|
OUTPUT_NAME "dpm-core"
|
|
VERSION ${PROJECT_VERSION}
|
|
SOVERSION 1
|
|
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)
|
|
|
|
# ---------------------------------------------------------------------
|
|
# Test fixture modules: one known-good stub, two deliberately broken
|
|
# ---------------------------------------------------------------------
|
|
enable_testing()
|
|
|
|
# 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: ${CMAKE_BINARY_DIR}/test-results\n")
|
|
|
|
set(FIXTURE_MODULE_DIR ${CMAKE_BINARY_DIR}/tests/fixtures)
|
|
|
|
foreach(fixture good missing_symbols bad_version)
|
|
add_library(fixture_${fixture} MODULE tests/fixtures/src/${fixture}.cpp)
|
|
set_target_properties(fixture_${fixture} PROPERTIES
|
|
PREFIX ""
|
|
SUFFIX ".so"
|
|
OUTPUT_NAME ${fixture}
|
|
LIBRARY_OUTPUT_DIRECTORY ${FIXTURE_MODULE_DIR}
|
|
)
|
|
endforeach()
|
|
|
|
# ---------------------------------------------------------------------
|
|
# API test binary — drives libdpm-core through its public C API
|
|
# ---------------------------------------------------------------------
|
|
add_executable(test_core tests/test_core.cpp)
|
|
|
|
target_link_libraries(test_core PRIVATE dpm-core)
|
|
|
|
target_compile_definitions(test_core PRIVATE
|
|
TEST_FIXTURE_MODULES="${FIXTURE_MODULE_DIR}"
|
|
TEST_FIXTURE_CONF="${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/conf"
|
|
DPM_CORE_VERSION_EXPECTED="${PROJECT_VERSION}"
|
|
)
|
|
|
|
set_target_properties(test_core PROPERTIES
|
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests
|
|
BUILD_RPATH "$ORIGIN/../lib"
|
|
)
|
|
|
|
foreach(fixture good missing_symbols bad_version)
|
|
add_dependencies(test_core fixture_${fixture})
|
|
endforeach()
|
|
|
|
add_test(NAME core_api COMMAND test_core)
|
|
|
|
# ---------------------------------------------------------------------
|
|
# CLI end-to-end tests (the dpm binary is the cheapest full-stack client)
|
|
# ---------------------------------------------------------------------
|
|
add_test(NAME cli_help COMMAND dpm --help)
|
|
set_tests_properties(cli_help PROPERTIES PASS_REGULAR_EXPRESSION "Usage: dpm")
|
|
|
|
add_test(NAME cli_list
|
|
COMMAND dpm -c ${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/conf
|
|
-m ${CMAKE_BINARY_DIR}/modules --list-modules)
|
|
set_tests_properties(cli_list PROPERTIES PASS_REGULAR_EXPRESSION "info")
|
|
|
|
add_test(NAME cli_info_version
|
|
COMMAND dpm -c ${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/conf
|
|
-m ${CMAKE_BINARY_DIR}/modules -L INFO info version)
|
|
set_tests_properties(cli_info_version PROPERTIES
|
|
PASS_REGULAR_EXPRESSION "libdpm-core Version: ${PROJECT_VERSION}")
|
|
|
|
add_test(NAME cli_module_not_found
|
|
COMMAND dpm -c ${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/conf
|
|
-m ${CMAKE_BINARY_DIR}/modules nonexistent)
|
|
set_tests_properties(cli_module_not_found PROPERTIES WILL_FAIL TRUE)
|
|
|
|
add_test(NAME cli_rejects_invalid_module
|
|
COMMAND dpm -c ${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/conf
|
|
-m ${FIXTURE_MODULE_DIR} missing_symbols)
|
|
set_tests_properties(cli_rejects_invalid_module PROPERTIES WILL_FAIL TRUE)
|
|
|
|
# ---------------------------------------------------------------------
|
|
# Code reference (Doxygen) — optional 'docs' target
|
|
# ---------------------------------------------------------------------
|
|
option(DPM_DOCS_HTML "Generate the code reference in HTML" OFF)
|
|
option(DPM_DOCS_PDF "Generate the code reference as PDF (requires LaTeX)" ON)
|
|
|
|
find_package(Doxygen)
|
|
if(DOXYGEN_FOUND)
|
|
# 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_STATIC YES)
|
|
set(DOXYGEN_QUIET YES)
|
|
set(DOXYGEN_WARN_IF_UNDOCUMENTED NO)
|
|
set(DOXYGEN_JAVADOC_AUTOBRIEF YES)
|
|
|
|
if(DPM_DOCS_HTML)
|
|
set(DOXYGEN_GENERATE_HTML YES)
|
|
else()
|
|
set(DOXYGEN_GENERATE_HTML NO)
|
|
endif()
|
|
|
|
if(DPM_DOCS_PDF)
|
|
set(DOXYGEN_GENERATE_LATEX YES)
|
|
set(DOXYGEN_USE_PDFLATEX YES)
|
|
set(DOXYGEN_PDF_HYPERLINKS YES)
|
|
else()
|
|
set(DOXYGEN_GENERATE_LATEX NO)
|
|
endif()
|
|
|
|
# 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}/src
|
|
${CMAKE_CURRENT_SOURCE_DIR}/docs
|
|
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)
|
|
find_program(PDFLATEX_EXECUTABLE pdflatex)
|
|
if(PDFLATEX_EXECUTABLE)
|
|
add_custom_command(TARGET docs POST_BUILD
|
|
COMMAND make -C ${CMAKE_BINARY_DIR}/docs/tmp/latex
|
|
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"
|
|
)
|
|
else()
|
|
message(WARNING "DPM_DOCS_PDF is ON but pdflatex was not found; no PDF will be produced")
|
|
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()
|
|
|
|
# ---------------------------------------------------------------------
|
|
# Clean
|
|
# ---------------------------------------------------------------------
|
|
# clean removes what the build produced: the artifact directories, the
|
|
# generated documentation, and the test scratch areas.
|
|
#
|
|
# The generated build system stays. CMakeCache.txt, the makefiles,
|
|
# CMakeFiles/, and the CMake file API directory under .cmake/ are what an
|
|
# IDE reads to know the project's targets exist; deleting them leaves the
|
|
# directory unconfigured, so every target in the IDE stops resolving until
|
|
# the project is reloaded. Removing the build system is what configuring a
|
|
# fresh directory is for.
|
|
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES
|
|
${CMAKE_BINARY_DIR}/test-results
|
|
${CMAKE_BINARY_DIR}/Testing
|
|
${CMAKE_BINARY_DIR}/bin
|
|
${CMAKE_BINARY_DIR}/lib
|
|
${CMAKE_BINARY_DIR}/modules
|
|
${CMAKE_BINARY_DIR}/tests
|
|
${CMAKE_BINARY_DIR}/docs
|
|
)
|
|
|
|
# ---------------------------------------------------------------------
|
|
# 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)
|