cmake_minimum_required(VERSION 3.22) project(dpm-core VERSION 1.0.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/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 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) # --------------------------------------------------------------------- # 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) # --------------------------------------------------------------------- # Code reference (Doxygen) — optional 'docs' target # --------------------------------------------------------------------- option(DPM_DOCS_HTML "Generate the code reference in HTML" ON) 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() # The prose documents, each rendered as its own page in the generated # reference. Named one per line so the set of documents reaching the # output is stated here instead of implied by a directory. set(DPM_DOC_PAGES ${CMAKE_CURRENT_SOURCE_DIR}/docs/OVERVIEW.md ${CMAKE_CURRENT_SOURCE_DIR}/docs/DESIGN.md ${CMAKE_CURRENT_SOURCE_DIR}/docs/CONSUMERS.md ${CMAKE_CURRENT_SOURCE_DIR}/docs/MODULES.md ${CMAKE_CURRENT_SOURCE_DIR}/docs/BUILD.md ${CMAKE_CURRENT_SOURCE_DIR}/docs/DOCUMENTATION.md ) # Two kinds of input: include/ and src/ supply the API and internals # reference extracted from the source, DPM_DOC_PAGES supplies the # prose pages. # # One target, so `cmake --build --target docs` is the whole # procedure and the IDE lists a single entry for it. The commands # below run after Doxygen and place the finished documents. doxygen_add_docs(docs ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src ${DPM_DOC_PAGES} COMMENT "Generating the reference with Doxygen" ) 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 rm -rf ${CMAKE_BINARY_DIR}/docs/pdf 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 rm -rf ${CMAKE_BINARY_DIR}/docs/html COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/docs/tmp/html ${CMAKE_BINARY_DIR}/docs/html COMMENT "Placing the HTML reference" ) endif() # Doxygen keeps output files it judges unchanged, so a run over a # populated scratch directory can carry pages forward from an earlier # one. Removing it here means the next run regenerates everything, # and leaves docs/ holding the finished documents alone. add_custom_command(TARGET docs POST_BUILD COMMAND ${CMAKE_COMMAND} -E rm -rf ${CMAKE_BINARY_DIR}/docs/tmp COMMENT "Clearing the generators' scratch directory" ) 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 ${DPM_TEST_RESULTS_DIR} ${CMAKE_BINARY_DIR}/Testing ${CMAKE_BINARY_DIR}/bin ${CMAKE_BINARY_DIR}/lib ${CMAKE_BINARY_DIR}/modules ${DPM_TEST_DIR} ${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)