Reputation: 381
I am a bit confused by the existence of the three upper levels in the Rust module hierarchy and why they are all needed. If I understand it correctly:
I understand the need to keep several crates together if they are being developed together, so either packages or workspaces make sense to me, but I don't get why both need to exist and why there would need to be a maximum of 1 library restriction on packages. What are the advantages of doing it this way?
I have read Why can a Cargo package only have one library target? that gives an explanation for the 1 library crate per package rule, but it made me more confused, because you can still have packages with binaries and even "worse" no libraries. If packages are meant to be an abstraction for Cargo, the package manager, why allow binaries in them at all? Why allow packages without a single library inside? Can you import a no-library-package as a dependency?
Upvotes: 22
Views: 3120
Reputation: 37
In my opinion, the reason that Rust designed packages and workspaces is to facilite various project organization and development needs.
For exemple, the Crate documents; This is Rust's fundamental compilation unit. A crate can be either a library or a binary application. Its modularity allows for easy code reuse across different projects.
And the Package, which is the primary management unit for Cargo can encompass multiple crates, it's restricted to just one library-type crate. This is because the library crate sets out the public interface of the package, with binary crates being applications that leverage this interface. This constraint streamlines dependency management and version control.
Further more, Workspace provides us a better chance for managing multiple packages concurrently in a unified setting, proving beneficial for large-scale projects or those made up of several interdependent packages.
The reason why some packages might only contain binaries and not libraries, may be is that not all Rust projects are intended to be libraries. Some are straightforward tools or applications that don't require a public library interface. It's also feasible to have packages devoid of libraries, consisting only of binary crates. Although such packages aren't typically used as dependencies, they can still be managed and distributed via Cargo.
Upvotes: 1
Reputation: 381
Crates:
They're the unit of compilation in Rust.
A crate can be a binary (executable) or a library.
Each crate has its own module hierarchy, and the top-most level is the crate root.
Packages:
A package contains one or more crates.
While a package can contain multiple binary crates, it can contain at most one library crate. This is because Cargo, Rust's package manager, uses the package name as the library name when you're importing it as a dependency in another project. Having multiple libraries in a single package would be ambiguous.
Workspaces:
A workspace allows you to group multiple packages together.
This is useful when you're working on multiple interdependent packages, and you want them to share the same Cargo.lock file and target directory.
Now, to address some of your specific questions:
Why there would need to be a maximum of 1 library restriction on packages?
When another package depends on a package, it specifies the package by name. In the Rust ecosystem, this name implies the name of the library crate contained within the package. If there were multiple libraries within a package, it would introduce ambiguity in terms of which library is being referred to. It's about ensuring clarity and simplicity in the dependency system.
If packages are meant to be an abstraction for Cargo, the package manager, why allow binaries in them at all? Why allow packages without a single library inside?
Packages are not exclusively an abstraction for libraries; they are an abstraction for distributing Rust code. Sometimes, this code might be a utility that's intended to be used as a command-line tool rather than a library. So, a package might contain binaries and no libraries. Conversely, a package might contain a library to be used as a dependency in other projects.
Can you import a no-library-package as a dependency?
If a package doesn't contain a library, it cannot be used as a dependency in the same way that you would use a library. But you could still list it as a dependency to ensure that it's built or to make use of any binaries it provides. This is, however, less common.
In summary, these levels of abstraction in the Rust ecosystem allow for flexibility in organizing, distributing, and building Rust code while maintaining clarity in terms of dependencies and package management.
Upvotes: 6
Reputation: 21
I've only just started with Rust, but as I see it a package with a library and binaries is basically just that a function specific library with tools (binaries), tools specific to that library.
Example - A 3D library for a game
Users of the library would be able to use the tools to for example create content, without having to pass on the tools to the end-user.
Upvotes: -1