我如何使用 Cargo 将库构建为 rlib 和 dylib 但内容不同?

How can I use Cargo to build a library as both an rlib and a dylib but with different contents?

我想制作一个包含以下内容的项目:

目录结构,不包括临时文件和其他垃圾:

.
├── Cargo.toml
├── src
│   ├── c_bindings.rs // contains C bindings for library
│   ├── compression.rs
│   ├── const_data.rs
│   ├── hash.rs
│   ├── lib.rs // library
│   └── main.rs // simple executable that uses library
└── target
    └── debug
        ├── gost_stribog
        ├── libgost_stribog.rlib

我想要cargo build这样做:

调试目录应该是:

└── target
    └── debug
        ├── gost_stribog
        ├── libgost_stribog.rlib
        ├── libgost_stribog.so

我的 Cargo.toml 应该是什么样子?

自以为是的答案:不要

相反,将您的代码分成两个或三个单独的箱子:

  1. 核心库。
  2. 库的 C 绑定。
  3. (可选)可执行文件。

然后,将您的 c_bindings.rs 移动到绑定箱,就像 lib.rs 一样。它可以依赖于核心库。您还可以将 main.rs 移动到另一个也依赖于核心库的板条箱中。

这三个 crate 可以在同一个源代码存储库中,但将通过单独的调用构建。

A Cargo workspace 可能有用;事实上,它被列为一个明确的原因 ("An FFI crate with a sub-crate for FFI bindings")。

事实上,你可以。这是如何做的。
$PROJECT_ROOT/.cargo/config.rs

[build]
rustflags = ["-C", "prefer-dynamic"]

请记住,您还需要使用 Rust 标准库来分发您的应用程序。

$ ls $(rustc --print=sysroot)/lib                                 
libLLVM-13-rust-1.57.0-beta.so  librustc_driver-3aebdc12af579500.so  libstd-c8bc39dac3997df6.so  libtest-4d997b51b1a49b1f.so  rustlib

在我的例子中它被命名为 libstd-c8bc39dac3997df6.so,因为我在 linux,如果你在 windows,它应该在 bin 文件夹而不是 lib文件夹。

此外,您还需要一个脚本来 运行 linux 和 MacOS 上的程序。在 linux 和 macOS 上,您不只是将库放在与您的应用程序相同的目录中并期望它能够工作,而是您有 2 个选项。

  1. 将库放入 /usr/lib 文件夹,然后 运行 它。
  2. 制作一个脚本:
exec LD_LIBRARY_PATH=$PWD ./YOU_APPLICATION $@ # this last commands tells sh to get the command line arguments.

仅此而已。 :)