Best practice for a crate that can produce multiple artifacts?

I'm working on an allocator that can produce three artifacts: a Rust crate that provides an implementation of the Alloc trait, a Rust crate that provides a global Rust allocator, and a C shared library that implements the C allocation API (malloc, free, etc).

Right now, I have split this project up by having one crate that serves the first two functions and a second crate that wraps the first in order to produce the C shared library. Is this the best way of doing it, or should I instead have a single crate that can produce all three artifact types depending on what features are used?

Separate crates are fine IMHO.

With Cargo workspaces and usage of path in dependencies you can keep them all together as one project.

OK sounds good. Thanks!