2
votes

I'm learning rust. As part of the guessing game tutorial, I downloaded the rand crate. I am concerned about dependency confusion, and do not wish to download any more packages than absolutely necessary.

Therefore, I set my Cargo.toml to:

[dependencies]
rand = "=0.5.5"

However, I noticed that 3 different versions of rand_core were downloaded, as well as libc.

    Updating crates.io index
  Downloaded rand_core v0.3.1
  Downloaded rand_core v0.4.2
  Downloaded rand v0.5.5
  Downloaded rand_core v0.2.2
  Downloaded libc v0.2.87
  Downloaded 5 crates (702.2 KB) in 1.17s
   Compiling libc v0.2.87
   Compiling rand_core v0.4.2
   Compiling rand_core v0.3.1
   Compiling rand_core v0.2.2
   Compiling rand v0.5.5
   Compiling guessing_game v0.1.0 (/home/user/projects/learn-rust/guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 26.19s
     Running `target/debug/guessing_game`

I went to the dependencies page for rand 0.5.5 on crates.io, and found that:

  1. rand 0.5.5 depends on
  2. rand_core ^0.2 (I downloaded 0.2.2) depends on
  3. rand_core ^0.3 (I downloaded 0.3.1) depends on
  4. rand_core ^0.4 (I downloaded 0.4.2).

However, no required dependency on libc anywhere.

Why am I downloading libc?

1
I am a little more curious about why the rand needs 3 different versions of rand_core as dependancies. According to the description 3 versions of rand_core are indeed downloaded, but I only find 1 line of ^0.2 rand_core in dependencies page for rand 0.5.5.rustyhu
@rustyhu I was wondering that too, assumed because as per 2nd part of my question, when I went to dependencies page for rand 0.5.5, I found that rand 0.5.5 depends on rand_core ^0.2 (I got 0.2.2) depends on rand_core ^0.3 (I got 0.3.1) depends on rand_core ^0.4 (I got 0.4.2). Which I thought was rather circular, but I assumed (perhaps wrongly) that 0.2 is essentially 0.3 which is essentially 0.4. I suppose instead of keeping old packages up, maybe just rewrite 0.2 to point to 0.3 to point to 0.4? Haven't looked at code so I could be totally wrong about this.faramirInIthilien
@faramirInIthilien see the rand readme "Rand libs have inter-dependencies and make use of the semver trick in order to make traits compatible across crate versions..."kmdreko
See the dependencies for rand 0.2.2 rand 0.3.1 rand 0.4.2faramirInIthilien
@kmdreko ah. that explains everything, thanks so much!faramirInIthilien

1 Answers

5
votes

You can use cargo tree -i <CRATE> to see what is depending on a particular crate:

$ cargo tree -i libc
libc v0.2.87
└── rand v0.5.5
    └── guessing_game v0.1.0 (...)

So it is rand. The dependencies page for rand 0.5.5 indeed says that rand_core is the only required crate, but libc is listed as optional. That means that it is gated by a feature.

You can look at the output of cargo tree -i libc -e features to see the features that are enabled, but its not exactly straightforward since it shows all the features enabled in the rand crate, not just the ones that enable libc.

The only sure-fire way to know is to look at the crate's Cargo.toml:

[features]
default = ["std"]
nightly = ["i128_support"]
std = ["rand_core/std", "alloc", "libc", "winapi", "cloudabi", "fuchsia-zircon"]
alloc = ["rand_core/alloc"]
i128_support = []
serde1 = ["serde", "serde_derive", "rand_core/serde1"]

[dependencies]
rand_core = { path = "rand_core", version = "0.2", default-features = false }
log = { version = "0.4", optional = true }
serde = { version = "1", optional = true }
serde_derive = { version = "1", optional = true }

[target.'cfg(unix)'.dependencies]
libc = { version = "0.2", optional = true }

So libc is both feature- and target-gated. Its only a dependency on unix platforms, and its only used if the "std" feature is enabled, which it is by "default". You can specify default-features = false to opt out of it, however be warned that it will end up disabling most of the crate.