9
votes

I'm new to Rust and I just created a new project via cargo new my_project. I noticed that cargo offers these two command-line options:

  • build: Compile a local package and all of its dependencies
  • rustc: Compile a package and all of its dependencies

I gather that the latter can be used to compile any project on my machine, while the former can only be used within the current working directory. Is that correct? Are there any other differences? Running both commands with no additional arguments gives me the exact same output.

3
Cargo normally doesn't have a rustc command. Did you install a cargo extension?nnnmmm
I only installed cargo-edit.Paul Razvan Berg
I was wrong, there is a cargo rustc command, but it only shows up with cargo --list, not cargo --helpnnnmmm

3 Answers

6
votes

Differences

To get a good grasp of how the commands differ on a high level, we can compare the implementation of the commands. So we'll first clone the cargo repo with

git clone https://github.com/rust-lang/cargo.git

and then compare the implementations of cargo build and cargo rustc with

diff -u -w cargo/src/bin/cargo/commands/build.rs cargo/src/bin/cargo/commands/rustc.rs

From this, it is easy to see that both cargo build and cargo rustc are thin wrappers around this internal cargo function:

pub fn compile<'a>(ws: &Workspace<'a>, options: &CompileOptions) -> CargoResult<Compilation<'a>> {
    // ...
}

but with differences in what kind of options that are exposed. In fact, one can read this comment at the top of cargo_compile.rs that defines that function:

//! This module contains the entry point for starting the compilation process
//! for commands like `build`, `test`, `doc`, `rustc`, etc.

In other words, cargo build and cargo rustc are not the only thin wrappers around the same compilation entry point.

Why have different commands?

So, why would the people behind cargo choose to do this? Why not have a single cargo compile command with tons of flags that fully exposes the underlying implementation?

It clearly must be a matter of organizing things in a way that is both easy to document and understand for various target audiences of the Rust ecosystem.

Most newcomers to the Rust ecosystem is not going to want to be exposed to the possibility of tweaking compiler flags, for example. So it makes sense to only expose them to cargo build and its documentation in the beginning, with its particular flavor of compilation options.

Once they become more advanced users, they'll discover that they can get a lot more detailed influence over the compilation process with cargo rustc.

2
votes

There is no difference with respect to the working directory. The difference is in how you can pass compiler options to rustc, many of which Cargo does not know about/expose:

cargo build [OPTIONS]: If you want to pass a flag to rustc, generally you cannot do that on the command line, you need to use the RUSTFLAGS variable or edit config files.

cargo rustc [OPTIONS] [-- ARGS]: The OPTIONS available are more or less the same as for cargo build, but the args are passed to rustc. So you can for instance write cargo rustc --release -- -C overflow-checks=yes.

0
votes

It was added in this issue and pull request:

As I understood, it was added to be able to pass compiler arguments to build. It is useful for debugging purposes mostly.