Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
88e5f89
Make Approx<double> relative for large values, handle NaN and inf
Jordan08 Sep 19, 2026
ee89eab
Build Codac on GAOL from Jordan Ninin's fork instead of IBEX
Jordan08 Sep 19, 2026
ed13cad
Stop installing IBEX in the workflows, Docker scripts and packages
Jordan08 Sep 19, 2026
66aefbb
Document in the manual that Codac depends on GAOL instead of IBEX
Jordan08 Sep 19, 2026
411b4cc
Hand Threads to the users of codac-config.cmake
Jordan08 Sep 19, 2026
280d765
Enable ASan/UBSan in Debug builds when the toolchain ships the runtime
Jordan08 Sep 19, 2026
a350f52
Update the examples to axis() in set_axes and draw every subset
Jordan08 Sep 19, 2026
c2e3357
Compile against the headers in src/ instead of build/include copies
Jordan08 Sep 19, 2026
e81bed1
Add the WITH_COVERAGE option and the coverage targets
Jordan08 Sep 19, 2026
80e702c
Retry the Doxygen install on Windows, pin 1.17.0 on Intel macOS
Jordan08 Sep 19, 2026
c1ce598
Build the wheels with python -m build and an SPDX license
Jordan08 Sep 19, 2026
96b172e
Run only the Python tests in the wheel-building matrices
Jordan08 Sep 19, 2026
d364001
Run the examples as tests in the package and wheel matrices
Jordan08 Sep 19, 2026
ec26dde
Run the examples as tests in the Windows Debug jobs too
Jordan08 Sep 19, 2026
50e71e9
Set CMAKE_POSITION_INDEPENDENT_CODE before add_subdirectory(src)
Jordan08 Sep 19, 2026
dcf274a
Build Catch2 for the macOS deployment target, not Homebrew's
Jordan08 Sep 19, 2026
d1e65a8
Merge branches 'dev-clean-v2-22' and 'dev-clean-v2-24'
Jordan08 Sep 19, 2026
91c65c8
Build and run the examples as ctest tests when TEST_EXAMPLES is ON
Jordan08 Sep 19, 2026
d26758d
Merge branches 'dev-clean-v2-23' and 'dev-clean-v2-25'
Jordan08 Sep 19, 2026
ab5bf69
Add Debug workflows with sanitizers and coverage
Jordan08 Sep 19, 2026
feba0f3
Merge branches 'dev-clean-v2-05', 'dev-clean-v2-32', 'dev-clean-v2-34…
Jordan08 Sep 19, 2026
21235fe
Drop the -fPIC given by hand in the workflows, scripts and manual
Jordan08 Sep 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 2 additions & 13 deletions .github/workflows/dockermatrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,14 @@ jobs:
if [ \"${{ matrix.cfg.deb }}\" = \"true\" ]; then \
sudo sh -c 'echo \"deb [trusted=yes] https://webperso.ensta.fr/packages/\$(if [ -z \"\$(. /etc/os-release && echo \$UBUNTU_CODENAME)\" ]; then echo debian/\$(. /etc/os-release && echo \$VERSION_CODENAME); else echo ubuntu/\$(. /etc/os-release && echo \$UBUNTU_CODENAME); fi) ./\" > /etc/apt/sources.list.d/ensta-bretagne.list' && \
#sudo apt-get -q update ; sudo apt-get -y install libeigen3-dev catch2 dpkg-dev || true && \\
sudo apt-get -q update ; sudo apt-get -y install catch2 dpkg-dev || true && \
wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20260819/libibex-dev-2.8.9.20260819-0${{ matrix.cfg.runtime }}0_\$(dpkg --print-architecture).deb --no-check-certificate -nv && \
sudo dpkg -i libibex-dev-2.8.9.20260819-0${{ matrix.cfg.runtime }}0_\$(dpkg --print-architecture).deb && \
rm -Rf libibex-dev-2.8.9.20260819-0${{ matrix.cfg.runtime }}0_\$(dpkg --print-architecture).deb ; \
else \
wget https://github.com/lebarsfa/ibex-lib/releases/download/ibex-2.8.9.20260819/ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip --no-check-certificate -nv && \
unzip -q ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip && \
rm -Rf ibex_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip && \
sudo cp -Rf ibex/* /usr/ ; \
sudo apt-get -q update ; sudo apt-get -y install catch2 dpkg-dev || true ; \
fi && \
mkdir build ; cd build && \
cmake -E env CXXFLAGS="${{ matrix.cfg.cmake_flags }}" CFLAGS="${{ matrix.cfg.cmake_flags }}" cmake ${{ matrix.cfg.cmake_params }} -D BUILD_TESTS=ON -D CMAKE_INSTALL_PREFIX="../codac" .. && \
cmake -E env CXXFLAGS="${{ matrix.cfg.cmake_flags }}" CFLAGS="${{ matrix.cfg.cmake_flags }}" cmake ${{ matrix.cfg.cmake_params }} -D BUILD_TESTS=ON -D TEST_EXAMPLES=ON -D CMAKE_INSTALL_PREFIX="../codac" .. && \
cmake --build . -j 4 --config Release --target install && \
cd .. && \
zip -q -r codac_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip codac && \
mkdir -p codac_standalone/example ; cd codac_standalone && \
if [ \"${{ matrix.cfg.deb }}\" = \"true\" ]; then mkdir -p ibex/include ; mkdir -p ibex/lib ; mkdir -p ibex/share ; mkdir -p ibex/bin ; cp -Rf /usr/include/ibex* ibex/include/ ; cp -Rf /usr/lib/*ibex* ibex/lib/ ; cp -Rf /usr/share/*ibex* ibex/share/ ; cp -Rf /usr/share/pkgconfig ibex/share/ ; cp -Rf /usr/bin/ibex* ibex/bin/ ; \
else cp -Rf ../ibex . ; \
fi && \
cp -Rf ../codac . ; cp -Rf ../tests/test_codac/* ./example/ ; cd .. ; zip -q -r codac_standalone_${{ matrix.cfg.arch }}_${{ matrix.cfg.runtime }}.zip codac_standalone && \
cd codac_standalone/example && \
cmake ${{ matrix.cfg.cmake_params }} . && \
Expand Down
189 changes: 189 additions & 0 deletions .github/workflows/macdebug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# Debug builds on macOS, under AddressSanitizer and UndefinedBehaviorSanitizer.
#
# The macOS counterpart of unixdebug.yml, and the same reasoning: every other
# workflow builds macOS in Release, so nothing was ever run there under a
# sanitizer. It also runs the examples, which -D TEST_EXAMPLES=ON registers as
# ctest integration tests (see examples/CMakeLists.txt).
#
# As on Linux, GitHub offers only two instruction sets here, so the third
# configuration is a compiler rather than a third architecture: AppleClang next
# to GCC, on arm64.
#
# Two things make macOS harder than Linux, and shape the matrix below.
#
# GCC on macOS links against libstdc++ while AppleClang links against libc++,
# so a library built with one of them cannot be linked by the other -- the two
# standard libraries are not ABI-compatible. GAOL is no obstacle: codac builds
# it with the compiler of the job (see scripts/CMakeModules/codac_gaol.cmake).
# Catch2 has to be treated the same way, which the Toolchain step below does.
#
# The Python bindings are left out of every job here, sanitized macOS being a
# configuration the test suite cannot currently run them in: the block of
# tests/CMakeLists.txt that hands the sanitizer runtime to the interpreter is
# Linux-only by construction, and says so -- LD_PRELOAD has no equivalent there,
# macOS needing DYLD_INSERT_LIBRARIES and a differently named runtime. Without
# that preload the extension module fails to load on the first unresolved
# __asan_* symbol. The Python half of the suite therefore runs under a sanitizer
# in unixdebug.yml, where the mechanism exists, and macOS covers the C++ half:
# the library, its unit tests and the C++ examples. Turning WITH_PYTHON off also
# removes the need for doxygen here, which doc/CMakeLists.txt only requires for
# the bindings.
on:
push:
branches: ['**']
tags-ignore: ['**'] # Ignore all tag pushes
pull_request:

concurrency:
# Keep only the newest run of this workflow for a given branch or pull
# request: a push that supersedes another leaves the older run computing a
# result nobody will read, while its jobs hold runners the newest run is
# waiting for.
#
# The three release branches are excluded. They are where the jobs upload
# their packages to a GitHub release (see the "github.ref_name==" conditions
# further down), and cancelling such a run halfway would leave the release
# with only part of its assets. The same expression is used in every
# workflow of this directory, including the ones that publish nothing, so
# that the rule stays a single thing to know.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref_name != 'codac1' && github.ref_name != 'codac2' && github.ref_name != 'codac2_codac4matlab' }}

jobs:
macdebug:
runs-on: ${{ matrix.cfg.os }}
# A sanitized Debug build is roughly an order of magnitude slower to run
# than the Release builds of the other workflows, and the examples are run
# on top of the test suite. Three hours leaves room for that while still
# turning a hang into a red job rather than into six hours of runner time.
timeout-minutes: 180
defaults:
run:
shell: bash
strategy:
fail-fast: false
matrix:
cfg:
- { os: macos-26 , arch: arm64 , runtime: tahoe , compiler: gcc , with_python: 'OFF', desc: 'macOS Tahoe GCC arm64 Debug ASan+UBSan' }
- { os: macos-15-intel, arch: x86_64, runtime: sequoia, compiler: gcc , with_python: 'OFF', desc: 'macOS Sequoia GCC x86_64 Debug ASan+UBSan' }
- { os: macos-26 , arch: arm64 , runtime: tahoe , compiler: appleclang, with_python: 'OFF', desc: 'macOS Tahoe AppleClang arm64 Debug ASan+UBSan' }
- { os: macos-26 , arch: arm64 , runtime: tahoe , compiler: llvm , with_python: 'OFF', desc: 'macOS Tahoe LLVM Clang arm64 Debug ASan+UBSan' }
name: ${{ matrix.cfg.desc }}
steps:
- uses: actions/checkout@v7
with:
submodules: true
fetch-depth: 0
clean: false

- run: echo "VERBOSE=1" >> $GITHUB_ENV

# Homebrew's "gcc" formula is the newest GCC it packages, and the binaries
# it installs carry the major version in their name (g++-15 and so on), the
# plain g++ of macOS being a symlink to AppleClang. The version is therefore
# resolved here rather than pinned, and written to the environment for the
# later steps.
# Catch2 is deliberately not installed from Homebrew: the bottle is built
# with AppleClang against libc++, so the GCC jobs cannot link it -- the
# standard-library split described at the top of this file, showing up as
# undefined std::__1:: symbols at link time. Leaving it out lets
# tests/CMakeLists.txt fetch Catch2 and build it with the compiler of the
# job, which is correct for every entry of this matrix.
- name: Toolchain
run: |
case "${{ matrix.cfg.compiler }}" in
gcc)
brew install gcc
GCC_MAJOR=$(brew list --versions gcc | awk '{print $2}' | cut -d. -f1)
echo "CC=gcc-${GCC_MAJOR}" >> "$GITHUB_ENV"
echo "CXX=g++-${GCC_MAJOR}" >> "$GITHUB_ENV"
;;
llvm)
# Upstream Clang, which is a different compiler from the AppleClang
# of the entry above: its own release cycle, its own diagnostics and
# its own sanitizer runtimes. Homebrew keeps it out of the way of the
# system toolchain, so it has to be named by its prefix, and it needs
# to be pointed at its own libc++ -- the formula says as much -- or
# it compiles against headers newer than the library it links.
brew install llvm
LLVM_PREFIX=$(brew --prefix llvm)
echo "CC=$LLVM_PREFIX/bin/clang" >> "$GITHUB_ENV"
echo "CXX=$LLVM_PREFIX/bin/clang++" >> "$GITHUB_ENV"
echo "LDFLAGS=-L$LLVM_PREFIX/lib/c++ -Wl,-rpath,$LLVM_PREFIX/lib/c++" >> "$GITHUB_ENV"
;;
*)
echo "CC=clang" >> "$GITHUB_ENV"
echo "CXX=clang++" >> "$GITHUB_ENV"
;;
esac

- name: Compiler version
run: $CXX --version

- name: Configure and build
run: |
mkdir build ; cd build
cmake \
-D CMAKE_BUILD_TYPE=Debug \
-D CMAKE_CXX_FLAGS="-fPIC" \
-D CMAKE_C_FLAGS="-fPIC" \
-D CMAKE_INSTALL_PREFIX="../codac" \
-D BUILD_TESTS=ON \
-D TEST_EXAMPLES=ON \
-D WITH_PYTHON=${{ matrix.cfg.with_python }} \
-D PYBIND11_FINDPYTHON=OFF \
-D WITH_CAPD=OFF \
.. 2>&1 | tee configure.log
cmake --build . -j 4

# The point of this workflow is the sanitizers, and the top-level
# CMakeLists.txt deliberately falls back to an unsanitized Debug build when
# it cannot find their runtime rather than failing to link. That fallback is
# the right default for someone building codac by hand, and exactly the
# wrong outcome here: the job would come out green having checked nothing it
# was written for. GCC's Darwin sanitizer support is the reason this is not
# theoretical.
- name: Check that the sanitizers really are enabled
run: |
if grep -q "will not be sanitized" build/configure.log ; then
echo "This job exists to run the suite under ASan and UBSan, and cmake reported:"
grep "will not be sanitized" build/configure.log
exit 1
fi
echo "Sanitizers enabled."

# The unit tests and the examples are the same ctest suite: examples are
# registered as tests by examples/CMakeLists.txt, so this one command runs
# both, and a sanitizer report in either fails the job.
- name: Unit tests and examples
run: |
cd build
ctest -V --output-on-failure 2>&1 | tee ctest.log

# ctest is run verbose so that everything the sanitizers print reaches the
# log. ASan and UBSan do not agree on what a diagnostic costs: a leak or a
# buffer overflow aborts the process and fails the test, but a UBSan runtime
# error only prints and lets the run continue, so a test can pass having
# reported dozens of undefined behaviours. Without -V that output is thrown
# away for every test that passes -- which is precisely the output worth
# reading here.
- name: Sanitizer diagnostics
if: always()
run: |
log=build/ctest.log
[ -f "$log" ] || { echo "No ctest output to scan." ; exit 0 ; }
# A digest, because the verbose log of the whole suite is far too long
# to scan by eye. The step reports rather than judges: it never fails
# the job, the tests themselves decide that.
n=$(grep -cE "runtime error:|ERROR: AddressSanitizer|ERROR: LeakSanitizer|SUMMARY: (Address|Undefined|Leak)Sanitizer" "$log" || true)
echo "Sanitizer diagnostics found: $n"
if [ "$n" -gt 0 ]; then
echo "--- distinct messages, most frequent first ---"
# awk rather than head: this shell runs with pipefail, and head
# closing the pipe early makes sort die on SIGPIPE, which failed the
# step -- the one thing it was written never to do.
grep -hoE "runtime error: .*|ERROR: (Address|Leak)Sanitizer: [a-z-]+" "$log" \
| sed -E "s/0x[0-9a-f]+/0xADDR/g" | sort | uniq -c | sort -rn | awk 'NR<=40'
echo "--- first occurrences in context ---"
grep -nE "runtime error:|ERROR: (Address|Leak)Sanitizer" "$log" | awk 'NR<=20'
fi
Loading
Loading