- Feature Name:
- Start Date: 2021-10-07
- RFC PR: rust-lang/rfcs#3180
- Tracking Issue: rust-lang/cargo#10083
Add the ability to provide
--crate-type <crate-type> as an argument to
cargo rustc. This would have the same affect of adding
crate-type in the
Cargo.toml, while taking higher priority than any value specified there.
A crate can declare in its
Cargo.toml manifest what sort of sort of compilation artifact to produce. However, there are times when the user of such a crate, as opposed to the author, would want to alter what artifacts are produced.
Some crates may provide both a Rust API and an optional C API. A current example is the hyper crate. Most users of the Rust API only need an
rlib, so forcing the compilation of a
cdylib as well is a waste. It can also cause problems for people including such a crate as a dependency when cross-compiling, or when combining with
-C prefer-dynamic (example).
Another usecase is sharing a library across different platforms (e.g. iOS, Android, WASM). iOS requires static linking (
staticlib) , , Android and WASM require dynamic linking (
cdylib) and in order to use it as a dependency in Rust requires
Lastly, being able to pick a specific crate type also decreases build times when you already know which platform you're targeting.
When a user builds a library, using
cargo rustc, they can provide a
--crate-type argument to adjust the crate type that is compiled. The argument can be any that can also be listed in the
cargo rustc --crate-type staticlib cargo rustc --crate-type cdylib --features ffi
A new command-line argument,
--crate-type, will be added to Cargo. It must be provided a comma-separated list of 1 or more crate types, of which the allowed values are the same as can be provided in the manifest.
The argument will be added for
As with the existing
crate-type manifest property, this will only work when building a
If the manifest contains a list, and this new command-line argument is provided by the user, the command-line argument value will override what is in the manifest. For example:
[lib] crate-type = ["lib", "staticlib", "cdylib"]
cargo rustc --crate-type staticlib
This will produce output only as a
staticlib, ignoring the other values in the manifest.
The usual reasons to not do this apply here:
- An additional feature means more surface area to maintain, and more possibility of bugs.
- The Cargo team is already stretched too thin to ask for another feature. However, in this case, an implementation is already written.
This gives direct control of the compilation to the end user, instead of making them depend on whatever the crate author put in the
An alternative detail to this proposal is to make it so specifying
--crate-type adds to the list in the
Cargo.toml, instead of overriding it. However, there would still be a need for end users to override, so there would need to be an additional argument, such as
--no-default-crate-type. Overriding feels like the less complex solution for a user to comprehend.
The story around compiling Rust for different targets, and especially in ways that are compatible with C, needs to grow stronger. Choosing not to do this would mean this pain point would continue to exist, which hurts the adoption of writing libraries in Rust instead of C.
There are a couple similar-looking features already in cargo:
--target: When building a crate, a user can specify the specific target architecture of the compilation output. When not specified, it defaults to the host architecture.
--features: A user can specify a list of features to enable when building a crate directly with
cargo build. The
Cargo.tomlcan provide a default set of features to compile. This differs from the other art, since specifying
--featureswill add to the default, instead of overriding it.
Should a user be able to configure the crate-type of all crates in the dependency graph?
When this feature was first proposed, it was suggested that a user may wish to configure many dependencies at once, not just the top level crate. This RFC doesn't propose how to solve that, but claims that it can be safely considered out of scope.
First, such a feature is much larger, and there isn't prior art in Cargo to have command-line arguments configuring other dependencies. Designing that would take much more effort. There doesn't seem to be resources available to explore that.
Additionally, the small focus of the feature proposed in this RFC doesn't prevent that larger design from being explored and added at a later point. Figuring out a way to specify configuration arguments for other dependencies would likely need to work for the existing
--features argument. Therefore, this isn't a 1-way-door decision, and thus we don't need to stop fixing this particular pain before that is figured out.
The command-line argument may be useful for other
cargo commands in the future. This RFC starts with a conservative list.
It may also be of interest to allow a crate "feature" enable different crate-types, such as
--features ffi enabling