Repository navigation
Expand file tree
/
Copy pathCMakeLists.txt
More file actions
257 lines (233 loc) · 14.4 KB
/
Copy pathCMakeLists.txt
File metadata and controls
257 lines (233 loc) · 14.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.23)
# The version is a committed literal, not derived from `git describe`.
# vcpkg_from_github extracts a tarball with no .git, where a derived version
# silently becomes 0.0.0 and every find_package(formula-cpp 0.1.0) then fails
# with an error the git tag does not explain.
project(formula-cpp
VERSION 0.5.0
DESCRIPTION "Declarative, traceable, self-documenting formulas for C++23"
HOMEPAGE_URL "https://github.com/LASTRADA-Software/formula-cpp"
LANGUAGES CXX)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
option(FORMULA_BUILD_TESTS "Build formula-cpp tests" ${PROJECT_IS_TOP_LEVEL})
option(FORMULA_BUILD_EXAMPLES "Build formula-cpp examples" ${PROJECT_IS_TOP_LEVEL})
option(FORMULA_INSTALL "Generate install rules" ${PROJECT_IS_TOP_LEVEL})
option(FORMULA_PEDANTIC "Compile with strict warnings" ON)
option(FORMULA_WERROR "Treat warnings as errors" OFF)
# Our own tooling (currently: the gallery generator under tools/gallery). A
# consumer embedding this library as a subproject must not build it -- it
# exists to maintain formula-cpp itself, not to be linked by anyone else.
option(FORMULA_TOOLS "Build formula-cpp's own tools" ${PROJECT_IS_TOP_LEVEL})
# The Doxygen API reference published under /api by .github/workflows/pages.yml.
# Same reasoning as FORMULA_TOOLS: a consumer embedding this library as a
# subproject has no use for formula-cpp's own documentation target.
option(FORMULA_BUILD_DOCS "Configure the formula-cpp-docs-api target" ${PROJECT_IS_TOP_LEVEL})
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(formula-cpp INTERFACE)
add_library(formula-cpp::formula-cpp ALIAS formula-cpp)
target_compile_features(formula-cpp INTERFACE cxx_std_23)
target_sources(formula-cpp INTERFACE
FILE_SET HEADERS
BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include"
FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/checked_int.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/enum_name.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/fixed_string.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/latex_math.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/least_squares_kernel.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/name_text.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/transcendental.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/type_name.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/type_list.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/wide_int.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/detail/wide_rounding.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/band.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/binning.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/calculation.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/citation.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/conditional.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/conformity.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/constraint.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/curve.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/critical_value.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/dimension.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/document.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/enumerator.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/environment.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/error.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/escape.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/evaluate.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/expression.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/format.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/formula.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/function.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/int128.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/least_squares.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/lineage.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/lookup.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/measured.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/method.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/number_text.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/observations.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/opaque.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/outcome.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/overlay.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/precision.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/predicate.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/quantity.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/render.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/rational.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/record.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/rejection.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/retry.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/rounded_root.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/rounded_transcendental.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/rounding.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/rounding_node.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/series.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/snap.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/sink.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/statistics.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/tag.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/trace.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/trace_render.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/unit.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/version.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/vocabulary.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/formula-cpp/yields.hpp")
# These three are workarounds for cl's non-conformance and are REQUIRED to
# compile this library's headers at all, so they are INTERFACE, not PRIVATE:
# a consumer using cl needs them too. $<CXX_COMPILER_ID:MSVC> matches the real
# cl driver only -- clang-cl reports "Clang" and needs none of them, being
# conforming, UTF-8 by default, and correct about __cplusplus already.
target_compile_options(formula-cpp INTERFACE
"$<$<CXX_COMPILER_ID:MSVC>:/permissive-;/utf-8;/Zc:__cplusplus>")
if(FORMULA_INSTALL)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
install(TARGETS formula-cpp
EXPORT formula-cpp-targets
FILE_SET HEADERS DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(EXPORT formula-cpp-targets
FILE formula-cpp-targets.cmake
NAMESPACE formula-cpp::
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/formula-cpp")
# ARCH_INDEPENDENT: a header-only package must not refuse a consumer whose
# pointer width differs from whatever configured the install.
# SameMinorVersion, not SameMajorVersion: before 1.0 the breaking changes
# land on the minor, so 0.1 must not silently satisfy a request for 0.2.
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/formula-cpp-config-version.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMinorVersion
ARCH_INDEPENDENT)
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/formula-cpp-config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/formula-cpp-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/formula-cpp")
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/formula-cpp-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/formula-cpp-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/formula-cpp")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/formula-cpp")
endif()
# Bare enable_testing() at top level, never include(CTest): examples/CMakeLists.txt
# calls add_test() unconditionally, so with -DFORMULA_BUILD_TESTS=OFF
# -DFORMULA_BUILD_EXAMPLES=ON that add_test needs a testing context to
# register into regardless of FORMULA_BUILD_TESTS, or CMake silently drops it.
# Bare enable_testing() only sets a directory property and writes
# CTestTestfile.cmake into the build tree -- it creates no targets, no cache
# variables and no install() rule, so the installed package config stays
# byte-identical. include(CTest) would not be safe as a substitute: it adds a
# BUILD_TESTING cache option and Nightly/Continuous/Experimental targets into
# any consumer's build, so it must not be introduced here.
enable_testing()
if(FORMULA_BUILD_TESTS)
add_subdirectory(test)
endif()
if(FORMULA_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
if(FORMULA_TOOLS)
add_subdirectory(tools/gallery)
endif()
# docs/numeric-headroom.md's census tables, regenerated from the census
# programs and compared (docs.numeric-headroom), or rewritten
# (formula-cpp-census-page) -- see cmake/CheckCensusPage.cmake.
if(FORMULA_BUILD_TESTS AND FORMULA_BUILD_EXAMPLES AND FORMULA_TOOLS)
get_property(censusExamples GLOBAL PROPERTY FORMULA_CENSUS_EXAMPLES)
set(censusPrograms "")
set(censusTargets formula-cpp-census-tests formula-cpp-census-gallery)
foreach(name IN LISTS censusExamples)
list(APPEND censusPrograms "${name}=$<TARGET_FILE:formula-cpp-census-example-${name}>")
list(APPEND censusTargets "formula-cpp-census-example-${name}")
endforeach()
list(JOIN censusPrograms "|" censusProgramsJoined)
set(censusPageArguments
-D "CENSUS_EXE=$<TARGET_FILE:formula-cpp-census-tests>"
-D "CENSUS_PROGRAMS=${censusProgramsJoined}"
-D "GALLERY_EXE=$<TARGET_FILE:formula-cpp-census-gallery>"
-D "PAGE=${PROJECT_SOURCE_DIR}/docs/numeric-headroom.md"
-D "BINARY_DIR=${PROJECT_BINARY_DIR}"
-D "CENSUS_COMPILER=${CMAKE_CXX_COMPILER_ID}")
find_package(Python3 COMPONENTS Interpreter QUIET)
if(Python3_Interpreter_FOUND)
list(APPEND censusPageArguments
-D "PYTHON=${Python3_EXECUTABLE}"
-D "EXACT_SCRIPT=${PROJECT_SOURCE_DIR}/tools/census/exact_sizes.py")
# The exact companion's own pins: its generator and fixture against
# the literals the census test holds the library to, and its headline
# figures. A PASS_REGULAR_EXPRESSION list passes on any one match, so
# each is one expression, with `.` for the `;` a list would split on.
add_test(NAME census.exact-sizes-self-check
COMMAND "${Python3_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/tools/census/exact_sizes.py" --self-check)
set_tests_properties(census.exact-sizes-self-check PROPERTIES PASS_REGULAR_EXPRESSION
"first draws at 6 dp, g: 4035209/100000, 20006919/500000, 40234577/1000000, 20376907/500000, 3931329/100000, 39674913/1000000[\r\n]+first draws at 4 dp, g: 48943/1250, 195969/5000, 393317/10000, 102131/2500, 198753/5000, 97743/2500[\r\n]+their sample variance, g2: 454295463/1000000000[\r\n]")
add_test(NAME census.exact-sizes
COMMAND "${Python3_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/tools/census/exact_sizes.py")
set_tests_properties(census.exact-sizes PROPERTIES PASS_REGULAR_EXPRESSION
"at 6 dp: the exact variance does not fit 128 bits in 0 of 1000 in kg2 \\(SI. widest 65 bits\\), in 0 of 1000 in g2 \\(declared. widest 45 bits\\)[\r\n]+[^\r\n]*in Pa \\(SI\\) the exact strength does not fit 128 bits at 0 of 63 \\(widest 64 bits\\)[\r\n]+[^\r\n]*in MPa \\(declared\\) it does not fit at 0 of 63 \\(widest 44 bits\\)")
endif()
add_test(NAME docs.numeric-headroom
COMMAND "${CMAKE_COMMAND}" ${censusPageArguments} -P "${PROJECT_SOURCE_DIR}/cmake/CheckCensusPage.cmake")
add_custom_target(formula-cpp-census-page
COMMAND "${CMAKE_COMMAND}" ${censusPageArguments} -D UPDATE=ON
-P "${PROJECT_SOURCE_DIR}/cmake/CheckCensusPage.cmake"
DEPENDS ${censusTargets}
VERBATIM)
endif()
if(FORMULA_BUILD_DOCS)
# QUIET: Doxygen is not installed on every machine that configures this
# project, and its absence must not fail configuration -- only whoever
# actually asks for the formula-cpp-docs-api target (in practice, just
# .github/workflows/pages.yml) needs it present.
find_package(Doxygen QUIET)
if(DOXYGEN_FOUND)
# A local build gets a build-tree default; the workflow overrides this
# with -DFORMULA_DOXYGEN_OUTPUT_DIR=<mkdocs site>/api so Doxygen writes
# its HTML straight into the already-built MkDocs site with no copy
# step. The default must not point inside the MkDocs site's own docs/
# directory (mkdocs build would then see stray HTML as source input).
set(FORMULA_DOXYGEN_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/docs-api" CACHE PATH
"Where the formula-cpp-docs-api target writes the generated HTML")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in"
"${CMAKE_CURRENT_BINARY_DIR}/Doxyfile"
@ONLY)
# Not part of the default build (`cmake --build --preset ...` does not
# touch this target): none of the four development presets install
# Doxygen, and the API reference is only ever built by the publishing
# workflow, on demand, against the version of Doxygen it installs.
add_custom_target(formula-cpp-docs-api
COMMAND "${CMAKE_COMMAND}" -E make_directory "${FORMULA_DOXYGEN_OUTPUT_DIR}"
COMMAND "${DOXYGEN_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "formula-cpp: generating the Doxygen API reference"
VERBATIM)
endif()
endif()