Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between Cargo's build and rustc commands?

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.

like image 955
Paul Razvan Berg Avatar asked Mar 07 '20 12:03

Paul Razvan Berg


People also ask

What does cargo build do?

Cargo is Rust's build system and package manager. Most Rustaceans use this tool to manage their Rust projects because Cargo handles a lot of tasks for you, such as building your code, downloading the libraries your code depends on, and building those libraries.

What is Rustc compiler?

rustc is the compiler for the Rust programming language, provided by the project itself. Compilers take your source code and produce binary code, either as a library or executable. Most Rust programmers don't invoke rustc directly, but instead do it through Cargo.

What is build script build EXE?

A build script is a file that is started by a build plan. The build script prepares output from generated files.

Where is cargo build output?

Cargo stores the output of a build into the "target" directory. By default, this is the directory named target in the root of your workspace. To change the location, you can set the CARGO_TARGET_DIR environment variable, the build. target-dir config value, or the --target-dir command-line flag.


2 Answers

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.

like image 65
Enselic Avatar answered Oct 22 '22 12:10

Enselic


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.

like image 44
nnnmmm Avatar answered Oct 22 '22 12:10

nnnmmm