Reorganise the tree into business vs frontend as separate directories:
src/core/{domain,imports,app} (was system/, imports/, app/)
src/frontends/tui/ (was tui/ + main.cpp)
tests/tui/ (the FTXUI-coupled helper test)
All cross-dir #include paths rewritten; same-dir includes untouched.
CMake: essim_core is the frontend-agnostic business library — links libzip,
pugixml and bsdl, NO GUI toolkit. Each frontend is a self-contained
src/frontends/<name>/ (own CMakeLists, toolkit, main.cpp) that links
essim_core, selected with -DESSIM_FRONTEND=<name> (default tui; 'none' = core +
tests only, no toolkit fetched). FTXUI moved into the tui frontend. Tests are
split: essim_tests links essim_core (no FTXUI), essim_tui_tests links essim_tui.
Verified: default tui build green (ctest 2/2); ESSIM_FRONTEND=none builds the
core + tests with FTXUI never fetched and no `essim` binary.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
133 lines
5.5 KiB
CMake
133 lines
5.5 KiB
CMake
cmake_minimum_required(VERSION 3.14)
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
|
|
project(essim
|
|
LANGUAGES CXX
|
|
VERSION 0.1
|
|
DESCRIPTION "System digital twin."
|
|
)
|
|
|
|
include(FetchContent)
|
|
|
|
# ----------------------------------------------------------------- core deps
|
|
# libbsdl — standalone BSDL parser (LGPL-2.1), dynamically linked (EUPL-1.2,
|
|
# which the LGPL permits). Override its path with -DBSDL_DIR=...
|
|
set(BSDL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../libbsdl" CACHE PATH "libbsdl source tree")
|
|
set(BSDL_BUILD_CLI OFF CACHE BOOL "" FORCE)
|
|
set(BSDL_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
|
add_subdirectory(${BSDL_DIR} ${CMAKE_BINARY_DIR}/libbsdl)
|
|
|
|
find_package(libzip REQUIRED)
|
|
find_package(pugixml REQUIRED)
|
|
|
|
# =============================================================== essim_core
|
|
# All business logic — domain model, importers, application operations
|
|
# (src/core/{domain,imports,app}). Frontend-agnostic: it links NO GUI/TUI
|
|
# toolkit, so every frontend and the test suite share the exact same core.
|
|
file(GLOB_RECURSE CORE_SOURCES "src/core/*.cpp")
|
|
add_library(essim_core STATIC ${CORE_SOURCES})
|
|
target_include_directories(essim_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
|
target_link_libraries(essim_core
|
|
PUBLIC
|
|
libzip::zip
|
|
pugixml::pugixml
|
|
bsdl::bsdl
|
|
)
|
|
|
|
# =============================================================== frontend(s)
|
|
# Pick the GUI/TUI frontend to build the `essim` binary against. Each frontend
|
|
# is a self-contained src/frontends/<name>/ (own CMakeLists, GUI toolkit, and
|
|
# main.cpp) that links essim_core. "none" builds the core + tests only — no GUI
|
|
# toolkit is fetched. To add a frontend (e.g. a Qt GUI), create
|
|
# src/frontends/gui/ and configure with -DESSIM_FRONTEND=gui.
|
|
set(ESSIM_FRONTEND "tui" CACHE STRING
|
|
"Frontend to build: a directory name under src/frontends/, or 'none'")
|
|
set_property(CACHE ESSIM_FRONTEND PROPERTY STRINGS tui none)
|
|
|
|
if(ESSIM_FRONTEND STREQUAL "none")
|
|
message(STATUS "essim: ESSIM_FRONTEND=none — core + tests only (no frontend, no GUI toolkit)")
|
|
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/frontends/${ESSIM_FRONTEND}/CMakeLists.txt")
|
|
message(STATUS "essim: building frontend '${ESSIM_FRONTEND}'")
|
|
add_subdirectory(src/frontends/${ESSIM_FRONTEND})
|
|
else()
|
|
message(FATAL_ERROR
|
|
"Unknown ESSIM_FRONTEND '${ESSIM_FRONTEND}' — expected "
|
|
"src/frontends/${ESSIM_FRONTEND}/CMakeLists.txt, or 'none'.")
|
|
endif()
|
|
|
|
# =============================================================== tests (core)
|
|
# The suite exercises essim_core only — no frontend, no GUI toolkit.
|
|
include(CTest)
|
|
if(BUILD_TESTING)
|
|
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)
|
|
FetchContent_Declare(doctest
|
|
GIT_REPOSITORY https://github.com/doctest/doctest.git
|
|
GIT_TAG v2.4.11
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
FetchContent_MakeAvailable(doctest)
|
|
unset(CMAKE_POLICY_VERSION_MINIMUM)
|
|
|
|
# Core tests — exercise essim_core only (tests/*.cpp, non-recursive, so the
|
|
# per-frontend tests under tests/<frontend>/ are not pulled in here).
|
|
file(GLOB TEST_SOURCES "tests/*.cpp")
|
|
if(TEST_SOURCES)
|
|
add_executable(essim_tests ${TEST_SOURCES})
|
|
target_link_libraries(essim_tests PRIVATE essim_core doctest::doctest)
|
|
add_test(NAME essim_tests COMMAND essim_tests)
|
|
endif()
|
|
|
|
# Per-frontend tests — tests/<frontend>/*.cpp, built and linked against that
|
|
# frontend's library only when the frontend itself is built.
|
|
if(TARGET essim_tui)
|
|
file(GLOB TUI_TEST_SOURCES "tests/tui/*.cpp")
|
|
if(TUI_TEST_SOURCES)
|
|
add_executable(essim_tui_tests
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/doctest_main.cpp" ${TUI_TEST_SOURCES})
|
|
target_link_libraries(essim_tui_tests PRIVATE essim_tui doctest::doctest)
|
|
add_test(NAME essim_tui_tests COMMAND essim_tui_tests)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
# =============================================================== documentation
|
|
# Doxygen → XML → gen_api_md.py → doc/api/, plus `essim --commands-md`. Needs the
|
|
# `essim` binary, so it's only wired when a frontend that provides one is built.
|
|
find_package(Doxygen COMPONENTS doxygen)
|
|
find_package(Python3 COMPONENTS Interpreter)
|
|
|
|
if(TARGET essim AND DOXYGEN_FOUND AND Python3_Interpreter_FOUND)
|
|
set(DOXYGEN_OUTPUT_DIR "${CMAKE_BINARY_DIR}/doc")
|
|
file(MAKE_DIRECTORY "${DOXYGEN_OUTPUT_DIR}")
|
|
configure_file(
|
|
"${CMAKE_SOURCE_DIR}/doc/Doxyfile.in"
|
|
"${DOXYGEN_OUTPUT_DIR}/Doxyfile"
|
|
@ONLY)
|
|
|
|
set(DOC_API_DIR "${CMAKE_SOURCE_DIR}/doc/api")
|
|
set(DOC_USER_DIR "${CMAKE_SOURCE_DIR}/doc/user")
|
|
add_custom_target(doc
|
|
DEPENDS essim
|
|
COMMAND ${CMAKE_COMMAND} -E rm -rf "${DOC_API_DIR}"
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${DOC_API_DIR}/classes"
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${DOC_API_DIR}/files"
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${DOC_USER_DIR}"
|
|
COMMAND ${DOXYGEN_EXECUTABLE} "${DOXYGEN_OUTPUT_DIR}/Doxyfile"
|
|
COMMAND ${Python3_EXECUTABLE}
|
|
"${CMAKE_SOURCE_DIR}/doc/gen_api_md.py"
|
|
"${DOXYGEN_OUTPUT_DIR}/xml"
|
|
"${DOC_API_DIR}"
|
|
COMMAND $<TARGET_FILE:essim> --commands-md "${DOC_USER_DIR}/commands.md"
|
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
|
COMMENT "Generating documentation (doxygen → gen_api_md.py → doc/api/, essim --commands-md → doc/user/commands.md)"
|
|
VERBATIM)
|
|
elseif(NOT TARGET essim)
|
|
message(STATUS "doc: no `essim` binary (ESSIM_FRONTEND=none) — `doc` target disabled.")
|
|
elseif(NOT DOXYGEN_FOUND)
|
|
message(STATUS "doc: Doxygen not found — `doc` target disabled.")
|
|
else()
|
|
message(STATUS "doc: Python 3 interpreter not found — `doc` target disabled.")
|
|
endif()
|