At the highest level, there is the crate. The Rust distribution contains a number of crates, such as the std crate of the standard library, which we have already used often. Other built-in crates include the collections crate, with functionality to work with strings, vectors, linked lists, and key-value maps, and the test or rustc-test crates, with unit-testing and micro-benchmarking functionality.
A crate is the equivalent of a package or library in other languages. It is also the unit of compilation: rustc only compiles one crate at a time. What does this mean? When our project has a code file containing a main() function, then it is clear that our project is an executable program (also called a binary), starting execution in main(). For example, if we compile structs.rs as follows:
rustc structs.rs
A .exe file, structs.exe, is produced in Windows, which can be executed on its own (and equivalent structs executables on other operating systems). This is the standard behavior when invoking rustc. When working with Cargo (see Chapter 1, Starting with Rust) we have to indicate that we want a binary project at its creation with the --bin flag:
cargo new projname --bin
However, often you want to write a project whose code will be called from other projects, a so-called shared library (in Windows this is a .dll file, in Linux an .so file, and on OSX a .dylib file). In that case, your code will only contain data structures and functions to work on them, so you must explicitly indicate this to the compiler using the --crate-type flag with the lib option:
rustc --crate-type=lib structs.rs
The resulting file is far smaller in size and is called libstructs.rlib; the suffix is now .rlib (for Rust library) and lib is prepended before the filename. If you want the crate to have another name, like mycrate, then use the --crate-name flag as follows:
rustc --crate-type=lib --crate-name=mycrate structs.rs
This creates a libmycrate.rlib as the output file.
An alternative to using the rustc flags is to put this info as the attributes at the top of the code file, like this:
// from Chapter 8/code/structs.rs #![crate_type = "lib"] #![crate_name = "mycrate"]
The crate_type attribute can take the following values: bin, lib, rlib, dylib, and staticlib, according to whether you want a binary executable or a library of a certain type, dynamically or statically linked (in general when an attr attribute applies to a whole crate, the syntax to use in code is #![crate_attr]).
Each library used in an application is a separate crate. In any case, you need an executable (binary) crate that uses the library crates.
Rust has a built-in library manager called Cargo (for more info on Cargo, see Chapter 1, Starting with Rust, and the Working with Cargo section); it creates a library project by default. Typically, when starting your own project, you would create it with Cargo, use the code organization techniques you will learn in this chapter, and then make this code into an executable with:
cargo build
You can install other crates into your project from the crates repository https://crates.io; in the Adding external crates to a project section, we see how this is done.