首页 > 解决方案 > 由于对 gcry-* 符号的许多未定义引用,无法链接 git2-rs

问题描述

环境

 $ cargo --version
cargo 1.41.0 (626f0f40e 2019-12-03)

 $ rustc --version
rustc 1.41.0 (5e1a79984 2020-01-27)

我做了什么

$ cargo new xxx
     Created binary (application) `xxx` package

我编辑Cargo.toml成这样:

[package]
  name = "xxx"
  version = "0.1.0"
  authors = ["Martin Marconcini <xxx@xxx.com>"]
  edition = "2018"

 [dependencies]
 git2 = "0.12.0"

并且main.rs

use git2::Repository;

fn main() {
    println!("Hello, world!");

    let repo = match Repository::open("fake/path") {
        Ok(repo) => repo,
        Err(e) => panic!("Failed to init {}", e),
    };
}

问题

我知道fake/path这行不通,但我希望程序在运行时能够构建、链接和恐慌。相反,当我进行货物运行时,这是我得到的:

 $ cargo run
    Updating crates.io index
   Compiling libc v0.2.67
   Compiling pkg-config v0.3.17
   Compiling autocfg v1.0.0
   Compiling smallvec v1.2.0
   Compiling matches v0.1.8
   Compiling bitflags v1.2.1
   Compiling log v0.4.8
   Compiling cfg-if v0.1.10
   Compiling percent-encoding v2.1.0
   Compiling openssl-probe v0.1.2
   Compiling unicode-bidi v0.3.4
   Compiling unicode-normalization v0.1.12
   Compiling jobserver v0.1.21
   Compiling idna v0.2.0
   Compiling cc v1.0.50
   Compiling url v2.1.1
   Compiling libz-sys v1.0.25
   Compiling openssl-sys v0.9.54
   Compiling libssh2-sys v0.2.16
   Compiling libgit2-sys v0.11.0+0.99.0
   Compiling git2 v0.12.0
   Compiling xxx v0.1.0 (/home/martin/dev/rust/xxx)
warning: unused variable: `repo`
 --> src/main.rs:6:9
  |
6 |     let repo = match Repository::open("/fake/path") {
  |         ^^^^ help: consider prefixing with an underscore: `_repo`
  |
  = note: `#[warn(unused_variables)]` on by default

error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.1g3apxivazecmby1.rcgu.o" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.1ktaa7mhzl12qb8s.rcgu.o" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.1of15nz9rghhwcp.rcgu.o" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.1pzhxyvu6x3rpyd4.rcgu.o" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.1xjrgwir8ul0gxyn.rcgu.o" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.236nnnkop2p1q7o.rcgu.o" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.346upd227a1u5o1x.rcgu.o" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.4vpli3o8gp9bo7bb.rcgu.o" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.fjvxd6ccfznqzmo.rcgu.o" "-o" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620" "/home/martin/dev/rust/xxx/target/debug/deps/xxx-fe6ac189d82a9620.2bpv5j881nolkdhg.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/home/martin/dev/rust/xxx/target/debug/deps" "-L" "/home/martin/dev/rust/xxx/target/debug/build/libgit2-sys-9a380c1f1af1ff52/out/build" "-L" "/usr/lib/x86_64-linux-gnu" "-L" "/home/martin/dev/rust/xxx/target/debug/build/libssh2-sys-76c9f6db4b487643/out/build" "-L" "/usr/lib/x86_64-linux-gnu" "-L" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/martin/dev/rust/xxx/target/debug/deps/libgit2-e4070b896a12b23e.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libopenssl_probe-02ad0051245c142f.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/liburl-752d8a16592303c8.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libpercent_encoding-3f375297ed36a953.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libidna-a849b89d54cc2589.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libunicode_normalization-81788f9135a21d94.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libsmallvec-e36b82e338fe18d3.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libunicode_bidi-901a064d2af6777d.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libmatches-ccee7833d11c4363.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/liblog-aba47d2dbe489265.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libcfg_if-fd0f59c38961bb3a.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/liblibgit2_sys-b077f325e2a7224c.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libopenssl_sys-b21cd1cefc781387.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/liblibz_sys-c72b1cae7b178c73.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/liblibc-a68ece9bb60c0ea2.rlib" "/home/martin/dev/rust/xxx/target/debug/deps/libbitflags-468acf5fe2f3e68a.rlib" "-Wl,--start-group" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-9d59e25e2eb2384d.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-4affccee0db9d60e.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-cd6b495608e342d1.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-347d88a586b28b4c.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace-46f3dc0b263b900a.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace_sys-6789aa6fbcfdf14c.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-9f9436f1ab051941.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-ad8ec269e6d86d01.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-3699f95d33475c27.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-fe798441633702e1.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-979288990efe6065.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-2181f1e1dd7399d7.rlib" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-b8952fd765001238.rlib" "-Wl,--end-group" "/home/martin/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-e99fedbd2b621435.rlib" "-Wl,-Bdynamic" "-lz" "-lssl" "-lcrypto" "-lz" "-lutil" "-ldl" "-lutil" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: /usr/bin/ld: /home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib(libgcrypt.o): in function `_libssh2_rsa_new':
          (.text+0x48): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: (.text+0x77): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: /home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib(libgcrypt.o): in function `_libssh2_rsa_sha1_verify':
          (.text+0xcb): undefined reference to `gcry_md_hash_buffer'
          /usr/bin/ld: (.text+0xe8): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: (.text+0x103): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: (.text+0x118): undefined reference to `gcry_pk_verify'
          /usr/bin/ld: (.text+0x123): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: (.text+0x12d): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: (.text+0x166): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: /home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib(libgcrypt.o): in function `_libssh2_dsa_new':
          (.text+0x1cc): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: (.text+0x203): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: /home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib(libgcrypt.o): in function `_libssh2_rsa_sha1_sign':
          (.text+0x73f): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: (.text+0x757): undefined reference to `gcry_pk_sign'
          /usr/bin/ld: (.text+0x763): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: (.text+0x77d): undefined reference to `gcry_sexp_find_token'
          /usr/bin/ld: (.text+0x79d): undefined reference to `gcry_sexp_nth_data'
          /usr/bin/ld: /home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib(libgcrypt.o): in function `_libssh2_dsa_sha1_sign':
          (.text+0x87c): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: (.text+0x896): undefined reference to `gcry_pk_sign'
          /usr/bin/ld: (.text+0x8a2): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: (.text+0x8d0): undefined reference to `gcry_sexp_find_token'
          /usr/bin/ld: (.text+0x8f3): undefined reference to `gcry_sexp_nth_data'
          /usr/bin/ld: (.text+0x937): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: (.text+0x946): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: (.text+0x985): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: (.text+0x998): undefined reference to `gcry_sexp_find_token'
          /usr/bin/ld: (.text+0x9b2): undefined reference to `gcry_sexp_nth_data'
          /usr/bin/ld: /home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib(libgcrypt.o): in function `_libssh2_dsa_sha1_verify':
          (.text+0xa62): undefined reference to `gcry_md_hash_buffer'
          /usr/bin/ld: (.text+0xa84): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: (.text+0xab2): undefined reference to `gcry_sexp_build'
          /usr/bin/ld: (.text+0xac9): undefined reference to `gcry_pk_verify'
          /usr/bin/ld: (.text+0xad4): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: (.text+0xade): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: (.text+0xb16): undefined reference to `gcry_sexp_release'
          /usr/bin/ld: /home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib(libgcrypt.o): in function `_libssh2_cipher_init':
          (.text+0xb5a): undefined reference to `gcry_cipher_get_algo_keylen'
          /usr/bin/ld: (.text+0xb6c): undefined reference to `gcry_cipher_open'
          /usr/bin/ld: (.text+0xb7f): undefined reference to `gcry_cipher_setkey'
          /usr/bin/ld: (.text+0xba4): undefined reference to `gcry_cipher_get_algo_blklen'
          /usr/bin/ld: (.text+0xbb8): undefined reference to `gcry_cipher_setiv'
          /usr/bin/ld: (.text+0xbc5): undefined reference to `gcry_cipher_close'
          /usr/bin/ld: (.text+0xbd1): undefined reference to `gcry_cipher_setctr'
          /usr/bin/ld: /home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib(libgcrypt.o): in function `_libssh2_cipher_crypt':
          (.text+0xc02): undefined reference to `gcry_cipher_encrypt'
          /usr/bin/ld: (.text+0xc11): undefined reference to `gcry_cipher_decrypt'
          /usr/bin/ld: /home/martin/dev/rust/xxx/target/debug/deps/liblibssh2_sys-187467b0efb35c13.rlib(global.o): in function `libssh2_init':
          (.text+0x38): undefined reference to `gcry_control'
          collect2: error: ld returned 1 exit status

我接下来看哪里?我的猜测是我缺少一个库,或者我拥有的版本不一样。

标签: linuxrustlinkerdependencies

解决方案


我想通了(经过一些实验和运气)。

整个问题闻起来像是ldgit 使用 SSH 连接所需的 C libssl 库的链接过程的问题。

Pop!_OS 以包含许多“需要开发”的东西而闻名,所以我很肯定我拥有所有这些(我做到了)。

我是如何解决的?

我看了看/etc/ld.so.conf.d/目录。那里有一些“.conf”文件。x86_64-linux-gnu.conf指向/usr/lib/x86_64-linux-gnu,所以我去那里看看哪些库匹配libssh*

我找到了这个:

$ ls -ls /usr/lib/x86_64-linux-gnu/libssh*
 312 -rw-r--r-- 1 root root  316732 Sep  5  2019 libssh2.a
   0 lrwxrwxrwx 1 root root      16 Sep  5  2019 libssh2.so -> libssh2.so.1.0.1
   0 lrwxrwxrwx 1 root root      16 Sep  5  2019 libssh2.so.1 -> libssh2.so.1.0.1
 184 -rw-r--r-- 1 root root  186856 Sep  5  2019 libssh2.so.1.0.1
1040 -rw-r--r-- 1 root root 1061468 Dec 10 16:24 libssh.a
   0 lrwxrwxrwx 1 root root      22 Dec 10 16:24 libssh-gcrypt.so.4 -> libssh-gcrypt.so.4.8.1
 552 -rw-r--r-- 1 root root  564760 Dec 10 16:24 libssh-gcrypt.so.4.8.1
   0 lrwxrwxrwx 1 root root      11 Dec 10 16:24 libssh.so -> libssh.so.4
   0 lrwxrwxrwx 1 root root      15 Dec 10 16:24 libssh.so.4 -> libssh.so.4.8.1
 552 -rw-r--r-- 1 root root  564856 Dec 10 16:24 libssh.so.4.8.1

当将此输出与出现此问题的新安装的 VM 进行比较时,我注意到libssh2*VM 中不存在所有文件。

由于链接器错误都在 gcry 中(我认为代表cryPT),我决定尝试删除这两个版本,只留下一个有效的版本:

$ sudo apt remove libssh2-1-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  libhttp-parser-dev libmbedtls-dev
Use 'sudo apt autoremove' to remove them.
The following packages will be REMOVED:
  libgit2-dev libssh2-1-dev
0 upgraded, 0 newly installed, 2 to remove and 0 not upgraded.
After this operation, 3,700 kB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database ... 412520 files and directories currently installed.)
Removing libgit2-dev:amd64 (0.27.7+dfsg.1-0.2build1) ...
Removing libssh2-1-dev:amd64 (1.8.0-2.1build1) ...
Processing triggers for man-db (2.8.7-3) ...

这样做之后,我得到了预期的输出:

 $ cargo run
warning: unused variable: `repo`
 --> src/main.rs:6:9
  |
6 |     let repo = match Repository::open("fakerepo") {
  |         ^^^^ help: consider prefixing with an underscore: `_repo`
  |
  = note: `#[warn(unused_variables)]` on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/xxx`
Hello, world!
thread 'main' panicked at 'Failed to init failed to resolve path 'fakerepo': No such file or directory; class=Os (2); code=NotFound (-3)', src/main.rs:8:19
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

如果我初始化一个 git repo 并再次运行它,就没有错误,正如预期的那样:

$ mkdir fakerepo; cd fakerepo ; git init ; cd ..
Initialized empty Git repository in /home/martin/dev/rust/xxx/fakerepo/.git/

$ cargo run
warning: unused variable: `repo`
 --> src/main.rs:6:9
  |
6 |     let repo = match Repository::open("fakerepo") {
  |         ^^^^ help: consider prefixing with an underscore: `_repo`
  |
  = note: `#[warn(unused_variables)]` on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/xxx`
Hello, world!

看来问题是那个图书馆。我将进一步调查以了解它来自哪里(谁安装了它),更重要的是,如何使它成为一个非问题(必须有一种方法来告诉整个构建过程选择哪个库),但这是另一个问题改天。

我做了什么来发现这一点?

VM 技巧是我之前为解决其他问题所做的事情。Linux 在虚拟机上安装非常容易/快速,并且 Gnome Boxes 已经在我的 Pop!_OS 上安装和配置,所以我花了 1 分钟来启动它并在我面前有一个新安装的操作系统(好吧,它不是新鲜的,我必须在虚拟机中下载大约 150 个更新):)

无论如何,我安装了Peppermint OS 。一个超轻的基于 Ubuntu 的发行版,没有太多的障碍,所以它非常适合我的需求。我在 Peppermint OS 上需要做的就是:

  • sudo apt install pkg-config
  • sudo apt install libssl-dev
  • sudo apt install curl(是的,它没有卷曲)
  • 安装 Rust (tl;dr: curl https://sh.rustup.rs -sSf | sh)

完成此操作后,我能够运行相同的 hello world 项目。当我意识到它正在这个 VM 上运行时,我也在一个 Pop!_OS 19.10 新安装的 VM 上再次这样做了。再一次,它奏效了。(这让我感到惊讶,因为我错误地归咎于“Pop_OS”)。

事实上,这在我很少输入的情况下在两个 VM 上都有效,这促使我继续在我的主机上尝试;我很高兴我做到了。


推荐阅读