Final whole-branch review fixes. 1 (Important). Plot::measurement() cached on (series pointer, sample count) only, so a saturated StreamSeries -- whose size() stays pinned while x0() advances every acquire() -- froze its readout on the first saturated frame until a cursor moved. The cache key now carries the series' x0() (new MeasureSlot::last_x0), so a sliding window recomputes and a static series still does not: asserted with a new macro-gated counter hook (plot/detail/measure_count.hpp, PLOT_COUNT_MEASURE_RECOMPUTES, wired like the pyramid and ring counters, absent from the release library). New case saturated_stream_measurement_tracks_the_sliding_window: saturated ring, stationary cursors, ramp in absolute x -- zero recomputes for repeated reads with nothing moving, one per acquire while it slides. 2-3, 9. Spec: 4.3 described a GL_LINE_STRIP path that does not exist (there is one rasteriser -- instanced anti-aliased quads -- and dense_threshold_spp selects the gather level, not a primitive); 8 named a PLOT_GL_CHECK() macro that exists nowhere, and stated no exception policy. The table, the field's comment and 8 now describe the real gather-level threshold, the real glGetError() drain plus the stores' drop-to-orphan fallbacks, and the real policy: library failures return Status/bool, allocating entry points propagate std::bad_alloc. 4. The frame handed back neither GL_UNPACK_ALIGNMENT (init() sets 1 for the atlas) nor the clear colour (queried once with a new glGetFloatv entry). end_frame() restores both and renderer.hpp lists them in the residue contract. 5. draw() kept a host TextBackend for layout while drawing with its own font. The renderer now installs its font unconditionally -- strips and labels measure and draw with one backend -- with a debug-build diagnostic if a different one was set, and Plot::set_text_backend() is documented as the no-renderer path. New case renderer_measures_the_labels_it_draws asserts layout, measuring and the drawn label's ink agree. 6-10. draw()'s style overwrite stated at the call site; the load-sensitive wall-clock bound in test_measure.cpp replaced by a counter assertion (same interval, same fold count over a 512x length ratio); dump_frame_ppm drops noexcept and says why it may allocate; error.txt ignored (not this project's, not generated here) rather than deleted. Verified: debug and release build clean (-Wall -Wextra -Wpedantic -Wconversion -Wshadow), 4/4 ctest entries pass, 130 cases pass (was 127), umbrella and header self-containment checks pass, and no counter symbol in the release archive.
141 lines
5.3 KiB
CMake
141 lines
5.3 KiB
CMake
cmake_minimum_required(VERSION 3.24)
|
|
project(plot VERSION 0.1.0 LANGUAGES CXX)
|
|
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|
include(plot_options)
|
|
|
|
add_library(plot_core
|
|
src/core/status.cpp
|
|
src/math/transform.cpp
|
|
src/data/minmax_pyramid.cpp
|
|
src/data/series.cpp
|
|
src/data/array_series.cpp
|
|
src/data/stream_series.cpp
|
|
src/gl/loader.cpp
|
|
src/gl/handle.cpp
|
|
src/render/shaders.cpp
|
|
src/render/bitmap_font.cpp
|
|
src/render/primitives.cpp
|
|
src/render/buffer.cpp
|
|
src/render/vertex_array.cpp
|
|
src/render/program.cpp
|
|
src/render/renderer.cpp
|
|
src/plot/ticks.cpp
|
|
src/plot/axis.cpp
|
|
src/plot/grid.cpp
|
|
src/plot/measure.cpp
|
|
src/plot/plot.cpp
|
|
src/input/controller.cpp
|
|
)
|
|
add_library(plot::core ALIAS plot_core)
|
|
# What the target is called in an installed tree. Without this the export set is
|
|
# namespaced by the target's own name (plot::plot_core), while the build tree --
|
|
# and every consumer, and this project's own comments -- says plot::core.
|
|
set_target_properties(plot_core PROPERTIES EXPORT_NAME core)
|
|
|
|
target_include_directories(plot_core PUBLIC
|
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
$<INSTALL_INTERFACE:include>)
|
|
target_compile_features(plot_core PUBLIC cxx_std_20)
|
|
target_link_libraries(plot_core PRIVATE ${CMAKE_DL_LIBS})
|
|
plot_apply_warnings(plot_core)
|
|
|
|
# Adapters own the surface and translate their host's events; examples link the
|
|
# adapter they demo. Both are opt-in, so the core library and its tests still build
|
|
# on a bare toolchain.
|
|
#
|
|
# They are added before the test suite on purpose: a test that drives an adapter
|
|
# needs that adapter's targets to exist, and with both switches on the suite can
|
|
# then exercise them (see tests/CMakeLists.txt).
|
|
if(PLOT_BUILD_GLFW)
|
|
add_subdirectory(adapters/glfw)
|
|
endif()
|
|
|
|
if(PLOT_BUILD_IMGUI)
|
|
add_subdirectory(adapters/imgui)
|
|
endif()
|
|
|
|
if(PLOT_BUILD_QT6)
|
|
add_subdirectory(adapters/qt6)
|
|
endif()
|
|
|
|
if(PLOT_BUILD_GTK4)
|
|
add_subdirectory(adapters/gtk4)
|
|
endif()
|
|
|
|
if(PLOT_BUILD_EXAMPLES)
|
|
add_subdirectory(examples)
|
|
endif()
|
|
|
|
if(PLOT_BUILD_TESTS)
|
|
# Test-only: counts the pyramid's covering-decomposition entries and its bucket
|
|
# merges so a test can pin the query's O(log n) cost and the append path's
|
|
# amortised O(1) cost, neither of which any answer reveals. Off in every
|
|
# non-test build (see include/plot/data/detail/{cover,merge}_count.hpp).
|
|
#
|
|
# PLOT_RING_STATS is the same for the persistent-mapped instance ring: the
|
|
# properties a frame must hold there -- no slot written twice within a frame,
|
|
# and one fence wait at most, at the start of the frame -- are invisible in the
|
|
# pixels, so a test reads counters instead (see
|
|
# include/plot/render/detail/ring_stats.hpp).
|
|
#
|
|
# PLOT_COUNT_MEASURE_RECOMPUTES is the same for the measurement cache: whether
|
|
# `Plot::measurement()` recomputed or returned a cached result is invisible in
|
|
# the value it returns, so a test that has to tell a live cache from one frozen
|
|
# on a stale window counts re-evaluations (see
|
|
# include/plot/plot/detail/measure_count.hpp).
|
|
target_compile_definitions(plot_core PRIVATE PLOT_PYRAMID_COUNT_COVERS
|
|
PLOT_PYRAMID_COUNT_MERGES
|
|
PLOT_RING_STATS
|
|
PLOT_COUNT_MEASURE_RECOMPUTES)
|
|
|
|
enable_testing()
|
|
add_subdirectory(tests)
|
|
endif()
|
|
|
|
# Install and export. The core always goes in; each adapter joins the set only if
|
|
# its toolkit can be re-found on a consumer's machine, which the adapter decided
|
|
# when it was added (plot_record_adapter_export() -- the decisions and the reasons
|
|
# are in the configure log above). plotConfig.cmake then re-finds exactly those
|
|
# toolkits before including the targets file the adapters are described in, so
|
|
# find_package(plot) + target_link_libraries(consumer PRIVATE plot::core) works
|
|
# from an installed prefix with no -I or -L of the consumer's own.
|
|
if(PLOT_INSTALL)
|
|
# The adapters that could be promised to a consumer, in the order they were
|
|
# added, and the find_dependency() calls that re-create their toolkits there.
|
|
get_property(PLOT_ADAPTER_EXPORT_TARGETS GLOBAL PROPERTY PLOT_ADAPTER_EXPORT_TARGETS)
|
|
# Substituted into plotConfig.cmake below (@PLOT_ADAPTER_DEPENDENCIES@).
|
|
get_property(PLOT_ADAPTER_DEPENDENCIES GLOBAL PROPERTY PLOT_ADAPTER_DEPENDENCIES)
|
|
|
|
include(CMakePackageConfigHelpers)
|
|
|
|
# No INCLUDES DESTINATION here: every target already declares
|
|
# $<INSTALL_INTERFACE:include> in its own target_include_directories(), and
|
|
# asking for it twice puts the same directory in the export twice.
|
|
install(TARGETS plot_core ${PLOT_ADAPTER_EXPORT_TARGETS}
|
|
EXPORT plotTargets
|
|
ARCHIVE DESTINATION lib
|
|
LIBRARY DESTINATION lib
|
|
RUNTIME DESTINATION bin)
|
|
install(DIRECTORY include/plot DESTINATION include)
|
|
|
|
install(EXPORT plotTargets
|
|
NAMESPACE plot::
|
|
FILE plotTargets.cmake
|
|
DESTINATION lib/cmake/plot)
|
|
|
|
configure_package_config_file(
|
|
cmake/plotConfig.cmake.in
|
|
"${CMAKE_CURRENT_BINARY_DIR}/plotConfig.cmake"
|
|
INSTALL_DESTINATION lib/cmake/plot)
|
|
write_basic_package_version_file(
|
|
"${CMAKE_CURRENT_BINARY_DIR}/plotConfigVersion.cmake"
|
|
VERSION ${PROJECT_VERSION}
|
|
COMPATIBILITY SameMajorVersion)
|
|
|
|
install(FILES
|
|
"${CMAKE_CURRENT_BINARY_DIR}/plotConfig.cmake"
|
|
"${CMAKE_CURRENT_BINARY_DIR}/plotConfigVersion.cmake"
|
|
DESTINATION lib/cmake/plot)
|
|
endif()
|