# Cargo
## Resources
## General
### Share test utilities across crates
See this [stack overflow answer](https://stackoverflow.com/a/42329538) for how to do it.
### Can't find `build.rs` artefact after moving repository location
- It seems that `OUT_DIR` (set during compilation) may be using some git references to determine the base path prior to target, e.g. `<base_path>/target/...`.
- I had this problem with the `bitcoind` dev dependency during tests - it's outlined pretty comprehensively in [the issue](https://github.com/RCasatta/bitcoind/issues/77)
- It appears that after a `bitcoind` executable was downloaded, it was 'pinned' to the repo location where it was downloaded. Since clearing all the Rust-related things didn't work, it may have been related to the contents of the `.git` folder
- Solution was just to nuke the repository entirely and reclone from scratch. You lose all your branches and remotes, but oh well.
### Clear the `~/.cargo` caches
Install `cargo cache`
```bash
cargo install cargo-cache
```
Clear the cache
```bash
cargo cache --autoclean
```
### Find unused dependencies with [cargo-udeps](https://github.com/est31/cargo-udeps)
**Install**
```bash
# from crates.io
cargo install cargo-udeps --locked
# from master branch
cargo install --git https://github.com/est31/cargo-udeps --locked
```
**Use**
```bash
cargo +nightly udeps
```
### Run tests in a specific module in a specific crate in a workspace
```bash
cargo test --package runner runner::tests
```
### Show `println!` and `dbg!` even if test doesn't fail
```bash
cargo test -- --nocapture
```
- Note that there is no `-` in `nocapture`
### Resolving strange verbose linker error on [[macOS]]
- e.g. [[2022-06-28 Rust linker error]]
- For me this only occurred for `cargo build --release`; `cargo build` worked fine
- My [[macOS]] was very out of date: I was on version 10.0 (Catalina) while the latest was 12.0 (Monterey). Updating Xcode required me to switch
- Running `cargo clean`, nuking `target/`, updating rust (nightly) version didn't help
![[signal-2022-06-27-224107_001.jpeg]]
![[signal-2022-06-27-224141_001.jpeg]]
**Quick fix:** Add following to `<project-dir>/.cargo/config.toml`
- Source: [This StackOverflow answer](https://stackoverflow.com/a/65698711/2513061)
```toml
[target.x86_64-apple-darwin]
rustflags = [
"-C", "link-arg=-undefined",
"-C", "link-arg=dynamic_lookup",
]
[target.aarch64-apple-darwin]
rustflags = [
"-C", "link-arg=-undefined",
"-C", "link-arg=dynamic_lookup",
]
```
**Longer term solution:** Update Xcode in the App Store (may require uninstall and reinstall)
- From the source above: "Whenever you update the Mac with the new major mac release, usually the XCODE toolchain gets outdated that's the root cause of getting this error. Reinstalling the latest Xcode most of the time fixed the issue."
### Document private items
```bash
cargo doc --document-private-items --open
```
### [Specifying Dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html) (Cargo book)
The string `"0.1.12"` is a version requirement. Although it looks like a specific version of the time crate, it actually specifies a range of versions and allows SemVer compatible updates. **An update is allowed if the new version number does not modify the left-most non-zero digit in the major, minor, patch grouping.**
**Tilde requirements** specify a minimal version with some ability to update. If you specify a major, minor, and patch version or only a major and minor version, only patch-level changes are allowed. If you only specify a major version, then minor- and patch-level changes are allowed.
**Wildcard requirements** allow for any version where the wildcard is positioned.
- To always be able to update to the latest versions (e.g. in an application, use `"*"`. This is not allowed for libraries on crates.io, however.)
### Update Cargo.lock dependencies
```bash
# Update all
cargo update
# Update specific crate
cargo update -p ftx
```
### Check that build succeeds with a specific (usually older) Rust version
```bash
cargo +1.41.1 check
```
### [Show the packages that depend on the given package](https://doc.rust-lang.org/cargo/commands/cargo-tree.html#tree-options)
Show the reverse dependencies for the given package. This flag will invert the tree and display the packages that depend on the given package.
```bash
cargo tree --invert <crate>
```
### See current system info
```bash
rustc -vV
rustc 1.62.0-nightly (ec77f2524 2022-04-17)
binary: rustc
commit-hash: ec77f252434a532fdb5699ae4f21a3072d211edd
commit-date: 2022-04-17
host: x86_64-apple-darwin
release: 1.62.0-nightly
LLVM version: 14.0.0
```
### (Repo) [cargo-deny](https://crates.io/crates/cargo-deny)
## Information
### Cargo.toml.vs Cargo.lock > [Why do binaries have Cargo.lock in version control, but not libraries?](https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries)
The purpose of a `Cargo.lock` lockfile is to describe the state of the world at the time of a successful build. Cargo uses the lockfile to provide deterministic builds on different times and different systems, by ensuring that the exact same dependencies and versions are used as when the `Cargo.lock` file was originally generated.
This property is most desirable from applications and packages which are at the very end of the dependency chain (binaries). As a result, it is recommended that all binaries check in their `Cargo.lock`.
For libraries the situation is somewhat different. A library is not only used by the library developers, but also any downstream consumers of the library. Users dependent on the library will not inspect the library’s `Cargo.lock` (even if it exists). This is precisely because a library should **not** be deterministically recompiled for all users of the library.
If a library ends up being used transitively by several dependencies, it’s likely that just a single copy of the library is desired (based on semver compatibility). If Cargo used all of the dependencies' `Cargo.lock` files, then multiple copies of the library could be used, and perhaps even a version conflict.
In other words, libraries specify SemVer requirements for their dependencies but cannot see the full picture. Only end products like binaries have a full picture to decide what versions of dependencies should be used.
## Troubleshooting
### If waiting for file lock on build directory...
![[Screen Shot 2021-09-08 at 9.20.22 PM.png]]
- I found that [[rust-analyzer]] was the culprit
```bash
$ ps | rg analyzer
33214 ttys000 2:36.88 rust-analyzer
33314 ttys000 0:03.53 /usr/local/bin/rust-analyzer proc-macro
40085 ttys012 0:00.00 rg analyzer
```
Killing `33214` and `33314` worked.