librebound-sys 4.6.0

Raw FFI bindings and safe RAII wrappers for the REBOUND N-body integrator
Documentation
// build.rs — Compile vendored REBOUND C sources + Rust-side accessor helpers.

use std::env;
use std::path::PathBuf;

fn main() {
    let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
    let rebound_src = manifest_dir.join("vendor/rebound/src");

    // REBOUND C sources (all except communication_mpi.c which needs MPI headers).
    let rebound_sources: Vec<String> = [
        "binarydiff",
        "boundary",
        "collision",
        "derivatives",
        "display",
        "fmemopen",
        "frequency_analysis",
        "glad",
        "gravity",
        "input",
        "integrator",
        "integrator_bs",
        "integrator_eos",
        "integrator_ias15",
        "integrator_janus",
        "integrator_leapfrog",
        "integrator_mercurius",
        "integrator_saba",
        "integrator_sei",
        "integrator_trace",
        "integrator_whfast",
        "integrator_whfast512",
        "output",
        "particle",
        "rebound",
        "rotations",
        "server",
        "simulationarchive",
        "tools",
        "transformations",
        "tree",
    ]
    .iter()
    .map(|name| format!("{}/{}.c", rebound_src.display(), name))
    .collect();

    // `-ffp-contract=off` matches REBOUND's upstream Python setup.py (which
    // sets FFP_CONTRACT_OFF=1). Without it the compiler may fold `a*b + c`
    // into a single FMA instruction, changing rounding vs. the upstream
    // reference and breaking bit-for-bit reproducibility across platforms.
    //
    // `-flto=thin` enables cross-translation-unit inlining when the C
    // compiler is clang. GCC silently ignores it (`flag_if_supported` skips).
    // For maximum performance, build with `CC=clang cargo build --release`.
    let mut rebound_build = cc::Build::new();
    rebound_build
        .include(&rebound_src)
        .define("LIBREBOUND", None)
        .define("_GNU_SOURCE", None)
        .flag_if_supported("-std=c99")
        .flag_if_supported("-ffp-contract=off")
        .flag_if_supported("-flto=thin")
        .flag_if_supported("-Wno-unused-parameter")
        .flag_if_supported("-Wno-sign-compare")
        .flag_if_supported("-Wno-unknown-pragmas")
        .flag_if_supported("-Wno-missing-field-initializers")
        .opt_level(3)
        .pic(true);

    for src in &rebound_sources {
        rebound_build.file(src);
    }
    rebound_build.compile("rebound");

    // Rust-side helper functions for opaque reb_simulation access.
    cc::Build::new()
        .include(&rebound_src)
        .file("src/helpers.c")
        .flag_if_supported("-std=c99")
        .flag_if_supported("-ffp-contract=off")
        .flag_if_supported("-flto=thin")
        .opt_level(3)
        .pic(true)
        .compile("librebound_sys_helpers");

    println!("cargo:rerun-if-changed=vendor/rebound/src");
    println!("cargo:rerun-if-changed=src/helpers.c");

    // Expose include path to downstream crates that depend on rebound headers
    // (e.g. libassist-sys). Cargo sets DEP_REBOUND_INCLUDE in their build env.
    println!("cargo:include={}", rebound_src.display());

    #[cfg(unix)]
    println!("cargo:rustc-link-lib=m");
}