Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Out of source builds (external build directory) with Cargo?

Having used CMake, I've become used to out-of-source builds, which are encouraged with CMake. How can out-of-source builds be done with Cargo?


Using in-source-builds again feels like a step backwards:

  • Development tools need to be configured to ignore paths. Sometimes multiple plugins and development tools - especially using VIM or Emacs!
  • Some tools can't be configured to easily hide build files. While dotfiles are typically hidden, they will still show Cargo.lock and target/, worse still, recursively exposing their contents.
  • Deleting un-tracked files to remove everything outside of version control, typically to cleanup editor temp files or some test output, can backfire if you forgot to add a new file to version control and don't manually check the file list properly before deleting them.
  • Dependencies are downloaded into your source code path, sometimes adding *.rs files in the target directory as part of building indirect deps, so operating on all *.rs files may accidentally pickup other files which aren't in a hidden directory, so might not be ignored even after development tools have been configured.

While it's possible to work around all these issues, I'd rather just have an external build path and keep the source directory pristine.

like image 486
ideasman42 Avatar asked Dec 22 '16 02:12

ideasman42


People also ask

Where does cargo build output to?

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.

Where is binary cargo build?

💡 When we build a binary crate via cargo build or cargo run , the executable file will be stored in the target/debug/ folder.


2 Answers

You can specify the directory of the target/ folder either via configuration file (key build.target-dir) or environment variable (CARGO_TARGET_DIR). Here is an example using a configuration file:

Suppose you want to have a directory ~/work/ in which you want to save the Cargo project (~/work/foo/) and next to it the target directory (~/work/my-target/).

$ cd ~/work
$ cargo new --bin foo
$ mkdir .cargo
$ $EDITOR .cargo/config

Then insert the following into the configuration file:

[build]
target-dir = "./my-target"

If you then build in your normal Cargo project directory:

$ cd foo
$ cargo build

You will notice that there is no target/ dir, but everything is in ~/work/my-target/.


However, the Cargo.lock is still saved inside the Cargo project directory, but that kinda makes sense. For executables, you should check the Cargo.lock file into your git! For libraries, you shouldn't. I guess having to ignore one file is better than having to ignore an entire folder.

Lastly, there are a few caveats to changing the target-dir, which are listed in the PR which introduced the feature.

like image 80
Lukas Kalbertodt Avatar answered Sep 22 '22 06:09

Lukas Kalbertodt


While useful manually setting this up isn't all that convenient, I wanted to be able to build multiple crates within a source tree, having all of them out-of-source, something that ../target-dir configuration option wouldn't achieve.


Helper utility for convenient out-of-source builds

Using the environment variable I've written a small utility to wrap cargo, so it automatically builds out-of-source, supporting crates both at the top-level, on in a subdirectory of the source tree.


Thanks to Lukas for pointing out CARGO_TARGET_DIR and target-dir configuration option.

like image 39
ideasman42 Avatar answered Sep 20 '22 06:09

ideasman42