Modern, header-only C++17 wrapper for siderust — a high-precision astronomical computation library written in Rust.
siderust-cpp provides idiomatic C++ types (RAII, exceptions, value semantics) on top of the C FFI layer generated by siderust-ffi and tempoch-ffi.
Features
| Module | What you get |
| Time (time.hpp) | Public tags (TT, UTC, JD, MJD, Unix, GPS), Time<Scale, Format>, Period<Scale, Format>, CivilTime, and TimeContext |
| Coordinates (coordinates.hpp) | Modular typed API (coordinates/{geodetic,spherical,cartesian,types}.hpp) plus selective alias headers under coordinates/types/{spherical,cartesian}/... |
| Frames & Centers (frames.hpp, centers.hpp) | Compile-time frame/center tags and transform capability traits |
| Orbits (orbit.hpp) | KeplerianOrbit, MeanMotionOrbit, ConicOrbit, PreparedOrbit |
| Bodies (bodies.hpp) | Star (RAII, catalog + custom), Planet (8 planets), ProperMotion, planet orbit data |
| Observatories (observatories.hpp) | Named sites: Roque de los Muchachos, Paranal, Mauna Kea, La Silla |
| Altitude (altitude.hpp) | Sun / Moon / Star / ICRS altitude: instant, above/below threshold, crossings, culminations |
| Azimuth (azimuth.hpp) | Sun / Moon / Star / ICRS azimuth: instant, crossings, extrema, range windows |
| Targets (trackable.hpp, target.hpp, body_target.hpp, star_target.hpp) | Polymorphic tracking with Trackable, Target, BodyTarget, and StarTarget |
| Lunar Phase (lunar_phase.hpp) | Phase geometry/labels, principal phase events, illumination window search |
| Ephemeris (ephemeris.hpp) | VSOP87 Sun/Earth positions, ELP2000 Moon position |
Quick Start
#include <iostream>
int main() {
std::cout << "Epoch: " << mjd << '\n';
std::cout <<
"Sun alt: " <<
sun::altitude_at(obs, mjd).to<qtty::Degree>() <<
'\n';
Target fixed(279.23473, 38.78369);
std::cout << "Target alt: " << fixed.altitude_at(obs, mjd).to<qtty::Degree>() << '\n';
std::cout << "Astronomical-night periods in next 24h: " << nights.size() << "\n";
}
Abstract base for any celestial object that can be tracked from an observer location.
qtty::Radian altitude_at(const Geodetic &obs, const Time< TT, MJD > &mjd)
Compute the Sun's altitude (radians) at a given Time<TT, MJD> instant.
qtty::Degree azimuth_at(const Geodetic &obs, const Time< TT, MJD > &mjd)
Compute the Sun's azimuth (degrees, N-clockwise) at a given Time<TT, MJD> instant.
std::vector< Period< TT, MJD > > below_threshold(const Geodetic &obs, const Period< TT, MJD > &window, qtty::Degree threshold, const SearchOptions &opts={})
Find periods when the Sun is below a threshold altitude.
const Geodetic & ROQUE_DE_LOS_MUCHACHOS()
Roque de los Muchachos Observatory (La Palma, Spain).
tempoch::EncodedTime< Scale, Format > Time
tempoch::Period< Time< Scale, Format > > Period
Umbrella header for the siderust C++ wrapper library.
Altitude Search Controls
Altitude searches use Siderust's internal optimized engines automatically. The only user-facing control is time tolerance:
std::vector< Period< TT, MJD > > altitude_ranges(const Geodetic &obs, const Period< TT, MJD > &window, qtty::Degree min_alt, qtty::Degree max_alt, const SearchOptions &opts={})
Find periods when the Sun's altitude is within [min, max].
Options for altitude search algorithms.
SearchOptions & with_tolerance(qtty::Day tolerance)
Set time tolerance.
Streaming and printing
Coordinate types, Geodetic, and qtty quantities support operator<< with frame/center context and unit labels, for example:
std::cout << jd << '\n';
std::cout <<
mars <<
'\n';
std::cout << mars_eq.to_spherical() << '\n';
cartesian::position::EclipticMeanJ2000< qtty::AstronomicalUnit > mars_heliocentric(const Time< TT, JD > &jd)
Mars's heliocentric position (EclipticMeanJ2000, AU) via VSOP87.
Geocenter (zero-cost, Params = void).
Mean equatorial of J2000.0 (FK5-aligned).
Time<TT, JD> / Time<TT, MJD> print as TT JD … / TT Time<TT, MJD> … via tempoch-cpp. Use std::cout in examples and tests rather than manual .value() formatting unless you need a raw scalar for computation.
Building
# Clone with the siderust submodule
git clone --recurse-submodules <url>
cd siderust-cpp
# Install official qtty-cpp and tempoch-cpp packages
scripts/install-official-cpp-deps.sh
# Build
mkdir build && cd build
cmake ..
cmake --build .
# Run example
./14_nutation_models_example
./15_orbit_models_example
# Run tests
ctest --output-on-failure
# Run benchmarks (night periods and fixed ICRS altitude windows)
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DSIDERUST_CPP_BUILD_BENCHES=ON
cmake --build build --target bench_night_periods bench_icrs_altitude_periods
./build/bench_night_periods
./build/bench_icrs_altitude_periods
See benches/README.md for details.
Deployment
Packages for Debian/Ubuntu (.deb) and RHEL/Fedora/openSUSE (.rpm) can be built with CMake + CPack.
Prerequisites
# Debian/Ubuntu
sudo apt-get install cmake ninja-build rpm curl
# RHEL/Fedora
sudo dnf install cmake ninja-build dpkg curl
# Install official qtty-cpp and tempoch-cpp packages
scripts/install-official-cpp-deps.sh
Build the packages
git clone --recurse-submodules <url>
cd siderust-cpp
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DSIDERUST_BUILD_DOCS=OFF
cmake --build build --parallel
# Install headers + cmake config to a staging prefix
cmake --install build --prefix build/staging
# Generate .deb and .rpm in build/packages/
cd build
cpack --config CPackConfig.cmake -G "DEB;RPM" -B packages
ls packages/
Install on the target system
# Debian/Ubuntu
sudo apt-get install ./packages/siderust-cpp-*.deb
# RHEL/Fedora/openSUSE
sudo dnf install ./packages/siderust-cpp-*.rpm
After installation, headers land in /usr/local/include/siderust/ and the siderust_ffi shared library lands in /usr/local/lib/. The qtty-cpp and tempoch-cpp shared libraries are provided by their official packages. CMake consumers can then use:
find_package(siderust_cpp REQUIRED)
target_link_libraries(your_target PRIVATE siderust::siderust_cpp)
A reference external-consumer fixture lives under tests/installed-consumer/ and is exercised by the ci-installed-consumer.yml workflow on every push.
Runtime shared libraries (loader path)
siderust-cpp is header-only, but every binary must load three Rust FFI shared libraries at runtime: libsiderust_ffi, libtempoch_ffi, and libqtty_ffi.
| Install layout | Linux / macOS | Windows (MSVC) |
| System packages (.deb / .rpm into /usr or /usr/local) | The dynamic linker finds libraries in standard lib/ paths after ldconfig or equivalent. No extra environment variables are usually required. | Install siderust_ffi.dll, tempoch_ffi.dll, and qtty_ffi.dll under bin/ (or ensure that directory is on PATH). Link via the .dll.lib import libraries in lib/. |
| Custom CMake prefix (cmake --install … --prefix /opt/foo) | Either add /opt/foo/lib to LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS), or link your executable with an RPATH/@rpath that points at $ORIGIN/../lib relative to your binary. The installed-consumer CI smoke test uses the latter when built with CMAKE_PREFIX_PATH set to the staged prefix. | Add the install bin/ directory to PATH, or copy the three DLLs next to your executable. find_package(siderust_cpp) sets IMPORTED_LOCATION (DLL) and IMPORTED_IMPLIB (.dll.lib) on siderust::siderust_ffi. |
| In-tree build (add_subdirectory / local build/) | CMake sets BUILD_RPATH for the local siderust/target/release library. qtty-cpp and tempoch-cpp come from installed packages or from a staged local prefix passed through CMAKE_PREFIX_PATH. | Same as custom prefix: ensure the official or staged dependency DLL directory is on PATH. |
find_package(siderust_cpp) defines imported targets siderust::siderust_cpp and siderust::siderust_ffi so that linking resolves symbols; loading still requires the platform loader to locate the .so/.dylib/.dll files using the rules above.
Note: Pre-built .deb and .rpm packages are automatically built by CI and attached to every GitHub Release.
Docker
The repository includes a root Dockerfile that installs all build dependencies (CMake, Rust, Doxygen), then runs configure/build/tests/docs during image build.
# Clone with the siderust submodule
git clone --recurse-submodules <url>
cd siderust-cpp
# Build image (validates build + tests + docs)
docker build -t siderust-cpp:dev .
# Open an interactive shell in the container
docker run --rm -it -v "$PWD":/workspace -w /workspace siderust-cpp:dev
Note: docker build writes generated docs inside the image layer, not your host filesystem.
To generate docs on the host, run the docs target in a bind-mounted container:
docker run --rm \
-u "$(id -u):$(id -g)" \
-v "$PWD":/workspace \
-w /workspace \
siderust-cpp:dev \
bash -lc 'cmake -S . -B build -G Ninja && cmake --build build --target docs'
Generated HTML entry point on host:
- build/docs/doxygen/html/index.html
Generated HTML entry point inside container:
- /workspace/build/docs/doxygen/html/index.html
API Documentation (Doxygen)
If Doxygen is installed, CMake exposes a docs target:
cmake -S . -B build
cmake --build build --target docs
Generated HTML entry point:
- build/docs/doxygen/html/index.html
Prerequisites
- C++17 compiler (GCC 8+, Clang 7+, MSVC 2019+)
- CMake 3.21+
- Rust toolchain (cargo) — Rust FFI libraries are built automatically
- Installed qtty-cpp and tempoch-cpp packages, or local staged installs passed through CMAKE_PREFIX_PATH
- Internet connection for Google Test (fetched automatically)
Project Layout
siderust-cpp/
├── CMakeLists.txt
├── docs/
│ ├── Doxyfile.in
│ └── mainpage.md
├── cmake/
│ └── siderust_cppConfig.cmake.in
├── include/siderust/
│ ├── siderust.hpp ← umbrella header
│ ├── ffi_core.hpp ← error handling, enums
│ ├── time.hpp ← time tags, `Time<Scale, Format>`, `Period<Scale, Format>`
│ ├── coordinates.hpp ← coordinate umbrella header
│ ├── coordinates/
│ │ ├── geodetic.hpp
│ │ ├── spherical.hpp
│ │ ├── cartesian.hpp
│ │ ├── types.hpp
│ │ └── conversions.hpp
│ ├── bodies.hpp ← Star, Planet, ProperMotion
│ ├── observatories.hpp ← named observatory locations
│ ├── altitude.hpp ← sun/moon/star altitude API
│ ├── azimuth.hpp ← azimuth queries and events
│ ├── lunar_phase.hpp ← moon phase geometry and events
│ ├── trackable.hpp ← polymorphic trackable interface
│ ├── target.hpp ← fixed ICRS target (RAII)
│ ├── body_target.hpp ← body enum trackable adapter
│ ├── star_target.hpp ← star trackable adapter
│ └── ephemeris.hpp ← VSOP87/ELP2000 positions
├── benches/
│ ├── bench_night_periods.cpp
│ ├── bench_icrs_altitude_periods.cpp
│ └── README.md
├── examples/demo.cpp
├── tests/
│ ├── main.cpp
│ ├── test_time.cpp
│ ├── test_observatories.cpp
│ ├── test_coordinates.cpp
│ ├── test_bodies.cpp
│ ├── test_altitude.cpp
│ └── test_ephemeris.cpp
└── siderust/ ← git submodule with `siderust-ffi`
Time API
- Default astronomy-facing code should use Time<TT, JD>, Time<TT, MJD>, and Period<TT, MJD>, all pinned to TT.
- Civil construction is available directly through Time<TT, JD>::from_utc(...) and Time<TT, MJD>::from_utc(...).
- Advanced mixed-scale work stays explicit with Time<Scale, Format> and time.to<Scale, Format>().
Architecture
┌──────────────┐
│ C++ user │ #include <siderust/siderust.hpp>
│ code │
└──────┬───────┘
│ header-only (inline)
┌──────▼───────┐
│ siderust-cpp │ C++17 types, RAII, exceptions
│ (headers) │
└──────┬───────┘
│ extern "C" calls
┌──────▼───────┐ ┌──────────────┐
│ siderust-ffi │──│ tempoch-ffi │ C ABI (cbindgen-generated)
│ (.so/.dylib) │ │ (.so/.dylib) │
└──────┬───────┘ └──────┬───────┘
│ │
┌──────▼─────────────────▼──┐
│ siderust (Rust) │
│ coordinates · altitude │
│ bodies · ephemeris │
│ tempoch · affn · qtty │
└───────────────────────────┘
License
Same license as siderust. See [LICENSE](LICENSE).