rf-geom / ridgeforge Public

building

Building the library

A default build needs a C++17 compiler and CMake 3.20. It takes about twelve seconds on four cores and produces one static library and nothing else. Everything optional is off by default, including the command line tool and the tests.

The short version

# from the unpacked release directory
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
# optional, installs headers + libridgeforge.a + CMake package files
cmake --install build --prefix /usr/local

There is no bootstrap script, no code generation step and nothing fetched while configuring. If your network is down the build still works.

Toolchains

Minimum means it compiles and the test suite passes. Tested means a maintainer runs it before tagging a release.

CompilerMinimumTested at releaseNotes
GCC1212, 13, 14reference toolchain for benchmarks
Clang1515, 17, 18used for the sanitizer builds
MSVC19.3619.38needs /std:c++17 explicitly
PlatformArchitectureStateNotes
Linuxx86-64, arm64supportedboth run before every tag
Windowsx64supportedstatic runtime untested
macOSarm64supportedOpenMP needs a separate runtime
Other Unix systems-unverifiednothing platform specific in the code
32-bit targets-unsupportedindex arithmetic assumes 64-bit size_t

CMake options

All options are booleans unless the table says otherwise, and all are prefixed RF_ so they never collide with your own cache variables.

OptionDefaultWhat it does
RF_BUILD_TOOLSOFFbuilds the rfmesh command line tool; adds about 90 KB to the build output
RF_BUILD_TESTSOFFbuilds the 411 test cases and registers them with CTest
RF_BUILD_SHAREDOFFproduces a shared library; symbol visibility is set to hidden except for the public API
RF_USE_OPENMPONparallelises the quadric pass and the intersection search when a runtime is found; silently off if not
RF_DOUBLE_PRECISIONOFFmakes rf::Scalar a double; roughly 1.9× memory for positions and 15 % slower collapses
RF_USE_EXCEPTIONSOFFwhen on, allocation failure propagates instead of returning a status
RF_ENABLE_ASSERTSDebug onlyinternal invariant checks; costs about 30 % on decimation, so keep it off in Release
RF_INSTALLONgenerates install rules and the package config; turn off when vendoring
RF_SANITIZEempty stringaccepts address, undefined or both separated by a semicolon
One mismatch to avoid

RF_DOUBLE_PRECISION changes the layout of every public struct. A program compiled against the single-precision headers and linked against a double-precision library will build, link and then read garbage out of positions. The package config records the setting, so find_package catches it; a hand-written link line does not.

Build types

Build typeDecimation, 2 M tri, 8 threadsUse it for
Release (-O2)4.6 severything; this is what the benchmarks use
RelWithDebInfo4.8 sprofiling, crash reports with usable frames
Debug with asserts61 sreproducing a suspected library bug
-O3 instead of -O24.5 snothing in particular; the gain is inside the noise

Do not build with fast-math. The collapse ordering depends on comparing quadric errors that routinely differ in the last two bits, and relaxed floating point makes the output depend on the inliner. The library will still produce a valid mesh, but two builds will disagree about which edges survived, which makes a regression impossible to bisect.

Amalgamation

If CMake is not available, or the project must ship as source, build the single-header form once and carry it along:

cmake -S . -B build -DRF_INSTALL=OFF
cmake --build build --target rf_amalgamate
# writes build/amalgamated/ridgeforge_all.hpp  (about 620 KB)

Include it in exactly one translation unit with the implementation macro defined, and include it plainly everywhere else:

// one file in the program, usually ridgeforge_impl.cpp
#define RF_ALL_IMPLEMENTATION
#include "ridgeforge_all.hpp"

The amalgamation is generated from the same sources and runs the same tests, but it cannot express the optional OpenMP path, so it is always single-threaded. For a 2 M triangle decimation that is the difference between 4.6 and 5.9 seconds.

Tests and sanitizers

cmake -S . -B build-test -DRF_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug
cmake --build build-test -j && ctest --test-dir build-test --output-on-failure
# 411 tests, about 70 s on four cores; 23 of them are marked slow
ctest --test-dir build-test -LE slow        # skip the slow ones

The sanitizer configuration is the one that catches real problems, and it is worth running if you report a crash:

cmake -S . -B build-asan -DRF_BUILD_TESTS=ON \
  -DRF_SANITIZE="address;undefined" -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build-asan -j && ctest --test-dir build-asan

Test meshes live in tests/data and are small on purpose: the largest is 180 KB. Four of them are hand-built pathological cases - a zero-area triangle fan, two shells sharing one vertex, a strip with inconsistent winding, and a cube with one face reversed.

When the build fails

MessageCauseFix
undefined reference to rf::io::readheaders found, library not linkedlink RidgeForge::ridgeforge, not just the include directory
'optional' is not a member of 'std'compiling as C++14 or earlierset CXX_STANDARD 17 on your target, or /std:c++17
omp.h: No such file or directorydetection passed, runtime headers absentconfigure with -DRF_USE_OPENMP=OFF
C2065: '40' near a digit separatorMSVC defaulting to C++14add /std:c++17 to the compile options
static assertion failed: Scalar mismatchdouble and single precision headers mixedrebuild everything with one setting; see the warning above
CMake cannot find RidgeForgeConfig.cmakeinstalled with RF_INSTALL=OFFreinstall with the default, or use add_subdirectory

If none of these match, the FAQ covers a few more cases, and dev@ridgeforge.dev reaches a maintainer. Include the CMake cache and the exact compiler version; without them the first reply will just ask for them.