Suppose there is a requirement that the Rust binary compiled in a fedora high version (2.34) glibc environment should be used in the customer’s centos7 glibc 2.17 environment, because the files compiled by the high version glibc will not work in the low version glibc environment

A possible solution is that the musl-gcc/musl-clang compiler makes the binary not strongly dependent on the glibc version, e.g. TabNine’s binary on Linux is musl’s

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ cargo b -p common --target x86_64-unknown-linux-musl
...
 $HOST = x86_64-unknown-linux-gnu
  $TARGET = x86_64-unknown-linux-musl
  openssl-sys = 0.9.72

  ', /home/w/.cargo/registry/src/rsproxy.cn-8f6827c7555bfaf8/openssl-sys-0.9.72/build/find_normal.rs:180:5
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed

Using musl as a compilation target is prone to the above-mentioned openssl-sys problem, and the usual solution is to switch to rust-tls.

But how to know which libraries in the project depend on openssl ?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ cargo tree | grep -B5 openssl
│   │   ├── nom_pem v4.0.0
│   │   │   └── nom v4.2.3
│   │   │       └── memchr v2.4.1
│   │   │       [build-dependencies]
│   │   │       └── version_check v0.1.5
│   │   ├── openssl v0.10.38
--
│   │   │   ├── cfg-if v1.0.0
│   │   │   ├── foreign-types v0.3.2
│   │   │   │   └── foreign-types-shared v0.1.1
│   │   │   ├── libc v0.2.112
│   │   │   ├── once_cell v1.9.0
│   │   │   └── openssl-sys v0.9.72
--
    │   ├── hyper-tls v0.5.0
    │   │   ├── bytes v1.1.0
    │   │   ├── hyper v0.14.16 (*)
    │   │   ├── native-tls v0.2.8
    │   │   │   ├── log v0.4.14 (*)
    │   │   │   ├── openssl v0.10.38 (*)
    │   │   │   ├── openssl-probe v0.1.4
    │   │   │   └── openssl-sys v0.9.72 (*)

It’s hard to find the “root” of openssl with grep -B5, so you might need to adjust -B5 to -B25 and still not see the root node…

So could you turn the tree “upside down” and treat openssl as the root node? That way the leaf nodes are the dependencies introduced by the project Cargo.toml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$ cargo tree --invert --package openssl-sys
openssl-sys v0.9.72
├── native-tls v0.2.8
│   ├── hyper-tls v0.5.0
│   │   └── reqwest v0.11.7
│   │       └── web v0.1.0 (/home/w/repos/haizhi/atlas/src/web)
│   │           └── server v0.1.0 (/home/w/repos/haizhi/atlas/src/server)
│   │       [dev-dependencies]
│   │       └── web v0.1.0 (/home/w/repos/haizhi/atlas/src/web) (*)
│   ├── reqwest v0.11.7 (*)
│   └── tokio-native-tls v0.3.0
│       ├── hyper-tls v0.5.0 (*)
│       └── reqwest v0.11.7 (*)
└── openssl v0.10.38
    ├── native-tls v0.2.8 (*)
    └── osshkeys v0.5.2
        ├── common v0.1.0 (/home/w/repos/haizhi/atlas/src/common)
...

This way, you can immediately find openssl dependencies in Cargo.toml for web and common

Later, if cargo audit finds a vulnerability in chrono, for example, you can also use cargo tree -p chrono –reverse to quickly locate which libraries in the project depend on chrono