feat(build): install/export rules, umbrella header, verified consumer
This commit is contained in:
1 parent
377cca8e9b
commit
0972903d27
11 files changed
+333
-7
No files matched your search
+53
-1
@@ -28,8 +28,14 @@ add_library(plot_core
|
|||||||
src/input/controller.cpp
|
src/input/controller.cpp
|
||||||
)
|
)
|
||||||
add_library(plot::core ALIAS plot_core)
|
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 "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
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_compile_features(plot_core PUBLIC cxx_std_20)
|
||||||
target_link_libraries(plot_core PRIVATE ${CMAKE_DL_LIBS})
|
target_link_libraries(plot_core PRIVATE ${CMAKE_DL_LIBS})
|
||||||
plot_apply_warnings(plot_core)
|
plot_apply_warnings(plot_core)
|
||||||
@@ -79,3 +85,49 @@ if(PLOT_BUILD_TESTS)
|
|||||||
enable_testing()
|
enable_testing()
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
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()
|
||||||
@@ -33,6 +33,20 @@
|
|||||||
"PLOT_BUILD_QT6": true,
|
"PLOT_BUILD_QT6": true,
|
||||||
"PLOT_BUILD_GTK4": true
|
"PLOT_BUILD_GTK4": true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-asan",
|
||||||
|
"displayName": "Linux Debug (AddressSanitizer)",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/build/asan",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Debug",
|
||||||
|
"PLOT_SANITIZE": "address",
|
||||||
|
"PLOT_BUILD_GLFW": true,
|
||||||
|
"PLOT_BUILD_IMGUI": true,
|
||||||
|
"PLOT_BUILD_QT6": true,
|
||||||
|
"PLOT_BUILD_GTK4": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"buildPresets": [
|
"buildPresets": [
|
||||||
@@ -43,6 +57,10 @@
|
|||||||
{
|
{
|
||||||
"name": "linux-release",
|
"name": "linux-release",
|
||||||
"configurePreset": "linux-release"
|
"configurePreset": "linux-release"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "linux-asan",
|
||||||
|
"configurePreset": "linux-asan"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -8,10 +8,36 @@ plot_find_glfw(plot_glfw_dep)
|
|||||||
|
|
||||||
add_library(plot_glfw STATIC glfw_host.cpp)
|
add_library(plot_glfw STATIC glfw_host.cpp)
|
||||||
add_library(plot::glfw ALIAS plot_glfw)
|
add_library(plot::glfw ALIAS plot_glfw)
|
||||||
|
# The installed tree names it plot::glfw, like the build tree (see plot_core's).
|
||||||
|
set_target_properties(plot_glfw PROPERTIES EXPORT_NAME glfw)
|
||||||
|
|
||||||
# The public include root is `adapters/`, so the header is reached as
|
# The public include root is `adapters/`, so the header is reached as
|
||||||
# <glfw/glfw_host.hpp> -- the toolkit's name first, like every other adapter's.
|
# <glfw/glfw_host.hpp> -- the toolkit's name first, like every other adapter's.
|
||||||
target_include_directories(plot_glfw PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
# The build interface is that root; the install one is the prefix's `include`,
|
||||||
|
# where glfw_host.hpp is installed as <glfw/glfw_host.hpp>, the same spelling.
|
||||||
|
target_include_directories(plot_glfw PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
|
||||||
# GLFW stays PRIVATE: the header forward-declares GLFWwindow and includes no GLFW
|
# GLFW stays PRIVATE: the header forward-declares GLFWwindow and includes no GLFW
|
||||||
# header, so a consumer of plot::glfw does not inherit the toolkit.
|
# header, so a consumer of plot::glfw does not inherit the toolkit.
|
||||||
target_link_libraries(plot_glfw PUBLIC plot::core PRIVATE ${plot_glfw_dep})
|
target_link_libraries(plot_glfw PUBLIC plot::core PRIVATE ${plot_glfw_dep})
|
||||||
plot_apply_warnings(plot_glfw)
|
plot_apply_warnings(plot_glfw)
|
||||||
|
|
||||||
|
# PLOT_GLFW_DEP is either a target find_package()/pkg-config created or one
|
||||||
|
# FetchContent built. The first two can be promised to a consumer -- the installed
|
||||||
|
# config file re-runs the very same discovery -- but a fetched GLFW cannot: there
|
||||||
|
# is no glfw3Config.cmake on the consumer's machine to find, so exporting this
|
||||||
|
# adapter would hand out a target its link interface cannot satisfy. In that case
|
||||||
|
# the adapter is not installed at all.
|
||||||
|
plot_glfw_dependency_snippet(plot_glfw_dependency)
|
||||||
|
if(PLOT_GLFW_DEP_ORIGIN STREQUAL "FetchContent")
|
||||||
|
plot_record_adapter_export(plot_glfw FALSE
|
||||||
|
"GLFW was fetched with FetchContent, so a consumer's find_package(plot) cannot re-find it" "")
|
||||||
|
else()
|
||||||
|
plot_record_adapter_export(plot_glfw TRUE
|
||||||
|
"GLFW was resolved by ${PLOT_GLFW_DEP_ORIGIN}" "${plot_glfw_dependency}")
|
||||||
|
if(PLOT_INSTALL)
|
||||||
|
install(FILES glfw_host.hpp DESTINATION include/glfw)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
@@ -22,13 +22,33 @@ endif()
|
|||||||
|
|
||||||
add_library(plot_gtk4 STATIC gtk_plot_area.cpp gtk_plot_area.hpp gtk_input.hpp)
|
add_library(plot_gtk4 STATIC gtk_plot_area.cpp gtk_plot_area.hpp gtk_input.hpp)
|
||||||
add_library(plot::gtk4 ALIAS plot_gtk4)
|
add_library(plot::gtk4 ALIAS plot_gtk4)
|
||||||
|
# The installed tree names it plot::gtk4, like the build tree (see plot_core's).
|
||||||
|
set_target_properties(plot_gtk4 PROPERTIES EXPORT_NAME gtk4)
|
||||||
|
|
||||||
# The public include root is `adapters/`, so the headers are reached as
|
# The public include root is `adapters/`, so the headers are reached as
|
||||||
# <gtk4/gtk_plot_area.hpp> and <gtk4/gtk_input.hpp> -- the toolkit's name first,
|
# <gtk4/gtk_plot_area.hpp> and <gtk4/gtk_input.hpp> -- the toolkit's name first,
|
||||||
# like every other adapter's.
|
# like every other adapter's. The build interface is that root; the install one is
|
||||||
target_include_directories(plot_gtk4 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
# the prefix's `include`, where both are installed under `gtk4/`, the same
|
||||||
|
# spelling.
|
||||||
|
target_include_directories(plot_gtk4 PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
# GTK is PUBLIC, unlike GLFW and ImGui: the adapter's factory hands out a
|
# GTK is PUBLIC, unlike GLFW and ImGui: the adapter's factory hands out a
|
||||||
# GtkWidget, so a consumer that embeds the area needs GTK's headers and libraries
|
# GtkWidget, so a consumer that embeds the area needs GTK's headers and libraries
|
||||||
# to put it anywhere -- the widget *is* the toolkit's object -- and GTK's include
|
# to put it anywhere -- the widget *is* the toolkit's object -- and GTK's include
|
||||||
# directory is not one the compiler searches by default.
|
# directory is not one the compiler searches by default.
|
||||||
target_link_libraries(plot_gtk4 PUBLIC plot::core PkgConfig::GTK4_PC)
|
target_link_libraries(plot_gtk4 PUBLIC plot::core PkgConfig::GTK4_PC)
|
||||||
plot_apply_warnings(plot_gtk4)
|
plot_apply_warnings(plot_gtk4)
|
||||||
|
|
||||||
|
# GTK came from pkg-config, which the installed config file can re-run: the
|
||||||
|
# snippet re-creates the exact PkgConfig::GTK4_PC target the adapter's public link
|
||||||
|
# interface names, so a consumer that links plot::gtk4 gets GTK's own include
|
||||||
|
# directories and libraries the same way this build did.
|
||||||
|
plot_record_adapter_export(plot_gtk4 TRUE "GTK4 was resolved by pkg-config"
|
||||||
|
"find_dependency(PkgConfig)\npkg_check_modules(GTK4_PC REQUIRED IMPORTED_TARGET gtk4)\n")
|
||||||
|
if(PLOT_INSTALL)
|
||||||
|
# gtk_input.hpp is installed with the public header: the demo and the test suite
|
||||||
|
# reach it as <gtk4/gtk_input.hpp>, and it is a toolkit-free header a consumer
|
||||||
|
# can use without GTK.
|
||||||
|
install(FILES gtk_plot_area.hpp gtk_input.hpp DESTINATION include/gtk4)
|
||||||
|
endif()
|
||||||
@@ -52,3 +52,12 @@ target_include_directories(plot_imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
|||||||
# consumer of plot::imgui does not inherit the toolkit's headers.
|
# consumer of plot::imgui does not inherit the toolkit's headers.
|
||||||
target_link_libraries(plot_imgui PUBLIC plot::core PRIVATE imgui ${plot_imgui_glfw_dep})
|
target_link_libraries(plot_imgui PUBLIC plot::core PRIVATE imgui ${plot_imgui_glfw_dep})
|
||||||
plot_apply_warnings(plot_imgui)
|
plot_apply_warnings(plot_imgui)
|
||||||
|
|
||||||
|
# Not installed and not exported, and not because of a discovery fallback: ImGui
|
||||||
|
# is *always* fetched here, so there is no ImGui package for an installed config
|
||||||
|
# file to find. Exporting plot::imgui would name the fetched `imgui` target in its
|
||||||
|
# link interface and leave every consumer of `find_package(plot)` unable to
|
||||||
|
# configure -- so plot::imgui is a build-tree target only, and a consumer that
|
||||||
|
# wants it adds the adapter's source or fetches the same pinned tag itself.
|
||||||
|
plot_record_adapter_export(plot_imgui FALSE
|
||||||
|
"ImGui is supplied by FetchContent, so find_package(plot) cannot promise it to a consumer" "")
|
||||||
@@ -19,9 +19,19 @@ endif()
|
|||||||
|
|
||||||
add_library(plot_qt6 STATIC qt_plot_widget.cpp qt_plot_widget.hpp)
|
add_library(plot_qt6 STATIC qt_plot_widget.cpp qt_plot_widget.hpp)
|
||||||
add_library(plot::qt6 ALIAS plot_qt6)
|
add_library(plot::qt6 ALIAS plot_qt6)
|
||||||
|
# The installed tree names it plot::qt6, like the build tree (see plot_core's).
|
||||||
|
set_target_properties(plot_qt6 PROPERTIES EXPORT_NAME qt6)
|
||||||
|
|
||||||
# The public include root is `adapters/`, so the header is reached as
|
# The public include root is `adapters/`, so the header is reached as
|
||||||
# <qt6/qt_plot_widget.hpp> -- the toolkit's name first, like every other adapter's.
|
# <qt6/qt_plot_widget.hpp> -- the toolkit's name first, like every other adapter's.
|
||||||
target_include_directories(plot_qt6 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
# The build interface is that root; the install one is the prefix's `include`,
|
||||||
|
# where both headers are installed as <qt6/...> -- the same spelling. The pointer
|
||||||
|
# anchor in qt_pointer.hpp is internal API, but it still ships: the widget's header
|
||||||
|
# includes it, so a consumer that gets one without the other does not compile.
|
||||||
|
target_include_directories(plot_qt6 PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
|
||||||
# Qt is PUBLIC, unlike GLFW and ImGui: the widget's header derives from
|
# Qt is PUBLIC, unlike GLFW and ImGui: the widget's header derives from
|
||||||
# QOpenGLWidget, so a consumer needs Qt's headers and libraries to use it at all.
|
# QOpenGLWidget, so a consumer needs Qt's headers and libraries to use it at all.
|
||||||
target_link_libraries(plot_qt6 PUBLIC
|
target_link_libraries(plot_qt6 PUBLIC
|
||||||
@@ -35,3 +45,12 @@ target_link_libraries(plot_qt6 PUBLIC
|
|||||||
# Qt class in it, and AUTOMOC scans every source of a target it is set on.
|
# Qt class in it, and AUTOMOC scans every source of a target it is set on.
|
||||||
set_target_properties(plot_qt6 PROPERTIES AUTOMOC ON)
|
set_target_properties(plot_qt6 PROPERTIES AUTOMOC ON)
|
||||||
plot_apply_warnings(plot_qt6)
|
plot_apply_warnings(plot_qt6)
|
||||||
|
|
||||||
|
# Qt is a system SDK found with find_package() -- a missing Qt6 is a configure
|
||||||
|
# error above, never a fetch -- so the installed config file can re-find it with
|
||||||
|
# the same components and the widget's public Qt link interface is satisfiable.
|
||||||
|
plot_record_adapter_export(plot_qt6 TRUE "Qt6 was resolved by find_package"
|
||||||
|
"find_dependency(Qt6 COMPONENTS Core Gui Widgets OpenGLWidgets)\n")
|
||||||
|
if(PLOT_INSTALL)
|
||||||
|
install(FILES qt_plot_widget.hpp qt_pointer.hpp DESTINATION include/qt6)
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
# Package config for `plot`. Include it with
|
||||||
|
#
|
||||||
|
# find_package(plot 0.1 REQUIRED)
|
||||||
|
# target_link_libraries(your_target PRIVATE plot::core)
|
||||||
|
#
|
||||||
|
# `plot::core` is the library, and carries no third-party dependency at all. The
|
||||||
|
# adapter targets (`plot::glfw`, `plot::qt6`, `plot::gtk4`) are here only when
|
||||||
|
# their toolkit could be promised to a consumer: an adapter whose toolkit the
|
||||||
|
# build fetched with FetchContent is deliberately not installed, because this
|
||||||
|
# file has nothing to point a consumer at -- see the build's configure log for
|
||||||
|
# which adapters were exported and which were skipped, and why.
|
||||||
|
#
|
||||||
|
# Those toolkits are re-found below, before plotTargets.cmake is included: the
|
||||||
|
# adapter targets name them in their own link interfaces, so the imported targets
|
||||||
|
# have to exist first.
|
||||||
|
|
||||||
|
include(CMakeFindDependencyMacro)
|
||||||
|
@PLOT_ADAPTER_DEPENDENCIES@
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/plotTargets.cmake")
|
||||||
|
|
||||||
|
check_required_components(plot)
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# LeakSanitizer suppressions for the `linux-asan` build (PLOT_SANITIZE=address).
|
||||||
|
# Pointed at by tests/CMakeLists.txt, which sets ASAN_OPTIONS on the test itself
|
||||||
|
# so `ctest --test-dir build/asan` gets it however it is launched.
|
||||||
|
#
|
||||||
|
# The boundary this file exists to hold: a sanitizer report from *our* code is a
|
||||||
|
# finding and must fail the run, so nothing here may ever suppress a frame under
|
||||||
|
# include/plot/ or src/. Only the GL driver may be named -- an EGL/GL stack
|
||||||
|
# (Mesa's libEGL, libgallium, libglapi, radeonsi's ACO, or the LLVM JIT behind
|
||||||
|
# llvmpipe) is a system library this project does not build and cannot fix, and
|
||||||
|
# it is loaded only by the headless EGL context the GL tests create.
|
||||||
|
#
|
||||||
|
# It is currently empty of entries on purpose. The asan suite runs clean against
|
||||||
|
# the installed driver -- 127 cases, no report of any origin (the leak checker was
|
||||||
|
# confirmed live with a deliberate 1 KB leak, which does report and exit 1) -- and
|
||||||
|
# a suppression nobody has needed is a suppression nobody can justify. If a driver
|
||||||
|
# report does appear, add the narrowest entry that names the library, e.g.
|
||||||
|
#
|
||||||
|
# leak:libEGL.so
|
||||||
|
# leak:libgallium*
|
||||||
|
#
|
||||||
|
# and leave the count in the commit message. The shape is `leak:<substring of a
|
||||||
|
# frame in the stack>`; ASan takes the same list through ASAN_OPTIONS.
|
||||||
@@ -16,6 +16,62 @@ option(PLOT_BUILD_GLFW "Build the GLFW adapter and demo" OFF)
|
|||||||
option(PLOT_BUILD_IMGUI "Build the Dear ImGui adapter and demo" OFF)
|
option(PLOT_BUILD_IMGUI "Build the Dear ImGui adapter and demo" OFF)
|
||||||
option(PLOT_BUILD_QT6 "Build the Qt6 adapter and demo" OFF)
|
option(PLOT_BUILD_QT6 "Build the Qt6 adapter and demo" OFF)
|
||||||
option(PLOT_BUILD_GTK4 "Build the GTK4 adapter and demo" OFF)
|
option(PLOT_BUILD_GTK4 "Build the GTK4 adapter and demo" OFF)
|
||||||
|
option(PLOT_INSTALL "Generate install and export rules (find_package(plot))" ON)
|
||||||
|
set(PLOT_SANITIZE "" CACHE STRING
|
||||||
|
"Sanitizers to build with, as the list a -fsanitize= flag takes (e.g. address); empty for none")
|
||||||
|
|
||||||
|
# Sanitizer flags go on every target in this project, fetched third-party sources
|
||||||
|
# included: a partially instrumented build reports as loudly about the
|
||||||
|
# instrumentation gap as about any real bug. The flags are one -fsanitize= list
|
||||||
|
# (PLOT_SANITIZE) rather than a set of per-sanitizer options so the preset, the
|
||||||
|
# tests' runtime environment and this file cannot disagree about what is on.
|
||||||
|
if(PLOT_SANITIZE)
|
||||||
|
add_compile_options(-fsanitize=${PLOT_SANITIZE} -fno-omit-frame-pointer)
|
||||||
|
add_link_options(-fsanitize=${PLOT_SANITIZE})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Read by tests/CMakeLists.txt, which points ASAN_OPTIONS at this project's
|
||||||
|
# suppressions file when the address sanitizer is on.
|
||||||
|
string(REPLACE "," ";" PLOT_SANITIZE_LIST "${PLOT_SANITIZE}")
|
||||||
|
if("address" IN_LIST PLOT_SANITIZE_LIST)
|
||||||
|
set(PLOT_ASAN_ENABLED TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- install / export bookkeeping --------------------------------------------
|
||||||
|
#
|
||||||
|
# An adapter can only be installed and exported when its toolkit can be found
|
||||||
|
# again on the consumer's machine. A dependency resolved by find_package() or
|
||||||
|
# pkg-config can be: the installed config file re-finds it with the very same
|
||||||
|
# call. A dependency that FetchContent supplied cannot -- there is nothing on the
|
||||||
|
# consumer's machine to point at, and promising it would make every consumer
|
||||||
|
# clone and build that toolkit at the same revision -- so those adapters stay out
|
||||||
|
# of the export set and the configure log says why (see each adapter's
|
||||||
|
# CMakeLists.txt for its own resolution order).
|
||||||
|
#
|
||||||
|
# The results are global properties, because the adapters decide inside their own
|
||||||
|
# subdirectory while the install rules run at the top level. A property rather
|
||||||
|
# than a cache entry: a cache value cannot hold the newlines a snippet of
|
||||||
|
# find_dependency() calls needs, and nothing here has to survive the configure
|
||||||
|
# pass that produced it.
|
||||||
|
|
||||||
|
# Records one adapter's install/export decision and prints it. `dependency` is
|
||||||
|
# the config-file snippet that re-creates the toolkit's imported target before
|
||||||
|
# plotTargets.cmake is included; it is empty when the target is not exported.
|
||||||
|
function(plot_record_adapter_export target exportable reason dependency)
|
||||||
|
if(NOT exportable)
|
||||||
|
message(STATUS "plot: not exporting ${target}: ${reason}")
|
||||||
|
elseif(NOT PLOT_INSTALL)
|
||||||
|
message(STATUS "plot: not exporting ${target}: PLOT_INSTALL is OFF")
|
||||||
|
else()
|
||||||
|
set_property(GLOBAL APPEND PROPERTY PLOT_ADAPTER_EXPORT_TARGETS "${target}")
|
||||||
|
# Read-modify-write, not APPEND: the snippets are one block of C++-style
|
||||||
|
# lines that must be substituted into one file, and a property read back is a
|
||||||
|
# list -- APPEND would join them with the separator ';' instead of a newline.
|
||||||
|
get_property(plot_dependencies GLOBAL PROPERTY PLOT_ADAPTER_DEPENDENCIES)
|
||||||
|
set_property(GLOBAL PROPERTY PLOT_ADAPTER_DEPENDENCIES "${plot_dependencies}${dependency}")
|
||||||
|
message(STATUS "plot: exporting ${target}: ${reason}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
# Apply the project warning set to a first-party target. Warnings are never
|
# Apply the project warning set to a first-party target. Warnings are never
|
||||||
# suppressed per file.
|
# suppressed per file.
|
||||||
@@ -38,15 +94,22 @@ endfunction()
|
|||||||
# GLFW (the last resort, because it needs the network). The result is cached in
|
# GLFW (the last resort, because it needs the network). The result is cached in
|
||||||
# PLOT_GLFW_DEP, so a build with several adapters enabled discovers -- and at
|
# PLOT_GLFW_DEP, so a build with several adapters enabled discovers -- and at
|
||||||
# worst fetches -- exactly one copy. Sets <out_var> to the target to link.
|
# worst fetches -- exactly one copy. Sets <out_var> to the target to link.
|
||||||
|
#
|
||||||
|
# PLOT_GLFW_DEP_ORIGIN records which of the three supplied it, because only the
|
||||||
|
# first two can be promised to a consumer of an installed adapter (see
|
||||||
|
# plot_record_adapter_export()).
|
||||||
function(plot_find_glfw out_var)
|
function(plot_find_glfw out_var)
|
||||||
if(NOT DEFINED PLOT_GLFW_DEP)
|
if(NOT DEFINED PLOT_GLFW_DEP)
|
||||||
set(plot_glfw_dep "")
|
set(plot_glfw_dep "")
|
||||||
|
set(plot_glfw_origin "")
|
||||||
|
|
||||||
find_package(glfw3 3.3 QUIET)
|
find_package(glfw3 3.3 QUIET)
|
||||||
if(TARGET glfw)
|
if(TARGET glfw)
|
||||||
set(plot_glfw_dep glfw)
|
set(plot_glfw_dep glfw)
|
||||||
|
set(plot_glfw_origin find_package)
|
||||||
elseif(TARGET glfw3::glfw3)
|
elseif(TARGET glfw3::glfw3)
|
||||||
set(plot_glfw_dep glfw3::glfw3)
|
set(plot_glfw_dep glfw3::glfw3)
|
||||||
|
set(plot_glfw_origin find_package)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT plot_glfw_dep)
|
if(NOT plot_glfw_dep)
|
||||||
@@ -55,6 +118,7 @@ function(plot_find_glfw out_var)
|
|||||||
pkg_check_modules(GLFW_PC QUIET IMPORTED_TARGET glfw3)
|
pkg_check_modules(GLFW_PC QUIET IMPORTED_TARGET glfw3)
|
||||||
if(TARGET PkgConfig::GLFW_PC)
|
if(TARGET PkgConfig::GLFW_PC)
|
||||||
set(plot_glfw_dep PkgConfig::GLFW_PC)
|
set(plot_glfw_dep PkgConfig::GLFW_PC)
|
||||||
|
set(plot_glfw_origin pkg-config)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@@ -72,12 +136,29 @@ function(plot_find_glfw out_var)
|
|||||||
GIT_SHALLOW TRUE)
|
GIT_SHALLOW TRUE)
|
||||||
FetchContent_MakeAvailable(glfw)
|
FetchContent_MakeAvailable(glfw)
|
||||||
set(plot_glfw_dep glfw)
|
set(plot_glfw_dep glfw)
|
||||||
|
set(plot_glfw_origin FetchContent)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(PLOT_GLFW_DEP "${plot_glfw_dep}" CACHE INTERNAL
|
set(PLOT_GLFW_DEP "${plot_glfw_dep}" CACHE INTERNAL
|
||||||
"GLFW target the plot adapters link against")
|
"GLFW target the plot adapters link against")
|
||||||
|
set(PLOT_GLFW_DEP_ORIGIN "${plot_glfw_origin}" CACHE INTERNAL
|
||||||
|
"How plot resolved GLFW: find_package, pkg-config or FetchContent")
|
||||||
message(STATUS "plot: GLFW adapter dependency: ${plot_glfw_dep}")
|
message(STATUS "plot: GLFW adapter dependency: ${plot_glfw_dep}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(${out_var} "${PLOT_GLFW_DEP}" PARENT_SCOPE)
|
set(${out_var} "${PLOT_GLFW_DEP}" PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# The find_dependency() snippet that re-creates an exported adapter's toolkit
|
||||||
|
# target on a consumer's machine, for the toolkits a config file can re-find.
|
||||||
|
# Adapters call these when they record their export decision; the snippets are
|
||||||
|
# substituted into cmake/plotConfig.cmake.in.
|
||||||
|
function(plot_glfw_dependency_snippet out_var)
|
||||||
|
if(PLOT_GLFW_DEP_ORIGIN STREQUAL "find_package")
|
||||||
|
set(${out_var} "find_dependency(glfw3 3.3)\n" PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${out_var}
|
||||||
|
"find_dependency(PkgConfig)\npkg_check_modules(GLFW_PC REQUIRED IMPORTED_TARGET glfw3)\n"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
+46
-2
@@ -1,7 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/// Umbrella header: pulls in every public component of the plot library.
|
/// Umbrella header: pulls in every public component of the plot library, in
|
||||||
/// Later layers (gl, data, render, plot, input) are added here as they land.
|
/// layer order (`core/math -> gl -> data -> render -> plot -> input`), so a
|
||||||
|
/// translation unit can include this one header and use the whole surface.
|
||||||
|
///
|
||||||
|
/// It deliberately stops at the library: the adapters under `adapters/` are
|
||||||
|
/// separate targets -- each one drags in GLFW, Dear ImGui, Qt6 or GTK4 -- and
|
||||||
|
/// pulling any of them in here would destroy the core's zero-dependency
|
||||||
|
/// property, which is the point of `plot_core`.
|
||||||
|
///
|
||||||
|
/// The macro-gated instrumentation under `*/detail/` is not here either: those
|
||||||
|
/// headers exist for the test suite's counters, define nothing without their
|
||||||
|
/// PLOT_*_COUNT/PLOT_RING_STATS macro, and are documented as not part of the
|
||||||
|
/// public surface.
|
||||||
|
|
||||||
#include <plot/core/color.hpp>
|
#include <plot/core/color.hpp>
|
||||||
#include <plot/core/rect.hpp>
|
#include <plot/core/rect.hpp>
|
||||||
@@ -12,3 +23,36 @@
|
|||||||
#include <plot/math/mat3.hpp>
|
#include <plot/math/mat3.hpp>
|
||||||
#include <plot/math/transform.hpp>
|
#include <plot/math/transform.hpp>
|
||||||
#include <plot/math/vec2.hpp>
|
#include <plot/math/vec2.hpp>
|
||||||
|
|
||||||
|
#include <plot/gl/api.hpp>
|
||||||
|
#include <plot/gl/caps.hpp>
|
||||||
|
#include <plot/gl/handle.hpp>
|
||||||
|
#include <plot/gl/loader.hpp>
|
||||||
|
|
||||||
|
#include <plot/data/array_series.hpp>
|
||||||
|
#include <plot/data/minmax_pyramid.hpp>
|
||||||
|
#include <plot/data/ring_buffer.hpp>
|
||||||
|
#include <plot/data/series.hpp>
|
||||||
|
#include <plot/data/stream_series.hpp>
|
||||||
|
|
||||||
|
#include <plot/render/bitmap_font.hpp>
|
||||||
|
#include <plot/render/buffer.hpp>
|
||||||
|
#include <plot/render/primitives.hpp>
|
||||||
|
#include <plot/render/program.hpp>
|
||||||
|
#include <plot/render/renderer.hpp>
|
||||||
|
#include <plot/render/shaders.hpp>
|
||||||
|
#include <plot/render/style.hpp>
|
||||||
|
#include <plot/render/text.hpp>
|
||||||
|
#include <plot/render/vertex_array.hpp>
|
||||||
|
|
||||||
|
#include <plot/plot/annotation.hpp>
|
||||||
|
#include <plot/plot/axis.hpp>
|
||||||
|
#include <plot/plot/cursor.hpp>
|
||||||
|
#include <plot/plot/grid.hpp>
|
||||||
|
#include <plot/plot/measure.hpp>
|
||||||
|
#include <plot/plot/plot.hpp>
|
||||||
|
#include <plot/plot/ticks.hpp>
|
||||||
|
#include <plot/plot/trace.hpp>
|
||||||
|
|
||||||
|
#include <plot/input/controller.hpp>
|
||||||
|
#include <plot/input/events.hpp>
|
||||||
@@ -73,3 +73,15 @@ target_compile_definitions(plot_tests PRIVATE PLOT_PYRAMID_COUNT_COVERS
|
|||||||
plot_apply_warnings(plot_tests)
|
plot_apply_warnings(plot_tests)
|
||||||
|
|
||||||
add_test(NAME plot_tests COMMAND plot_tests)
|
add_test(NAME plot_tests COMMAND plot_tests)
|
||||||
|
|
||||||
|
# The GL tests create a real EGL context, and llvmpipe's teardown leaks driver
|
||||||
|
# allocations that are not this library's. The suppressions file names those
|
||||||
|
# libraries and nothing else (see cmake/plot_asan_suppressions.txt); a report from
|
||||||
|
# anything under include/plot/ or src/ is still an error. The environment is set
|
||||||
|
# on the test rather than in a preset so `ctest --test-dir build/asan` gets it
|
||||||
|
# however it is launched, and print_suppressions makes the counts visible -- a run
|
||||||
|
# must show what it suppressed, not hide it.
|
||||||
|
if(PLOT_ASAN_ENABLED)
|
||||||
|
set_tests_properties(plot_tests PROPERTIES ENVIRONMENT
|
||||||
|
"ASAN_OPTIONS=detect_leaks=1:print_suppressions=1:suppressions=${CMAKE_SOURCE_DIR}/cmake/plot_asan_suppressions.txt")
|
||||||
|
endif()
|
||||||
Reference in new issue
Block a user