Each Rust crate now calls `bn_add_rust_crate` to configure its build,
greatly reducing the amount of boilerplate.
This CMake function discovers dependencies on other crates within the
repository and generates the appropriate CMake dependencies. The build
invocation for crates within the same workspace are combined where
possible (i.e., no custom cargo flags are required) in order to allow
dependencies to be reused and to improve scheduling efficiency.
Static library variants of crates are generated when needed (static-only
targets, or targets that are statically linked for demo builds),
removing the need to maintain custom static variants of crates. Static
libraries are merged into a static umbrella crate to avoid the duplicate
symbol errors related to the Rust standard library that would otherwise
occur when linking multiple static crates into the same binary.