robot-bus 2.3.2

ZeroMQ message bus: broker routing and participant SDK
Documentation
use std::env;
use std::path::Path;

fn main() {
    // libzmq uses Advapi32 security APIs on Windows. Recent Rust toolchains no
    // longer link advapi32 via std, so cdylib (maturin) builds fail with
    // LNK2019 for InitializeSecurityDescriptor / SetSecurityDescriptorDacl.
    //
    // Protobuf / gRPC stubs are pre-generated (`just gen-rust`); this build
    // script does not invoke protoc.
    let target = env::var("TARGET").unwrap_or_default();
    if target.contains("windows") {
        println!("cargo:rustc-link-lib=advapi32");
    }

    // ROS 2 bridge uses system typesupport via AMENT_PREFIX_PATH (same as rclrs).
    if env::var_os("CARGO_FEATURE_ROS2").is_some() {
        if let Ok(ament) = env::var("AMENT_PREFIX_PATH") {
            for prefix in ament.split(':').filter(|p| !p.is_empty()) {
                println!(
                    "cargo:rustc-link-search=native={}",
                    Path::new(prefix).join("lib").display()
                );
            }
        }
    }

    // Embedded console UI is generated by `just console` (not committed).
    // Fail early when the feature is on but assets are missing. Watch the whole
    // tree so SVG/JS asset edits after `just console` actually recompile the
    // include_dir! embed (index.html alone is not enough).
    if env::var_os("CARGO_FEATURE_CONSOLE").is_some() {
        let root = Path::new("assets/console");
        let index = root.join("index.html");
        println!("cargo:rerun-if-changed=assets/console");
        if root.is_dir() {
            for entry in walkdir_files(root) {
                println!("cargo:rerun-if-changed={}", entry.display());
            }
        }
        if !index.is_file() {
            panic!(
                "console feature enabled but assets/console/index.html is missing.\n\
                 \n\
                 Build the embed once, then re-run cargo:\n\
                   just console\n\
                 (or: cd console && pnpm build && ../scripts/sync_console_assets.sh)\n\
                 \n\
                 For UI hot-reload during development, use `cd console && pnpm dev`\n\
                 (proxies /api to the broker) instead of rebuilding assets every time.\n\
                 Or build without the UI: cargo build --no-default-features --features ws"
            );
        }
    }
}

fn walkdir_files(dir: &Path) -> Vec<std::path::PathBuf> {
    let mut out = Vec::new();
    let mut stack = vec![dir.to_path_buf()];
    while let Some(cur) = stack.pop() {
        let Ok(rd) = std::fs::read_dir(&cur) else {
            continue;
        };
        for entry in rd.flatten() {
            let path = entry.path();
            if path.is_dir() {
                stack.push(path);
            } else if path.is_file() {
                out.push(path);
            }
        }
    }
    out
}