[workspace] # Keep source-only members discoverable in Maturin's dependency-pruned archive, # including the separately packaged UniFFI generator. members = ["demo/carla/bridge", "rs/*", "rs/kio/macros", "rs/moq-mux/fuzz", "rs/moq-net/fuzz", "rs/moq-quic/fuzz", "rs/moq-rtmp/fuzz"] default-members = [ "rs/bench-harness", "rs/kio", "rs/kio/macros", "rs/hang", # "rs/moq-c", # requires C toolchain "rs/moq-congestion", "rs/moq-archive", "rs/moq-auth", "rs/moq-boy", "rs/moq-audio", "rs/moq-bench", "rs/moq-cli", "rs/moq-crypto", # "rs/moq-ffi", # requires Python/maturin # "rs/moq-gst", # requires GStreamer "rs/moq-hls", "rs/moq-json", "rs/moq-loc", "rs/moq-msf", "rs/moq-net", "rs/moq-net-tests", "rs/moq-mux", "rs/moq-native", "rs/moq-nvenc", "rs/moq-pattern", "rs/moq-quic", "rs/moq-relay", "rs/moq-room", "rs/moq-rtmp", "rs/moq-rtsp", "rs/moq-shaper", "rs/moq-sock", "rs/moq-srt", "rs/moq-stats", "rs/moq-tokio", "rs/moq-transcode", "rs/moq-uring", "rs/moq-v4l", "rs/moq-vaapi", "rs/moq-video", "rs/moq-webrtc", "rs/qmux", "rs/test-env", # Maturin runs the workspace's `uniffi-bindgen` binary from the root to # generate the Python wheel, and that only searches default members. Its # `cli` feature keeps a plain check from compiling the generator. "rs/uniffi-bindgen", ] resolver = "2" [workspace.package] # Floor for the library surface: usage-rs 7.1 (via moq-tokio) needs 1.91. This is # what consumers of moq-net / hang / moq-tokio / etc. see. moq-relay overrides # it to 1.95 (sysinfo 0.39), and moq-cli does too because it depends on that # library. Those crates are applications; the point of the per-crate override # is to keep the bump off the libraries others actually build on. The nix flake # / rust-toolchain.toml pin the build toolchain to a fixed version rather than # latest stable, which keeps the relay's ceiling from creeping up unnoticed. # That pin sits above every MSRV here; rust-toolchain.toml says why. rust-version = "1.91" [workspace.lints.clippy] # Every suppression says why, so the next lint audit can judge it. allow_attributes_without_reason = "warn" [workspace.dependencies] aes = "0.9" anyhow = "1" arrayvec = "0.7.6" ash = "0.38" async-trait = "0.1" # Keep axum's defaults except tower-log, which enables tracing-to-log macros workspace-wide. axum = { version = "0.8", default-features = false, features = [ "form", "http1", "json", "matched-path", "original-uri", "query", "tokio", "tracing", ] } # Features off so each consumer picks its rustls provider. axum-server = "0.8" base64 = "0.23" base64ct = "1" bitflags = "2" # MSB-first bit reading for codec configs; the version h264-reader builds on. bitstream-io = "4.10" block2 = "0.6.2" bytes = "1" ccm = { version = "0.6", default-features = false } clap = { version = "4", features = ["derive"] } combine = "4.6.6" crc = "3" # CUDA driver bindings for the NVENC/NVDEC path. dlopen'd at runtime # (`fallback-dynamic-loading`), so nothing links against libcuda at build time. cudarc = { version = "0.19", default-features = false, features = ["driver", "fallback-dynamic-loading", "cuda-12020"] } data-encoding = "2.11" dispatch2 = "0.3.1" ebml-iterable = "0.7.1" fastrand = "2" flate2 = { version = "1.1", default-features = false } futures = "0.3" h2 = "0.4" hang = { version = "0.21.11", path = "rs/hang" } hashbrown = { version = "0.17.1", default-features = false } hashlink = "0.12.2" hex = "0.4" http-body = "1.0.1" httparse = "1.10" humantime = "2.3" humantime-serde = "1.1.1" hyper = "1.11" hyper-util = { version = "0.1.21", features = ["tokio"] } # Interface addresses for WebRTC host candidates (moq-webrtc's `p2p` feature). if-addrs = "0.15" indexmap = "2.14.2" io-uring = "0.7.15" jni = "0.22" jsonwebtoken = "11" kio = { version = "0.6.2", path = "rs/kio" } kio-macros = { version = "0.1.0", path = "rs/kio/macros" } libc = "0.2" libloading = "0.9" linux-raw-sys = { version = "0.12.1", features = ["ioctl"] } # DNS-SD advertisement and browsing for LAN peer discovery (moq-tokio's `mdns` feature), # and `.local` candidate resolution (moq-webrtc's `p2p` feature). # `async` awaits the event channel instead of blocking a thread on it. mdns-sd = { version = "0.21", features = ["async"] } moq-archive = { version = "0.0.11", path = "rs/moq-archive" } moq-audio = { version = "0.1.10", path = "rs/moq-audio", default-features = false } moq-auth = { version = "0.2.1", path = "rs/moq-auth" } moq-congestion = { version = "0.1.0", path = "rs/moq-congestion" } # default-features off: moq-auth takes only the endpoint key and its text codec. moq-crypto = { version = "0.0.11", path = "rs/moq-crypto", default-features = false } moq-hls = { version = "0.5.11", path = "rs/moq-hls", default-features = false } moq-json = { version = "0.5.8", path = "rs/moq-json" } moq-loc = { version = "0.2.19", path = "rs/moq-loc" } moq-msf = { version = "0.5.1", path = "rs/moq-msf" } moq-mux = { version = "0.10.11", path = "rs/moq-mux" } moq-net = { version = "0.3.10", path = "rs/moq-net" } # NVENC bindings, forked from ViliamVadocz/nvidia-video-codec-sdk to dlopen the # driver at runtime. Compiles on any platform (macOS included) but only actually # used by moq-video on Linux. moq-nvenc = { version = "0.1.2", path = "rs/moq-nvenc" } moq-pattern = { version = "0.1.2", path = "rs/moq-pattern" } # default-features off so each consumer picks its crypto provider. moq-quic = { version = "0.1.0", path = "rs/moq-quic", default-features = false } moq-relay = { version = "0.17.2", path = "rs/moq-relay", default-features = false } moq-rtmp = { version = "0.3.11", path = "rs/moq-rtmp" } moq-rtsp = { version = "0.1.0", path = "rs/moq-rtsp" } moq-sock = { version = "0.2.0", path = "rs/moq-sock" } moq-srt = { version = "0.3.11", path = "rs/moq-srt" } moq-stats = { version = "0.2.12", path = "rs/moq-stats" } moq-tokio = { version = "0.19.23", path = "rs/moq-tokio", default-features = false } # Default features off on moq-transcode and moq-video so each workspace consumer # chooses native codecs and rendering explicitly. OpenH264 is opt-in everywhere: # each consumer forwards an `openh264` feature that release builds turn on. # NVIDIA and VAAPI dlopen their drivers and need nothing on the build host, so # the consumers that build video turn both on. moq-transcode = { version = "0.1.10", path = "rs/moq-transcode", default-features = false } # default-features off (the `quic` backend) so the consumer opts into the QUIC # stack the io_uring path compiles; cargo features are additive, so a default-on # backend could not be opted out of. moq-uring = { version = "0.0.12", path = "rs/moq-uring", default-features = false } # In-tree fork of `v4l` with the videodev2.h bindings checked in, so moq-video's # `capture` and `v4l2` need no libclang or kernel headers. Linux only; an empty # stub elsewhere. moq-v4l = { version = "0.1.0", path = "rs/moq-v4l" } # In-tree fork of cros-libva + cros-codecs with the libva bindings checked in. # dlopen's libva at runtime (no libva-dev at build, no NEEDED libva in the binary). moq-vaapi = { version = "0.2.1", path = "rs/moq-vaapi" } # `default-features = false` is here for `capture` (V4L2, libclang), which the # cross-compiled Python, Swift, Kotlin, and Go builds have no use for: adding # `features = ["capture"]` to a consumer that ships in those bindings pulls the # whole device graph into every one of them. Codec features are independent of # that argument, so moq-ffi and moq-c opt NVIDIA and VAAPI back in (OpenH264 # through their own `openh264` feature, which release builds enable). moq-video = { version = "0.1.10", path = "rs/moq-video", default-features = false } moq-webrtc = { version = "0.3.12", path = "rs/moq-webrtc" } mp4-atom = "0.17.1" nix = { version = "0.31.3", features = ["net", "socket", "uio"] } nom = { version = "8", default-features = false, features = ["std"] } num_enum = "0.7" objc2 = "0.6.4" objc2-av-foundation = "0.3.2" objc2-core-media = "0.3.2" objc2-foundation = "0.3.2" objc2-screen-capture-kit = "0.3.2" # Default features off so a consumer that only needs InMemory does not pull the # local-filesystem stack; `fs` (and cloud backends) are opted in by the caller. object_store = { version = "0.14", default-features = false } once_cell = "1.21.3" pcap-file = "2" pem = "4.0.0" percent-encoding = "2" pkcs1 = { version = "0.7.5", features = ["alloc"] } pkcs8 = "0.11.0" pollster = "1.0" # default-features off to skip the fork and timeout machinery; crates opt into what they use. proptest = { version = "1.12.0", default-features = false, features = ["std"] } qmux = { version = "0.7.0", path = "rs/qmux", default-features = false } rand = "0.10.1" rand_pcg = "0.10" rangemap = "1.8" # default-features off so each consumer picks its crypto provider. rcgen = { version = "0.14", default-features = false } # default-features off so each consumer picks its own TLS backend and body # features; nothing here wants the default native-tls stack. reqwest = { version = "0.13", default-features = false } rind = { version = "0.3.1", features = ["wipe"] } rind-jsonwebtoken = "11.0.2" rind-object-store = "0.14.2" rind-rcgen = "0.14.2" rind-rustls = "0.23.2" rustc-hash = "2.1.3" rustls-native-certs = "0.8.5" sd-notify = "0.5" send_wrapper = "0.6" serde = { version = "1", features = ["derive"] } serde_json = "1" serde_with = "3" slab = "0.4.12" socket2 = "0.6" spki = "0.8" stun-types = "2.0.3" subtle = "2.6" tempfile = "3" thiserror = "2" time = "0.3" tokio = "1.48" tokio-rustls = { version = "0.26", default-features = false } tokio-tungstenite = { version = "0.30", default-features = false } tokio-util = "0.7" toml = "1.1" tower-http = { version = "0.7", features = ["cors"] } tracing = "0.1" tracing-subscriber = "0.3" tracing-test = "0.2" # Runtime used by the published moq-ffi crate. The unpublished bindgen CLI # carries generator-only patches against this release in its own manifest. uniffi = "0.32" url = "2" usage-rs = "7.3.0" uuid = { version = "1.26", features = ["v7"] } web-transport-proto = "0.6.4" web-transport-trait = "0.5" wgpu = "30" x11rb = { version = "0.14.0", features = ["randr", "xfixes"] } x509-cert = { version = "0.3", default-features = false } x509-parser = "0.18" zeroize = { version = "1", features = ["derive"] } [profile.dev] # Full DWARF is what makes a debug build enormous: the debug `libmoq_ffi.a` # measured 619 MiB against a 100 MiB ceiling for the published one, and a # workspace of those fills a laptop (and a CI runner) fast. Line tables keep # what we actually read -- file and line in every backtrace and panic -- and # drop the variable and type records only an interactive debugger uses. Reach # for `debug = true` in a temporary edit if you need to step through something # in lldb. `profile.test` inherits this. debug = "line-tables-only" # Optimize the sonora echo canceller even in dev/test builds. Its hot loops # are `core::arch` NEON/SSE intrinsics, which at opt-level 0 compile to out-of-line calls carrying the # debug UB preconditions of `read_unaligned` and `copy_nonoverlapping`: a # profile of `aec::tests::survives_a_moving_echo_delay` spends 65% of its # samples in those checks and intrinsic shims and only 20% in sonora's own # arithmetic. Unoptimized, cancelling 15 seconds of audio costs 12 seconds of # CPU, which is slower than the realtime callback this runs in and leaves the # test no headroom under the nextest timeout. [profile.dev.package.sonora] opt-level = 3 [profile.dev.package.sonora-aec3] opt-level = 3 [profile.dev.package.sonora-agc2] opt-level = 3 [profile.dev.package.sonora-common-audio] opt-level = 3 [profile.dev.package.sonora-fft] opt-level = 3 [profile.dev.package.sonora-ns] opt-level = 3 [profile.dev.package.sonora-simd] opt-level = 3 # Same for the rubato resampler, whose SIMD intrinsics are all of # `resample::tests::duration_and_samples_are_invariant_across_partitions_and_epochs`: # 0.9 CPU-seconds unoptimized, 0.14 optimized. [profile.dev.package.rubato] opt-level = 3 # The Go mirror stores native staticlibs in Git, whose per-file limit is 100 MB. # Keep all release entry points on the same compact native profile. [profile.release] lto = "fat" codegen-units = 1 strip = "symbols" # UniFFI reads ELF's regular symbol table to generate bindings, including in # maturin and downstream generators. Remove debug data but retain that metadata. [profile.release.package.moq-ffi] strip = "debuginfo" [profile.profiling] inherits = "release" debug = "line-tables-only" strip = "none" # frame pointers: pass RUSTFLAGS="-C force-frame-pointers=yes" when building # Package overrides are inherited too and take precedence over the profile. [profile.profiling.package.moq-ffi] strip = "none" [profile.release-with-debug] inherits = "release" debug = true strip = "none" [profile.release-with-debug.package.moq-ffi] strip = "none"