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/context.cpp src/core/modules.cpp src/core/version.cpp ) target_include_directories(dpm-core PUBLIC $ $ ) # 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 ` 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)