From 7e1a230f4b8ddb6bb646af7fb60fd92fd4c5cc73 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 10:12:55 +0200 Subject: [PATCH 01/27] meson.build: GAOL as a meson subproject, with project arguments and the flags of gaol.pc in gaol_dep --- gaol/meson.build | 8 ++++++-- meson.build | 43 ++++++++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/gaol/meson.build b/gaol/meson.build index 3ba3ca9d..b6d0f1de 100755 --- a/gaol/meson.build +++ b/gaol/meson.build @@ -194,11 +194,15 @@ else gaollib_static = gaollib.get_static_lib() endif -# GAOL, for the tests and the examples of this build, and for a meson project -# bringing GAOL in as a subproject +# GAOL, for the examples of this build, and for a meson project bringing GAOL +# in as a subproject: the flags of interval arithmetic and the link option +# gaol.pc gives, which the code including GAOL's headers is to be compiled and +# linked with, the arguments of this project not reaching the targets of +# another one (GAOL v5) gaol_dep = declare_dependency( link_with: gaollib, include_directories: include_directories('..'), + compile_args: pc_cflags, link_args: gaol_link_args, dependencies: deps, ) diff --git a/meson.build b/meson.build index e8e7daaf..ff1a8d0b 100755 --- a/meson.build +++ b/meson.build @@ -202,27 +202,32 @@ endif # CMakeLists.txt and configure give them: -frounding-math; -ffp-contract=off # (without it, compilers contract a multiplication and an addition into a fused # one as if rounding to nearest: on 64-bit ARM, -(.5*l - .5*r) and -.5*l + .5*r -# both became fnma(.5, l, .5*r), and mid() a single double); -fno-fast-math +# both became fnma(.5, l, .5*r), and mid() a single double); -fno-fast-math. +# These flags, and the others below, are arguments of the project rather than +# global ones, which meson refuses in a subproject: GAOL can then be a +# subproject of a meson project, whose own targets they do not reach, and +# gaol_dep gives that project's code the flags gaol.pc gives (pc_cflags, see +# gaol/meson.build) (GAOL v5) pc_cflags = [] # the flags of interval arithmetic, which gaol.pc gives the code using GAOL foreach flag : ['-frounding-math', '-ffp-contract=off', '-fno-fast-math'] if cpp_comp.has_argument(flag) - add_global_arguments([flag], language: 'cpp') + add_project_arguments([flag], language: 'cpp') pc_cflags += [flag] endif if c_comp.has_argument(flag) - add_global_arguments([flag], language: 'c') + add_project_arguments([flag], language: 'c') endif endforeach # Visual C++: /fp:strict, as CMakeLists.txt gives it to GAOL and to CORE-MATH, # without which gaol/gaol_config.h refuses to compile if msvc - add_global_arguments(['/fp:strict'], language: ['c', 'cpp']) + add_project_arguments(['/fp:strict'], language: ['c', 'cpp']) pc_cflags += ['/fp:strict'] # clang-cl for 32-bit x86 computes doubles on the x87 unit, even with # /arch:SSE2, which gaol/gaol_config.h refuses: -msse2 has it compute them # in SSE2, as CMakeLists.txt gives it if cpp_comp.get_id() == 'clang-cl' and host_machine.cpu_family() == 'x86' - add_global_arguments(['-msse2'], language: ['c', 'cpp']) + add_project_arguments(['-msse2'], language: ['c', 'cpp']) pc_cflags += ['-msse2'] endif endif @@ -231,23 +236,23 @@ endif # public declarations carry __attribute__ ((visibility("default"))) if cpp_comp.has_multi_arguments('-fvisibility-inlines-hidden', '-fvisibility=hidden') conf_data.set('GAOL_HAVE_VISIBILITY_OPTIONS', 1) - add_global_arguments(['-fvisibility-inlines-hidden', '-fvisibility=hidden'], language: 'cpp') + add_project_arguments(['-fvisibility-inlines-hidden', '-fvisibility=hidden'], language: 'cpp') endif if cpp_comp.has_argument('-Wconversion') - add_global_arguments(['-Wconversion'], language: 'cpp') + add_project_arguments(['-Wconversion'], language: 'cpp') endif if c_comp.has_argument('-Wconversion') - add_global_arguments(['-Wconversion'], language: 'c') + add_project_arguments(['-Wconversion'], language: 'c') endif # The optimizations configure (--enable-optimize) and the Release build of # CMake add to -O3, in the release build type, where the compiler takes them if get_option('buildtype') == 'release' foreach flag : ['-funroll-loops', '-fomit-frame-pointer', '-fexpensive-optimizations'] if cpp_comp.has_argument(flag) - add_global_arguments([flag], language: 'cpp') + add_project_arguments([flag], language: 'cpp') endif if c_comp.has_argument(flag) - add_global_arguments([flag], language: 'c') + add_project_arguments([flag], language: 'c') endif endforeach endif @@ -277,18 +282,18 @@ int main() { return 0; } if target_x86 if target_x86_32 and cpp_comp.has_multi_arguments('-msse2', '-mfpmath=sse') x86_args = ['-msse2', '-mfpmath=sse'] - add_global_arguments(x86_args, language: 'cpp') - add_global_arguments(x86_args, language: 'c') + add_project_arguments(x86_args, language: 'cpp') + add_project_arguments(x86_args, language: 'c') pc_cflags += x86_args endif if simd and not msvc and not (target_x86_32 and os_win) and cpp_comp.has_argument('-msse2') use_sse2 = true conf_data.set('GAOL_USING_SSE2_INSTRUCTIONS', 1) - add_global_arguments(['-msse2'], language: 'cpp') + add_project_arguments(['-msse2'], language: 'cpp') pc_cflags += ['-msse2'] if cpp_comp.has_argument('-msse3') conf_data.set('GAOL_USING_SSE3_INSTRUCTIONS', 1) - add_global_arguments(['-msse3'], language: 'cpp') + add_project_arguments(['-msse3'], language: 'cpp') pc_cflags += ['-msse3'] endif endif @@ -399,8 +404,8 @@ if get_option('enable-fma') endif endif if fma_args.length() > 0 - add_global_arguments(fma_args, language: 'c') - add_global_arguments(fma_args, language: 'cpp') + add_project_arguments(fma_args, language: 'c') + add_project_arguments(fma_args, language: 'cpp') pc_cflags += fma_args endif endif @@ -409,7 +414,7 @@ message('Fused multiply-add flags: ' + ' '.join(fma_args)) # -ffloat-store only where doubles are still computed on the x87 unit # (FLT_EVAL_METHOD not 0), whose 80-bit registers keep more digits than a # double (as CMakeLists.txt): checked with the flags of 32-bit x86 above, which -# the checks of the compiler do not get from add_global_arguments() +# the checks of the compiler do not get from add_project_arguments() float_store_needed = cpp_comp.compiles(''' #include #if defined(FLT_EVAL_METHOD) && FLT_EVAL_METHOD == 0 @@ -418,8 +423,8 @@ float_store_needed = cpp_comp.compiles(''' int main() { return 0; } ''', args: x86_args, name: 'doubles computed in extended precision') if float_store_needed and cpp_comp.has_argument('-ffloat-store') - add_global_arguments(['-ffloat-store'], language: 'c') - add_global_arguments(['-ffloat-store'], language: 'cpp') + add_project_arguments(['-ffloat-store'], language: 'c') + add_project_arguments(['-ffloat-store'], language: 'cpp') pc_cflags += ['-ffloat-store'] endif From 37549a1cbe8ef6f64bd9422255032315aeb65837 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 10:13:10 +0200 Subject: [PATCH 02/27] tests/meson_subproject: GAOL as a meson subproject, its tests and the flags of their code, in the CI --- .github/workflows/build-systems.yml | 36 +++++++++++++++++++++- .gitignore | 4 +++ CMakeLists.txt | 2 +- tests/meson_subproject/check_flags.py | 44 +++++++++++++++++++++++++++ tests/meson_subproject/meson.build | 39 ++++++++++++++++++++++++ 5 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 tests/meson_subproject/check_flags.py create mode 100644 tests/meson_subproject/meson.build diff --git a/.github/workflows/build-systems.yml b/.github/workflows/build-systems.yml index c9f2d5b6..01211bf3 100644 --- a/.github/workflows/build-systems.yml +++ b/.github/workflows/build-systems.yml @@ -9,7 +9,8 @@ # locale writing a decimal comma, which the Linux jobs and the containers # generate first, macOS and Windows having one (.github/scripts/comma-locale.sh, # GAOL v5). The autotools jobs check that make distclean gives the sources back -# as git has them. +# as git has them. One job builds GAOL as a subproject of a meson project +# (tests/meson_subproject, GAOL v5). # # Copyright (c) 2026 ENSTA, France # @@ -209,6 +210,39 @@ jobs: - name: Performance run: ./performance | tee -a "$GITHUB_STEP_SUMMARY" + # GAOL as a subproject of a meson project, tests/meson_subproject, which + # builds tests of tests/ with gaol_dep and checks that their code gets the + # flags of interval arithmetic: meson refused the add_global_arguments() of + # meson.build in a subproject (GAOL v5) + meson-subproject: + name: Meson, Ubuntu 24.04 x86_64, GAOL as a subproject + runs-on: ubuntu-24.04 + timeout-minutes: 60 + steps: + - uses: actions/checkout@v7 + - name: Tools + run: | + sudo apt-get update -q + sudo apt-get install -y -q g++ pipx + pipx install meson + pipx install ninja + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + - name: Configure tests/meson_subproject, a project bringing GAOL in as a subproject, from this checkout + run: | + meson --version + mkdir tests/meson_subproject/subprojects + ln -s "$PWD" tests/meson_subproject/subprojects/gaol + meson setup build-meson-subproject tests/meson_subproject --buildtype=release | tee configure.log + grep -q "Elementary functions: CORE-MATH" configure.log + - name: Build + run: meson compile -C build-meson-subproject + - name: Locale writing a decimal comma + run: sh .github/scripts/comma-locale.sh generate + - name: Tests (ninja test, make test of meson), the flags of their code among them + run: ninja -C build-meson-subproject test + - name: The test numbers ran under a locale writing a decimal comma + run: sh .github/scripts/comma-locale.sh check build-meson-subproject/meson-logs/testlog.txt + # meson with Visual C++: the static libgaol, as CMake builds it, its tests, # and the installed GAOL, with which a test is compiled again (GAOL v5). In # PowerShell: the link of Git Bash would hide the linker of Visual C++. diff --git a/.gitignore b/.gitignore index dadb3d90..1c0d91ce 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,10 @@ coverage/coverage.json 3rd/math-core/**/.deps/ 3rd/math-core/**/.dirstamp +# The link to the sources of GAOL that tests/meson_subproject takes as its +# subproject (see its meson.build) +tests/meson_subproject/subprojects/ + # Written by the performance target of check/Makefile.am check/performances_result.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index b3ceb2e5..6e663b18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -941,7 +941,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set(CPACK_SOURCE_IGNORE_FILES "/\\.git/" "/\\.git$" "/\\.claude/" "/\\.vscode/" "/\\.idea/" "/\\.cache/" "\\.swp$" "~$" "/#" "/\\.#" - "/autom4te\\.cache/" "/doc/compare/code/work/" + "/autom4te\\.cache/" "/doc/compare/code/work/" "/tests/meson_subproject/subprojects/" "/coverage/[^/]*\\.(css|js)$" "/coverage/coverage\\.json$" "\\.o$" "\\.lo$" "/\\.libs/" "/\\.deps/" "\\.dirstamp$" "/check/performances_result\\.txt$" "^${_gaol_source_regex}/build[^/]*/" "/_CPack_Packages/" diff --git a/tests/meson_subproject/check_flags.py b/tests/meson_subproject/check_flags.py new file mode 100644 index 00000000..9156941b --- /dev/null +++ b/tests/meson_subproject/check_flags.py @@ -0,0 +1,44 @@ +"""The flags of interval arithmetic in the code of a meson project using GAOL +as a subproject (GAOL v5). + + python3 check_flags.py + +Fails unless each command of compile_commands.json that compiles a source of +the project, not of its subprojects, holds the flags of the Cflags of the +gaol.pc the subproject GAOL wrote in meson-private, its include directory +aside: the code including GAOL's headers is to be compiled with them (see +doc/using.md), and gaol_dep alone gives them, the arguments of the project +GAOL reaching none of the targets of another project. + +Copyright (c) 2026 ENSTA, France + +Created 2026-10-06 by Jordan NININ +""" +import json +import os +import shlex +import sys + +build, source = sys.argv[1], sys.argv[2] +with open(os.path.join(build, 'meson-private', 'gaol.pc')) as pc: + cflags = [line for line in pc if line.startswith('Cflags:')][0] +flags = [f for f in shlex.split(cflags[len('Cflags:'):]) + if not f.startswith('-I')] +with open(os.path.join(build, 'compile_commands.json')) as db: + commands = json.load(db) +subprojects = os.path.join(os.path.normpath(source), 'subprojects') + os.sep +checked = 0 +failed = 0 +for command in commands: + path = os.path.normpath(os.path.join(command['directory'], command['file'])) + if path.startswith(subprojects): + continue + checked += 1 + missing = [f for f in flags if f not in shlex.split(command['command'])] + if missing: + failed += 1 + print('%s is compiled without %s' + % (command['file'], ' '.join(missing))) +print('%d command(s) of the project checked for %s' + % (checked, ' '.join(flags))) +sys.exit(1 if failed or not checked or not flags else 0) diff --git a/tests/meson_subproject/meson.build b/tests/meson_subproject/meson.build new file mode 100644 index 00000000..19c8b488 --- /dev/null +++ b/tests/meson_subproject/meson.build @@ -0,0 +1,39 @@ +# ================================================================== +# The tests of GAOL built with a GAOL brought in as a meson subproject +# ================================================================== +# +# Builds the tests of the parent directory as a meson project bringing GAOL in +# as a subproject would (GAOL v5): GAOL is then targets of this project, built +# with it, and gaol_dep gives the code of this project the flags of interval +# arithmetic, which the test flags checks. GAOL is to be in subprojects/gaol, a +# link to its sources, as the continuous integration makes it +# (.github/workflows/build-systems.yml): +# +# mkdir tests/meson_subproject/subprojects +# ln -s tests/meson_subproject/subprojects/gaol +# meson setup build-meson-subproject tests/meson_subproject --buildtype=release +# meson test -C build-meson-subproject +# +# Copyright (c) 2026 ENSTA, France +# +# Created 2026-10-06 by Jordan NININ + +project('gaol_tests_meson_subproject', 'cpp') + +gaol_dep = subproject('gaol').get_variable('gaol_dep') + +foreach t : ['arithmetic', 'elementary', 'rounding_direction', 'numbers', + 'other_functions', 'reverse'] + exe = executable('gaol_test_' + t, '../' + t + '.cpp', + dependencies: gaol_dep, + override_options: ['cpp_std=c++17']) + test(t, exe, timeout: 300) +endforeach + +# The arguments GAOL gives its own targets do not reach those of this project: +# the commands that compile the tests above have to hold the flags of the +# gaol.pc the subproject wrote, which only gaol_dep gives them. Without them, +# the tests pass all the same (GCC 9.4, x86_64) +test('flags', find_program('python3'), + args: [files('check_flags.py'), meson.build_root(), + meson.current_source_dir()]) From 96764254f06bb32afdc0e69e45d68dd98d451a35 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 10:13:28 +0200 Subject: [PATCH 03/27] doc, manual: GAOL as a meson subproject, gaol_dep, and the build type of meson before 1.8.4 --- doc/continuous-integration.md | 5 ++++- doc/tests.md | 5 +++++ doc/using.md | 21 +++++++++++++++++++++ manual/v5/gaol.tex | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/doc/continuous-integration.md b/doc/continuous-integration.md index 2f955a5d..6dcb4c2e 100644 --- a/doc/continuous-integration.md +++ b/doc/continuous-integration.md @@ -54,7 +54,10 @@ Visual Studio 2022 and 2026 (x64, x86), run the tests (`make test`, GAOL they install, which is the only library installed, CORE-MATH being compiled into it; build GAOL as a part of another project, brought in by FetchContent (`tests/fetch_content`), and the tests with the GAOL that project -installs; check that the three builds agree on each of these machines; check +installs; build GAOL as a subproject of a meson project +(`tests/meson_subproject`, Ubuntu x86_64), whose code compiled with `gaol_dep` +has to get the flags of `gaol.pc` (GAOL v5); check that the three builds agree +on each of these machines; check that configure and meson, and autoconf when it generates configure (Linux), read a `VERSION.txt` that starts with a byte order mark or has the line ends of Windows (`.github/scripts/version-file.sh`), and that meson reads it with diff --git a/doc/tests.md b/doc/tests.md index b30935a5..b2e78b1b 100644 --- a/doc/tests.md +++ b/doc/tests.md @@ -790,6 +790,11 @@ the examples of `examples/` too, where they are built (see continuous integration runs `make test` in every job. `tests/find_package` builds some of the same tests with an installed GAOL, and `.github/scripts/tests.sh` with a GAOL installed by configure or meson. +`tests/fetch_content` builds them with a GAOL brought in by FetchContent, and +`tests/meson_subproject` with a GAOL brought in as a meson subproject, whose +test `flags` checks that `gaol_dep` gives their compilation the flags of the +`Cflags` of `gaol.pc`: meson refused GAOL as a subproject, and the tests pass +without these flags (GAOL v5). `tests/performance.cpp` (`gaol_performance`) measures the time per operation of GAOL's arithmetic and elementary functions, of the constructor `interval(a, b)`, diff --git a/doc/using.md b/doc/using.md index 39e9b310..40f49422 100644 --- a/doc/using.md +++ b/doc/using.md @@ -146,6 +146,27 @@ c++ -std=c++17 -O2 $(pkg-config --cflags gaol) program.cpp $(pkg-config --libs g In a meson project, `dependency('gaol')`. +A meson project can also build GAOL for itself, as a subproject, the sources +of GAOL being in its `subprojects/gaol` (GAOL v5): + +```meson +gaol_dep = dependency('gaol', fallback: ['gaol', 'gaol_dep']) +executable('program', 'program.cpp', dependencies: gaol_dep) +``` + +`dependency()` takes an installed GAOL where it finds one, and builds the +subproject otherwise; `subproject('gaol').get_variable('gaol_dep')` always +builds it. `gaol_dep` carries the include directory, the flags above and the +link option above, as `gaol.pc` does: the flags GAOL's `meson.build` gives its +own targets do not reach those of the project. Where the project leaves the +build type to its default, `debug`, meson before 1.8.4 builds GAOL without +optimization, and before 1.8 with its assertions (`GAOL_DEBUGGING`) too, so +that the project is to be configured with `--buildtype=release`; meson 1.8.4 +and later build it in `release`, the default of GAOL's `meson.build`. +`tests/meson_subproject` is a project building GAOL this way. GAOL could not +be a subproject before GAOL v5: meson refuses the `add_global_arguments()` +its `meson.build` called in a subproject. + ## Initialization and cleanup GAOL initializes itself before `main()`, with every compiler: `gaol::init()` diff --git a/manual/v5/gaol.tex b/manual/v5/gaol.tex index 7e00feb0..4e636328 100644 --- a/manual/v5/gaol.tex +++ b/manual/v5/gaol.tex @@ -984,6 +984,25 @@ \subsection{From pkg-config} \section{The rounding direction}\label{sec:rounding-direction} %%------------------------------ \cindex{rounding!direction}% +A meson project can also build GAOL for itself, as a subproject, the sources +of GAOL being in its \file{subprojects/gaol}: +\cindex{meson!using gaol from}% + +\begin{example} +gaol_dep = dependency('gaol', fallback: ['gaol', 'gaol_dep']) +executable('program', 'program.cpp', dependencies: gaol_dep) +\end{example} + +\noindent +\code{dependency()} takes an installed GAOL where it finds one, and builds the +subproject otherwise. \code{gaol\_dep} carries the include directory, the flags +above and the link option above, as \file{gaol.pc} does. Where the project +leaves the build type to its default, \code{debug}, meson before 1.8.4 builds +GAOL without optimization, and before 1.8 with its assertions too, so that the +project is to be configured with \loption{buildtype=release}; meson 1.8.4 and +later build it in \code{release}, the default of GAOL's +\file{meson.build}.\newinvfive + Floating-point interval arithmetic requires \dfn{outward rounding} in order to fulfill the \dfn{containment property}: for example, to add From d68685e5042df1c156e41173d3b6a92f35282c7d Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 10:13:37 +0200 Subject: [PATCH 04/27] doc/building.md, manual, meson.build: the python.exe alias of WindowsApps not checked, USERPROFILE --- doc/building.md | 18 +++++++++--------- manual/v5/gaol.tex | 17 ++++++++++------- meson.build | 7 ++++--- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/doc/building.md b/doc/building.md index d371a8a4..6280ffb8 100644 --- a/doc/building.md +++ b/doc/building.md @@ -274,15 +274,15 @@ Python for that name alone; the continuous integration checks it on Linux with a `meson setup` whose `PATH` holds no Python. On Windows, the directory `%USERPROFILE%\AppData\Local\Microsoft\WindowsApps` -holds the aliases `python.exe` and `python3.exe`, which only open the -Microsoft Store when Python was not installed from it. meson 0.53.1 and later -(the 0.53.2 of Ubuntu 20.04 and the meson of pip among them) leave that -directory out of their search for programs, as long as `PATH` names it by -that path (not for a profile whose directory differs from `USERPROFILE`). -meson 0.53.0 and earlier take the alias, and `meson setup` stops on the -failure of the command that reads `VERSION.txt`: use a later meson -(`pip install meson`), or turn off the aliases of `python.exe` and -`python3.exe` in the Windows settings ("Manage app execution aliases"). +can hold aliases of Python, `python3.exe` and perhaps `python.exe` too (not +checked on Windows), which only open the Microsoft Store when Python was not +installed from it. meson 0.53.1 and later (the 0.53.2 of Ubuntu 20.04 and the +meson of pip among them) leave that directory out of their search for +programs, as long as `PATH` names it by that path (not for a profile whose +directory differs from `USERPROFILE`). meson 0.53.0 and earlier take such an +alias, and `meson setup` stops on the failure of the command that reads +`VERSION.txt`: use a later meson (`pip install meson`), or turn off the +aliases of Python in the Windows settings ("Manage app execution aliases"). ## Tests, examples, performance and the parser diff --git a/manual/v5/gaol.tex b/manual/v5/gaol.tex index 4e636328..d1beae7c 100644 --- a/manual/v5/gaol.tex +++ b/manual/v5/gaol.tex @@ -683,10 +683,13 @@ \section{Building and installing with meson} \cmd{meson setup} runs Python to read the version of GAOL in \file{VERSION.txt}: the first of \cmd{python3} and \cmd{python} found in the \code{PATH}, or, if there is none, the Python that runs meson. On Windows, -meson 0.53.0 and earlier may take the \file{python.exe} or \file{python3.exe} -alias of the Microsoft Store (in \file{WindowsApps}), which only opens the -Store, and \cmd{meson setup} then stops; use meson 0.53.1 or later, or turn off -the aliases in the Windows settings (\emph{Manage app execution aliases}). +meson 0.53.0 and earlier may take an alias of Python of the Microsoft Store +(\file{python3.exe}, and perhaps \file{python.exe}, in \file{WindowsApps}; not +checked on Windows), which only opens the Store, and \cmd{meson setup} then +stops; use meson 0.53.1 or later, or turn off the aliases in the Windows +settings (\emph{Manage app execution aliases}). Later versions of meson leave +\file{WindowsApps} out only where the \code{PATH} names it under the directory +of \code{USERPROFILE}, not for a profile whose directory differs from it. \section{Tests}\label{sec:tests} %%------------- @@ -981,9 +984,6 @@ \subsection{From pkg-config} \noindent In a meson project, \code{dependency('gaol')} finds it. -\section{The rounding direction}\label{sec:rounding-direction} -%%------------------------------ -\cindex{rounding!direction}% A meson project can also build GAOL for itself, as a subproject, the sources of GAOL being in its \file{subprojects/gaol}: \cindex{meson!using gaol from}% @@ -1003,6 +1003,9 @@ \section{The rounding direction}\label{sec:rounding-direction} later build it in \code{release}, the default of GAOL's \file{meson.build}.\newinvfive +\section{The rounding direction}\label{sec:rounding-direction} +%%------------------------------ +\cindex{rounding!direction}% Floating-point interval arithmetic requires \dfn{outward rounding} in order to fulfill the \dfn{containment property}: for example, to add diff --git a/meson.build b/meson.build index ff1a8d0b..b2f94d42 100755 --- a/meson.build +++ b/meson.build @@ -16,9 +16,10 @@ project( # python3 stays first: only when the first name ends with python3 does # meson fall back on its own Python (the meson.exe of the Windows installer) # if it finds none. Looking for python first would lose that fallback, and - # would not avoid the Microsoft Store aliases of meson 0.53.0, which - # WindowsApps holds for python.exe as for python3.exe: meson 0.53.1 and later - # leave that directory out (doc/building.md). The encoding utf-8-sig skips + # would not avoid the Microsoft Store aliases that meson 0.53.0 takes where + # WindowsApps holds a python.exe as well as a python3.exe (not checked on + # Windows): meson 0.53.1 and later leave that directory out + # (doc/building.md). The encoding utf-8-sig skips # the byte order mark that some editors of Windows write at # the start of a file, which the default encoding (the code page of Windows, # cp1252) reads as three characters of the version. The blanks stripped are From 5465a03e9e9ebc9513b91f54b50267a1c6913746 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 10:13:46 +0200 Subject: [PATCH 05/27] meson.build: the files Python reads VERSION.txt from closed, by with --- meson.build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index b2f94d42..a379d6b5 100755 --- a/meson.build +++ b/meson.build @@ -30,7 +30,7 @@ project( # byte, \n), which show in the error message below, on one line, and which # the pipe to meson carries whatever the code page (GAOL v5) version: run_command(find_program('python3', 'python', native: true), '-c', - 'import string, sys; print(ascii(open(sys.argv[-1], encoding=\'utf-8-sig\', errors=\'surrogateescape\').read().strip(string.whitespace))[1:-1])', + 'import string, sys\nwith open(sys.argv[-1], encoding=\'utf-8-sig\', errors=\'surrogateescape\') as f: print(ascii(f.read().strip(string.whitespace))[1:-1])', join_paths(meson.current_source_dir(), 'VERSION.txt'), check: true).stdout().strip(), # Optimized by default, as configure builds GAOL (meson's own default, debug, @@ -51,14 +51,14 @@ if not gaol_version_ok # The first bytes of the file in hexadecimal, which show what the quoted text # does not (a zero-width space, a second byte order mark) gaol_version_bytes = run_command(find_program('python3', 'python', native: true), '-c', - 'import sys; print(*[\'%02x\' % b for b in open(sys.argv[-1], \'rb\').read(32)])', + 'import sys\nwith open(sys.argv[-1], \'rb\') as f: print(*[\'%02x\' % b for b in f.read(32)])', join_paths(meson.current_source_dir(), 'VERSION.txt'), check: false).stdout().strip() # A file of UTF-16 characters, which starts with its byte order mark (FF FE, # FE FF) or holds NUL bytes, is not read as UTF-16: the message says so, as # those of CMake and configure do gaol_version_utf16 = run_command(find_program('python3', 'python', native: true), '-c', - 'import sys; b = open(sys.argv[-1], \'rb\').read(); print(\'mark\' if b[:2] in (bytes([255, 254]), bytes([254, 255])) else \'nul\' if 0 in b else \'\')', + 'import sys\nwith open(sys.argv[-1], \'rb\') as f: b = f.read()\nprint(\'mark\' if b[:2] in (bytes([255, 254]), bytes([254, 255])) else \'nul\' if 0 in b else \'\')', join_paths(meson.current_source_dir(), 'VERSION.txt'), check: false).stdout().strip() gaol_version_hint = '' From 3d4d310792be60996dc63cbb2c4334a273db427c Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 10:13:47 +0200 Subject: [PATCH 06/27] tests: C++17 for the hexadecimal floating literals of the tests, not of elementary_values.h alone --- tests/CMakeLists.txt | 6 ++++-- tests/Makefile.am | 12 +++++++----- tests/Makefile.in | 12 +++++++----- tests/meson.build | 10 ++++++---- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 626466c5..4c77e03f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,8 +7,10 @@ # check/ and ran with CppUnit, check the results of the operations on chosen # intervals (see unit_tests.h). They are compiled as any code using GAOL, with # the flags gaol::gaol carries, and in C++17 for the hexadecimal floating -# literals of elementary_values.h. WITH_TESTS builds them (CMakeLists.txt); -# make test and make check run them, with the label unit. +# literals of the tests, such as 0x1p-1060: those of gaol_tests.h, which all +# but u128.cpp include, of the *_values.h, and of most of the programs. +# WITH_TESTS builds them (CMakeLists.txt); make test and make check run them, +# with the label unit. # # Copyright (c) 2026 ENSTA, France # diff --git a/tests/Makefile.am b/tests/Makefile.am index 1efc7197..19281cf2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -3,11 +3,13 @@ # ./configure --with-tests builds them with GAOL (make), and make check and # make test run them (see ../Makefile.am). They are compiled as any code using # GAOL, with the flags of interval arithmetic configure gives, in C++17 for the -# hexadecimal floating literals of elementary_values.h, and linked with the -# static libgaol just built (-static: a libtool library not installed), and -# with the link option gaol.pc gives (-mno-daz-ftz, where the compiler takes -# it), as CMake links them. Exit status 77 is a test skipped (intervalf and -# interval2f where the intervals of floats are not compiled). +# hexadecimal floating literals of the tests (those of gaol_tests.h, which all +# but u128.cpp include, of the *_values.h, and of most of the programs; see +# CMakeLists.txt), and linked with the static libgaol just built (-static: a +# libtool library not installed), and with the link option gaol.pc gives +# (-mno-daz-ftz, where the compiler takes it), as CMake links them. Exit status +# 77 is a test skipped (intervalf and interval2f where the intervals of floats +# are not compiled). # # make perf measures GAOL v5 on the benchmark of doc/compare/performance.md # (doc/compare/code/run_perf.sh). diff --git a/tests/Makefile.in b/tests/Makefile.in index 31d51b45..b4700498 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -19,11 +19,13 @@ # ./configure --with-tests builds them with GAOL (make), and make check and # make test run them (see ../Makefile.am). They are compiled as any code using # GAOL, with the flags of interval arithmetic configure gives, in C++17 for the -# hexadecimal floating literals of elementary_values.h, and linked with the -# static libgaol just built (-static: a libtool library not installed), and -# with the link option gaol.pc gives (-mno-daz-ftz, where the compiler takes -# it), as CMake links them. Exit status 77 is a test skipped (intervalf and -# interval2f where the intervals of floats are not compiled). +# hexadecimal floating literals of the tests (those of gaol_tests.h, which all +# but u128.cpp include, of the *_values.h, and of most of the programs; see +# CMakeLists.txt), and linked with the static libgaol just built (-static: a +# libtool library not installed), and with the link option gaol.pc gives +# (-mno-daz-ftz, where the compiler takes it), as CMake links them. Exit status +# 77 is a test skipped (intervalf and interval2f where the intervals of floats +# are not compiled). # # make perf measures GAOL v5 on the benchmark of doc/compare/performance.md # (doc/compare/code/run_perf.sh). diff --git a/tests/meson.build b/tests/meson.build index 70a6a68a..391d5299 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -8,10 +8,12 @@ # Built where with-tests is true; each is a test of the suite unit, which meson # test (make test) and meson test --setup check (make check) run. They are # compiled as any code using GAOL, in C++17 for the hexadecimal floating -# literals of elementary_values.h, and linked with the static libgaol, as CMake -# links them. Exit status 77 is a test skipped (intervalf and interval2f where -# the intervals of floats are not compiled). check/, which built the unit tests -# of GAOL 4 with CppUnit, is gone: they are among these (GAOL v5). +# literals of the tests (those of gaol_tests.h, which all but u128.cpp include, +# of the *_values.h, and of most of the programs; see CMakeLists.txt), and +# linked with the static libgaol, as CMake links them. Exit status 77 is a test +# skipped (intervalf and interval2f where the intervals of floats are not +# compiled). check/, which built the unit tests of GAOL 4 with CppUnit, is +# gone: they are among these (GAOL v5). gaol_tests = [ 'arithmetic', 'elementary', 'rounding_direction', 'numbers', 'other_functions', 'ieee1788', 'reverse', 'u128', 'core_math', 'expressions', 'extended_precision', From 765722af9b955748919e3689ec46dc281b93d894 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 11:30:00 +0200 Subject: [PATCH 07/27] meson.build: no default test setup nor target check when GAOL is a subproject --- meson.build | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index a379d6b5..8b399a26 100755 --- a/meson.build +++ b/meson.build @@ -460,13 +460,17 @@ endif if build_examples subdir('examples') endif -if meson.version().version_compare('>=0.57') +# Not in a subproject, whose default test setup would be the project's, which +# may have one of its own, and would leave out its tests of a suite examples; +# nor its target check, which names the build directory of the project (GAOL v5) +if meson.is_subproject() +elif meson.version().version_compare('>=0.57') add_test_setup('unit', exclude_suites: ['examples'], is_default: true) add_test_setup('check') else message('meson ' + meson.version() + ': meson test and ninja test run the examples too (meson test --suite unit runs the unit tests only)') endif -if build_tests or build_examples +if (build_tests or build_examples) and not meson.is_subproject() run_target('check', command: [find_program('meson'), 'test', '-C', meson.current_build_dir(), '--no-rebuild', '--print-errorlogs'] + (meson.version().version_compare('>=0.57') ? ['--setup', 'check'] : []), From f4d1b36cca290a256215f32994ad9d6b50f874bf Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 11:30:11 +0200 Subject: [PATCH 08/27] meson.build: GAOL in release as a subproject, where meson before 1.8.4 gives the project's debug --- gaol/meson.build | 8 ++++++-- meson.build | 28 +++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/gaol/meson.build b/gaol/meson.build index b6d0f1de..3c41679a 100755 --- a/gaol/meson.build +++ b/gaol/meson.build @@ -51,8 +51,10 @@ endif # which the c99 of the project refuses, but with Visual C++, which has no GNU # C and compiles them as CMake does. And b_lto=false keeps the interprocedural # optimization of -Db_lto=true away from them: reached by it, sin and cos took -# half as long again (see doc/three-builds.md) -core_math_overrides = ['b_lto=false'] +# half as long again (see doc/three-builds.md). In a subproject, the options +# of release where meson gives it the build type of the project +# (gaol_release_options, see meson.build) +core_math_overrides = ['b_lto=false'] + gaol_release_options if not msvc core_math_overrides += ['c_std=gnu11'] endif @@ -177,6 +179,7 @@ if msvc include_directories: [incdir, include_directories('../cmake/msvc')], c_args: gaol_msvc_args, cpp_args: gaol_msvc_args, + override_options: gaol_release_options, ) gaollib_static = gaollib else @@ -190,6 +193,7 @@ else include_directories: incdir, version: meson.project_version(), soversion: major_version.to_string(), + override_options: gaol_release_options, ) gaollib_static = gaollib.get_static_lib() endif diff --git a/meson.build b/meson.build index 8b399a26..00b9225a 100755 --- a/meson.build +++ b/meson.build @@ -105,6 +105,32 @@ exception = get_option('enable-exception') # only defined GAOL_DEBUGGING, is gone, as enable-optimize: the build type # gives both (GAOL v5) debug = get_option('buildtype') == 'debug' +release = get_option('buildtype') == 'release' +# Brought in as a subproject, GAOL is built in release by default, as CMake and +# configure build it brought into another project (GAOL v5). meson 1.8.4 and +# later give a subproject its own default build type, release here; earlier +# ones give it the build type of the project, without optimization in meson's +# default, debug, and before 1.8 with GAOL_DEBUGGING too, while 1.8.0 to 1.8.3 +# have get_option('buildtype') read the release of GAOL: the options +# optimization and debug tell the build type of the project there. A +# subproject cannot tell meson's default from a --buildtype=debug asked for: +# where they are those of debug, the libraries of GAOL and CORE-MATH are +# compiled as in release (override_options, gaol/meson.build), and in the +# release of the project with NDEBUG, which the b_ndebug=if-release of +# default_options gives where they apply. Not with Visual C++ before meson +# 0.57, whose build type debug gives /RTC1, which cl refuses with the /O2 of +# optimization=3, and whose C runtime follows the build type of the target. +gaol_release_options = [] +if meson.is_subproject() and meson.version().version_compare('<1.8.4') and not (msvc and meson.version().version_compare('<0.57')) + debug = false + release = get_option('optimization') == '3' and not get_option('debug') + if get_option('optimization') == '0' and get_option('debug') + gaol_release_options = ['optimization=3', 'debug=false', 'b_ndebug=true'] + release = true + elif release + gaol_release_options = ['b_ndebug=true'] + endif +endif # The mathematical library # # GAOL bounds every one of its elementary functions with CORE-MATH @@ -247,7 +273,7 @@ if c_comp.has_argument('-Wconversion') endif # The optimizations configure (--enable-optimize) and the Release build of # CMake add to -O3, in the release build type, where the compiler takes them -if get_option('buildtype') == 'release' +if release foreach flag : ['-funroll-loops', '-fomit-frame-pointer', '-fexpensive-optimizations'] if cpp_comp.has_argument(flag) add_project_arguments([flag], language: 'cpp') From fbe11fc55128a13fba034ec38c2e09c1e91bfcf5 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 11:30:18 +0200 Subject: [PATCH 09/27] CMakeLists.txt: without a build type, GAOL and CORE-MATH compiled as in Release, NDEBUG included --- CMakeLists.txt | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e663b18..ac7bc211 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -676,12 +676,14 @@ if(NOT MSVC) endif() endforeach() # The optimizations configure adds to -O3, in the Release configuration + set(GAOL_RELEASE_FLAGS "") foreach(flag -funroll-loops -fomit-frame-pointer -fexpensive-optimizations) string(MAKE_C_IDENTIFIER "${flag}" _flag_id) string(TOUPPER "GAOL_COMPILER_SUPPORTS${_flag_id}" _flag_var) check_cxx_compiler_flag("${flag}" ${_flag_var}) if(${_flag_var}) list(APPEND GAOL_LIBRARY_FLAGS "$<$:${flag}>") + list(APPEND GAOL_RELEASE_FLAGS ${flag}) endif() endforeach() endif() @@ -787,14 +789,19 @@ endif() # Without a build type, CMake gives no optimization flag at all. GAOL sets # Release when it is the top-level project, but brought in by a project that # sets none (add_subdirectory, FetchContent), GAOL and CORE-MATH were compiled -# without optimization: they are compiled with -O3 then, as in Release (/O2 -# with Visual C++). +# without optimization: they are compiled then as in Release, with -O3 (/O2 +# with Visual C++), NDEBUG and the optimizations configure adds, as configure +# and meson build GAOL brought into another project (GAOL v5: GAOL alone had +# -O3, and CORE-MATH, compiled apart, no optimization) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - if(MSVC) - target_compile_options(gaol PRIVATE /O2) - else() - target_compile_options(gaol PRIVATE -O3) - endif() + foreach(target gaol gaol_core_math) + if(MSVC) + target_compile_options(${target} PRIVATE /O2) + else() + target_compile_options(${target} PRIVATE -O3 ${GAOL_RELEASE_FLAGS}) + endif() + target_compile_definitions(${target} PRIVATE NDEBUG) + endforeach() endif() if(MSVC) # The lexer includes , which Visual C++ does not have From b3bd4212ed5ce26acc431b53b40ce4f430e3e1b6 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 11:30:27 +0200 Subject: [PATCH 10/27] tests/release_flags.py: GAOL in release brought into a CMake or meson project, checked in the CI --- .github/workflows/build-systems.yml | 35 +++++++++++++----- .github/workflows/linux.yml | 9 ++++- tests/meson_subproject/meson.build | 35 +++++++++++++----- tests/release_flags.py | 56 +++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 tests/release_flags.py diff --git a/.github/workflows/build-systems.yml b/.github/workflows/build-systems.yml index 01211bf3..eb413586 100644 --- a/.github/workflows/build-systems.yml +++ b/.github/workflows/build-systems.yml @@ -212,27 +212,46 @@ jobs: # GAOL as a subproject of a meson project, tests/meson_subproject, which # builds tests of tests/ with gaol_dep and checks that their code gets the - # flags of interval arithmetic: meson refused the add_global_arguments() of - # meson.build in a subproject (GAOL v5) + # flags of interval arithmetic, and that GAOL is built in release in the + # default build type of meson: meson refused the add_global_arguments() of + # meson.build in a subproject, and before 1.8.4 gives a subproject the build + # type of the project, which the meson of Ubuntu 24.04 (1.3.2) checks (GAOL + # v5) meson-subproject: - name: Meson, Ubuntu 24.04 x86_64, GAOL as a subproject + name: ${{ matrix.cfg.desc }} runs-on: ubuntu-24.04 timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + cfg: + - { meson: pipx, desc: 'Meson, Ubuntu 24.04 x86_64, GAOL as a subproject' } + - { meson: apt, desc: 'Meson of Ubuntu 24.04, x86_64, GAOL as a subproject' } steps: - uses: actions/checkout@v7 - name: Tools run: | sudo apt-get update -q - sudo apt-get install -y -q g++ pipx - pipx install meson - pipx install ninja - echo "$HOME/.local/bin" >> "$GITHUB_PATH" + if [ "${{ matrix.cfg.meson }}" = pipx ]; then + sudo apt-get install -y -q g++ pipx + pipx install meson + pipx install ninja + echo "$HOME/.local/bin" >> "$GITHUB_PATH" + else + sudo apt-get install -y -q g++ meson ninja-build + fi - name: Configure tests/meson_subproject, a project bringing GAOL in as a subproject, from this checkout run: | + set -o pipefail meson --version + # The meson of Ubuntu has to be older than 1.8.4, which builds a + # subproject in its own default build type itself + if [ "${{ matrix.cfg.meson }}" = apt ]; then + python3 -c 'import sys; sys.exit(tuple(map(int, sys.argv[1].split(".")[:3])) >= (1, 8, 4))' "$(meson --version)" + fi mkdir tests/meson_subproject/subprojects ln -s "$PWD" tests/meson_subproject/subprojects/gaol - meson setup build-meson-subproject tests/meson_subproject --buildtype=release | tee configure.log + meson setup build-meson-subproject tests/meson_subproject | tee configure.log grep -q "Elementary functions: CORE-MATH" configure.log - name: Build run: meson compile -C build-meson-subproject diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 5a6c564b..c3f6b2c4 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -3,7 +3,8 @@ # (BUILD_SHARED_LIBS). Also with the sanitizers, with -Wall -Wextra -Werror, # checking the headers it installs too (GAOL v5), with the minimum version of # CMake GAOL declares, and as a part of another project, brought in by -# FetchContent (tests/fetch_content). +# FetchContent (tests/fetch_content), which builds GAOL as in Release where it +# gives no build type (tests/release_flags.py, GAOL v5). # # The runners have no locale writing a decimal comma, which tests/numbers.cpp # reads and writes numbers under where there is one, and where there is none it @@ -270,6 +271,12 @@ jobs: run: | cmake -S tests/fetch_content -B build-fetch-content -DCMAKE_BUILD_TYPE=Release -DFETCHCONTENT_SOURCE_DIR_GAOL="$PWD" -DCMAKE_INSTALL_PREFIX="$PWD/gaol-install" | tee configure.log grep -q "Elementary functions: CORE-MATH" configure.log + - name: Without a build type, GAOL and CORE-MATH compiled as in Release all the same + run: | + # configure only: tests/release_flags.py reads compile_commands.json + # (GAOL v5: CORE-MATH was compiled without optimization) + cmake -S tests/fetch_content -B build-fetch-content-default -DFETCHCONTENT_SOURCE_DIR_GAOL="$PWD" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + python3 tests/release_flags.py build-fetch-content-default "$PWD" - name: Build run: cmake --build build-fetch-content -j 4 - name: Tests (make test) diff --git a/tests/meson_subproject/meson.build b/tests/meson_subproject/meson.build index 19c8b488..b6e7f1ab 100644 --- a/tests/meson_subproject/meson.build +++ b/tests/meson_subproject/meson.build @@ -2,17 +2,24 @@ # The tests of GAOL built with a GAOL brought in as a meson subproject # ================================================================== # -# Builds the tests of the parent directory as a meson project bringing GAOL in -# as a subproject would (GAOL v5): GAOL is then targets of this project, built -# with it, and gaol_dep gives the code of this project the flags of interval -# arithmetic, which the test flags checks. GAOL is to be in subprojects/gaol, a -# link to its sources, as the continuous integration makes it -# (.github/workflows/build-systems.yml): +# Builds six of the tests of the parent directory, those of tests/fetch_content, +# as a meson project bringing GAOL in as a subproject would (GAOL v5): GAOL is +# then targets of this project, built with it, and gaol_dep gives the code of +# this project the flags of interval arithmetic, which the test flags checks. +# In the default build type of meson, debug, which this project is to be +# configured in, GAOL is built in release all the same, which the test release +# checks. GAOL is to be in subprojects/gaol, a link to its sources, as the +# continuous integration makes it (.github/workflows/build-systems.yml): # # mkdir tests/meson_subproject/subprojects # ln -s tests/meson_subproject/subprojects/gaol -# meson setup build-meson-subproject tests/meson_subproject --buildtype=release +# meson setup build-meson-subproject tests/meson_subproject # meson test -C build-meson-subproject +# rm tests/meson_subproject/subprojects/gaol +# +# The link, which git ignores, is to be removed after: it leads back to the +# root of the sources, and a copy of them that follows links, as tar -h does, +# would never end. # # Copyright (c) 2026 ENSTA, France # @@ -20,6 +27,11 @@ project('gaol_tests_meson_subproject', 'cpp') +# A default test setup of this project's own, as a project may have: GAOL +# declared one too as a subproject, and meson stopped on it ("is_default can be +# set to true only once") +add_test_setup('meson_subproject', is_default: true) + gaol_dep = subproject('gaol').get_variable('gaol_dep') foreach t : ['arithmetic', 'elementary', 'rounding_direction', 'numbers', @@ -35,5 +47,12 @@ endforeach # gaol.pc the subproject wrote, which only gaol_dep gives them. Without them, # the tests pass all the same (GCC 9.4, x86_64) test('flags', find_program('python3'), - args: [files('check_flags.py'), meson.build_root(), + args: [files('check_flags.py'), meson.current_build_dir(), meson.current_source_dir()]) + +# The libraries of GAOL and CORE-MATH compiled as in release, -O3 and NDEBUG, +# and GAOL_DEBUGGING undefined: before 1.8.4, meson gives a subproject the +# build type of the project (see meson.build) +test('release', find_program('python3'), + args: [files('../release_flags.py'), meson.current_build_dir(), + join_paths(meson.current_source_dir(), 'subprojects', 'gaol')]) diff --git a/tests/release_flags.py b/tests/release_flags.py new file mode 100644 index 00000000..4165efbb --- /dev/null +++ b/tests/release_flags.py @@ -0,0 +1,56 @@ +"""GAOL built in release by default, brought into another project (GAOL v5). + + python3 release_flags.py + +Fails unless each command of the compile_commands.json of the build directory +that compiles a source of GAOL or of CORE-MATH (/gaol/, +/3rd/) optimizes as the release build does (its last -O is -O3, or +/O2 with Visual C++) and defines NDEBUG, and unless the gaol_configuration.h +of the build leaves GAOL_DEBUGGING undefined: a project that brings GAOL in +without choosing a build type, as a CMake project without CMAKE_BUILD_TYPE +(add_subdirectory, FetchContent) or a meson project in the default build type +of meson (a subproject), gets GAOL in release, as configure builds it. +tests/meson_subproject runs it, and the continuous integration on +tests/fetch_content (.github/workflows/linux.yml). + +Copyright (c) 2026 ENSTA, France + +Created 2026-10-06 by Jordan NININ +""" +import json +import os +import re +import shlex +import sys + +build, sources = sys.argv[1], os.path.normpath(sys.argv[2]) +roots = tuple(os.path.join(sources, d) + os.sep for d in ('gaol', '3rd')) +with open(os.path.join(build, 'compile_commands.json')) as db: + commands = json.load(db) +checked = 0 +failed = 0 +for command in commands: + path = os.path.normpath(os.path.join(command['directory'], command['file'])) + if not path.startswith(roots): + continue + checked += 1 + tokens = shlex.split(command['command']) + levels = [t for t in tokens if re.match(r'^[-/]O([0-3sgdxz]|fast)?$', t)] + problems = [] + if not levels or levels[-1] not in ('-O3', '/O2'): + problems.append('optimization %s' % (levels[-1] if levels else 'none')) + if not ({'-DNDEBUG', '/DNDEBUG', '-DNDEBUG=1', '/DNDEBUG=1'} & set(tokens)): + problems.append('no NDEBUG') + if problems: + failed += 1 + print('%s: %s' % (command['file'], ', '.join(problems))) +headers = [os.path.join(d, f) for d, _, files in os.walk(build) for f in files + if f == 'gaol_configuration.h'] +for header in headers: + with open(header) as h: + if re.search(r'^\s*#\s*define\s+GAOL_DEBUGGING\b', h.read(), re.M): + failed += 1 + print('%s defines GAOL_DEBUGGING' % header) +print('%d command(s) of GAOL and CORE-MATH checked, %d gaol_configuration.h' + % (checked, len(headers))) +sys.exit(1 if failed or not checked or not headers else 0) From 8de25bafd145fdaefd97fe73815f78eb6e0dd994 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 11:30:27 +0200 Subject: [PATCH 11/27] version-file.sh: the copy leaves out the link that tests/meson_subproject takes as its subproject --- .github/scripts/version-file.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/scripts/version-file.sh b/.github/scripts/version-file.sh index e2c9e0bc..ac26efc8 100644 --- a/.github/scripts/version-file.sh +++ b/.github/scripts/version-file.sh @@ -40,8 +40,10 @@ work=$(mktemp -d "${TMPDIR:-/tmp}/gaol-version.XXXXXX") trap 'rm -rf "$work"' EXIT INT TERM mkdir "$work/src" # -h: README is a symbolic link to README.md, which tar of MSYS2 cannot create when it -# extracts it ("Cannot create symlink"): the copy holds the file itself -tar -c -h -f - --exclude=.git --exclude=autom4te.cache . | tar -x -f - -C "$work/src" +# extracts it ("Cannot create symlink"): the copy holds the file itself. Not +# the link that tests/meson_subproject takes as its subproject, which leads +# back to the root of the sources, and which -h would follow without end +tar -c -h -f - --exclude=.git --exclude=autom4te.cache --exclude=./tests/meson_subproject/subprojects . | tar -x -f - -C "$work/src" cd "$work" # The version is not the one of GAOL: it is the file the build reads, not a From 5f35c8cf66953522be2671e2530df584dff17b30 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 11:30:38 +0200 Subject: [PATCH 12/27] doc, manual, README: GAOL in release brought into a CMake or meson project --- README.md | 3 ++- doc/building.md | 8 +++++--- doc/continuous-integration.md | 17 ++++++++++------- doc/tests.md | 18 ++++++++++++------ doc/three-builds.md | 8 +++++++- doc/using.md | 24 ++++++++++++++++-------- manual/v5/gaol.tex | 20 ++++++++++++-------- 7 files changed, 64 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index adff3a8d..75eda5b5 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,8 @@ target_link_libraries(my_target PRIVATE gaol::gaol) `gaol::gaol`, and `gaol.pc` for pkg-config, carry the flags of interval arithmetic that the code including GAOL's headers has to be compiled with. A project can also build GAOL for itself, with FetchContent (see -[Using GAOL](doc/using.md#from-cmake)). +[Using GAOL](doc/using.md#from-cmake)), or as a meson subproject (see +[Using GAOL](doc/using.md#from-pkg-config)). A program calls `gaol::cleanup()` right after its last use of GAOL: GAOL's initialization, which runs by itself before `main()`, sets the diff --git a/doc/building.md b/doc/building.md index 6280ffb8..3cfc5a39 100644 --- a/doc/building.md +++ b/doc/building.md @@ -109,8 +109,10 @@ CMake 3.14 or later. The build compiles the thirty-six sources of CORE-MATH into `libgaol`, which is static unless `BUILD_SHARED_LIBS` is `ON`: there is nothing else to build and nothing else to install. The build type is Release unless another is given; brought in by a project that gives none -(`add_subdirectory`, FetchContent), GAOL and CORE-MATH are compiled with `-O3` -all the same (`/O2` with Visual C++). +(`add_subdirectory`, FetchContent), GAOL and CORE-MATH are compiled as in +Release all the same: `-O3` (`/O2` with Visual C++), `NDEBUG` and the +optimizations of configure (GAOL v5: GAOL had `-O3` alone, and CORE-MATH no +optimization). | Option | Default | | |---|---|---| @@ -242,7 +244,7 @@ Ubuntu 20.04, `ninja -C build` builds GAOL as well. The options | Option | Default | | |---|---|---| -| `buildtype` | `release` | `-O3`, `NDEBUG` and `-funroll-loops -fomit-frame-pointer -fexpensive-optimizations`, as the Release build of CMake and configure; `debug` builds GAOL without optimization, with debugging information, and GAOL checks its assertions (`GAOL_DEBUGGING`), as the Debug build of CMake and `configure --enable-debug`. The options `enable-optimize` and `enable-debug` are gone | +| `buildtype` | `release` | `-O3`, `NDEBUG` and `-funroll-loops -fomit-frame-pointer -fexpensive-optimizations`, as the Release build of CMake and configure; `debug` builds GAOL without optimization, with debugging information, and GAOL checks its assertions (`GAOL_DEBUGGING`), as the Debug build of CMake and `configure --enable-debug`. The options `enable-optimize` and `enable-debug` are gone. Brought in as a subproject, GAOL is built in `release` too where the project leaves the build type to its default (GAOL v5, see [Using GAOL](using.md#from-pkg-config)) | | `enable-simd` | `true` | The SSE2 intervals on x86 processors, as `GAOL_SIMD` | | `enable-fma` | `true` | The fused multiply-add instructions of the processor, as `GAOL_FMA` | | `enable-asm` | `true` | GAOL's assembly code, as `GAOL_ASM` | diff --git a/doc/continuous-integration.md b/doc/continuous-integration.md index 6dcb4c2e..03313da5 100644 --- a/doc/continuous-integration.md +++ b/doc/continuous-integration.md @@ -54,13 +54,16 @@ Visual Studio 2022 and 2026 (x64, x86), run the tests (`make test`, GAOL they install, which is the only library installed, CORE-MATH being compiled into it; build GAOL as a part of another project, brought in by FetchContent (`tests/fetch_content`), and the tests with the GAOL that project -installs; build GAOL as a subproject of a meson project -(`tests/meson_subproject`, Ubuntu x86_64), whose code compiled with `gaol_dep` -has to get the flags of `gaol.pc` (GAOL v5); check that the three builds agree -on each of these machines; check -that configure and meson, and autoconf when it generates configure (Linux), -read a `VERSION.txt` that starts with a byte order mark or has the line ends -of Windows (`.github/scripts/version-file.sh`), and that meson reads it with +installs, and check that GAOL and CORE-MATH are compiled as in Release where +that project gives no build type (`tests/release_flags.py`, GAOL v5); build +GAOL as a subproject of a meson project (`tests/meson_subproject`, Ubuntu +x86_64, with the meson of pipx and the meson 1.3 of Ubuntu), whose code +compiled with `gaol_dep` has to get the flags of `gaol.pc`, and GAOL to be +built in release in the default build type of meson (GAOL v5); check that the +three builds agree on each of these machines; check that configure and +meson, and autoconf when it generates configure (Linux), read a `VERSION.txt` +that starts with a byte order mark or has the line ends of Windows +(`.github/scripts/version-file.sh`), and that meson reads it with no Python on `PATH` (Linux); check that `make distclean` gives the source tree back as git has it, after the autotools have built, installed and tested GAOL in it (Ubuntu, macOS); check that the builds diff --git a/doc/tests.md b/doc/tests.md index b2e78b1b..69f076a3 100644 --- a/doc/tests.md +++ b/doc/tests.md @@ -339,8 +339,9 @@ mode there. read as in the C locale, and `exact_string()` has to write points and read back bit for bit: the reading never ended there, and the test, which ctest would otherwise let run with no limit, fails after 5 minutes should it hang - again (GAOL v5), in `tests/find_package` and `tests/fetch_content` too; the - cache variable `GAOL_NUMBERS_TIMEOUT` gives it more time on a slower build + again (GAOL v5), in `tests/find_package`, `tests/fetch_content` and + `tests/meson_subproject` too; the cache variable `GAOL_NUMBERS_TIMEOUT` + gives it more time on a slower build (600 s with GCC and the sanitizers on macOS x86_64). Numbers of 5000 to 20000 characters, in decimal, in hexadecimal and in the uncertain form, have to be read as the tightest enclosures, known without reading them (`1.5` followed by zeros is 1.5, and @@ -791,10 +792,15 @@ continuous integration runs `make test` in every job. `tests/find_package` builds some of the same tests with an installed GAOL, and `.github/scripts/tests.sh` with a GAOL installed by configure or meson. `tests/fetch_content` builds them with a GAOL brought in by FetchContent, and -`tests/meson_subproject` with a GAOL brought in as a meson subproject, whose -test `flags` checks that `gaol_dep` gives their compilation the flags of the -`Cflags` of `gaol.pc`: meson refused GAOL as a subproject, and the tests pass -without these flags (GAOL v5). +`tests/meson_subproject` with a GAOL brought in as a meson subproject (GAOL +v5), which meson refused. Its test `flags` checks that `gaol_dep` gives their +compilation the flags of the `Cflags` of `gaol.pc`, without which the tests +pass all the same, and its test `release` that GAOL is built in release in +the default build type of meson, debug: `tests/release_flags.py` checks that +the sources of GAOL and CORE-MATH are compiled with `-O3` and `NDEBUG`, and +that `GAOL_DEBUGGING` is left undefined. The continuous integration runs it on +`tests/fetch_content` configured without a build type too, where CORE-MATH +was compiled without optimization. `tests/performance.cpp` (`gaol_performance`) measures the time per operation of GAOL's arithmetic and elementary functions, of the constructor `interval(a, b)`, diff --git a/doc/three-builds.md b/doc/three-builds.md index 2733afa4..91f96c5c 100644 --- a/doc/three-builds.md +++ b/doc/three-builds.md @@ -14,7 +14,13 @@ build, and the CMake build follows them, apart from the errors corrected (see (`-funroll-loops -fomit-frame-pointer -fexpensive-optimizations`, each where the compiler takes it), `NDEBUG`, `-std=c++11`, hidden visibility (`-fvisibility=hidden -fvisibility-inlines-hidden`) and `-Wall -Wconversion`, - which GAOL compiles without warnings, `-Wsign-conversion` of Clang included; + which GAOL compiles without warnings, `-Wsign-conversion` of Clang included. + Its libraries are compiled in release too where a project brings GAOL in + without choosing a build type, as by a configure calling GAOL's: a CMake + project without `CMAKE_BUILD_TYPE`, with a generator of one configuration + (a generator of several, as Visual Studio, builds the configuration + `cmake --build --config` asks for, Debug without one), a meson project in + the default build type of meson, with its ninja backend (GAOL v5); - with the flags of interval arithmetic of [Using GAOL](using.md), and the code using GAOL, the tests included, is linked with `-mno-daz-ftz` where the compiler accepts it (GCC 13 and later on x86, and from 11.4 and 12.4 in the diff --git a/doc/using.md b/doc/using.md index 40f49422..77bdd12a 100644 --- a/doc/using.md +++ b/doc/using.md @@ -158,14 +158,22 @@ executable('program', 'program.cpp', dependencies: gaol_dep) subproject otherwise; `subproject('gaol').get_variable('gaol_dep')` always builds it. `gaol_dep` carries the include directory, the flags above and the link option above, as `gaol.pc` does: the flags GAOL's `meson.build` gives its -own targets do not reach those of the project. Where the project leaves the -build type to its default, `debug`, meson before 1.8.4 builds GAOL without -optimization, and before 1.8 with its assertions (`GAOL_DEBUGGING`) too, so -that the project is to be configured with `--buildtype=release`; meson 1.8.4 -and later build it in `release`, the default of GAOL's `meson.build`. -`tests/meson_subproject` is a project building GAOL this way. GAOL could not -be a subproject before GAOL v5: meson refuses the `add_global_arguments()` -its `meson.build` called in a subproject. +own targets do not reach those of the project. GAOL is built in `release`, +as CMake and configure build it brought into another project, where the +project leaves the build type to its default, `debug`. meson 1.8.4 and later +give a subproject its own default build type, and a `--buildtype=debug` asked +for builds GAOL for debugging. Earlier ones give it the build type of the +project, which would have built GAOL without optimization, and before 1.8 with +its assertions: there, where the options are those of `debug`, GAOL compiles +its libraries as in `release` all the same, as it cannot tell the default +from a `--buildtype=debug` asked for, so that building GAOL for debugging as +a subproject takes meson 1.8.4 or later. Two cases keep the build type of the +project: Visual C++ with meson before 0.57, whose `debug` gives `/RTC1`, which +`cl` refuses with `/O2`, and the Visual Studio backend of meson +(`--backend=vs`), which takes the build type of the project for every target; +the default backend, ninja, is not one. `tests/meson_subproject` is a project +building GAOL this way. GAOL could not be a subproject before GAOL v5: meson +refuses the `add_global_arguments()` its `meson.build` called in a subproject. ## Initialization and cleanup diff --git a/manual/v5/gaol.tex b/manual/v5/gaol.tex index d1beae7c..f8be7112 100644 --- a/manual/v5/gaol.tex +++ b/manual/v5/gaol.tex @@ -444,8 +444,9 @@ \section{Building and installing with CMake}\label{sec:cmake} \file{libgaol}, which is a static library unless \option{BUILD\_SHARED\_LIBS} is \code{ON}: there is nothing else to build and nothing else to install. The build type is \code{Release} unless another is given; brought in by a project that gives none (\code{add\_subdirectory}, -\code{FetchContent}), GAOL and CORE-MATH are compiled with \option{-O3} all -the same (\option{/O2} with Visual C++). +\code{FetchContent}), GAOL and CORE-MATH are compiled as in \code{Release} +all the same: \option{-O3} (\option{/O2} with Visual C++), \code{NDEBUG} and +the optimizations of \cmd{configure}.\newinvfive \subsection{Options}\label{sec:cmake-options} %%.................. @@ -996,12 +997,15 @@ \subsection{From pkg-config} \noindent \code{dependency()} takes an installed GAOL where it finds one, and builds the subproject otherwise. \code{gaol\_dep} carries the include directory, the flags -above and the link option above, as \file{gaol.pc} does. Where the project -leaves the build type to its default, \code{debug}, meson before 1.8.4 builds -GAOL without optimization, and before 1.8 with its assertions too, so that the -project is to be configured with \loption{buildtype=release}; meson 1.8.4 and -later build it in \code{release}, the default of GAOL's -\file{meson.build}.\newinvfive +above and the link option above, as \file{gaol.pc} does. GAOL is built in +\code{release}, as CMake and \cmd{configure} build it brought into another +project, where the project leaves the build type to its default, +\code{debug}: meson 1.8.4 and later give a subproject its own default build +type, and GAOL compiles its libraries as in \code{release} with earlier ones, +which give it the build type of the project; it cannot tell there the default +from a \loption{buildtype=debug} asked for (but with Visual C++ before meson +0.57, and with the Visual Studio backend of meson, which keep the build type +of the project).\newinvfive \section{The rounding direction}\label{sec:rounding-direction} %%------------------------------ From 71b8cd441b04b08179fd3fffe1a61d0325383f59 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 11:30:47 +0200 Subject: [PATCH 13/27] tests: several of the programs, not most, have hexadecimal floating literals of their own --- tests/CMakeLists.txt | 2 +- tests/Makefile.am | 2 +- tests/Makefile.in | 2 +- tests/meson.build | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4c77e03f..10338c89 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -8,7 +8,7 @@ # intervals (see unit_tests.h). They are compiled as any code using GAOL, with # the flags gaol::gaol carries, and in C++17 for the hexadecimal floating # literals of the tests, such as 0x1p-1060: those of gaol_tests.h, which all -# but u128.cpp include, of the *_values.h, and of most of the programs. +# but u128.cpp include, of the *_values.h, and of several of the programs. # WITH_TESTS builds them (CMakeLists.txt); make test and make check run them, # with the label unit. # diff --git a/tests/Makefile.am b/tests/Makefile.am index 19281cf2..5253d2af 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,7 +4,7 @@ # make test run them (see ../Makefile.am). They are compiled as any code using # GAOL, with the flags of interval arithmetic configure gives, in C++17 for the # hexadecimal floating literals of the tests (those of gaol_tests.h, which all -# but u128.cpp include, of the *_values.h, and of most of the programs; see +# but u128.cpp include, of the *_values.h, and of several of the programs; see # CMakeLists.txt), and linked with the static libgaol just built (-static: a # libtool library not installed), and with the link option gaol.pc gives # (-mno-daz-ftz, where the compiler takes it), as CMake links them. Exit status diff --git a/tests/Makefile.in b/tests/Makefile.in index b4700498..e9007d75 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -20,7 +20,7 @@ # make test run them (see ../Makefile.am). They are compiled as any code using # GAOL, with the flags of interval arithmetic configure gives, in C++17 for the # hexadecimal floating literals of the tests (those of gaol_tests.h, which all -# but u128.cpp include, of the *_values.h, and of most of the programs; see +# but u128.cpp include, of the *_values.h, and of several of the programs; see # CMakeLists.txt), and linked with the static libgaol just built (-static: a # libtool library not installed), and with the link option gaol.pc gives # (-mno-daz-ftz, where the compiler takes it), as CMake links them. Exit status diff --git a/tests/meson.build b/tests/meson.build index 391d5299..c1c32327 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -9,7 +9,7 @@ # test (make test) and meson test --setup check (make check) run. They are # compiled as any code using GAOL, in C++17 for the hexadecimal floating # literals of the tests (those of gaol_tests.h, which all but u128.cpp include, -# of the *_values.h, and of most of the programs; see CMakeLists.txt), and +# of the *_values.h, and of several of the programs; see CMakeLists.txt), and # linked with the static libgaol, as CMake links them. Exit status 77 is a test # skipped (intervalf and interval2f where the intervals of floats are not # compiled). check/, which built the unit tests of GAOL 4 with CppUnit, is From 162e1f884a90c64ade1cf70fa0daa39d94c21c2d Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 11:30:47 +0200 Subject: [PATCH 14/27] doc/building.md, meson.build: meson 0.53.0 and earlier may take an alias, nothing checked on Windows --- doc/building.md | 21 +++++++++++---------- meson.build | 14 +++++++------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/doc/building.md b/doc/building.md index 3cfc5a39..69511233 100644 --- a/doc/building.md +++ b/doc/building.md @@ -275,16 +275,17 @@ of a file it refuses: the first of `python3` and `python` that it finds in Python for that name alone; the continuous integration checks it on Linux with a `meson setup` whose `PATH` holds no Python. -On Windows, the directory `%USERPROFILE%\AppData\Local\Microsoft\WindowsApps` -can hold aliases of Python, `python3.exe` and perhaps `python.exe` too (not -checked on Windows), which only open the Microsoft Store when Python was not -installed from it. meson 0.53.1 and later (the 0.53.2 of Ubuntu 20.04 and the -meson of pip among them) leave that directory out of their search for -programs, as long as `PATH` names it by that path (not for a profile whose -directory differs from `USERPROFILE`). meson 0.53.0 and earlier take such an -alias, and `meson setup` stops on the failure of the command that reads -`VERSION.txt`: use a later meson (`pip install meson`), or turn off the -aliases of Python in the Windows settings ("Manage app execution aliases"). +On Windows, none of what follows was checked, but read in the sources of +meson. The directory `%USERPROFILE%\AppData\Local\Microsoft\WindowsApps` can +hold aliases of Python, `python3.exe` and perhaps `python.exe` too, which only +open the Microsoft Store when Python was not installed from it. meson 0.53.1 +and later (the 0.53.2 of Ubuntu 20.04 and the meson of pip among them) leave +that directory out of their search for programs, as long as `PATH` names it +by that path (not for a profile whose directory differs from `USERPROFILE`). +meson 0.53.0 and earlier may take such an alias, and `meson setup` then stops +on the failure of the command that reads `VERSION.txt`: use a later meson +(`pip install meson`), or turn off the aliases of Python in the Windows +settings ("Manage app execution aliases"). ## Tests, examples, performance and the parser diff --git a/meson.build b/meson.build index 00b9225a..cf6e15c1 100755 --- a/meson.build +++ b/meson.build @@ -16,13 +16,13 @@ project( # python3 stays first: only when the first name ends with python3 does # meson fall back on its own Python (the meson.exe of the Windows installer) # if it finds none. Looking for python first would lose that fallback, and - # would not avoid the Microsoft Store aliases that meson 0.53.0 takes where - # WindowsApps holds a python.exe as well as a python3.exe (not checked on - # Windows): meson 0.53.1 and later leave that directory out - # (doc/building.md). The encoding utf-8-sig skips - # the byte order mark that some editors of Windows write at - # the start of a file, which the default encoding (the code page of Windows, - # cp1252) reads as three characters of the version. The blanks stripped are + # would not avoid the Microsoft Store aliases that meson 0.53.0 and earlier + # take where WindowsApps holds a python.exe as well as a python3.exe (not + # checked on Windows): meson 0.53.1 and later leave that directory out + # (doc/building.md). The encoding utf-8-sig skips the byte order mark that + # some editors of Windows write at the start of a file, which the default + # encoding (the code page of Windows, cp1252) reads as three characters of + # the version. The blanks stripped are # the six of ASCII (string.whitespace), which CMake and configure strip, not # all those of Unicode, which strip() alone strips (a no-break space). What # is not the version is written as ASCII, with escapes (\u200b for a From a8b1aec3e2fe9e37f39352ef027750b4b3e5c052 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 11:30:47 +0200 Subject: [PATCH 15/27] manual: gaol.pc names no mathematical library, which the C++ compiler links itself --- manual/v5/gaol.tex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/manual/v5/gaol.tex b/manual/v5/gaol.tex index f8be7112..74c88496 100644 --- a/manual/v5/gaol.tex +++ b/manual/v5/gaol.tex @@ -830,8 +830,9 @@ \chapter{An overview of GAOL}\label{chap:overview} \end{cmdshell} \noindent - GAOL is the only library to link, with the C mathematical library: CORE-MATH, - which computes its elementary functions, is compiled into it. + GAOL is the only library to link: CORE-MATH, which computes its elementary + functions, is compiled into it, and the C++ compiler links the mathematical + library of the system itself. Executing \file{f}, we obtain: @@ -953,7 +954,7 @@ \subsection{From pkg-config} Each build installs \file{gaol.pc} in the \file{pkgconfig} directory of its library directory, except the CMake build with Visual C++. Its \code{Cflags} carries the flags above with the include directory, and its \code{Libs} GAOL -itself with the C mathematical library and the link option above: +itself and the link option above: \cindex{pkg-config}% \begin{cmdshell} From bc1e28b1597594da8de567acdf99867153bc30b3 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 13:16:20 +0200 Subject: [PATCH 16/27] workflows: set -o pipefail where a step pipes into tee, and no such pipe in the sh of the containers --- .github/workflows/build-systems.yml | 17 +++++++++++++---- .github/workflows/containers.yml | 3 ++- .github/workflows/linux.yml | 6 +++++- .github/workflows/macos.yml | 4 +++- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-systems.yml b/.github/workflows/build-systems.yml index eb413586..14e0c49e 100644 --- a/.github/workflows/build-systems.yml +++ b/.github/workflows/build-systems.yml @@ -88,6 +88,7 @@ jobs: sh .github/scripts/version-file.sh autoconf - name: Configure, build and install run: | + set -o pipefail # The same date on every file, as in a release archive: make then # does not regenerate configure, the Makefile.in or the lexer find . -path ./.git -prune -o -exec touch -h -d '2020-01-01 00:00:00' {} + @@ -132,7 +133,9 @@ jobs: run: | sh .github/scripts/tests.sh "$RUNNER_TEMP/gaol" static - name: Performance - run: ./performance | tee -a "$GITHUB_STEP_SUMMARY" + run: | + set -o pipefail + ./performance | tee -a "$GITHUB_STEP_SUMMARY" meson: name: ${{ matrix.cfg.desc }} @@ -190,6 +193,7 @@ jobs: PATH="$nopython" meson setup "$RUNNER_TEMP/build-no-python" - name: Configure, build and install run: | + set -o pipefail meson --version meson setup build-meson --prefix="$RUNNER_TEMP/gaol" --libdir=lib -Dwith-tests=true ${{ matrix.cfg.options }} | tee configure.log meson compile -C build-meson @@ -208,7 +212,9 @@ jobs: - name: Tests built with the installed GAOL run: sh .github/scripts/tests.sh "$RUNNER_TEMP/gaol" shared - name: Performance - run: ./performance | tee -a "$GITHUB_STEP_SUMMARY" + run: | + set -o pipefail + ./performance | tee -a "$GITHUB_STEP_SUMMARY" # GAOL as a subproject of a meson project, tests/meson_subproject, which # builds tests of tests/ with gaol_dep and checks that their code gets the @@ -361,7 +367,8 @@ jobs: sh .github/scripts/comma-locale.sh check build-meson/meson-logs/testlog.txt sh .github/scripts/tests.sh /tmp/gaol shared fi - ./performance | tee /gaol/performance.md" + ./performance > /gaol/performance.md + cat /gaol/performance.md" cat performance.md >> "$GITHUB_STEP_SUMMARY" msys2: @@ -408,7 +415,9 @@ jobs: - name: Tests built with the installed GAOL run: sh .github/scripts/tests.sh "$(cygpath -m "$RUNNER_TEMP")/gaol" static - name: Performance - run: ./performance | tee -a "$GITHUB_STEP_SUMMARY" + run: | + set -o pipefail + ./performance | tee -a "$GITHUB_STEP_SUMMARY" # The three builds give GAOL the same configuration (.github/audit) agree: diff --git a/.github/workflows/containers.yml b/.github/workflows/containers.yml index 5c176c14..b3dadb1d 100644 --- a/.github/workflows/containers.yml +++ b/.github/workflows/containers.yml @@ -101,7 +101,8 @@ jobs: cmake --build /tmp/build --target test $comma_check cd /tmp/build - ./tests/gaol_performance | tee /gaol/performance.md" + ./tests/gaol_performance > /gaol/performance.md + cat /gaol/performance.md" cat performance.md >> "$GITHUB_STEP_SUMMARY" clang-arm32: diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index c3f6b2c4..e5b7bb44 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -96,7 +96,9 @@ jobs: - name: The test numbers ran under a locale writing a decimal comma run: sh .github/scripts/comma-locale.sh check build - name: Performance - run: build/tests/gaol_performance | tee -a "$GITHUB_STEP_SUMMARY" + run: | + set -o pipefail + build/tests/gaol_performance | tee -a "$GITHUB_STEP_SUMMARY" - name: Install run: cmake --install build - name: Tests built with the installed GAOL @@ -269,6 +271,7 @@ jobs: run: sh .github/scripts/comma-locale.sh generate - name: Configure tests/fetch_content, a project building GAOL for itself with FetchContent, from this checkout run: | + set -o pipefail cmake -S tests/fetch_content -B build-fetch-content -DCMAKE_BUILD_TYPE=Release -DFETCHCONTENT_SOURCE_DIR_GAOL="$PWD" -DCMAKE_INSTALL_PREFIX="$PWD/gaol-install" | tee configure.log grep -q "Elementary functions: CORE-MATH" configure.log - name: Without a build type, GAOL and CORE-MATH compiled as in Release all the same @@ -320,6 +323,7 @@ jobs: run: sh .github/scripts/comma-locale.sh generate - name: Configure run: | + set -o pipefail cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=ON \ -DGAOL_U128_EMULATION=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -DCMAKE_C_COMPILER=${{ matrix.cc }} -DCMAKE_CXX_COMPILER=${{ matrix.cxx }} | tee configure.log diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 43794bc9..327934f9 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -65,7 +65,9 @@ jobs: - name: The test numbers ran under a locale writing a decimal comma run: sh .github/scripts/comma-locale.sh check build - name: Performance - run: build/tests/gaol_performance | tee -a "$GITHUB_STEP_SUMMARY" + run: | + set -o pipefail + build/tests/gaol_performance | tee -a "$GITHUB_STEP_SUMMARY" - name: Install run: cmake --install build - name: Tests built with the installed GAOL From 6cfbe443254c90b44afcb5cff6c8ef445ae2351b Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 14:22:25 +0200 Subject: [PATCH 17/27] meson: enable-debug builds GAOL and CORE-MATH for debugging whatever the build type --- gaol/meson.build | 12 ++++++------ meson.build | 22 +++++++++++++++------- meson_options.txt | 8 ++++++-- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/gaol/meson.build b/gaol/meson.build index 3c41679a..dc9e0779 100755 --- a/gaol/meson.build +++ b/gaol/meson.build @@ -51,10 +51,10 @@ endif # which the c99 of the project refuses, but with Visual C++, which has no GNU # C and compiles them as CMake does. And b_lto=false keeps the interprocedural # optimization of -Db_lto=true away from them: reached by it, sin and cos took -# half as long again (see doc/three-builds.md). In a subproject, the options -# of release where meson gives it the build type of the project -# (gaol_release_options, see meson.build) -core_math_overrides = ['b_lto=false'] + gaol_release_options +# half as long again (see doc/three-builds.md). The options of enable-debug, or +# in a subproject those of release where meson gives it the build type of the +# project (gaol_build_options, see meson.build) +core_math_overrides = ['b_lto=false'] + gaol_build_options if not msvc core_math_overrides += ['c_std=gnu11'] endif @@ -179,7 +179,7 @@ if msvc include_directories: [incdir, include_directories('../cmake/msvc')], c_args: gaol_msvc_args, cpp_args: gaol_msvc_args, - override_options: gaol_release_options, + override_options: gaol_build_options, ) gaollib_static = gaollib else @@ -193,7 +193,7 @@ else include_directories: incdir, version: meson.project_version(), soversion: major_version.to_string(), - override_options: gaol_release_options, + override_options: gaol_build_options, ) gaollib_static = gaollib.get_static_lib() endif diff --git a/meson.build b/meson.build index cf6e15c1..97bcfb81 100755 --- a/meson.build +++ b/meson.build @@ -101,11 +101,16 @@ preserve_rounding = get_option('enable-preserve-rounding') prefer_avx512_requested = get_option('enable-prefer-avx512') exception = get_option('enable-exception') # The Debug build, as CMAKE_BUILD_TYPE=Debug and configure --enable-debug: -# GAOL checks its assertions (GAOL_DEBUGGING). The option enable-debug, which -# only defined GAOL_DEBUGGING, is gone, as enable-optimize: the build type -# gives both (GAOL v5) +# GAOL checks its assertions (GAOL_DEBUGGING). The build type gives it with the +# optimizations, and enable-optimize is gone (GAOL v5) debug = get_option('buildtype') == 'debug' release = get_option('buildtype') == 'release' +# The options of the libraries of GAOL and CORE-MATH (gaol/meson.build) +gaol_build_options = [] +# enable-debug builds them for debugging whatever the build type, a subproject +# included, as GAOL_DEBUG of CMake: without optimization, without NDEBUG, and +# with GAOL_DEBUGGING (GAOL v5: it defined GAOL_DEBUGGING alone, and was gone) +# # Brought in as a subproject, GAOL is built in release by default, as CMake and # configure build it brought into another project (GAOL v5). meson 1.8.4 and # later give a subproject its own default build type, release here; earlier @@ -120,15 +125,18 @@ release = get_option('buildtype') == 'release' # default_options gives where they apply. Not with Visual C++ before meson # 0.57, whose build type debug gives /RTC1, which cl refuses with the /O2 of # optimization=3, and whose C runtime follows the build type of the target. -gaol_release_options = [] -if meson.is_subproject() and meson.version().version_compare('<1.8.4') and not (msvc and meson.version().version_compare('<0.57')) +if get_option('enable-debug') + gaol_build_options = ['optimization=0', 'debug=true', 'b_ndebug=false'] + debug = true + release = false +elif meson.is_subproject() and meson.version().version_compare('<1.8.4') and not (msvc and meson.version().version_compare('<0.57')) debug = false release = get_option('optimization') == '3' and not get_option('debug') if get_option('optimization') == '0' and get_option('debug') - gaol_release_options = ['optimization=3', 'debug=false', 'b_ndebug=true'] + gaol_build_options = ['optimization=3', 'debug=false', 'b_ndebug=true'] release = true elif release - gaol_release_options = ['b_ndebug=true'] + gaol_build_options = ['b_ndebug=true'] endif endif # The mathematical library diff --git a/meson_options.txt b/meson_options.txt index 71d00693..1f5fb6f1 100755 --- a/meson_options.txt +++ b/meson_options.txt @@ -6,14 +6,18 @@ # The build type gives the optimizations and the debugging, as with CMake: # --buildtype=release (the default) for -O3 and the optimizations of # configure's --enable-optimize, --buildtype=debug for GAOL_DEBUGGING, as -# configure's --enable-debug. The options enable-optimize and enable-debug, -# and enable-relations, with-test and check-perf, are gone (GAOL v5). +# configure's --enable-debug. enable-debug builds the libraries of GAOL for +# debugging whatever the build type, as GAOL_DEBUG of CMake, a subproject +# included, which meson before 1.8.4 builds in release otherwise (see +# meson.build). The options enable-optimize, enable-relations, with-test and +# check-perf are gone (GAOL v5). option('enable-simd', type : 'boolean', value : true, description : 'Compute the intervals with SSE2 instructions on x86 processors [default=yes, as configure]') option('enable-fma', type : 'boolean', value : true, description : 'Compile GAOL and CORE-MATH with the fused multiply-add instructions of the processor, where the compiler has a flag for them (false: a library for any processor of the architecture) [default=yes, as configure and CMake]') option('enable-asm', type : 'boolean', value : true, description : 'Use assembler code [default=yes, as configure]') option('enable-verbose-mode', type : 'boolean', value : false, description : 'Write a line on the standard error when GAOL initializes and cleans up [default=no: GAOL is silent, as with configure and CMake]') option('enable-preserve-rounding', type : 'boolean', value : false, description : 'Restore the rounding direction after each operation, rather than leaving it upward') option('enable-prefer-avx512', type : 'boolean', value : false, description : 'Have +, -, *, / and sqrt take the AVX-512 instructions and the rounding direction they carry in themselves, which sets neither the rounding direction nor the flush-to-zero modes, on a processor that has them [default=false, true with enable-preserve-rounding on a compiler that takes the path; meson cannot refuse the path under enable-preserve-rounding, which -DGAOL_PREFER_AVX512=OFF of CMake and --disable-prefer-avx512 of configure do, as CMake and configure]') +option('enable-debug', type: 'boolean', value: false, description: 'Build GAOL and CORE-MATH for debugging, without optimization and with GAOL_DEBUGGING, whatever the build type, a subproject included [default=no, as GAOL_DEBUG of CMake; configure --enable-debug]') option('enable-exception', type: 'boolean', value: true, description: 'Raise exceptions to signal errors [default=yes]') option('with-tests', type: 'boolean', value: false, description: 'Build the unit tests of tests/, which meson test (make test) and ninja check (make check) run [default=no, as WITH_TESTS of CMake and --with-tests of configure]') option('with-examples', type: 'boolean', value: false, description: 'Build the examples of examples/, which ninja check (make check) runs [default=no, as WITH_EXAMPLES of CMake and --with-examples of configure]') From f4b08ffbed7d052d5825dc9971b6fdc921fddbc0 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 14:22:25 +0200 Subject: [PATCH 18/27] CMakeLists.txt: Release first among the configurations of a generator of several, GAOL built alone --- CMakeLists.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac7bc211..d8dfa66d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,14 @@ if(_gaol_version_error) message(FATAL_ERROR "${_gaol_version_error}") endif() +# Whether the configurations of a generator of several were given, on the +# command line or in the environment, before project() sets their default +if(DEFINED CMAKE_CONFIGURATION_TYPES OR DEFINED ENV{CMAKE_CONFIGURATION_TYPES}) + set(_gaol_configuration_types_given ON) +else() + set(_gaol_configuration_types_given OFF) +endif() + project(gaol VERSION ${_gaol_version} LANGUAGES C CXX) # A change of VERSION.txt configures again @@ -69,6 +77,18 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) endif() + # With a generator of several configurations (Visual Studio, Xcode, Ninja + # Multi-Config), Release first among them, unless they were given: Ninja + # Multi-Config builds the first by default, and the IDEs show it first. + # cmake --build with Visual Studio builds Debug all the same without --config + # (GAOL v5) + get_property(_gaol_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(_gaol_multi_config AND NOT _gaol_configuration_types_given AND "Release" IN_LIST CMAKE_CONFIGURATION_TYPES) + set(_gaol_types ${CMAKE_CONFIGURATION_TYPES}) + list(REMOVE_ITEM _gaol_types Release) + list(INSERT _gaol_types 0 Release) + set(CMAKE_CONFIGURATION_TYPES "${_gaol_types}" CACHE STRING "The configurations of the generator" FORCE) + endif() endif() # libgaol, a static library, is compiled as position-independent From d09cdc9e9103ce178c832ad376ed5d7defbab26d Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 14:22:25 +0200 Subject: [PATCH 19/27] CMakeLists.txt: GAOL_DEBUG builds GAOL and CORE-MATH for debugging whatever the build type --- CMakeLists.txt | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8dfa66d..9ea48da1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,6 +123,10 @@ option(WITH_EXAMPLES "Build the examples of examples/, which make check runs" OF option(GAOL_SIMD "Compute the intervals with SSE2 instructions on x86 processors" ON) option(GAOL_ASM "Use assembler code (GAOL_USING_ASM)" ON) option(GAOL_VERBOSE_MODE "Write a line on the standard error when GAOL initializes and cleans up" OFF) +# GAOL and CORE-MATH built for debugging whatever the build type or the +# configuration, a project bringing GAOL in included, as enable-debug of meson +# and --enable-debug of configure (GAOL v5; see the end of this file) +option(GAOL_DEBUG "Build GAOL and CORE-MATH for debugging, without optimization and with GAOL_DEBUGGING, whatever the build type or the configuration" OFF) # No option for the intervals of floats, gaol::intervalf and gaol::interval2f, # unfinished, which only a developer of GAOL compiles (see gaol/gaol_config.h) # Coverage: the library and the tests compiled with the counters of gcov @@ -582,7 +586,7 @@ set(GAOL_EXCEPTIONS_ENABLED ON) # generator of several configurations (Visual Studio, Xcode), whose # configurations share gaol/gaol_configuration.h, GAOL_DEBUGGING is given to # the sources of GAOL in the Debug configuration below. -if(CMAKE_BUILD_TYPE STREQUAL "Debug") +if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR GAOL_DEBUG) set(GAOL_DEBUGGING ON) endif() @@ -696,12 +700,13 @@ if(NOT MSVC) endif() endforeach() # The optimizations configure adds to -O3, in the Release configuration + # (not with GAOL_DEBUG) set(GAOL_RELEASE_FLAGS "") foreach(flag -funroll-loops -fomit-frame-pointer -fexpensive-optimizations) string(MAKE_C_IDENTIFIER "${flag}" _flag_id) string(TOUPPER "GAOL_COMPILER_SUPPORTS${_flag_id}" _flag_var) check_cxx_compiler_flag("${flag}" ${_flag_var}) - if(${_flag_var}) + if(${_flag_var} AND NOT GAOL_DEBUG) list(APPEND GAOL_LIBRARY_FLAGS "$<$:${flag}>") list(APPEND GAOL_RELEASE_FLAGS ${flag}) endif() @@ -813,7 +818,7 @@ endif() # with Visual C++), NDEBUG and the optimizations configure adds, as configure # and meson build GAOL brought into another project (GAOL v5: GAOL alone had # -O3, and CORE-MATH, compiled apart, no optimization) -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES AND NOT GAOL_DEBUG) foreach(target gaol gaol_core_math) if(MSVC) target_compile_options(${target} PRIVATE /O2) @@ -1181,3 +1186,27 @@ if(GAOL_COVERAGE) COMMENT "Running the tests and writing the coverage report in coverage/" VERBATIM) endif() + +# GAOL_DEBUG: the targets of this directory, libgaol and the sources of +# CORE-MATH, compiled with the flags of Debug in every configuration, or +# with them added to those of the project where it gives no build type, so +# that they are built without optimization nor NDEBUG (GAOL v5). The flags of a +# configuration are those of the directory of the target at its end: the +# tests and the examples, whose directories were added before, keep theirs, as +# does a project bringing GAOL in. /RTC1 of Visual C++ is left out of +# configurations whose C runtime is not the Debug one. +if(GAOL_DEBUG) + foreach(lang C CXX) + string(REPLACE "/RTC1" "" _gaol_debug_flags "${CMAKE_${lang}_FLAGS_DEBUG}") + if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) + foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES CMAKE_BUILD_TYPE) + string(TOUPPER "${config}" config) + if(NOT config STREQUAL "DEBUG") + set(CMAKE_${lang}_FLAGS_${config} "${_gaol_debug_flags}") + endif() + endforeach() + else() + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} ${_gaol_debug_flags}") + endif() + endforeach() +endif() From 3906d9e220a7c3690db916546dd180990ee9a0fc Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 14:22:25 +0200 Subject: [PATCH 20/27] tests/release_flags.py --debug: GAOL_DEBUG, enable-debug and Ninja Multi-Config checked in the CI --- .github/workflows/build-systems.yml | 6 ++++ .github/workflows/linux.yml | 30 ++++++++++++++++ tests/release_flags.py | 55 +++++++++++++++++++++-------- 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-systems.yml b/.github/workflows/build-systems.yml index 14e0c49e..56164c86 100644 --- a/.github/workflows/build-systems.yml +++ b/.github/workflows/build-systems.yml @@ -267,6 +267,12 @@ jobs: run: ninja -C build-meson-subproject test - name: The test numbers ran under a locale writing a decimal comma run: sh .github/scripts/comma-locale.sh check build-meson-subproject/meson-logs/testlog.txt + - name: enable-debug builds GAOL for debugging, as a subproject and alone + run: | + meson setup build-meson-subproject-debug tests/meson_subproject -Dgaol:enable-debug=true + python3 tests/release_flags.py --debug build-meson-subproject-debug "$PWD/tests/meson_subproject/subprojects/gaol" + meson setup build-meson-debug -Denable-debug=true + python3 tests/release_flags.py --debug build-meson-debug "$PWD" # meson with Visual C++: the static libgaol, as CMake builds it, its tests, # and the installed GAOL, with which a test is compiled again (GAOL v5). In diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index e5b7bb44..83551e21 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -302,6 +302,36 @@ jobs: cmake --build build-find-package -j 4 cmake --build build-find-package --target test + # The build types, configured only: GAOL_DEBUG builds the libraries of GAOL + # and CORE-MATH for debugging whatever the build type, a project bringing + # GAOL in included, and a generator of several configurations builds Release + # by default (tests/release_flags.py, GAOL v5) + build-types: + name: Ubuntu 24.04 x86_64 GCC, GAOL_DEBUG and Ninja Multi-Config + runs-on: ubuntu-24.04 + timeout-minutes: 30 + steps: + - uses: actions/checkout@v7 + - name: Tools + run: | + sudo apt-get update -q + sudo apt-get install -y -q ninja-build + - name: GAOL_DEBUG, GAOL built alone in Release + run: | + cmake -S . -B build-debug -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=ON -DGAOL_DEBUG=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + python3 tests/release_flags.py --debug build-debug "$PWD" + - name: GAOL_DEBUG, GAOL brought in by FetchContent without a build type + run: | + cmake -S tests/fetch_content -B build-fetch-content-debug -DFETCHCONTENT_SOURCE_DIR_GAOL="$PWD" -DGAOL_DEBUG=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + python3 tests/release_flags.py --debug build-fetch-content-debug "$PWD" + - name: Ninja Multi-Config builds Release by default + run: | + cmake -G "Ninja Multi-Config" -S . -B build-multi + grep '^CMAKE_CONFIGURATION_TYPES:' build-multi/CMakeCache.txt + ninja -C build-multi -n > plan.txt + grep -q 'CMakeFiles/gaol.dir/Release/' plan.txt + if grep -q 'CMakeFiles/gaol.dir/Debug/' plan.txt; then echo "Debug built by default"; exit 1; fi + # The 128-bit integer computed with two 64-bit halves, which is the code # Visual C++ and the 32-bit targets of GCC take: built and tested on an # ordinary machine, where the native type is there to compare with diff --git a/tests/release_flags.py b/tests/release_flags.py index 4165efbb..dc229c9d 100644 --- a/tests/release_flags.py +++ b/tests/release_flags.py @@ -1,6 +1,6 @@ """GAOL built in release by default, brought into another project (GAOL v5). - python3 release_flags.py + python3 release_flags.py [--debug] Fails unless each command of the compile_commands.json of the build directory that compiles a source of GAOL or of CORE-MATH (/gaol/, @@ -13,6 +13,11 @@ tests/meson_subproject runs it, and the continuous integration on tests/fetch_content (.github/workflows/linux.yml). +With --debug, the other way round, for GAOL_DEBUG of CMake and enable-debug of +meson: no optimization (no -O, or a last -O0 or /Od), NDEBUG not defined in +the end (no -DNDEBUG, or a -UNDEBUG after it), and GAOL_DEBUGGING defined, by +gaol_configuration.h or on the command line. + Copyright (c) 2026 ENSTA, France Created 2026-10-06 by Jordan NININ @@ -23,10 +28,21 @@ import shlex import sys -build, sources = sys.argv[1], os.path.normpath(sys.argv[2]) +args = sys.argv[1:] +debug = args[:1] == ['--debug'] +if debug: + args = args[1:] +build, sources = args[0], os.path.normpath(args[1]) roots = tuple(os.path.join(sources, d) + os.sep for d in ('gaol', '3rd')) with open(os.path.join(build, 'compile_commands.json')) as db: commands = json.load(db) +headers = [os.path.join(d, f) for d, _, files in os.walk(build) for f in files + if f == 'gaol_configuration.h'] +header_debugging = False +for header in headers: + with open(header) as h: + if re.search(r'^\s*#\s*define\s+GAOL_DEBUGGING\b', h.read(), re.M): + header_debugging = True checked = 0 failed = 0 for command in commands: @@ -36,21 +52,30 @@ checked += 1 tokens = shlex.split(command['command']) levels = [t for t in tokens if re.match(r'^[-/]O([0-3sgdxz]|fast)?$', t)] + level = levels[-1] if levels else None + ndebug = [t for t in tokens if re.match(r'^[-/][DU]NDEBUG(=1)?$', t)] + ndebug = bool(ndebug) and ndebug[-1][1] == 'D' + debugging = header_debugging or any( + re.match(r'^[-/]DGAOL_DEBUGGING(=1)?$', t) for t in tokens) problems = [] - if not levels or levels[-1] not in ('-O3', '/O2'): - problems.append('optimization %s' % (levels[-1] if levels else 'none')) - if not ({'-DNDEBUG', '/DNDEBUG', '-DNDEBUG=1', '/DNDEBUG=1'} & set(tokens)): - problems.append('no NDEBUG') + if debug: + if level not in (None, '-O0', '/Od'): + problems.append('optimization %s' % level) + if ndebug: + problems.append('NDEBUG') + if not debugging: + problems.append('no GAOL_DEBUGGING') + else: + if level not in ('-O3', '/O2'): + problems.append('optimization %s' % (level or 'none')) + if not ndebug: + problems.append('no NDEBUG') + if debugging: + problems.append('GAOL_DEBUGGING') if problems: failed += 1 print('%s: %s' % (command['file'], ', '.join(problems))) -headers = [os.path.join(d, f) for d, _, files in os.walk(build) for f in files - if f == 'gaol_configuration.h'] -for header in headers: - with open(header) as h: - if re.search(r'^\s*#\s*define\s+GAOL_DEBUGGING\b', h.read(), re.M): - failed += 1 - print('%s defines GAOL_DEBUGGING' % header) -print('%d command(s) of GAOL and CORE-MATH checked, %d gaol_configuration.h' - % (checked, len(headers))) +print('%d command(s) of GAOL and CORE-MATH checked for %s, ' + '%d gaol_configuration.h' + % (checked, 'debug' if debug else 'release', len(headers))) sys.exit(1 if failed or not checked or not headers else 0) From ffefac908106a559d5829b8c90b8ad443adb0a60 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 14:22:25 +0200 Subject: [PATCH 21/27] doc, manual: GAOL_DEBUG, enable-debug, and Release first with several configurations --- doc/building.md | 15 +++++++++++---- doc/continuous-integration.md | 13 ++++++++----- doc/tests.md | 6 +++++- doc/three-builds.md | 13 +++++++++---- doc/using.md | 10 +++++++--- manual/v5/gaol.tex | 20 ++++++++++++++++---- 6 files changed, 56 insertions(+), 21 deletions(-) diff --git a/doc/building.md b/doc/building.md index 69511233..623a2d46 100644 --- a/doc/building.md +++ b/doc/building.md @@ -112,7 +112,12 @@ unless another is given; brought in by a project that gives none (`add_subdirectory`, FetchContent), GAOL and CORE-MATH are compiled as in Release all the same: `-O3` (`/O2` with Visual C++), `NDEBUG` and the optimizations of configure (GAOL v5: GAOL had `-O3` alone, and CORE-MATH no -optimization). +optimization). With a generator of several configurations (Visual Studio, +Xcode, Ninja Multi-Config), GAOL built alone puts Release first among them, +which Ninja Multi-Config builds by default and the IDEs show first, unless +`CMAKE_CONFIGURATION_TYPES` is given; `cmake --build` with Visual Studio +builds Debug all the same without `--config` (GAOL v5). `GAOL_DEBUG` builds +GAOL for debugging whatever the build type or the configuration (below). | Option | Default | | |---|---|---| @@ -128,6 +133,7 @@ optimization). | `GAOL_FMA` | `ON` | Compile GAOL and CORE-MATH with the fused multiply-add instructions of the processor, where the compiler has a flag for them and the machine building runs a program compiled with it (not checked when cross-compiling): `-mfma` on x86 (not with GCC for Windows), `/arch:AVX2` with Visual C++ for x64, `-mfpu=neon-vfpv4 -mfloat-abi=hard` on 32-bit ARM; 64-bit ARM, POWER, s390x and RISC-V have them without a flag. The library then needs a processor with them (on x86, Intel Haswell and AMD Piledriver, 2012-2013, and later); `OFF` builds it for any processor of the architecture. The code using GAOL is given the flag too, in `gaol::gaol` and `gaol.pc`, and `-ffp-contract=off` stays (see [The three builds](three-builds.md)) | | `GAOL_ASM` | `ON` | Use GAOL's assembly code where it has some (`GAOL_USING_ASM`) | | `GAOL_VERBOSE_MODE` | `OFF` | Write a line on the standard error when GAOL initializes and cleans up (`GAOL_VERBOSE_MODE`); GAOL is silent by default | +| `GAOL_DEBUG` | `OFF` | Build `libgaol` and CORE-MATH for debugging, without optimization nor `NDEBUG` and with `GAOL_DEBUGGING`, whatever the build type or the configuration, a project bringing GAOL in included, as `enable-debug` of meson and `--enable-debug` of configure; the tests and the examples, and the code of that project, keep their build type (GAOL v5) | | `GAOL_PRESERVE_ROUNDING` | `OFF` | Restore the rounding direction found after each operation, rather than leaving it upward (see [The rounding direction](using.md#the-rounding-direction)) | | `GAOL_PREFER_AVX512` | `OFF`, `ON` with `GAOL_PRESERVE_ROUNDING` | Have +, -, *, / and sqrt take the AVX-512 instructions and the rounding direction they carry in themselves, on a processor that has them, which sets neither the rounding direction nor the flush-to-zero modes (GAOL v5, see [The rounding direction](using.md#the-avx-512-path)) | @@ -208,7 +214,7 @@ their defaults: | Option | Default | | |---|---|---| | `--enable-optimize` | `yes` | `-O3 -funroll-loops -fomit-frame-pointer -fexpensive-optimizations` and `NDEBUG`, for the C++ and C sources alike (GAOL and CORE-MATH), as the Release build of CMake; `--disable-optimize` compiles with `-O` | -| `--enable-debug` | `no` | The Debug build of CMake: `-g`, no optimization and no `NDEBUG` (`--enable-optimize` is then ignored), and GAOL's assertions (`GAOL_DEBUGGING`) | +| `--enable-debug` | `no` | The Debug build of CMake: `-g`, no optimization and no `NDEBUG` (`--enable-optimize` is then ignored), and GAOL's assertions (`GAOL_DEBUGGING`); brought into another project with `AC_CONFIG_SUBDIRS`, the `--enable-debug` of its configure, which passes on its options, as `GAOL_DEBUG` of CMake and `enable-debug` of meson | | `--enable-simd` | `yes` | The SSE2 intervals on x86 processors, as `GAOL_SIMD` | | `--enable-fma` | `yes` | The fused multiply-add instructions of the processor, as `GAOL_FMA` | | `--enable-asm` | `yes` | GAOL's assembly code, as `GAOL_ASM` | @@ -244,10 +250,11 @@ Ubuntu 20.04, `ninja -C build` builds GAOL as well. The options | Option | Default | | |---|---|---| -| `buildtype` | `release` | `-O3`, `NDEBUG` and `-funroll-loops -fomit-frame-pointer -fexpensive-optimizations`, as the Release build of CMake and configure; `debug` builds GAOL without optimization, with debugging information, and GAOL checks its assertions (`GAOL_DEBUGGING`), as the Debug build of CMake and `configure --enable-debug`. The options `enable-optimize` and `enable-debug` are gone. Brought in as a subproject, GAOL is built in `release` too where the project leaves the build type to its default (GAOL v5, see [Using GAOL](using.md#from-pkg-config)) | +| `buildtype` | `release` | `-O3`, `NDEBUG` and `-funroll-loops -fomit-frame-pointer -fexpensive-optimizations`, as the Release build of CMake and configure; `debug` builds GAOL without optimization, with debugging information, and GAOL checks its assertions (`GAOL_DEBUGGING`), as the Debug build of CMake and `configure --enable-debug`. The option `enable-optimize` is gone. Brought in as a subproject, GAOL is built in `release` too where the project leaves the build type to its default (GAOL v5, see [Using GAOL](using.md#from-pkg-config)) | | `enable-simd` | `true` | The SSE2 intervals on x86 processors, as `GAOL_SIMD` | | `enable-fma` | `true` | The fused multiply-add instructions of the processor, as `GAOL_FMA` | | `enable-asm` | `true` | GAOL's assembly code, as `GAOL_ASM` | +| `enable-debug` | `false` | Build `libgaol` and CORE-MATH for debugging, without optimization nor `NDEBUG` and with `GAOL_DEBUGGING`, whatever the build type, a subproject included (`-Dgaol:enable-debug=true`), as `GAOL_DEBUG` of CMake and `--enable-debug` of configure (GAOL v5: it defined `GAOL_DEBUGGING` alone, and was gone) | | `enable-verbose-mode` | `false` | The line on the standard error, as `GAOL_VERBOSE_MODE` | | `enable-preserve-rounding` | `false` | Restore the rounding direction after each operation, as `GAOL_PRESERVE_ROUNDING` | | `enable-prefer-avx512` | `false`, `true` with `enable-preserve-rounding` | Have +, -, *, / and sqrt take the AVX-512 instructions and the rounding direction they carry in themselves, on a processor that has them, as `GAOL_PREFER_AVX512`; meson cannot refuse the path under `enable-preserve-rounding`, which `-DGAOL_PREFER_AVX512=OFF` of CMake and `--disable-prefer-avx512` of configure do (GAOL v5) | @@ -338,7 +345,7 @@ integration checks that they write the same header on each kind of machine | Macro | Defined | CMake | configure | meson | |---|---|---|---|---| | `GAOL_MAJOR_VERSION`, `GAOL_MINOR_VERSION`, `GAOL_MICRO_VERSION`, `GAOL_VERSION` | Always, from `VERSION.txt` (see [above](#the-version-of-gaol)): `5`, `0`, `0` and `"5.0.0"` for GAOL 5.0.0 | `project()` | `VERSION.txt`, read when configure runs | `project()` | -| `GAOL_DEBUGGING` | In a Debug build: GAOL checks its assertions (`GAOL_ASSERT`), and `GAOL_DEBUG` runs its commands | `CMAKE_BUILD_TYPE=Debug` | `--enable-debug` | `--buildtype=debug` | +| `GAOL_DEBUGGING` | In a Debug build: GAOL checks its assertions (`GAOL_ASSERT`), and `GAOL_DEBUG` runs its commands | `CMAKE_BUILD_TYPE=Debug`, or `GAOL_DEBUG` | `--enable-debug` | `--buildtype=debug`, or `enable-debug` | | `GAOL_EXCEPTIONS_ENABLED` | GAOL raises exceptions rather than abort | always | `--enable-exceptions` (default) | `enable-exception` (default) | | `GAOL_PRESERVE_ROUNDING` | The operations restore the rounding direction they found | `GAOL_PRESERVE_ROUNDING` | `--enable-preserve-rounding` | `enable-preserve-rounding` | | `GAOL_PREFER_AVX512` | +, -, *, / and sqrt take the AVX-512 instructions on a processor that has them | `GAOL_PREFER_AVX512` (with `GAOL_PRESERVE_ROUNDING`) | `--enable-prefer-avx512` (with `--enable-preserve-rounding`) | `enable-prefer-avx512` (with `enable-preserve-rounding`) | diff --git a/doc/continuous-integration.md b/doc/continuous-integration.md index 03313da5..332d4bb0 100644 --- a/doc/continuous-integration.md +++ b/doc/continuous-integration.md @@ -59,11 +59,14 @@ that project gives no build type (`tests/release_flags.py`, GAOL v5); build GAOL as a subproject of a meson project (`tests/meson_subproject`, Ubuntu x86_64, with the meson of pipx and the meson 1.3 of Ubuntu), whose code compiled with `gaol_dep` has to get the flags of `gaol.pc`, and GAOL to be -built in release in the default build type of meson (GAOL v5); check that the -three builds agree on each of these machines; check that configure and -meson, and autoconf when it generates configure (Linux), read a `VERSION.txt` -that starts with a byte order mark or has the line ends of Windows -(`.github/scripts/version-file.sh`), and that meson reads it with +built in release in the default build type of meson (GAOL v5); check that +`GAOL_DEBUG` and `enable-debug` build GAOL for debugging, alone and brought +into another project, and that GAOL built alone with Ninja Multi-Config builds +Release by default (`linux.yml`, `build-systems.yml`, configured only, GAOL +v5); check that the three builds agree on each of these machines; check that +configure and meson, and autoconf when it generates configure (Linux), read a +`VERSION.txt` that starts with a byte order mark or has the line ends of +Windows (`.github/scripts/version-file.sh`), and that meson reads it with no Python on `PATH` (Linux); check that `make distclean` gives the source tree back as git has it, after the autotools have built, installed and tested GAOL in it (Ubuntu, macOS); check that the builds diff --git a/doc/tests.md b/doc/tests.md index 69f076a3..c5355e3e 100644 --- a/doc/tests.md +++ b/doc/tests.md @@ -800,7 +800,11 @@ the default build type of meson, debug: `tests/release_flags.py` checks that the sources of GAOL and CORE-MATH are compiled with `-O3` and `NDEBUG`, and that `GAOL_DEBUGGING` is left undefined. The continuous integration runs it on `tests/fetch_content` configured without a build type too, where CORE-MATH -was compiled without optimization. +was compiled without optimization. With `--debug`, it checks the other way +round that `GAOL_DEBUG` of CMake and `enable-debug` of meson build GAOL and +CORE-MATH for debugging (no optimization, no `NDEBUG`, `GAOL_DEBUGGING`), GAOL +built alone and brought into another project, which the continuous +integration configures (GAOL v5). `tests/performance.cpp` (`gaol_performance`) measures the time per operation of GAOL's arithmetic and elementary functions, of the constructor `interval(a, b)`, diff --git a/doc/three-builds.md b/doc/three-builds.md index 91f96c5c..3eff07a5 100644 --- a/doc/three-builds.md +++ b/doc/three-builds.md @@ -18,9 +18,10 @@ build, and the CMake build follows them, apart from the errors corrected (see Its libraries are compiled in release too where a project brings GAOL in without choosing a build type, as by a configure calling GAOL's: a CMake project without `CMAKE_BUILD_TYPE`, with a generator of one configuration - (a generator of several, as Visual Studio, builds the configuration - `cmake --build --config` asks for, Debug without one), a meson project in - the default build type of meson, with its ninja backend (GAOL v5); + (with a generator of several, as Visual Studio, Release comes first among + the configurations of GAOL built alone, and a project bringing GAOL in + chooses its configuration), a meson project in the default build type of + meson, with its ninja backend (GAOL v5); - with the flags of interval arithmetic of [Using GAOL](using.md), and the code using GAOL, the tests included, is linked with `-mno-daz-ftz` where the compiler accepts it (GCC 13 and later on x86, and from 11.4 and 12.4 in the @@ -84,7 +85,11 @@ optimization nor `NDEBUG`, and checks its assertions (`GAOL_DEBUGGING`). It was `configure --enable-debug` alone that defined `GAOL_DEBUGGING`, adding `-g -ansi -Weffc++ -pedantic` for `g++` alone to the optimizations of `--enable-optimize`; the Debug build of CMake did not define it, and meson -defined it with its option `enable-debug`, now gone (GAOL v5). +defined it with its option `enable-debug` (GAOL v5). `GAOL_DEBUG` of CMake and +`enable-debug` of meson build the libraries of GAOL and CORE-MATH so whatever +the build type or the configuration, a project bringing GAOL in included, as +`configure --enable-debug` does for a configure calling GAOL's: the code of +that project, and the tests and the examples, keep their own (GAOL v5). `.github/audit/` configures the three builds and compares the macros GAOL sees, the macros each writes into `gaol/gaol_configuration.h`, and the flags diff --git a/doc/using.md b/doc/using.md index 77bdd12a..5f19e660 100644 --- a/doc/using.md +++ b/doc/using.md @@ -117,7 +117,10 @@ target_link_libraries(my_target PUBLIC gaol::gaol) GAOL is then a target of the project (`gaol::gaol`), built with it, and `cmake --install` of the project installs it with it, CMake package and `gaol.pc` included; nothing is downloaded beyond GAOL's sources. `tests/fetch_content` is a project -building GAOL this way. +building GAOL this way. GAOL is built in Release where the project gives no +build type, and `-DGAOL_DEBUG=ON` builds it for debugging whatever the build +type or the configuration of the project, whose own code keeps them (see +[Building GAOL](building.md#with-cmake)) (GAOL v5). GAOL, a static library, is compiled as position-independent code (`-fPIC`), so that `gaol::gaol` can be linked into a shared library, such as @@ -166,8 +169,9 @@ for builds GAOL for debugging. Earlier ones give it the build type of the project, which would have built GAOL without optimization, and before 1.8 with its assertions: there, where the options are those of `debug`, GAOL compiles its libraries as in `release` all the same, as it cannot tell the default -from a `--buildtype=debug` asked for, so that building GAOL for debugging as -a subproject takes meson 1.8.4 or later. Two cases keep the build type of the +from a `--buildtype=debug` asked for: `-Dgaol:enable-debug=true` (or +`default_options: ['enable-debug=true']` in `subproject()` or `dependency()`) +builds GAOL for debugging, with any meson. Two cases keep the build type of the project: Visual C++ with meson before 0.57, whose `debug` gives `/RTC1`, which `cl` refuses with `/O2`, and the Visual Studio backend of meson (`--backend=vs`), which takes the build type of the project for every target; diff --git a/manual/v5/gaol.tex b/manual/v5/gaol.tex index 74c88496..5729bc9d 100644 --- a/manual/v5/gaol.tex +++ b/manual/v5/gaol.tex @@ -446,7 +446,10 @@ \section{Building and installing with CMake}\label{sec:cmake} given; brought in by a project that gives none (\code{add\_subdirectory}, \code{FetchContent}), GAOL and CORE-MATH are compiled as in \code{Release} all the same: \option{-O3} (\option{/O2} with Visual C++), \code{NDEBUG} and -the optimizations of \cmd{configure}.\newinvfive +the optimizations of \cmd{configure}. With a generator of several +configurations, GAOL built alone puts \code{Release} first among them, which +Ninja Multi-Config builds by default; \cmd{cmake --build} with Visual Studio +builds \code{Debug} all the same without \option{-{}-config}.\newinvfive \subsection{Options}\label{sec:cmake-options} %%.................. @@ -491,6 +494,11 @@ \subsection{Options}\label{sec:cmake-options} \item \option{GAOL\_VERBOSE\_MODE}. \code{OFF} by default: writes a line on the standard error when GAOL initializes and cleans up; \cindex{verbose mode}% +\item \option{GAOL\_DEBUG}. \code{OFF} by default: builds \file{libgaol} and + CORE-MATH for debugging, without optimization nor \code{NDEBUG} and with + \code{GAOL\_DEBUGGING}, whatever the build type or the configuration, a + project bringing GAOL in included, as \code{enable-debug} of meson and + \loption{enable-debug} of \cmd{configure};\newinvfive \item \option{GAOL\_PRESERVE\_ROUNDING}. \code{OFF} by default: each operation restores the rounding direction it found, rather than leaving it upward (\pxref{sec:rounding-direction}); @@ -672,6 +680,7 @@ \section{Building and installing with meson} \code{enable-asm} & \code{true}\\ \code{enable-verbose-mode} & \code{false}\\ \code{enable-preserve-rounding} & \code{false}\\ + \code{enable-debug} & \code{false}; builds \file{libgaol} for debugging whatever the build type, as \option{GAOL\_DEBUG}\\ \code{enable-exception} & \code{true}\\ \code{with-tests} & \code{false}; builds the unit tests\\ \code{with-examples} & \code{false}; builds the examples\\ @@ -1006,7 +1015,8 @@ \subsection{From pkg-config} which give it the build type of the project; it cannot tell there the default from a \loption{buildtype=debug} asked for (but with Visual C++ before meson 0.57, and with the Visual Studio backend of meson, which keep the build type -of the project).\newinvfive +of the project). \code{-Dgaol:enable-debug=true} builds it for +debugging.\newinvfive \section{The rounding direction}\label{sec:rounding-direction} %%------------------------------ @@ -4976,8 +4986,10 @@ \chapter{Debugging facilities}\label{sec:debugging-facilities} GAOL has been configured with the debugging facilities enabled, which the \code{Debug} build of each build does: \option{-DCMAKE\_BUILD\_TYPE=Debug} with CMake, the \option{-{}-enable-debug} option of \cmd{configure} -(\pxref{sec:configuration}), or \option{-{}-buildtype=debug} with meson. They -define \code{GAOL\_DEBUGGING} in \file{gaol/gaol\_configuration.h}: GAOL then +(\pxref{sec:configuration}), or \option{-{}-buildtype=debug} with meson, and +\option{-DGAOL\_DEBUG=ON} with CMake and \option{-Denable-debug=true} with +meson whatever the build type.\newinvfive{} They define +\code{GAOL\_DEBUGGING} in \file{gaol/gaol\_configuration.h}: GAOL then checks its assertions. \begin{deffun}{int}{debug\_level}{} From f5ffb2059dea559e94f309c5ebd04eb9d8437572 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 14:49:13 +0200 Subject: [PATCH 22/27] CMakeLists.txt: GAOL_DEBUG keeps the other flags of each configuration, and gives no target perf --- CMakeLists.txt | 54 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ea48da1..81fb1b59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,9 +79,8 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) endif() # With a generator of several configurations (Visual Studio, Xcode, Ninja # Multi-Config), Release first among them, unless they were given: Ninja - # Multi-Config builds the first by default, and the IDEs show it first. - # cmake --build with Visual Studio builds Debug all the same without --config - # (GAOL v5) + # Multi-Config builds the first by default. cmake --build with Visual Studio + # builds Debug all the same without --config (GAOL v5) get_property(_gaol_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(_gaol_multi_config AND NOT _gaol_configuration_types_given AND "Release" IN_LIST CMAKE_CONFIGURATION_TYPES) set(_gaol_types ${CMAKE_CONFIGURATION_TYPES}) @@ -1099,9 +1098,10 @@ endif() # doc/compare/code/results.csv holds (see doc/compare/code/run_perf.sh). It # needs bash and Python 3 with numpy, which draws the intervals. GAOL 4.2.3, # filib++, libieeep1788 and PROFIL/BIAS are not run: doc/compare/code/run_all.sh -# measures them all again. Linux only, as the benchmark (GAOL v5). +# measures them all again. Linux only, as the benchmark, and not with +# GAOL_DEBUG, which would measure GAOL built for debugging (GAOL v5). -if(GAOL_IS_TOP_LEVEL AND CMAKE_SYSTEM_NAME STREQUAL "Linux") +if(GAOL_IS_TOP_LEVEL AND CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT GAOL_DEBUG) find_program(GAOL_BASH bash) mark_as_advanced(GAOL_BASH) if(GAOL_BASH) @@ -1188,25 +1188,45 @@ if(GAOL_COVERAGE) endif() # GAOL_DEBUG: the targets of this directory, libgaol and the sources of -# CORE-MATH, compiled with the flags of Debug in every configuration, or -# with them added to those of the project where it gives no build type, so -# that they are built without optimization nor NDEBUG (GAOL v5). The flags of a -# configuration are those of the directory of the target at its end: the -# tests and the examples, whose directories were added before, keep theirs, as -# does a project bringing GAOL in. /RTC1 of Visual C++ is left out of -# configurations whose C runtime is not the Debug one. +# CORE-MATH, compiled without optimization nor NDEBUG and with debugging +# information in every configuration (GAOL v5). Each configuration keeps its +# own flags but those of optimization and NDEBUG (the C runtime of Visual C++, +# sanitizers, macros of the project...), so that GAOL still links with the +# code of that configuration; where no build type is given, the flags are +# added to those of the project. The flags of a configuration are those of the +# directory of the target at its end: the tests and the examples, whose +# directories were added before, keep theirs, as does a project bringing GAOL +# in. With Visual C++, the debugging information is the property +# MSVC_DEBUG_INFORMATION_FORMAT where CMP0141 is NEW (CMake 3.25 and later), and +# /Zi otherwise. if(GAOL_DEBUG) + if(MSVC) + set(_gaol_debug_flags /Od /Ob0) + set(_gaol_cmp0141 OLD) + if(POLICY CMP0141) + cmake_policy(GET CMP0141 _gaol_cmp0141) + endif() + if(_gaol_cmp0141 STREQUAL "NEW") + set_property(TARGET gaol gaol_core_math PROPERTY MSVC_DEBUG_INFORMATION_FORMAT ProgramDatabase) + else() + list(APPEND _gaol_debug_flags /Zi) + endif() + else() + set(_gaol_debug_flags -O0 -g) + endif() + string(REPLACE ";" " " _gaol_debug_string "${_gaol_debug_flags}") foreach(lang C CXX) - string(REPLACE "/RTC1" "" _gaol_debug_flags "${CMAKE_${lang}_FLAGS_DEBUG}") if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES CMAKE_BUILD_TYPE) string(TOUPPER "${config}" config) - if(NOT config STREQUAL "DEBUG") - set(CMAKE_${lang}_FLAGS_${config} "${_gaol_debug_flags}") - endif() + separate_arguments(_gaol_flags UNIX_COMMAND "${CMAKE_${lang}_FLAGS_${config}}") + list(FILTER _gaol_flags EXCLUDE REGEX "^[-/](O[0-9sgdxz]?|Ofast|Ob[0-3]|DNDEBUG(=.*)?)$") + list(APPEND _gaol_flags ${_gaol_debug_flags}) + string(REPLACE ";" " " _gaol_flags "${_gaol_flags}") + set(CMAKE_${lang}_FLAGS_${config} "${_gaol_flags}") endforeach() else() - set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} ${_gaol_debug_flags}") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} ${_gaol_debug_string}") endif() endforeach() endif() From 74a0e31ca05ba64f43764dfba118eefeaaf97dcd Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 14:49:13 +0200 Subject: [PATCH 23/27] meson.build: enable-debug keeps the configure optimizations of the tests, and gives no target perf --- meson.build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 97bcfb81..aa1f06ea 100755 --- a/meson.build +++ b/meson.build @@ -128,7 +128,6 @@ gaol_build_options = [] if get_option('enable-debug') gaol_build_options = ['optimization=0', 'debug=true', 'b_ndebug=false'] debug = true - release = false elif meson.is_subproject() and meson.version().version_compare('<1.8.4') and not (msvc and meson.version().version_compare('<0.57')) debug = false release = get_option('optimization') == '3' and not get_option('debug') @@ -513,9 +512,10 @@ endif # make perf, as with CMake and configure: GAOL v5 measured on the benchmark of # doc/compare/performance.md, whose tables get its new times (see -# doc/compare/code/run_perf.sh). Linux only, as the benchmark (GAOL v5). +# doc/compare/code/run_perf.sh). Linux only, as the benchmark, and not with +# enable-debug, which would measure GAOL built for debugging (GAOL v5). bash = find_program('bash', required: false) -if host_machine.system() == 'linux' and bash.found() +if host_machine.system() == 'linux' and bash.found() and not get_option('enable-debug') bench_dir = meson.current_source_dir() + '/doc/compare/code' gaol_bench = executable('gaol_bench', bench_dir + '/bench_gaol.cpp', include_directories: include_directories('.', 'doc/compare/code'), From 9cdb21c86f129fea8c7d029cb7b32ff0c8662939 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 14:49:13 +0200 Subject: [PATCH 24/27] linux.yml: GAOL_DEBUG checked to reach the libraries alone and keep the flags of the configuration --- .github/workflows/linux.yml | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 83551e21..478daead 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -320,10 +320,40 @@ jobs: run: | cmake -S . -B build-debug -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=ON -DGAOL_DEBUG=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON python3 tests/release_flags.py --debug build-debug "$PWD" - - name: GAOL_DEBUG, GAOL brought in by FetchContent without a build type + - name: GAOL_DEBUG, GAOL brought in by FetchContent without a build type, and in Release run: | cmake -S tests/fetch_content -B build-fetch-content-debug -DFETCHCONTENT_SOURCE_DIR_GAOL="$PWD" -DGAOL_DEBUG=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON python3 tests/release_flags.py --debug build-fetch-content-debug "$PWD" + cmake -S tests/fetch_content -B build-fetch-content-release-debug -DFETCHCONTENT_SOURCE_DIR_GAOL="$PWD" -DGAOL_DEBUG=ON \ + -DCMAKE_BUILD_TYPE=Release "-DCMAKE_CXX_FLAGS_RELEASE=-O3 -DNDEBUG -DPROJECT_RELEASE" "-DCMAKE_CXX_FLAGS_DEBUG=-g -DPROJECT_DEBUG" \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + python3 tests/release_flags.py --debug build-fetch-content-release-debug "$PWD" + - name: GAOL_DEBUG reaches the libraries of GAOL alone, and keeps the other flags of the configuration + run: | + # GAOL takes the flags of the configuration less the optimization and + # NDEBUG, never those of Debug, which may hold what the code of the + # project does not get (a sanitizer, a C runtime); the tests of GAOL + # and of the project keep theirs + python3 - "$PWD" <<'EOF' + import json, os, sys + src = os.path.normpath(sys.argv[1]) + def commands(build): + for e in json.load(open(os.path.join(build, 'compile_commands.json'))): + if e['file'].endswith('.cpp'): + yield os.path.normpath(os.path.join(e['directory'], e['file'])), e['command'].split() + gaol, tests = os.path.join(src, 'gaol') + os.sep, os.path.join(src, 'tests') + os.sep + seen = 0 + for path, flags in commands('build-debug'): + if path.startswith(tests): + assert '-O3' in flags and '-DNDEBUG' in flags, (path, flags); seen += 1 + for path, flags in commands('build-fetch-content-release-debug'): + if path.startswith(gaol): + assert '-DPROJECT_RELEASE' in flags and '-DPROJECT_DEBUG' not in flags, (path, flags); seen += 1 + elif path.startswith(tests): + assert '-O3' in flags and '-DNDEBUG' in flags and '-DPROJECT_RELEASE' in flags, (path, flags); seen += 1 + assert seen, 'no command checked' + print(seen, 'commands checked') + EOF - name: Ninja Multi-Config builds Release by default run: | cmake -G "Ninja Multi-Config" -S . -B build-multi From 0f339e5a29bbc2ba2deec57a5a78bddcddb48c87 Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 14:49:13 +0200 Subject: [PATCH 25/27] doc/building.md: GAOL_DEBUG and enable-debug keep the other flags, no perf; the macro GAOL_DEBUG --- doc/building.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/building.md b/doc/building.md index 623a2d46..937ee111 100644 --- a/doc/building.md +++ b/doc/building.md @@ -114,10 +114,10 @@ Release all the same: `-O3` (`/O2` with Visual C++), `NDEBUG` and the optimizations of configure (GAOL v5: GAOL had `-O3` alone, and CORE-MATH no optimization). With a generator of several configurations (Visual Studio, Xcode, Ninja Multi-Config), GAOL built alone puts Release first among them, -which Ninja Multi-Config builds by default and the IDEs show first, unless -`CMAKE_CONFIGURATION_TYPES` is given; `cmake --build` with Visual Studio -builds Debug all the same without `--config` (GAOL v5). `GAOL_DEBUG` builds -GAOL for debugging whatever the build type or the configuration (below). +which Ninja Multi-Config builds by default, unless `CMAKE_CONFIGURATION_TYPES` +is given; `cmake --build` with Visual Studio builds Debug all the same without +`--config` (GAOL v5). `GAOL_DEBUG` builds GAOL for debugging whatever the +build type or the configuration (below). | Option | Default | | |---|---|---| @@ -133,7 +133,7 @@ GAOL for debugging whatever the build type or the configuration (below). | `GAOL_FMA` | `ON` | Compile GAOL and CORE-MATH with the fused multiply-add instructions of the processor, where the compiler has a flag for them and the machine building runs a program compiled with it (not checked when cross-compiling): `-mfma` on x86 (not with GCC for Windows), `/arch:AVX2` with Visual C++ for x64, `-mfpu=neon-vfpv4 -mfloat-abi=hard` on 32-bit ARM; 64-bit ARM, POWER, s390x and RISC-V have them without a flag. The library then needs a processor with them (on x86, Intel Haswell and AMD Piledriver, 2012-2013, and later); `OFF` builds it for any processor of the architecture. The code using GAOL is given the flag too, in `gaol::gaol` and `gaol.pc`, and `-ffp-contract=off` stays (see [The three builds](three-builds.md)) | | `GAOL_ASM` | `ON` | Use GAOL's assembly code where it has some (`GAOL_USING_ASM`) | | `GAOL_VERBOSE_MODE` | `OFF` | Write a line on the standard error when GAOL initializes and cleans up (`GAOL_VERBOSE_MODE`); GAOL is silent by default | -| `GAOL_DEBUG` | `OFF` | Build `libgaol` and CORE-MATH for debugging, without optimization nor `NDEBUG` and with `GAOL_DEBUGGING`, whatever the build type or the configuration, a project bringing GAOL in included, as `enable-debug` of meson and `--enable-debug` of configure; the tests and the examples, and the code of that project, keep their build type (GAOL v5) | +| `GAOL_DEBUG` | `OFF` | Build `libgaol` and CORE-MATH for debugging, without optimization nor `NDEBUG`, with debugging information and `GAOL_DEBUGGING`, whatever the build type or the configuration, a project bringing GAOL in included, as `enable-debug` of meson and `--enable-debug` of configure. Each configuration keeps its other flags (the C runtime of Visual C++, sanitizers...); the tests and the examples, and the code of that project, keep their build type; there is no target `perf` (GAOL v5) | | `GAOL_PRESERVE_ROUNDING` | `OFF` | Restore the rounding direction found after each operation, rather than leaving it upward (see [The rounding direction](using.md#the-rounding-direction)) | | `GAOL_PREFER_AVX512` | `OFF`, `ON` with `GAOL_PRESERVE_ROUNDING` | Have +, -, *, / and sqrt take the AVX-512 instructions and the rounding direction they carry in themselves, on a processor that has them, which sets neither the rounding direction nor the flush-to-zero modes (GAOL v5, see [The rounding direction](using.md#the-avx-512-path)) | @@ -214,7 +214,7 @@ their defaults: | Option | Default | | |---|---|---| | `--enable-optimize` | `yes` | `-O3 -funroll-loops -fomit-frame-pointer -fexpensive-optimizations` and `NDEBUG`, for the C++ and C sources alike (GAOL and CORE-MATH), as the Release build of CMake; `--disable-optimize` compiles with `-O` | -| `--enable-debug` | `no` | The Debug build of CMake: `-g`, no optimization and no `NDEBUG` (`--enable-optimize` is then ignored), and GAOL's assertions (`GAOL_DEBUGGING`); brought into another project with `AC_CONFIG_SUBDIRS`, the `--enable-debug` of its configure, which passes on its options, as `GAOL_DEBUG` of CMake and `enable-debug` of meson | +| `--enable-debug` | `no` | The Debug build of CMake: `-g`, no optimization and no `NDEBUG` (`--enable-optimize` is then ignored), and GAOL's assertions (`GAOL_DEBUGGING`); brought into another project with `AC_CONFIG_SUBDIRS`, the `--enable-debug` of its configure, which passes on its options (and which that configure may read too), for the tests of GAOL as well, where `GAOL_DEBUG` of CMake and `enable-debug` of meson build the libraries alone so | | `--enable-simd` | `yes` | The SSE2 intervals on x86 processors, as `GAOL_SIMD` | | `--enable-fma` | `yes` | The fused multiply-add instructions of the processor, as `GAOL_FMA` | | `--enable-asm` | `yes` | GAOL's assembly code, as `GAOL_ASM` | @@ -254,7 +254,7 @@ Ubuntu 20.04, `ninja -C build` builds GAOL as well. The options | `enable-simd` | `true` | The SSE2 intervals on x86 processors, as `GAOL_SIMD` | | `enable-fma` | `true` | The fused multiply-add instructions of the processor, as `GAOL_FMA` | | `enable-asm` | `true` | GAOL's assembly code, as `GAOL_ASM` | -| `enable-debug` | `false` | Build `libgaol` and CORE-MATH for debugging, without optimization nor `NDEBUG` and with `GAOL_DEBUGGING`, whatever the build type, a subproject included (`-Dgaol:enable-debug=true`), as `GAOL_DEBUG` of CMake and `--enable-debug` of configure (GAOL v5: it defined `GAOL_DEBUGGING` alone, and was gone) | +| `enable-debug` | `false` | Build `libgaol` and CORE-MATH for debugging, without optimization nor `NDEBUG` and with `GAOL_DEBUGGING`, whatever the build type, a subproject included (`-Dgaol:enable-debug=true`), as `GAOL_DEBUG` of CMake and `--enable-debug` of configure; the tests and the examples keep the build type, and there is no target `perf` (GAOL v5: it defined `GAOL_DEBUGGING` alone, and was gone) | | `enable-verbose-mode` | `false` | The line on the standard error, as `GAOL_VERBOSE_MODE` | | `enable-preserve-rounding` | `false` | Restore the rounding direction after each operation, as `GAOL_PRESERVE_ROUNDING` | | `enable-prefer-avx512` | `false`, `true` with `enable-preserve-rounding` | Have +, -, *, / and sqrt take the AVX-512 instructions and the rounding direction they carry in themselves, on a processor that has them, as `GAOL_PREFER_AVX512`; meson cannot refuse the path under `enable-preserve-rounding`, which `-DGAOL_PREFER_AVX512=OFF` of CMake and `--disable-prefer-avx512` of configure do (GAOL v5) | @@ -345,7 +345,7 @@ integration checks that they write the same header on each kind of machine | Macro | Defined | CMake | configure | meson | |---|---|---|---|---| | `GAOL_MAJOR_VERSION`, `GAOL_MINOR_VERSION`, `GAOL_MICRO_VERSION`, `GAOL_VERSION` | Always, from `VERSION.txt` (see [above](#the-version-of-gaol)): `5`, `0`, `0` and `"5.0.0"` for GAOL 5.0.0 | `project()` | `VERSION.txt`, read when configure runs | `project()` | -| `GAOL_DEBUGGING` | In a Debug build: GAOL checks its assertions (`GAOL_ASSERT`), and `GAOL_DEBUG` runs its commands | `CMAKE_BUILD_TYPE=Debug`, or `GAOL_DEBUG` | `--enable-debug` | `--buildtype=debug`, or `enable-debug` | +| `GAOL_DEBUGGING` | In a Debug build: GAOL checks its assertions (`GAOL_ASSERT`), and the macro `GAOL_DEBUG(level, command)` runs its commands | `CMAKE_BUILD_TYPE=Debug`, or `GAOL_DEBUG` | `--enable-debug` | `--buildtype=debug`, or `enable-debug` | | `GAOL_EXCEPTIONS_ENABLED` | GAOL raises exceptions rather than abort | always | `--enable-exceptions` (default) | `enable-exception` (default) | | `GAOL_PRESERVE_ROUNDING` | The operations restore the rounding direction they found | `GAOL_PRESERVE_ROUNDING` | `--enable-preserve-rounding` | `enable-preserve-rounding` | | `GAOL_PREFER_AVX512` | +, -, *, / and sqrt take the AVX-512 instructions on a processor that has them | `GAOL_PREFER_AVX512` (with `GAOL_PRESERVE_ROUNDING`) | `--enable-prefer-avx512` (with `--enable-preserve-rounding`) | `enable-prefer-avx512` (with `enable-preserve-rounding`) | From 3b48f30502b9e7e56e41c250a40ba1032e0ca74f Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 16:15:59 +0200 Subject: [PATCH 26/27] gaol_common.h: the macro GAOL_DEBUG(lvl, cmd) renamed GAOL_DEBUG_VERBOSE, apart from the CMake option --- doc/building.md | 2 +- doc/tests.md | 9 +-- gaol/gaol_common.h | 20 +++--- gaol/gaol_expression.cpp | 132 +++++++++++++++++++-------------------- gaol/gaol_expression.h | 60 +++++++++--------- manual/v5/gaol.tex | 10 +-- tests/debugging.cpp | 25 ++++---- 7 files changed, 134 insertions(+), 124 deletions(-) diff --git a/doc/building.md b/doc/building.md index badd4d58..9c7ab05c 100644 --- a/doc/building.md +++ b/doc/building.md @@ -347,7 +347,7 @@ integration checks that they write the same header on each kind of machine | Macro | Defined | CMake | configure | meson | |---|---|---|---|---| | `GAOL_MAJOR_VERSION`, `GAOL_MINOR_VERSION`, `GAOL_MICRO_VERSION`, `GAOL_VERSION` | Always, from `VERSION.txt` (see [above](#the-version-of-gaol)): `5`, `0`, `0` and `"5.0.0"` for GAOL 5.0.0 | `project()` | `VERSION.txt`, read when configure runs | `project()` | -| `GAOL_DEBUGGING` | In a Debug build: GAOL checks its assertions (`GAOL_ASSERT`), and the macro `GAOL_DEBUG(level, command)` runs its commands | `CMAKE_BUILD_TYPE=Debug`, or `GAOL_DEBUG` | `--enable-debug` | `--buildtype=debug`, or `enable-debug` | +| `GAOL_DEBUGGING` | In a Debug build: GAOL checks its assertions (`GAOL_ASSERT`), and `GAOL_DEBUG_VERBOSE(level, command)` runs its commands | `CMAKE_BUILD_TYPE=Debug`, or `GAOL_DEBUG` | `--enable-debug` | `--buildtype=debug`, or `enable-debug` | | `GAOL_EXCEPTIONS_ENABLED` | GAOL raises exceptions rather than abort | always | `--enable-exceptions` (default) | `enable-exception` (default) | | `GAOL_PRESERVE_ROUNDING` | The operations restore the rounding direction they found | `GAOL_PRESERVE_ROUNDING` | `--enable-preserve-rounding` | `enable-preserve-rounding` | | `GAOL_PREFER_AVX512` | +, -, *, / and sqrt take the AVX-512 instructions on a processor that has them | `GAOL_PREFER_AVX512` (with `GAOL_PRESERVE_ROUNDING`) | `--enable-prefer-avx512` (with `--enable-preserve-rounding`) | `enable-prefer-avx512` (with `enable-preserve-rounding`) | diff --git a/doc/tests.md b/doc/tests.md index 0e750ed8..7531ab53 100644 --- a/doc/tests.md +++ b/doc/tests.md @@ -640,10 +640,11 @@ mode there. - **`debugging`:** GAOL's headers compiled with `GAOL_DEBUGGING`, which the Debug builds define (`CMAKE_BUILD_TYPE=Debug`, `configure --enable-debug`, `meson setup --buildtype=debug`), whatever the build: an expression is built - and evaluated, its nodes calling `GAOL_DEBUG`, which has to run its command - at the level given to `gaol::init()` and not above. `gaol/gaol_expression.h` - did not compile with `GAOL_DEBUGGING`: its `GAOL_DEBUG` wrote on `std::cout`, - which no header included (GAOL v5). + and evaluated, its nodes calling `GAOL_DEBUG_VERBOSE` (`GAOL_DEBUG` before + GAOL v5), which has to run its command at the level given to `gaol::init()` + and not above. `gaol/gaol_expression.h` did not compile with + `GAOL_DEBUGGING`: its `GAOL_DEBUG_VERBOSE` wrote on `std::cout`, which no + header included (GAOL v5). - **`version_file`** (CMake only: a script of CMake, not a program): the reading of `VERSION.txt` by `CMakeLists.txt`, `gaol_read_version()` of `cmake/gaol_version.cmake`, has to ignore a UTF-8 byte order mark at the diff --git a/gaol/gaol_common.h b/gaol/gaol_common.h index 1ed133d6..179d8525 100644 --- a/gaol/gaol_common.h +++ b/gaol/gaol_common.h @@ -32,23 +32,27 @@ #include "gaol/gaol_config.h" #include "gaol/gaol_port.h" -// The commands of GAOL_DEBUG (below) write on std::cout: gaol/gaol_expression.h -// did not compile with GAOL_DEBUGGING, which configure --enable-debug defined, -// without (GAOL v5) +// The commands of GAOL_DEBUG_VERBOSE (below) write on std::cout: +// gaol/gaol_expression.h did not compile with GAOL_DEBUGGING, which configure +// --enable-debug defined, without (GAOL v5) #if GAOL_DEBUGGING # include #endif namespace gaol_core { - // defined in gaol_common.cpp; public, as GAOL_DEBUG reads it in the inline - // functions of the headers, compiled into the code using GAOL (GAOL v5) + // defined in gaol_common.cpp; public, as GAOL_DEBUG_VERBOSE reads it in the + // inline functions of the headers, compiled into the code using GAOL (GAOL + // v5) extern GAOL_PUBLIC int debug_level; + // GAOL_DEBUG before GAOL v5, now the option of CMake that builds GAOL for + // debugging (GAOL v5) #if GAOL_DEBUGGING -# define GAOL_DEBUG(lvl,cmd) do { if (debug_level>=lvl) {cmd;} } while(0) +# define GAOL_DEBUG_VERBOSE(lvl,cmd) \ + do { if (debug_level>=lvl) {cmd;} } while(0) #else -# define GAOL_DEBUG(lvl,cmd) +# define GAOL_DEBUG_VERBOSE(lvl,cmd) #endif /*! @@ -109,7 +113,7 @@ GAOL_NODISCARD extern GAOL_PUBLIC double minimum(double a, double b); \brief Initialization of the library \return true if the library was not already initialized and false otherwise \param dbg_lvl current debugging level: a debugging code inside - a call to GAOL_DEBUG will be executed only if its level is lower or + a call to GAOL_DEBUG_VERBOSE will be executed only if its level is lower or equal to the current debugging level. A debugging level equal to zero means that no debugging message will appear. */ diff --git a/gaol/gaol_expression.cpp b/gaol/gaol_expression.cpp index 08877baf..b84a8f27 100644 --- a/gaol/gaol_expression.cpp +++ b/gaol/gaol_expression.cpp @@ -72,33 +72,33 @@ namespace gaol_core { expression::expression() : root(the_null_expr) { root->inc_refcount(); - GAOL_DEBUG(3,std::cout << "creating null expression" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "creating null expression" << std::endl); } expression::expression(double d) { - GAOL_DEBUG(3,std::cout << "creating expression from " << d << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "creating expression from " << d << std::endl); root= new double_node(d); root->inc_refcount(); } expression::expression(const interval& I) { - GAOL_DEBUG(3,std::cout << "creating expression from " << I << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "creating expression from " << I << std::endl); root= new interval_node(I); root->inc_refcount(); } expression::expression(const expression& e) : root(e.root) { - GAOL_DEBUG(3,std::cout << "creating expression from expression " + GAOL_DEBUG_VERBOSE(3,std::cout << "creating expression from expression " << std::endl); root->inc_refcount(); } expression::expression(const expr_node& e) { - GAOL_DEBUG(3,std::cout << "creating expression from node " << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "creating expression from node " << std::endl); root = &const_cast(e); root->inc_refcount(); } @@ -106,7 +106,7 @@ namespace gaol_core { expression::~expression() { - GAOL_DEBUG(3,std::cout << "deleting expression" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "deleting expression" << std::endl); if (root->dec_refcount() == 0) { delete root; @@ -269,13 +269,13 @@ namespace gaol_core { */ null_node::null_node() { - GAOL_DEBUG(3,std::cout << "null_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "null_node created" << std::endl); } null_node::~null_node() { - GAOL_DEBUG(3,std::cout << "null_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "null_node destroyed" << std::endl); } expr_node* null_node::clone() const @@ -300,12 +300,12 @@ namespace gaol_core { double_node::double_node(double d) : val(d) { - GAOL_DEBUG(3,std::cout << "double_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "double_node created" << std::endl); } double_node::~double_node() { - GAOL_DEBUG(3,std::cout << "double_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "double_node destroyed" << std::endl); } std::ostream& double_node::display(std::ostream& os) const @@ -336,13 +336,13 @@ namespace gaol_core { interval_node::interval_node(const interval& I) { val = new interval(I); - GAOL_DEBUG(3,std::cout << "interval_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "interval_node created" << std::endl); } interval_node::~interval_node() { delete val; - GAOL_DEBUG(3,std::cout << "interval_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "interval_node destroyed" << std::endl); } std::ostream& interval_node::display(std::ostream& os) const @@ -372,7 +372,7 @@ namespace gaol_core { { e_left->inc_refcount(); e_right->inc_refcount(); - GAOL_DEBUG(3,std::cout << "add_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "add_node created" << std::endl); } add_node::~add_node() @@ -383,7 +383,7 @@ namespace gaol_core { if (e_right->dec_refcount() == 0) { delete e_right; } - GAOL_DEBUG(3,std::cout << "add_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "add_node destroyed" << std::endl); } std::ostream& add_node::display(std::ostream& os) const @@ -412,7 +412,7 @@ namespace gaol_core { unary_minus_node::unary_minus_node(const expression& e) : e_uminus(e.get_root()) { e_uminus->inc_refcount(); - GAOL_DEBUG(3,std::cout << "unary_minus_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "unary_minus_node created" << std::endl); } unary_minus_node::~unary_minus_node() @@ -420,7 +420,7 @@ namespace gaol_core { if (e_uminus->dec_refcount() == 0) { delete e_uminus; } - GAOL_DEBUG(3,std::cout << "unary_minus_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "unary_minus_node destroyed" << std::endl); } std::ostream& unary_minus_node::display(std::ostream& os) const @@ -455,7 +455,7 @@ namespace gaol_core { { e_left->inc_refcount(); e_right->inc_refcount(); - GAOL_DEBUG(3,std::cout << "sub_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "sub_node created" << std::endl); } sub_node::~sub_node() @@ -466,7 +466,7 @@ namespace gaol_core { if (e_right->dec_refcount() == 0) { delete e_right; } - GAOL_DEBUG(3,std::cout << "sub_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "sub_node destroyed" << std::endl); } std::ostream& sub_node::display(std::ostream& os) const @@ -499,7 +499,7 @@ namespace gaol_core { { e_left->inc_refcount(); e_right->inc_refcount(); - GAOL_DEBUG(3,std::cout << "mult_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "mult_node created" << std::endl); } mult_node::~mult_node() @@ -510,7 +510,7 @@ namespace gaol_core { if (e_right->dec_refcount() == 0) { delete e_right; } - GAOL_DEBUG(3,std::cout << "mult_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "mult_node destroyed" << std::endl); } std::ostream& mult_node::display(std::ostream& os) const @@ -543,7 +543,7 @@ namespace gaol_core { { e_left->inc_refcount(); e_right->inc_refcount(); - GAOL_DEBUG(3,std::cout << "div_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "div_node created" << std::endl); } div_node::~div_node() @@ -554,7 +554,7 @@ namespace gaol_core { if (e_right->dec_refcount() == 0) { delete e_right; } - GAOL_DEBUG(3,std::cout << "div_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "div_node destroyed" << std::endl); } // '/', where GAOL wrote '*': x/(y*z) was shown as x*(y*z) (GAOL v5) @@ -585,7 +585,7 @@ namespace gaol_core { { exponent = n; e_pow->inc_refcount(); - GAOL_DEBUG(3,std::cout << "pow_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "pow_node created" << std::endl); } pow_node::~pow_node() @@ -593,7 +593,7 @@ namespace gaol_core { if (e_pow->dec_refcount() == 0) { delete e_pow; } - GAOL_DEBUG(3,std::cout << "pow_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "pow_node destroyed" << std::endl); } std::ostream& pow_node::display(std::ostream& os) const @@ -624,7 +624,7 @@ namespace gaol_core { { e_left->inc_refcount(); e_right->inc_refcount(); - GAOL_DEBUG(3,std::cout << "pow_itv_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "pow_itv_node created" << std::endl); } pow_itv_node::~pow_itv_node() @@ -635,7 +635,7 @@ namespace gaol_core { if (e_right->dec_refcount() == 0) { delete e_right; } - GAOL_DEBUG(3,std::cout << "pow_itv_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "pow_itv_node destroyed" << std::endl); } std::ostream& pow_itv_node::display(std::ostream& os) const @@ -665,7 +665,7 @@ namespace gaol_core { { exponent = n; e_nth_root->inc_refcount(); - GAOL_DEBUG(3,std::cout << "nth_root_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "nth_root_node created" << std::endl); } nth_root_node::~nth_root_node() @@ -673,7 +673,7 @@ namespace gaol_core { if (e_nth_root->dec_refcount() == 0) { delete e_nth_root; } - GAOL_DEBUG(3,std::cout << "nth_root_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "nth_root_node destroyed" << std::endl); } std::ostream& nth_root_node::display(std::ostream& os) const @@ -700,7 +700,7 @@ namespace gaol_core { cos_node::cos_node(const expression& e) : e_cos(e.get_root()) { e_cos->inc_refcount(); - GAOL_DEBUG(3,std::cout << "cos_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "cos_node created" << std::endl); } cos_node::~cos_node() @@ -708,7 +708,7 @@ namespace gaol_core { if (e_cos->dec_refcount() == 0) { delete e_cos; } - GAOL_DEBUG(3,std::cout << "cos_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "cos_node destroyed" << std::endl); } std::ostream& cos_node::display(std::ostream& os) const @@ -736,7 +736,7 @@ namespace gaol_core { sin_node::sin_node(const expression& e) : e_sin(e.get_root()) { e_sin->inc_refcount(); - GAOL_DEBUG(3,std::cout << "sin_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "sin_node created" << std::endl); } sin_node::~sin_node() @@ -744,7 +744,7 @@ namespace gaol_core { if (e_sin->dec_refcount() == 0) { delete e_sin; } - GAOL_DEBUG(3,std::cout << "sin_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "sin_node destroyed" << std::endl); } std::ostream& sin_node::display(std::ostream& os) const @@ -772,7 +772,7 @@ namespace gaol_core { tan_node::tan_node(const expression& e) : e_tan(e.get_root()) { e_tan->inc_refcount(); - GAOL_DEBUG(3,std::cout << "tan_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "tan_node created" << std::endl); } tan_node::~tan_node() @@ -780,7 +780,7 @@ namespace gaol_core { if (e_tan->dec_refcount() == 0) { delete e_tan; } - GAOL_DEBUG(3,std::cout << "tan_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "tan_node destroyed" << std::endl); } std::ostream& tan_node::display(std::ostream& os) const @@ -810,7 +810,7 @@ namespace gaol_core { { Y->inc_refcount(); X->inc_refcount(); - GAOL_DEBUG(3,std::cout << "atan2_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "atan2_node created" << std::endl); } atan2_node::~atan2_node() @@ -821,7 +821,7 @@ namespace gaol_core { if (X->dec_refcount() == 0) { delete X; } - GAOL_DEBUG(3,std::cout << "atan2_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "atan2_node destroyed" << std::endl); } std::ostream& atan2_node::display(std::ostream& os) const @@ -851,7 +851,7 @@ namespace gaol_core { acos_node::acos_node(const expression& e) : e_acos(e.get_root()) { e_acos->inc_refcount(); - GAOL_DEBUG(3,std::cout << "acos_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "acos_node created" << std::endl); } acos_node::~acos_node() @@ -859,7 +859,7 @@ namespace gaol_core { if (e_acos->dec_refcount() == 0) { delete e_acos; } - GAOL_DEBUG(3,std::cout << "acos_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "acos_node destroyed" << std::endl); } std::ostream& acos_node::display(std::ostream& os) const @@ -887,7 +887,7 @@ namespace gaol_core { asin_node::asin_node(const expression& e) : e_asin(e.get_root()) { e_asin->inc_refcount(); - GAOL_DEBUG(3,std::cout << "asin_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "asin_node created" << std::endl); } asin_node::~asin_node() @@ -895,7 +895,7 @@ namespace gaol_core { if (e_asin->dec_refcount() == 0) { delete e_asin; } - GAOL_DEBUG(3,std::cout << "asin_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "asin_node destroyed" << std::endl); } std::ostream& asin_node::display(std::ostream& os) const @@ -923,7 +923,7 @@ namespace gaol_core { atan_node::atan_node(const expression& e) : e_atan(e.get_root()) { e_atan->inc_refcount(); - GAOL_DEBUG(3,std::cout << "atan_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "atan_node created" << std::endl); } atan_node::~atan_node() @@ -931,7 +931,7 @@ namespace gaol_core { if (e_atan->dec_refcount() == 0) { delete e_atan; } - GAOL_DEBUG(3,std::cout << "atan_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "atan_node destroyed" << std::endl); } std::ostream& atan_node::display(std::ostream& os) const @@ -959,7 +959,7 @@ namespace gaol_core { cosh_node::cosh_node(const expression& e) : e_cosh(e.get_root()) { e_cosh->inc_refcount(); - GAOL_DEBUG(3,std::cout << "cosh_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "cosh_node created" << std::endl); } cosh_node::~cosh_node() @@ -967,7 +967,7 @@ namespace gaol_core { if (e_cosh->dec_refcount() == 0) { delete e_cosh; } - GAOL_DEBUG(3,std::cout << "cosh_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "cosh_node destroyed" << std::endl); } std::ostream& cosh_node::display(std::ostream& os) const @@ -995,7 +995,7 @@ namespace gaol_core { sinh_node::sinh_node(const expression& e) : e_sinh(e.get_root()) { e_sinh->inc_refcount(); - GAOL_DEBUG(3,std::cout << "sinh_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "sinh_node created" << std::endl); } sinh_node::~sinh_node() @@ -1003,7 +1003,7 @@ namespace gaol_core { if (e_sinh->dec_refcount() == 0) { delete e_sinh; } - GAOL_DEBUG(3,std::cout << "sinh_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "sinh_node destroyed" << std::endl); } std::ostream& sinh_node::display(std::ostream& os) const @@ -1031,7 +1031,7 @@ namespace gaol_core { tanh_node::tanh_node(const expression& e) : e_tanh(e.get_root()) { e_tanh->inc_refcount(); - GAOL_DEBUG(3,std::cout << "tanh_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "tanh_node created" << std::endl); } tanh_node::~tanh_node() @@ -1039,7 +1039,7 @@ namespace gaol_core { if (e_tanh->dec_refcount() == 0) { delete e_tanh; } - GAOL_DEBUG(3,std::cout << "tanh_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "tanh_node destroyed" << std::endl); } std::ostream& tanh_node::display(std::ostream& os) const @@ -1068,7 +1068,7 @@ namespace gaol_core { acosh_node::acosh_node(const expression& e) : e_acosh(e.get_root()) { e_acosh->inc_refcount(); - GAOL_DEBUG(3,std::cout << "acosh_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "acosh_node created" << std::endl); } acosh_node::~acosh_node() @@ -1076,7 +1076,7 @@ namespace gaol_core { if (e_acosh->dec_refcount() == 0) { delete e_acosh; } - GAOL_DEBUG(3,std::cout << "acosh_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "acosh_node destroyed" << std::endl); } std::ostream& acosh_node::display(std::ostream& os) const @@ -1104,7 +1104,7 @@ namespace gaol_core { asinh_node::asinh_node(const expression& e) : e_asinh(e.get_root()) { e_asinh->inc_refcount(); - GAOL_DEBUG(3,std::cout << "asinh_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "asinh_node created" << std::endl); } asinh_node::~asinh_node() @@ -1112,7 +1112,7 @@ namespace gaol_core { if (e_asinh->dec_refcount() == 0) { delete e_asinh; } - GAOL_DEBUG(3,std::cout << "asinh_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "asinh_node destroyed" << std::endl); } std::ostream& asinh_node::display(std::ostream& os) const @@ -1140,7 +1140,7 @@ namespace gaol_core { atanh_node::atanh_node(const expression& e) : e_atanh(e.get_root()) { e_atanh->inc_refcount(); - GAOL_DEBUG(3,std::cout << "atanh_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "atanh_node created" << std::endl); } atanh_node::~atanh_node() @@ -1148,7 +1148,7 @@ namespace gaol_core { if (e_atanh->dec_refcount() == 0) { delete e_atanh; } - GAOL_DEBUG(3,std::cout << "atanh_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "atanh_node destroyed" << std::endl); } std::ostream& atanh_node::display(std::ostream& os) const @@ -1177,7 +1177,7 @@ namespace gaol_core { exp_node::exp_node(const expression& e) : e_exp(e.get_root()) { e_exp->inc_refcount(); - GAOL_DEBUG(3,std::cout << "exp_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "exp_node created" << std::endl); } exp_node::~exp_node() @@ -1185,7 +1185,7 @@ namespace gaol_core { if (e_exp->dec_refcount() == 0) { delete e_exp; } - GAOL_DEBUG(3,std::cout << "exp_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "exp_node destroyed" << std::endl); } std::ostream& exp_node::display(std::ostream& os) const @@ -1213,7 +1213,7 @@ namespace gaol_core { log_node::log_node(const expression& e) : e_log(e.get_root()) { e_log->inc_refcount(); - GAOL_DEBUG(3,std::cout << "log_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "log_node created" << std::endl); } log_node::~log_node() @@ -1221,7 +1221,7 @@ namespace gaol_core { if (e_log->dec_refcount() == 0) { delete e_log; } - GAOL_DEBUG(3,std::cout << "log_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "log_node destroyed" << std::endl); } std::ostream& log_node::display(std::ostream& os) const @@ -1249,7 +1249,7 @@ namespace gaol_core { exp2_node::exp2_node(const expression& e) : e_exp2(e.get_root()) { e_exp2->inc_refcount(); - GAOL_DEBUG(3,std::cout << "exp2_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "exp2_node created" << std::endl); } exp2_node::~exp2_node() @@ -1257,7 +1257,7 @@ namespace gaol_core { if (e_exp2->dec_refcount() == 0) { delete e_exp2; } - GAOL_DEBUG(3,std::cout << "exp2_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "exp2_node destroyed" << std::endl); } std::ostream& exp2_node::display(std::ostream& os) const @@ -1285,7 +1285,7 @@ namespace gaol_core { log2_node::log2_node(const expression& e) : e_log2(e.get_root()) { e_log2->inc_refcount(); - GAOL_DEBUG(3,std::cout << "log2_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "log2_node created" << std::endl); } log2_node::~log2_node() @@ -1293,7 +1293,7 @@ namespace gaol_core { if (e_log2->dec_refcount() == 0) { delete e_log2; } - GAOL_DEBUG(3,std::cout << "log2_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "log2_node destroyed" << std::endl); } std::ostream& log2_node::display(std::ostream& os) const @@ -1321,7 +1321,7 @@ namespace gaol_core { sign_node::sign_node(const expression& e) : e_sign(e.get_root()) { e_sign->inc_refcount(); - GAOL_DEBUG(3,std::cout << "sign_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "sign_node created" << std::endl); } sign_node::~sign_node() @@ -1329,7 +1329,7 @@ namespace gaol_core { if (e_sign->dec_refcount() == 0) { delete e_sign; } - GAOL_DEBUG(3,std::cout << "sign_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "sign_node destroyed" << std::endl); } std::ostream& sign_node::display(std::ostream& os) const @@ -1357,7 +1357,7 @@ namespace gaol_core { trunc_node::trunc_node(const expression& e) : e_trunc(e.get_root()) { e_trunc->inc_refcount(); - GAOL_DEBUG(3,std::cout << "trunc_node created" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "trunc_node created" << std::endl); } trunc_node::~trunc_node() @@ -1365,7 +1365,7 @@ namespace gaol_core { if (e_trunc->dec_refcount() == 0) { delete e_trunc; } - GAOL_DEBUG(3,std::cout << "trunc_node destroyed" << std::endl); + GAOL_DEBUG_VERBOSE(3,std::cout << "trunc_node destroyed" << std::endl); } std::ostream& trunc_node::display(std::ostream& os) const diff --git a/gaol/gaol_expression.h b/gaol/gaol_expression.h index f2dfd693..2a76375b 100644 --- a/gaol/gaol_expression.h +++ b/gaol/gaol_expression.h @@ -890,7 +890,7 @@ typedef struct { */ GAOL_INLINE void null_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "null_node accepting visitor" << std::endl); + GAOL_DEBUG_VERBOSE(2,std::cout << "null_node accepting visitor" << std::endl); visitor.visit(this); } @@ -900,7 +900,7 @@ typedef struct { */ GAOL_INLINE void double_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "double_node accepting visitor" << std::endl); + GAOL_DEBUG_VERBOSE(2,std::cout << "double_node accepting visitor" << std::endl); visitor.visit(this); } @@ -914,7 +914,7 @@ typedef struct { */ GAOL_INLINE void interval_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "interval_node accepting visitor" << std::endl); + GAOL_DEBUG_VERBOSE(2,std::cout << "interval_node accepting visitor" << std::endl); visitor.visit(this); } @@ -929,7 +929,7 @@ typedef struct { */ GAOL_INLINE void add_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "add_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "add_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -948,7 +948,7 @@ typedef struct { */ GAOL_INLINE void unary_minus_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "unary_minus_node accepting visitor" + GAOL_DEBUG_VERBOSE(2,std::cout << "unary_minus_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -963,7 +963,7 @@ typedef struct { */ GAOL_INLINE void sub_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "sub_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "sub_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -982,7 +982,7 @@ typedef struct { */ GAOL_INLINE void mult_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "mult_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "mult_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1001,7 +1001,7 @@ typedef struct { */ GAOL_INLINE void div_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "div_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "div_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1020,7 +1020,7 @@ typedef struct { */ GAOL_INLINE void pow_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "pow_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "pow_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1040,7 +1040,7 @@ typedef struct { */ GAOL_INLINE void pow_itv_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "pow_itv_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "pow_itv_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1065,7 +1065,7 @@ typedef struct { */ GAOL_INLINE void nth_root_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "nth_root_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "nth_root_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1085,7 +1085,7 @@ typedef struct { */ GAOL_INLINE void cos_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "cos_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "cos_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1099,7 +1099,7 @@ typedef struct { */ GAOL_INLINE void sin_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "sin_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "sin_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1113,7 +1113,7 @@ typedef struct { */ GAOL_INLINE void tan_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "tan_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "tan_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1127,7 +1127,7 @@ typedef struct { */ GAOL_INLINE void atan2_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "atan2_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "atan2_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1146,7 +1146,7 @@ typedef struct { */ GAOL_INLINE void acos_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "acos_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "acos_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1160,7 +1160,7 @@ typedef struct { */ GAOL_INLINE void asin_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "asin_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "asin_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1174,7 +1174,7 @@ typedef struct { */ GAOL_INLINE void atan_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "atan_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "atan_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1188,7 +1188,7 @@ typedef struct { */ GAOL_INLINE void cosh_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "cosh_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "cosh_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1202,7 +1202,7 @@ typedef struct { */ GAOL_INLINE void sinh_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "sinh_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "sinh_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1216,7 +1216,7 @@ typedef struct { */ GAOL_INLINE void tanh_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "tanh_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "tanh_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1230,7 +1230,7 @@ typedef struct { */ GAOL_INLINE void acosh_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "acosh_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "acosh_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1244,7 +1244,7 @@ typedef struct { */ GAOL_INLINE void asinh_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "asinh_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "asinh_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1258,7 +1258,7 @@ typedef struct { */ GAOL_INLINE void atanh_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "atanh_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "atanh_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1272,7 +1272,7 @@ typedef struct { */ GAOL_INLINE void exp_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "exp_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "exp_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1286,7 +1286,7 @@ typedef struct { */ GAOL_INLINE void log_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "log_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "log_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1300,7 +1300,7 @@ typedef struct { */ GAOL_INLINE void exp2_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "exp2_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "exp2_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1314,7 +1314,7 @@ typedef struct { */ GAOL_INLINE void log2_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "log2_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "log2_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1328,7 +1328,7 @@ typedef struct { */ GAOL_INLINE void sign_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "sign_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "sign_node accepting visitor" << std::endl;); visitor.visit(this); } @@ -1342,7 +1342,7 @@ typedef struct { */ GAOL_INLINE void trunc_node::accept(expr_visitor& visitor) { - GAOL_DEBUG(2,std::cout << "trunc_node accepting visitor" << std::endl;); + GAOL_DEBUG_VERBOSE(2,std::cout << "trunc_node accepting visitor" << std::endl;); visitor.visit(this); } diff --git a/manual/v5/gaol.tex b/manual/v5/gaol.tex index 9de7b5f2..bdfd13c1 100644 --- a/manual/v5/gaol.tex +++ b/manual/v5/gaol.tex @@ -5000,9 +5000,11 @@ \chapter{Debugging facilities}\label{sec:debugging-facilities} \code{gaol} too. \end{deffun} -\begin{defmacroA}{GAOL\_DEBUG}{(\var{lvl},\var{cmd})} +\begin{defmacroA}{GAOL\_DEBUG\_VERBOSE}{(\var{lvl},\var{cmd})} Executes \var{cmd} if \var{lvl} is lower or equal to the current debugging - level (see the variable \code{debug\_level} above). + level (see the variable \code{debug\_level} above). It was named + \code{GAOL\_DEBUG} before GAOL v5, which is now the option of CMake that + builds GAOL for debugging.\newinvfive This macro defaults to nothing if the library was not configured with the debugging facilities. @@ -5016,9 +5018,9 @@ \chapter{Debugging facilities}\label{sec:debugging-facilities} @emph^[Some code]~ -GAOL_DEBUG(1,cout << "The value of x is " << x); +GAOL_DEBUG_VERBOSE(1,cout << "The value of x is " << x); x += interval(3.5,4.5); -GAOL_DEBUG(2,cout << "Now the value of x is " << x); +GAOL_DEBUG_VERBOSE(2,cout << "Now the value of x is " << x); \end{example} The first message will be displayed whenever the debugging level is at least diff --git a/tests/debugging.cpp b/tests/debugging.cpp index 0df324da..7cfa8b67 100644 --- a/tests/debugging.cpp +++ b/tests/debugging.cpp @@ -6,13 +6,15 @@ * The Debug builds define GAOL_DEBUGGING in gaol/gaol_configuration.h * (CMAKE_BUILD_TYPE=Debug, configure --enable-debug, meson * --buildtype=debug): GAOL then checks its assertions (GAOL_ASSERT), and - * GAOL_DEBUG(level, command) runs command where the level given to + * GAOL_DEBUG_VERBOSE(level, command) runs command where the level given to * gaol::init() is level or more. gaol/gaol_expression.h did not compile with - * it: its GAOL_DEBUG write on std::cout, which no header of GAOL included - * (configure --enable-debug, the only build that defined it, failed). This - * test includes GAOL's headers with GAOL_DEBUGGING whatever the build, builds - * and evaluates an expression, whose nodes call GAOL_DEBUG, and checks that - * GAOL_DEBUG runs its command at the level given to gaol::init(). + * it: its GAOL_DEBUG_VERBOSE write on std::cout, which no header of GAOL + * included (configure --enable-debug, the only build that defined it, + * failed). This test includes GAOL's headers with GAOL_DEBUGGING whatever the + * build, builds and evaluates an expression, whose nodes call + * GAOL_DEBUG_VERBOSE, and checks that GAOL_DEBUG_VERBOSE runs its command at + * the level given to gaol::init(). The macro was named GAOL_DEBUG before GAOL + * v5. * * Copyright (c) 2026 ENSTA, France * @@ -40,7 +42,8 @@ using namespace gaol_tests; int main() { - // Level 2: the commands of GAOL_DEBUG(1, ...) and GAOL_DEBUG(2, ...) run + // Level 2: the commands of GAOL_DEBUG_VERBOSE(1, ...) and + // GAOL_DEBUG_VERBOSE(2, ...) run gaol::init(2); std::ostringstream out; @@ -49,15 +52,15 @@ int main() const expression e = x + x * expression(3.0); expr_eval ev; e.get_root()->accept(ev); - GAOL_DEBUG(2, std::cout << "level 2"); - GAOL_DEBUG(3, std::cout << "level 3"); + GAOL_DEBUG_VERBOSE(2, std::cout << "level 2"); + GAOL_DEBUG_VERBOSE(3, std::cout << "level 3"); std::cout.rdbuf(saved); check("GAOL_DEBUGGING: an expression is evaluated", ev.result().set_eq(interval(4.0, 8.0)), [&] { return hex(ev.result()); }); - check("GAOL_DEBUGGING: GAOL_DEBUG runs its command at the level given to init()", + check("GAOL_DEBUGGING: GAOL_DEBUG_VERBOSE runs its command at the level given to init()", out.str().find("level 2") != std::string::npos, [&] { return out.str(); }); - check("GAOL_DEBUGGING: GAOL_DEBUG does not run it above that level", + check("GAOL_DEBUGGING: GAOL_DEBUG_VERBOSE does not run it above that level", out.str().find("level 3") == std::string::npos, [&] { return out.str(); }); gaol::cleanup(); From 5c5631429d8108c2e4c0e87216cc3a7c0d69068a Mon Sep 17 00:00:00 2001 From: Jordan08 Date: Tue, 6 Oct 2026 16:15:59 +0200 Subject: [PATCH 27/27] tests/meson_subproject: check_flags.py checks the link option of gaol.pc too (-mno-daz-ftz) --- doc/tests.md | 3 ++- tests/meson_subproject/check_flags.py | 36 ++++++++++++++++++++++++--- tests/meson_subproject/meson.build | 5 ++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/doc/tests.md b/doc/tests.md index 7531ab53..cd680af9 100644 --- a/doc/tests.md +++ b/doc/tests.md @@ -815,7 +815,8 @@ builds some of the same tests with an installed GAOL, and `tests/meson_subproject` with a GAOL brought in as a meson subproject (GAOL v5), which meson refused. Its test `flags` checks that `gaol_dep` gives their compilation the flags of the `Cflags` of `gaol.pc`, without which the tests -pass all the same, and its test `release` that GAOL is built in release in +pass all the same, and their link the options of its `Libs` (`-mno-daz-ftz`, +where the compiler takes it), and its test `release` that GAOL is built in release in the default build type of meson, debug: `tests/release_flags.py` checks that the sources of GAOL and CORE-MATH are compiled with `-O3` and `NDEBUG`, and that `GAOL_DEBUGGING` is left undefined. The continuous integration runs it on diff --git a/tests/meson_subproject/check_flags.py b/tests/meson_subproject/check_flags.py index 9156941b..c5a003fe 100644 --- a/tests/meson_subproject/check_flags.py +++ b/tests/meson_subproject/check_flags.py @@ -6,7 +6,10 @@ Fails unless each command of compile_commands.json that compiles a source of the project, not of its subprojects, holds the flags of the Cflags of the gaol.pc the subproject GAOL wrote in meson-private, its include directory -aside: the code including GAOL's headers is to be compiled with them (see +aside, and unless each command of build.ninja that links an executable of the +project holds the options of its Libs, -L and -l aside (-mno-daz-ftz, where +the compiler takes it; with a compiler that refuses it, there is none): the +code including GAOL's headers is to be compiled and linked with them (see doc/using.md), and gaol_dep alone gives them, the arguments of the project GAOL reaching none of the targets of another project. @@ -21,9 +24,13 @@ build, source = sys.argv[1], sys.argv[2] with open(os.path.join(build, 'meson-private', 'gaol.pc')) as pc: - cflags = [line for line in pc if line.startswith('Cflags:')][0] + lines = pc.read().splitlines() +cflags = [line for line in lines if line.startswith('Cflags:')][0] +libs = [line for line in lines if line.startswith('Libs:')][0] flags = [f for f in shlex.split(cflags[len('Cflags:'):]) if not f.startswith('-I')] +link_flags = [f for f in shlex.split(libs[len('Libs:'):]) + if not f.startswith(('-L', '-l'))] with open(os.path.join(build, 'compile_commands.json')) as db: commands = json.load(db) subprojects = os.path.join(os.path.normpath(source), 'subprojects') + os.sep @@ -41,4 +48,27 @@ % (command['file'], ' '.join(missing))) print('%d command(s) of the project checked for %s' % (checked, ' '.join(flags))) -sys.exit(1 if failed or not checked or not flags else 0) + +# The links of the executables of the project: a statement "build : +# cpp_LINKER ..." of build.ninja, whose variable LINK_ARGS follows on an +# indented line; those of the subprojects are under subprojects/ +linked = 0 +with open(os.path.join(build, 'build.ninja')) as ninja: + statements = ninja.read().split('\nbuild ') +for statement in statements[1:]: + head, _, rest = statement.partition('\n') + target, _, rule = head.partition(': ') + if not rule.startswith(('cpp_LINKER', 'c_LINKER')) or \ + target.startswith('subprojects/'): + continue + args = [line.strip()[len('LINK_ARGS = '):] for line in rest.split('\n') + if line.startswith(' ') and line.strip().startswith('LINK_ARGS = ')] + linked += 1 + missing = [f for f in link_flags + if f not in shlex.split(args[0] if args else '')] + if missing: + failed += 1 + print('%s is linked without %s' % (target, ' '.join(missing))) +print('%d link(s) of the project checked for %s' + % (linked, ' '.join(link_flags) or 'no option (gaol.pc gives none)')) +sys.exit(1 if failed or not checked or not flags or not linked else 0) diff --git a/tests/meson_subproject/meson.build b/tests/meson_subproject/meson.build index b6e7f1ab..c5b65723 100644 --- a/tests/meson_subproject/meson.build +++ b/tests/meson_subproject/meson.build @@ -44,8 +44,9 @@ endforeach # The arguments GAOL gives its own targets do not reach those of this project: # the commands that compile the tests above have to hold the flags of the -# gaol.pc the subproject wrote, which only gaol_dep gives them. Without them, -# the tests pass all the same (GCC 9.4, x86_64) +# gaol.pc the subproject wrote, and those that link them its link option +# (-mno-daz-ftz, where the compiler takes it), which only gaol_dep gives them. +# Without them, the tests pass all the same (GCC 9.4, x86_64) test('flags', find_program('python3'), args: [files('check_flags.py'), meson.current_build_dir(), meson.current_source_dir()])