Files
cppcourse/cmat/CMakeLists.txt
T
porterskyandQwen 3.8 27B e09540c2b2 feat(cmat): add cmake build for course material
Add a CMakeLists.txt to each exercise directory, included from
cmat/CMakeLists.txt, so every exercise and solution becomes a buildable
target. GUI exercises link the curses-based DOS_Unix implementations on
Unix-like systems; the Windows-specific DOS variants are not compiled.
Exercises without a portable path or with missing dependencies (Boost)
are reported as not available at configure time.

Targets are excluded from the default build and built by name, e.g.
`cmake --build build --target Ex11`, so intentionally buggy exercises
such as Ex21 do not break the default build.

Also fix two portability issues: rename Ex11bug/pole.h to Pole.h for
case-sensitive filesystems and drop the extra Light:: qualification in
SolutionEx71A/Light.h. Document build commands and layout in AGENTS.md.

Co-authored-by: Qwen 3.8 27B <qwen3.8_27b-q3_k_xl@lmstudio.local>
2026-10-05 11:55:00 +02:00

146 lines
5.7 KiB
CMake

# ==============================================================================
# Course Material (cmat)
# ==============================================================================
# Exercises copied from 397. Each exercise directory holds its own
# CMakeLists.txt (included below) and defines one executable target with the
# directory's name via cmat_add_exercise().
#
# Targets are excluded from the default build; build one by name:
# cmake --build build --target Ex11
#
# Some exercises intentionally contain bugs that students fix during the
# course. Those targets fail to compile (or misbehave at runtime) until the
# bug is fixed, which is expected.
# ------------------------------------------------------------------------------
# Compile options
# ------------------------------------------------------------------------------
# Legacy course material: keep the project's warning flags but drop -Werror;
# these old sources produce warnings that must not block the build.
set(CMAT_OPTIONS "")
foreach (opt IN LISTS BASE_OPTIONS)
if (NOT opt STREQUAL "-Werror" AND NOT opt STREQUAL "/WX")
list(APPEND CMAT_OPTIONS "${opt}")
endif()
endforeach()
# ------------------------------------------------------------------------------
# Keyboard/Screen support (DOS_Unix/)
# ------------------------------------------------------------------------------
# GUI exercises use the Keyboard/Screen abstraction from DOS_Unix/. The DOS
# variants (Keyboard_DOS.cpp, Screen_DOS.cpp) are Windows-specific and are not
# compiled. On Unix-like systems the curses variants provide the same
# interface instead.
set(CMAT_GUI_LIB "")
if (IS_LINUX OR IS_MACOS)
find_package(Curses QUIET)
if (Curses_FOUND)
add_library(dos_unix STATIC
DOS_Unix/CursesObj.cpp
DOS_Unix/Keyboard_Unix.cpp
DOS_Unix/Screen_Unix.cpp
)
set_target_properties(dos_unix PROPERTIES EXCLUDE_FROM_ALL TRUE)
target_include_directories(dos_unix PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/DOS_Unix")
if (CURSES_INCLUDE_DIRS)
target_include_directories(dos_unix SYSTEM PUBLIC ${CURSES_INCLUDE_DIRS})
endif()
target_link_libraries(dos_unix PUBLIC ${CURSES_LIBRARIES})
set(CMAT_GUI_LIB dos_unix)
else()
message(STATUS "Curses not found; GUI exercises are unavailable")
endif()
else()
# Windows: only the DOS keyboard/screen implementations exist, which are
# Windows-specific; there is nothing portable to build with.
endif()
# Exercises using Boost.Serialization (system install; not fetched). CONFIG
# mode uses Boost's own CMake package, since the FindBoost module was removed
# in CMake 4.
find_package(Boost CONFIG QUIET COMPONENTS serialization)
# ------------------------------------------------------------------------------
# Target helpers
# ------------------------------------------------------------------------------
# cmat_add_exercise(<name> [GUI] [BOOST] <sources>...)
#
# Creates an executable target from the given sources. GUI links the
# Keyboard/Screen support library; BOOST links Boost.Serialization. If a
# required dependency is missing, the exercise is reported as not available
# and no target is created.
function(cmat_add_exercise name)
cmake_parse_arguments(ARG "GUI;BOOST" "" "SOURCES" ${ARGN})
if (ARG_GUI AND NOT CMAT_GUI_LIB)
cmat_unavailable(${name} "requires the Keyboard/Screen abstraction, which is Windows-specific (DOS_Unix/)")
return()
endif()
if (ARG_BOOST AND NOT Boost_FOUND)
cmat_unavailable(${name} "requires Boost.Serialization")
return()
endif()
add_executable(${name} ${ARG_SOURCES})
target_compile_features(${name} PRIVATE cxx_std_23)
target_compile_options(${name} PRIVATE ${CMAT_OPTIONS})
set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL TRUE)
if (ARG_GUI)
target_link_libraries(${name} PRIVATE ${CMAT_GUI_LIB})
endif()
if (ARG_BOOST)
target_link_libraries(${name} PRIVATE Boost::serialization)
endif()
endfunction()
# cmat_unavailable(<name> <reason>)
#
# Reports that an exercise cannot be built on this platform. A warning (not a
# hard error) is used so the configuration completes and all other exercises
# remain available.
function(cmat_unavailable name reason)
message(WARNING "Exercise ${name} is not available on this platform: ${reason}")
endfunction()
# ------------------------------------------------------------------------------
# Exercises
# ------------------------------------------------------------------------------
add_subdirectory(Ex11)
add_subdirectory(Ex11bug)
add_subdirectory(Ex21)
add_subdirectory(Ex22)
add_subdirectory(Ex31)
add_subdirectory(Ex32)
add_subdirectory(Ex33)
add_subdirectory(Ex41)
add_subdirectory(Ex42)
add_subdirectory(Ex51)
add_subdirectory(Ex61)
add_subdirectory(Ex62)
add_subdirectory(Ex71)
add_subdirectory(Ex71A)
add_subdirectory(SolutionEx11bug)
add_subdirectory(SolutionEx21)
add_subdirectory(SolutionEx22)
add_subdirectory(SolutionEx22Bonus)
add_subdirectory(SolutionEx31)
add_subdirectory(SolutionEx31Bonus)
add_subdirectory(SolutionEx32)
add_subdirectory(SolutionEx33)
add_subdirectory(SolutionEx33Bonus)
add_subdirectory(SolutionEx41)
add_subdirectory(SolutionEx41Bonus)
add_subdirectory(SolutionEx42)
add_subdirectory(SolutionEx51)
add_subdirectory(SolutionEx51Bonus2)
add_subdirectory(SolutionEx61InterimSolution)
add_subdirectory(SolutionEx61Part1)
add_subdirectory(SolutionEx61Part2)
add_subdirectory(SolutionEx61Part2Bonus)
add_subdirectory(SolutionEx62)
add_subdirectory(SolutionEx62Bonus)
add_subdirectory(SolutionEx62Bonus2)
add_subdirectory(SolutionEx71)
add_subdirectory(SolutionEx71A)
add_subdirectory(SolutionEx71ABonus)
add_subdirectory(SolutionEx71Bonus)